specrails-desktop 2.57.0 → 2.58.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 +1 -1
- package/cli/dist/args.js +10 -4
- package/cli/dist/help.js +1 -1
- package/client/dist/assets/{ActivityFeedPage-DdMNmVBk.js → ActivityFeedPage-BQGppIR0.js} +1 -1
- package/client/dist/assets/{AgentBrowserCapture-CeerUf--.js → AgentBrowserCapture-PI-cxyxi.js} +1 -1
- package/client/dist/assets/{AgentModeAnalyticsPane-BjGb-8rh.js → AgentModeAnalyticsPane-mQsOqdXx.js} +2 -2
- package/client/dist/assets/{AgentModeCodePane-8XRkQEo_.js → AgentModeCodePane-BL-vpmlY.js} +2 -2
- package/client/dist/assets/{AgentModeJobsPane-BN3dgJOA.js → AgentModeJobsPane-DR_06oqH.js} +1 -1
- package/client/dist/assets/AgentsPage-BKIKjm_1.js +118 -0
- package/client/dist/assets/{AnalyticsPage-CyfhYiBn.js → AnalyticsPage-069npRVo.js} +1 -1
- package/client/dist/assets/{CodePage-C2Nf-Q5W.js → CodePage-Alitorrv.js} +2 -2
- package/client/dist/assets/DesktopAnalyticsPage-qtWAPM47.js +1 -0
- package/client/dist/assets/{DocsDialog-Br3bczCp.js → DocsDialog-DwL6rgcT.js} +1 -1
- package/client/dist/assets/{DocsPage-BcDr2cBm.js → DocsPage-BA1hiJZ-.js} +1 -1
- package/client/dist/assets/{ExportDropdown-BVGKEgkd.js → ExportDropdown-BcMpvV89.js} +1 -1
- package/client/dist/assets/InteractiveJobComposer-B3H1YHr6.js +19 -0
- package/client/dist/assets/JobDetailModal-XZQ9eAAy.js +1 -0
- package/client/dist/assets/{JobDetailPage-vBbNeRuz.js → JobDetailPage-B-SIaq_q.js} +1 -1
- package/client/dist/assets/{JobsPage-CJCtPhIz.js → JobsPage-iQXAv2mx.js} +1 -1
- package/client/dist/assets/LoopBuilderPage-B_gbFAHn.js +1 -0
- package/client/dist/assets/LoopPreviewModal-je5pSCf-.js +1 -0
- package/client/dist/assets/LoopsPage-BZwcY5cu.js +2 -0
- package/client/dist/assets/{MinimizedChatsContext-D3QzgV0B.js → MinimizedChatsContext-CNx_0bZu.js} +1 -1
- package/client/dist/assets/{PluginsPage-DOpTV75p.js → PluginsPage-DFocnoHX.js} +2 -2
- package/client/dist/assets/{ProjectSettingsDialog-Dkwrn0z1.js → ProjectSettingsDialog-Bh3S6EBB.js} +1 -1
- package/client/dist/assets/{RepositoryDeliveries-Du2UCf1a.js → RepositoryDeliveries-BiwJuS8r.js} +1 -1
- package/client/dist/assets/{RepositoryScopeSelector-hPGZNRBm.js → RepositoryScopeSelector-C2mvWBQ6.js} +1 -1
- package/client/dist/assets/{ReviewPacketPage-DcOq-UTA.js → ReviewPacketPage-CrAf-WDy.js} +2 -2
- package/client/dist/assets/TemplatePreviewModal-C7DordpN.js +1 -0
- package/client/dist/assets/{TicketDetailModalContext-DAK-NoK6.js → TicketDetailModalContext-B-DySpKL.js} +1 -1
- package/client/dist/assets/{Trans-DEbgkuAY.js → Trans-D3AfDylf.js} +1 -1
- package/client/dist/assets/agentRuntime-BeUb3g9g.js +1 -0
- package/client/dist/assets/agentRuntime-Bg9tbmqm.js +1 -0
- package/client/dist/assets/agentRuntime-D-GJVGkj.js +1 -0
- package/client/dist/assets/agentRuntime-D2__CVI_.js +1 -0
- package/client/dist/assets/agentRuntime-D35dGVOP.js +1 -0
- package/client/dist/assets/agentRuntime-DGz_IqKW.js +1 -0
- package/client/dist/assets/agentRuntime-O1liDt6G.js +1 -0
- package/client/dist/assets/agentRuntime-hInH9Fzj.js +1 -0
- package/client/dist/assets/agentstudio-B2CTtQgZ.js +1 -0
- package/client/dist/assets/agentstudio-BWAKeGgB.js +1 -0
- package/client/dist/assets/{agentstudio-DR7doNBV.js → agentstudio-Cja8Sjcp.js} +1 -1
- package/client/dist/assets/agentstudio-DtfPcr99.js +1 -0
- package/client/dist/assets/agentstudio-QdAJIDef.js +1 -0
- package/client/dist/assets/agentstudio-X70BKf6u.js +1 -0
- package/client/dist/assets/agentstudio-fLXpRGIi.js +1 -0
- package/client/dist/assets/agentstudio-qXKqVnWS.js +1 -0
- package/client/dist/assets/{analytics-jzCkOec3.js → analytics-B1DIQd4m.js} +1 -1
- package/client/dist/assets/{analytics-CoEzWPx4.js → analytics-BAIZ9vE_.js} +1 -1
- package/client/dist/assets/{analytics-DjLlE7jS.js → analytics-BTqgmgBd.js} +1 -1
- package/client/dist/assets/analytics-BWynXPEm.js +1 -0
- package/client/dist/assets/{analytics-nZIjjtCc.js → analytics-DGcUsQ44.js} +1 -1
- package/client/dist/assets/{analytics-BNgZ1Nj7.js → analytics-GnSnpJ4W.js} +1 -1
- package/client/dist/assets/{analytics-DFh5lSOl.js → analytics-TWgYaoO0.js} +1 -1
- package/client/dist/assets/{analytics-DZp-DS2U.js → analytics-kJy6Tuko.js} +1 -1
- package/client/dist/assets/builder-C0FyvM83.js +1 -0
- package/client/dist/assets/builder-C1neIYGR.js +1 -0
- package/client/dist/assets/builder-CvnFm0im.js +1 -0
- package/client/dist/assets/builder-CzW5ovyI.js +1 -0
- package/client/dist/assets/builder-D06L7iPy.js +1 -0
- package/client/dist/assets/builder-DGETbtZj.js +1 -0
- package/client/dist/assets/builder-DXEJUlC0.js +1 -0
- package/client/dist/assets/builder-DyQperXU.js +1 -0
- package/client/dist/assets/common-BCK7c9Pv.js +1 -0
- package/client/dist/assets/common-C0BOdeNi.js +1 -0
- package/client/dist/assets/common-C4Yvvhp6.js +1 -0
- package/client/dist/assets/{common-BrlwEnL7.js → common-DmsclwjP.js} +1 -1
- package/client/dist/assets/common-DpLWwgI1.js +1 -0
- package/client/dist/assets/common-OCvl3c8t.js +1 -0
- package/client/dist/assets/common-c0aujEZC.js +1 -0
- package/client/dist/assets/common-od8WThlf.js +1 -0
- package/client/dist/assets/dashboard-B1ndRHuC.js +1 -0
- package/client/dist/assets/dashboard-BX7KXiqA.js +1 -0
- package/client/dist/assets/dashboard-B_BSNxcN.js +1 -0
- package/client/dist/assets/dashboard-CCeFN7-V.js +1 -0
- package/client/dist/assets/dashboard-CRl0WtFJ.js +1 -0
- package/client/dist/assets/dashboard-XGdQ5mjw.js +1 -0
- package/client/dist/assets/dashboard-_oltA6Jd.js +1 -0
- package/client/dist/assets/dashboard-bAuf5KVk.js +1 -0
- package/client/dist/assets/{formatDistanceToNow-Cc2u5FwQ.js → formatDistanceToNow-aBss1Nai.js} +1 -1
- package/client/dist/assets/{getTimezoneOffsetInMilliseconds-BHm2U-w1.js → getTimezoneOffsetInMilliseconds-DOGj1Mfz.js} +1 -1
- package/client/dist/assets/index-BS7KCWkV.css +2 -0
- package/client/dist/assets/{index-Cxb288Rj.js → index-C4Mv6tV6.js} +32 -32
- package/client/dist/assets/{jira-api-DrGxiD9p.js → jira-api-BYbEPlkr.js} +1 -1
- package/client/dist/assets/{jobs-DSp9DoD_.js → jobs-6_-r75yC.js} +1 -1
- package/client/dist/assets/{jobs-C6qmvUAi.js → jobs-B1yqyId5.js} +1 -1
- package/client/dist/assets/{jobs-DoFaEl9g.js → jobs-BFuV7ttH.js} +1 -1
- package/client/dist/assets/{jobs-DTQO08nJ.js → jobs-BKa8LuwA.js} +1 -1
- package/client/dist/assets/{jobs-DrF8Do8s.js → jobs-BKiK-ZWh.js} +1 -1
- package/client/dist/assets/{jobs-DLHdDkHc.js → jobs-DmKV7b7d.js} +1 -1
- package/client/dist/assets/{jobs-C9j2PuwW.js → jobs-KG4Sn12X.js} +1 -1
- package/client/dist/assets/{jobs-Dpw6AEOP.js → jobs-pPv4KWjb.js} +1 -1
- package/client/dist/assets/loop-layout-BF8xMiNv.js +7 -0
- package/client/dist/assets/loops-B4_D-nbg.js +1 -0
- package/client/dist/assets/loops-BJDY9FTh.js +1 -0
- package/client/dist/assets/loops-BO3V8244.js +1 -0
- package/client/dist/assets/loops-C-hZK8pf.js +1 -0
- package/client/dist/assets/loops-CDOWZ0ci.js +1 -0
- package/client/dist/assets/loops-Dv849ckF.js +1 -0
- package/client/dist/assets/loops-Q9LIgGkq.js +1 -0
- package/client/dist/assets/loops-eUnCfLjC.js +1 -0
- package/client/dist/assets/{project-repositories-9Wzs0coQ.js → project-repositories-CSnfzUpg.js} +1 -1
- package/client/dist/assets/settings-3o4Ntzi5.js +1 -0
- package/client/dist/assets/settings-B97jlkwD.js +1 -0
- package/client/dist/assets/settings-BTaT_bsS.js +1 -0
- package/client/dist/assets/settings-CT8w7WiC.js +1 -0
- package/client/dist/assets/settings-Cvr8_tvh.js +1 -0
- package/client/dist/assets/settings-Dn1qgAC8.js +1 -0
- package/client/dist/assets/settings-EShDdg4J.js +1 -0
- package/client/dist/assets/settings-tfLhQZRN.js +1 -0
- package/client/dist/assets/{setup-Dwzt5nO1.js → setup-CBMu3tqH.js} +1 -1
- package/client/dist/assets/{setup-B5FHuxvB.js → setup-CPh-e6J2.js} +1 -1
- package/client/dist/assets/{setup-DpqzaEEA.js → setup-CRKLp_ke.js} +1 -1
- package/client/dist/assets/{setup-CROyqD5N.js → setup-Cy302v4J.js} +1 -1
- package/client/dist/assets/{setup-C9Fy9PKQ.js → setup-D681vTPf.js} +1 -1
- package/client/dist/assets/{setup-BihzXadx.js → setup-DYK0VBkE.js} +1 -1
- package/client/dist/assets/{setup-BtC6Hg4K.js → setup-KAuiIiVs.js} +1 -1
- package/client/dist/assets/{setup-zLEDnG7N.js → setup-OGX-oCfI.js} +1 -1
- package/client/dist/assets/{spending-T5GM7wpn.js → spending-HBSk-6jv.js} +1 -1
- package/client/dist/assets/{useDesktop-QogiN0zR.js → useDesktop-0unHDBJJ.js} +1 -1
- package/client/dist/assets/useRuntimeRuns-BN1rhyEm.js +1 -0
- package/client/dist/assets/{useSharedWebSocket-Dz-HI6De.js → useSharedWebSocket-BZMrX4jr.js} +2 -2
- package/client/dist/index.html +25 -25
- package/docs/agent-live-steering.md +16 -0
- package/docs/cli.md +7 -7
- package/docs/codex.md +2 -2
- package/docs/customizing.md +1 -1
- package/docs/gemini.md +1 -1
- package/docs/getting-started.md +1 -1
- package/docs/guide/de/integrations/7-local-engines.md +1 -1
- package/docs/guide/de/pipeline/1-rails-and-jobs.md +8 -6
- package/docs/guide/de/pipeline/2-the-job-detail-view.md +11 -2
- package/docs/guide/de/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/de/pipeline/5-the-loop-builder.md +24 -5
- package/docs/guide/en/integrations/7-local-engines.md +1 -1
- package/docs/guide/en/pipeline/1-rails-and-jobs.md +8 -6
- package/docs/guide/en/pipeline/2-the-job-detail-view.md +11 -2
- package/docs/guide/en/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/en/pipeline/5-the-loop-builder.md +34 -5
- package/docs/guide/en/settings/3-pipeline-telemetry-and-diagnostics.md +1 -1
- package/docs/guide/es/integrations/7-local-engines.md +1 -1
- package/docs/guide/es/pipeline/1-rails-and-jobs.md +8 -6
- package/docs/guide/es/pipeline/2-the-job-detail-view.md +11 -2
- package/docs/guide/es/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/es/pipeline/5-the-loop-builder.md +30 -5
- package/docs/guide/es/settings/3-pipeline-telemetry-and-diagnostics.md +1 -2
- package/docs/guide/fr/integrations/7-local-engines.md +1 -1
- package/docs/guide/fr/pipeline/1-rails-and-jobs.md +8 -6
- package/docs/guide/fr/pipeline/2-the-job-detail-view.md +11 -2
- package/docs/guide/fr/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/fr/pipeline/5-the-loop-builder.md +24 -5
- package/docs/guide/it/integrations/7-local-engines.md +1 -1
- package/docs/guide/it/pipeline/1-rails-and-jobs.md +8 -6
- package/docs/guide/it/pipeline/2-the-job-detail-view.md +11 -2
- package/docs/guide/it/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/it/pipeline/5-the-loop-builder.md +24 -5
- package/docs/guide/ja/integrations/7-local-engines.md +1 -1
- package/docs/guide/ja/pipeline/1-rails-and-jobs.md +8 -6
- package/docs/guide/ja/pipeline/2-the-job-detail-view.md +11 -2
- package/docs/guide/ja/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/ja/pipeline/5-the-loop-builder.md +24 -5
- package/docs/guide/pt/integrations/7-local-engines.md +1 -1
- package/docs/guide/pt/pipeline/1-rails-and-jobs.md +8 -6
- package/docs/guide/pt/pipeline/2-the-job-detail-view.md +11 -2
- package/docs/guide/pt/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/pt/pipeline/5-the-loop-builder.md +24 -5
- package/docs/guide/zh/integrations/7-local-engines.md +1 -1
- package/docs/guide/zh/pipeline/1-rails-and-jobs.md +8 -6
- package/docs/guide/zh/pipeline/2-the-job-detail-view.md +11 -2
- package/docs/guide/zh/pipeline/4-picking-an-engine-per-rail.md +2 -2
- package/docs/guide/zh/pipeline/5-the-loop-builder.md +24 -5
- package/docs/internals/api-reference.md +2 -2
- package/docs/internals/ci-performance.md +71 -0
- package/docs/internals/companion-rails-as-loops-contract.md +4 -3
- package/docs/internals/configuration.md +3 -3
- package/docs/internals/core-runtime-updates.md +3 -2
- package/docs/internals/interactive-jobs.md +2 -2
- package/docs/internals/loop-step-log-explorer.md +42 -0
- package/docs/internals/mission-rail-cards.md +1 -1
- package/docs/internals/operations-runbook.md +22 -0
- package/docs/internals/programmatic-agent-runtime.md +130 -7
- package/docs/internals/project-builder.md +35 -16
- package/docs/internals/source-map.md +48 -2
- package/docs/kimi.md +2 -2
- package/docs/local-providers.md +1 -1
- package/docs/running-pipelines.md +26 -18
- package/docs/tracking-cost.md +10 -1
- package/package.json +2 -1
- package/server/dist/core-compat.js +8 -3
- package/server/dist/core-execution.js +49 -3
- package/server/dist/db/migrations.js +101 -0
- package/server/dist/desktop-db.js +28 -0
- package/server/dist/desktop-router.js +2 -0
- package/server/dist/mcp/guide.js +6 -3
- package/server/dist/mcp/tools/jobs.js +14 -1
- package/server/dist/mcp/tools/loops.js +17 -8
- package/server/dist/mcp/tools/rails.js +3 -3
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-bridge.js +313 -9
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-controls-router.js +34 -1
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-controls.js +203 -21
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-effective-config.js +46 -1
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-engines.js +10 -0
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-loader.js +68 -3
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-metrics.js +16 -8
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-package-gc.js +81 -0
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-package-lock.js +37 -0
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-package.js +30 -24
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-retention-host.js +87 -0
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-retention-quarantine.js +231 -0
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-retention-records.js +32 -0
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-retention.js +102 -0
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-settings-router.js +12 -7
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-settings.js +57 -13
- package/server/dist/modules/agents/runtime/agent-catalog.js +32 -0
- package/server/dist/modules/agents/runtime/agent-refine-manager.js +12 -0
- package/server/dist/modules/agents/runtime/agent-role-descriptor.js +64 -0
- package/server/dist/modules/agents/runtime/profiles-router.js +26 -34
- package/server/dist/modules/builder/runtime/milestone-chain.js +121 -73
- package/server/dist/modules/delivery/runtime/definition-fork.js +158 -0
- package/server/dist/modules/delivery/runtime/delivery-evidence.js +56 -10
- package/server/dist/modules/delivery/runtime/isolated-settlement-reconstruction.js +99 -0
- package/server/dist/modules/delivery/runtime/isolated-settlement-store.js +53 -0
- package/server/dist/modules/delivery/runtime/multi-repo-execution-store.js +3 -1
- package/server/dist/modules/delivery/runtime/rail-isolated-launch.js +388 -203
- package/server/dist/modules/delivery/runtime/rail-launch-parser.js +3 -2
- package/server/dist/modules/delivery/runtime/rail-pr-store.js +6 -1
- package/server/dist/modules/delivery/runtime/rails-router.js +66 -10
- package/server/dist/modules/execution/runtime/queue-manager.js +11 -2
- package/server/dist/modules/loops/runtime/builtin-loops.js +70 -0
- package/server/dist/modules/loops/runtime/definition-cancellation.js +31 -0
- package/server/dist/modules/loops/runtime/legacy-launch-telemetry.js +78 -0
- package/server/dist/modules/loops/runtime/loop-command-catalog.js +13 -12
- package/server/dist/modules/loops/runtime/loop-compat.js +219 -0
- package/server/dist/modules/loops/runtime/loop-core-factory.js +42 -0
- package/server/dist/modules/loops/runtime/loop-definition-controls.js +48 -0
- package/server/dist/modules/loops/runtime/loop-definition-events.js +145 -0
- package/server/dist/modules/loops/runtime/loop-definition-recovery.js +106 -0
- package/server/dist/modules/loops/runtime/loop-definition-run.js +36 -0
- package/server/dist/modules/loops/runtime/loop-definition.js +246 -0
- package/server/dist/modules/loops/runtime/loop-effect.js +10 -1
- package/server/dist/modules/loops/runtime/loop-executors.js +63 -3
- package/server/dist/modules/loops/runtime/loop-factory.js +35 -15
- package/server/dist/modules/loops/runtime/loop-graph.js +84 -8
- package/server/dist/modules/loops/runtime/loop-migration.js +36 -0
- package/server/dist/modules/loops/runtime/loop-preview.js +10 -0
- package/server/dist/modules/loops/runtime/loop-run-manager.js +206 -13
- package/server/dist/modules/loops/runtime/loop-runs-store.js +271 -7
- package/server/dist/modules/loops/runtime/loop-templates.js +205 -45
- package/server/dist/modules/loops/runtime/loops-router.js +246 -29
- package/server/dist/modules/loops/runtime/loops-store.js +140 -20
- package/server/dist/modules/missions/runtime/agent-operator-prompt.js +14 -11
- package/server/dist/modules/specs/runtime/spec-addenda.js +28 -0
- package/server/dist/project-registry.js +87 -51
- package/server/dist/project-router-jobs.js +17 -6
- package/server/dist/project-router-loop-runs.js +200 -0
- package/server/dist/project-router-spending.js +17 -0
- package/server/dist/project-router.js +8 -6
- package/server/dist/schemas/agent-runtime.schema.json +93 -1
- package/server/dist/schemas/workflow-definition.schema.json +312 -0
- package/server/dist/vitest-setup.js +22 -0
- package/server/dist/worktree-overlay.js +1 -1
- package/client/dist/assets/AgentsPage-DfHWgP_x.js +0 -87
- package/client/dist/assets/DesktopAnalyticsPage-tc0p4jJW.js +0 -1
- package/client/dist/assets/InteractiveJobComposer-DFPpdg2D.js +0 -19
- package/client/dist/assets/JobDetailModal-BdOv-l-M.js +0 -1
- package/client/dist/assets/LoopBuilderPage-BemvUOxy.js +0 -7
- package/client/dist/assets/LoopPreviewModal-C6hNAeYN.js +0 -1
- package/client/dist/assets/LoopsPage-BZr0quvh.js +0 -1
- package/client/dist/assets/TemplatePreviewModal-Cejcquah.js +0 -1
- package/client/dist/assets/agentRuntime-BUimiX__.js +0 -1
- package/client/dist/assets/agentRuntime-BcN97sAB.js +0 -1
- package/client/dist/assets/agentRuntime-Ckyg-ahT.js +0 -1
- package/client/dist/assets/agentRuntime-DJCwyX4t.js +0 -1
- package/client/dist/assets/agentRuntime-DVzPJOl0.js +0 -1
- package/client/dist/assets/agentRuntime-V9AZTG3c.js +0 -1
- package/client/dist/assets/agentRuntime-bAAjw1vw.js +0 -1
- package/client/dist/assets/agentRuntime-v4qKAYH-.js +0 -1
- package/client/dist/assets/agentstudio-BNUth0uj.js +0 -1
- package/client/dist/assets/agentstudio-BNdB5hkr.js +0 -1
- package/client/dist/assets/agentstudio-C7-bt8FO.js +0 -1
- package/client/dist/assets/agentstudio-C8uNchpV.js +0 -1
- package/client/dist/assets/agentstudio-CKabyMlg.js +0 -1
- package/client/dist/assets/agentstudio-CN2pokQu.js +0 -1
- package/client/dist/assets/agentstudio-y2dVDXeM.js +0 -1
- package/client/dist/assets/analytics-BlypLLR6.js +0 -1
- package/client/dist/assets/builder-765NeYTp.js +0 -1
- package/client/dist/assets/builder-8MG3V6ea.js +0 -1
- package/client/dist/assets/builder-B-1UBs5K.js +0 -1
- package/client/dist/assets/builder-BTiGnPT0.js +0 -1
- package/client/dist/assets/builder-Cx9Rz-7u.js +0 -1
- package/client/dist/assets/builder-DKFMELBl.js +0 -1
- package/client/dist/assets/builder-OcmKrC0h.js +0 -1
- package/client/dist/assets/builder-P9qVBXFZ.js +0 -1
- package/client/dist/assets/common-B5AZNYMH.js +0 -1
- package/client/dist/assets/common-BFZ0c_vN.js +0 -1
- package/client/dist/assets/common-BttQx3z4.js +0 -1
- package/client/dist/assets/common-CM65k_-e.js +0 -1
- package/client/dist/assets/common-D4mvFFlu.js +0 -1
- package/client/dist/assets/common-TZ9Ny96S.js +0 -1
- package/client/dist/assets/common-nFpSF4GC.js +0 -1
- package/client/dist/assets/dashboard-B9uWNGO2.js +0 -1
- package/client/dist/assets/dashboard-BIwmO9wc.js +0 -1
- package/client/dist/assets/dashboard-BV4vOZkR.js +0 -1
- package/client/dist/assets/dashboard-Bf6MPVsM.js +0 -1
- package/client/dist/assets/dashboard-C8klWVvZ.js +0 -1
- package/client/dist/assets/dashboard-D1ORhPF0.js +0 -1
- package/client/dist/assets/dashboard-DSubvs9x.js +0 -1
- package/client/dist/assets/dashboard-px_vlRx_.js +0 -1
- package/client/dist/assets/index-C51x61Bz.css +0 -2
- package/client/dist/assets/loops-B7YpGizO.js +0 -1
- package/client/dist/assets/loops-BomD2J-h.js +0 -1
- package/client/dist/assets/loops-BrQHSQw3.js +0 -1
- package/client/dist/assets/loops-BvBwvTPA.js +0 -1
- package/client/dist/assets/loops-CODk6Slz.js +0 -1
- package/client/dist/assets/loops-DC6k-Ym-.js +0 -1
- package/client/dist/assets/loops-DSEg8-uY.js +0 -1
- package/client/dist/assets/loops-DhCoXD_v.js +0 -1
- package/client/dist/assets/settings-BsehKpty.js +0 -1
- package/client/dist/assets/settings-CQWob3SB.js +0 -1
- package/client/dist/assets/settings-CgCl0hzy.js +0 -1
- package/client/dist/assets/settings-DLRLd22L.js +0 -1
- package/client/dist/assets/settings-Dn5prAFl.js +0 -1
- package/client/dist/assets/settings-HZSu-K4l.js +0 -1
- package/client/dist/assets/settings-p4OVIyRh.js +0 -1
- package/client/dist/assets/settings-rddaldUp.js +0 -1
- package/client/dist/assets/useRuntimeRuns-Dqmz9fS9.js +0 -1
- package/docs/guide/de/pipeline/3-batch-implement-and-multi-feature.md +0 -84
- package/docs/guide/en/pipeline/3-batch-implement-and-multi-feature.md +0 -126
- package/docs/guide/es/pipeline/3-batch-implement-and-multi-feature.md +0 -114
- package/docs/guide/fr/pipeline/3-batch-implement-and-multi-feature.md +0 -84
- package/docs/guide/it/pipeline/3-batch-implement-and-multi-feature.md +0 -84
- package/docs/guide/ja/pipeline/3-batch-implement-and-multi-feature.md +0 -84
- package/docs/guide/pt/pipeline/3-batch-implement-and-multi-feature.md +0 -84
- package/docs/guide/zh/pipeline/3-batch-implement-and-multi-feature.md +0 -84
- package/server/dist/modules/loops/runtime/loop-templates-ported.js +0 -675
- /package/client/dist/assets/{LoopBuilderPage-DtxX27Jz.css → loop-layout-DtxX27Jz.css} +0 -0
|
@@ -15,9 +15,10 @@ function withDefaultRoleModels(body) {
|
|
|
15
15
|
if (!agents || typeof agents !== 'object' || !Array.isArray(providers))
|
|
16
16
|
return body;
|
|
17
17
|
// Only LOCAL roles: a CLI role saved without a model keeps meaning "provider default" (never frozen into the file).
|
|
18
|
+
const roles = body.roles && typeof body.roles === 'object' && !Array.isArray(body.roles) ? structuredClone(body.roles) : undefined;
|
|
18
19
|
const fixer = body.fixer && typeof body.fixer === 'object' ? structuredClone(body.fixer) : undefined;
|
|
19
|
-
const filled = (0, agent_runtime_effective_config_1.fillDefaultRoleModels)({ agents: structuredClone(agents), providers: providers, ...(fixer ? { fixer: fixer } : {}) }, { localOnly: true });
|
|
20
|
-
return { ...body, agents: filled.agents, ...(filled.fixer ? { fixer: filled.fixer } : {}) };
|
|
20
|
+
const filled = (0, agent_runtime_effective_config_1.fillDefaultRoleModels)({ agents: structuredClone(agents), providers: providers, ...(roles ? { roles: roles } : {}), ...(fixer ? { fixer: fixer } : {}) }, { localOnly: true });
|
|
21
|
+
return { ...body, agents: filled.agents, ...(filled.roles ? { roles: filled.roles } : {}), ...(filled.fixer ? { fixer: filled.fixer } : {}) };
|
|
21
22
|
}
|
|
22
23
|
const loop_role_engines_1 = require("../../loops/runtime/loop-role-engines");
|
|
23
24
|
function registerAgentRuntimeSettingsRoutes({ router, ctx }) {
|
|
@@ -62,12 +63,15 @@ function registerAgentRuntimeSettingsRoutes({ router, ctx }) {
|
|
|
62
63
|
const project = ctx(_req).project;
|
|
63
64
|
const configured = (0, node_fs_1.existsSync)((0, agent_runtime_settings_1.agentRuntimeConfigPath)(project));
|
|
64
65
|
const config = (0, agent_runtime_settings_1.loadAgentRuntimeConfig)(project);
|
|
65
|
-
let efficiencyAvailable = false;
|
|
66
|
+
let efficiencyAvailable = false, openRolesAvailable = false;
|
|
66
67
|
try {
|
|
67
|
-
|
|
68
|
+
const capabilities = (await (0, agent_runtime_loader_1.loadCoreAgentRuntime)()).api?.capabilities;
|
|
69
|
+
efficiencyAvailable = capabilities?.efficientRoleExecution === 1;
|
|
70
|
+
openRolesAvailable = capabilities?.openRoles === 1;
|
|
68
71
|
}
|
|
69
72
|
catch { /* Ordinary settings remain readable without capability support. */ }
|
|
70
|
-
res.json({ configured, config, runtimeAvailable: (0, agent_runtime_loader_1.findCoreAgentRuntimeEntry)() !== null, efficiencyAvailable
|
|
73
|
+
res.json({ configured, config, runtimeAvailable: (0, agent_runtime_loader_1.findCoreAgentRuntimeEntry)() !== null, efficiencyAvailable, openRolesAvailable,
|
|
74
|
+
workflowRoleDefaults: openRolesAvailable && config ? (0, agent_runtime_effective_config_1.workflowRoleDefaults)(config) : {} });
|
|
71
75
|
}
|
|
72
76
|
catch (err) {
|
|
73
77
|
const validation = err instanceof agent_runtime_settings_1.AgentRuntimeConfigError;
|
|
@@ -127,7 +131,7 @@ function registerAgentRuntimeSettingsRoutes({ router, ctx }) {
|
|
|
127
131
|
res.status(503).json({ error: 'runtime_unavailable', message: 'Update Core to an installation with the agent runtime before enabling it' });
|
|
128
132
|
return;
|
|
129
133
|
}
|
|
130
|
-
let efficiencyAvailable = false;
|
|
134
|
+
let efficiencyAvailable = false, openRolesAvailable = false;
|
|
131
135
|
if (config.enabled && runtimeAvailable) {
|
|
132
136
|
try {
|
|
133
137
|
const runtime = await (0, agent_runtime_loader_1.loadCoreAgentRuntime)();
|
|
@@ -135,6 +139,7 @@ function registerAgentRuntimeSettingsRoutes({ router, ctx }) {
|
|
|
135
139
|
runtime.validateRuntimeConfig(coreConfig);
|
|
136
140
|
(0, agent_runtime_loader_1.validateRequestedRoleEfforts)(runtime, coreConfig);
|
|
137
141
|
efficiencyAvailable = runtime.api?.capabilities?.efficientRoleExecution === 1;
|
|
142
|
+
openRolesAvailable = runtime.api?.capabilities?.openRoles === 1;
|
|
138
143
|
}
|
|
139
144
|
catch {
|
|
140
145
|
res.status(503).json({ error: 'runtime_incompatible', message: 'The installed Core runtime could not validate this configuration; update Core and retry' });
|
|
@@ -142,7 +147,7 @@ function registerAgentRuntimeSettingsRoutes({ router, ctx }) {
|
|
|
142
147
|
}
|
|
143
148
|
}
|
|
144
149
|
const saved = (0, agent_runtime_settings_1.saveAgentRuntimeConfig)(ctx(req).project, config);
|
|
145
|
-
res.json({ configured: true, config: saved, runtimeAvailable, efficiencyAvailable });
|
|
150
|
+
res.json({ configured: true, config: saved, runtimeAvailable, efficiencyAvailable, openRolesAvailable });
|
|
146
151
|
}
|
|
147
152
|
catch (err) {
|
|
148
153
|
const validation = err instanceof agent_runtime_settings_1.AgentRuntimeConfigError;
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.AgentRuntimeConfigError = exports.REVIEW_THRESHOLD_FLOORS = exports.MAX_OUTPUT_TOKENS_MAX = exports.MAX_OUTPUT_TOKENS_MIN = exports.CONTEXT_WINDOW_TOKENS_MAX = exports.CONTEXT_WINDOW_TOKENS_MIN = void 0;
|
|
6
|
+
exports.AgentRuntimeConfigError = exports.REVIEW_THRESHOLD_FLOORS = exports.MAX_OUTPUT_TOKENS_MAX = exports.MAX_OUTPUT_TOKENS_MIN = exports.CONTEXT_WINDOW_TOKENS_MAX = exports.CONTEXT_WINDOW_TOKENS_MIN = exports.RUNTIME_ROLE_ID = void 0;
|
|
7
7
|
exports.stripDesktopConnectionFields = stripDesktopConnectionFields;
|
|
8
8
|
exports.coreConnectionFieldGates = coreConnectionFieldGates;
|
|
9
9
|
exports.validateAgentRuntimeConfig = validateAgentRuntimeConfig;
|
|
@@ -26,9 +26,14 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
26
26
|
const node_os_1 = __importDefault(require("node:os"));
|
|
27
27
|
const node_crypto_1 = require("node:crypto");
|
|
28
28
|
const ajv_1 = __importDefault(require("ajv"));
|
|
29
|
+
const node_util_1 = require("node:util");
|
|
29
30
|
const agent_runtime_schema_json_1 = __importDefault(require("../../../schemas/agent-runtime.schema.json"));
|
|
30
31
|
const workspace_resolution_1 = require("../../../workspace-resolution");
|
|
31
32
|
const registry_1 = require("../../../providers/registry");
|
|
33
|
+
const agent_catalog_1 = require("../../agents/runtime/agent-catalog");
|
|
34
|
+
const agent_role_descriptor_1 = require("../../agents/runtime/agent-role-descriptor");
|
|
35
|
+
var agent_role_descriptor_2 = require("../../agents/runtime/agent-role-descriptor");
|
|
36
|
+
Object.defineProperty(exports, "RUNTIME_ROLE_ID", { enumerable: true, get: function () { return agent_role_descriptor_2.RUNTIME_ROLE_ID; } });
|
|
32
37
|
const DESKTOP_CONNECTION_FIELDS = ['label', 'defaultModel', 'rates'];
|
|
33
38
|
/** Core-owned small-model fields: known only to cores advertising `capabilities.compactAgentLoop`
|
|
34
39
|
* (`supportsReasoningEffort` moved here: core forwards it as OpenAI `reasoning_effort`). */
|
|
@@ -145,7 +150,7 @@ function validateAgentRuntimeConfig(input) {
|
|
|
145
150
|
}
|
|
146
151
|
const config = input;
|
|
147
152
|
if (config.rolePrompts !== undefined)
|
|
148
|
-
validateRuntimeRolePrompts(config.rolePrompts);
|
|
153
|
+
validateRuntimeRolePrompts(config.rolePrompts, Object.keys(config.roles ?? {}));
|
|
149
154
|
if (new Set(config.providers.map(({ id }) => id)).size !== config.providers.length)
|
|
150
155
|
throw new AgentRuntimeConfigError('Provider IDs must be unique');
|
|
151
156
|
for (const provider of config.providers) {
|
|
@@ -165,8 +170,8 @@ function validateAgentRuntimeConfig(input) {
|
|
|
165
170
|
if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password || url.search || url.hash || provider.baseUrl.includes('\0'))
|
|
166
171
|
throw new AgentRuntimeConfigError('Provider URLs must use HTTP(S) without credentials, query parameters or fragments');
|
|
167
172
|
}
|
|
168
|
-
|
|
169
|
-
|
|
173
|
+
const assignments = [...Object.entries(config.agents), ...Object.entries(config.roles ?? {}), ...(config.fixer ? [['fixer', config.fixer]] : [])];
|
|
174
|
+
for (const [role, agent] of assignments) {
|
|
170
175
|
const provider = config.providers.find(({ id }) => id === agent.provider);
|
|
171
176
|
if (!provider)
|
|
172
177
|
throw new AgentRuntimeConfigError(`Role ${role} references a provider that is not configured`);
|
|
@@ -191,6 +196,22 @@ function validateAgentRuntimeConfig(input) {
|
|
|
191
196
|
if (agent.thinking !== undefined && agent.thinking !== 'on' && agent.thinking !== 'off')
|
|
192
197
|
throw new AgentRuntimeConfigError(`Role ${role} thinking must be "on" or "off"`);
|
|
193
198
|
}
|
|
199
|
+
const builtinPolicies = {
|
|
200
|
+
architect: { access: 'read', artifacts: 'all', openspecSkill: 'openspec-ff-change' },
|
|
201
|
+
developer: { access: 'write', artifacts: 'tasks-checkboxes', openspecSkill: 'openspec-apply-change' },
|
|
202
|
+
reviewer: { access: 'read', artifacts: 'none', openspecSkill: 'openspec-verify-change' },
|
|
203
|
+
};
|
|
204
|
+
for (const [id, descriptor] of Object.entries(config.roles ?? {})) {
|
|
205
|
+
if (!agent_role_descriptor_1.RUNTIME_ROLE_ID.test(id) || id === 'fixer')
|
|
206
|
+
throw new AgentRuntimeConfigError(`Invalid custom role ID: ${id}`);
|
|
207
|
+
if (descriptor.prompt !== undefined && (!descriptor.prompt.trim() || descriptor.prompt.includes('\0')))
|
|
208
|
+
throw new AgentRuntimeConfigError(`Role ${id} requires a nonblank prompt without null bytes`);
|
|
209
|
+
if (ROLES.includes(id)) {
|
|
210
|
+
const { access, artifacts, openspecSkill, prompt, ...assignment } = descriptor;
|
|
211
|
+
if (prompt !== undefined || !(0, node_util_1.isDeepStrictEqual)(assignment, config.agents[id]) || !(0, node_util_1.isDeepStrictEqual)({ access, artifacts, openspecSkill }, builtinPolicies[id]))
|
|
212
|
+
throw new AgentRuntimeConfigError(`Built-in role ${id} must retain its implicit assignment and access policy`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
194
215
|
for (const [key, value] of Object.entries(config.limits ?? {})) {
|
|
195
216
|
if (!Number.isFinite(value) || (key !== 'maxCostUsd' && !Number.isSafeInteger(value)))
|
|
196
217
|
throw new AgentRuntimeConfigError('Workflow limits must be finite, safe numbers');
|
|
@@ -301,7 +322,7 @@ function loadRuntimeConfigFile(file, fallbackProvider) {
|
|
|
301
322
|
throw new AgentRuntimeConfigError('Configure project role models before using API-only connections');
|
|
302
323
|
for (const role of ROLES)
|
|
303
324
|
config.agents[role].provider = selected.id;
|
|
304
|
-
return validateAgentRuntimeConfig({ ...config, providers });
|
|
325
|
+
return withCustomAgentRoles(validateAgentRuntimeConfig({ ...config, providers }), file, fallbackProvider);
|
|
305
326
|
}
|
|
306
327
|
if (Array.isArray(parsed.providers)) {
|
|
307
328
|
const legacy = validateAgentRuntimeConfig(parsed);
|
|
@@ -309,9 +330,9 @@ function loadRuntimeConfigFile(file, fallbackProvider) {
|
|
|
309
330
|
let connection = providers.find(item => item.id === original.id);
|
|
310
331
|
if (connection && JSON.stringify(connection) !== JSON.stringify(original)) {
|
|
311
332
|
const id = `${original.id.slice(0, 117)}-${(0, node_crypto_1.createHash)('sha256').update(JSON.stringify(original)).digest('hex').slice(0, 10)}`;
|
|
312
|
-
for (const role of
|
|
313
|
-
if (
|
|
314
|
-
|
|
333
|
+
for (const role of [...Object.values(legacy.agents), ...Object.values(legacy.roles ?? {}), ...(legacy.fixer ? [legacy.fixer] : [])])
|
|
334
|
+
if (role.provider === original.id)
|
|
335
|
+
role.provider = id;
|
|
315
336
|
connection = providers.find(item => item.id === id);
|
|
316
337
|
if (!connection)
|
|
317
338
|
providers.push({ ...original, id });
|
|
@@ -324,7 +345,24 @@ function loadRuntimeConfigFile(file, fallbackProvider) {
|
|
|
324
345
|
atomicJson(file, settings);
|
|
325
346
|
parsed = settings;
|
|
326
347
|
}
|
|
327
|
-
return validateAgentRuntimeConfig({ ...parsed, enabled: true, providers });
|
|
348
|
+
return withCustomAgentRoles(validateAgentRuntimeConfig({ ...parsed, enabled: true, providers }), file, fallbackProvider);
|
|
349
|
+
}
|
|
350
|
+
/** Agent Studio documents supply defaults; explicit project roles always win. */
|
|
351
|
+
function withCustomAgentRoles(config, file, fallbackProvider) {
|
|
352
|
+
const connection = config.providers.find(connection => connection.id === config.agents.architect.provider);
|
|
353
|
+
const provider = fallbackProvider && (0, registry_1.hasAdapter)(fallbackProvider) && (0, registry_1.adapterKind)(fallbackProvider) !== 'local'
|
|
354
|
+
? fallbackProvider : connection?.kind === 'cli' ? connection.cli : 'claude';
|
|
355
|
+
try {
|
|
356
|
+
const documents = (0, agent_catalog_1.listNativeAgentFiles)(node_path_1.default.dirname(node_path_1.default.dirname(file)), provider).filter(entry => entry.id.startsWith('custom-'))
|
|
357
|
+
.map(entry => ({ id: entry.id, content: node_fs_1.default.readFileSync(entry.file, 'utf8') }));
|
|
358
|
+
if (!documents.length)
|
|
359
|
+
return config;
|
|
360
|
+
const roles = (0, agent_role_descriptor_1.projectCustomAgentRoles)(documents, config.agents.architect, config.roles);
|
|
361
|
+
return validateAgentRuntimeConfig({ ...config, roles });
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
throw new AgentRuntimeConfigError(error instanceof Error ? error.message : 'Custom agent roles could not be loaded');
|
|
365
|
+
}
|
|
328
366
|
}
|
|
329
367
|
/** Missing settings use the programmatic engine. Malformed files fail closed. */
|
|
330
368
|
function loadAgentRuntimeConfig(project) {
|
|
@@ -339,12 +377,12 @@ function saveAgentRuntimeConfig(project, input) {
|
|
|
339
377
|
return config;
|
|
340
378
|
}
|
|
341
379
|
const PROMPT_ROLES = [...ROLES, 'fixer'];
|
|
342
|
-
function validateRuntimeRolePrompts(input) {
|
|
380
|
+
function validateRuntimeRolePrompts(input, extraRoles = []) {
|
|
343
381
|
if (!input || typeof input !== 'object' || Array.isArray(input))
|
|
344
382
|
throw new AgentRuntimeConfigError('Role prompts must be an object');
|
|
345
383
|
const prompts = {};
|
|
346
384
|
for (const [role, text] of Object.entries(input)) {
|
|
347
|
-
if (!PROMPT_ROLES.includes(role) || typeof text !== 'string' || !text.trim() || text.length > 20000 || text.includes('\0'))
|
|
385
|
+
if (![...PROMPT_ROLES, ...extraRoles].includes(role) || typeof text !== 'string' || !text.trim() || text.length > 20000 || text.includes('\0'))
|
|
348
386
|
throw new AgentRuntimeConfigError('Role prompts must use architect, developer, reviewer or fixer with 1–20000 nonblank characters and no null bytes');
|
|
349
387
|
prompts[role] = text;
|
|
350
388
|
}
|
|
@@ -382,14 +420,20 @@ function validateRuntimeProviderOverride(value) {
|
|
|
382
420
|
/** Older Core runtimes reject unknown top-level keys: drop `guardrails` unless the loaded Core advertises `configurableGuardrails`. */
|
|
383
421
|
function forCoreRuntime(config, capabilities) {
|
|
384
422
|
let out = config;
|
|
423
|
+
if (capabilities?.openRoles !== 1 && out.roles !== undefined) {
|
|
424
|
+
if (Object.keys(out.roles).length)
|
|
425
|
+
throw new AgentRuntimeConfigError('Update the paired Core runtime to use custom roles');
|
|
426
|
+
const { roles: _roles, ...rest } = out;
|
|
427
|
+
out = rest;
|
|
428
|
+
}
|
|
385
429
|
if (capabilities?.configurableGuardrails !== 1 && out.guardrails !== undefined) {
|
|
386
430
|
const { guardrails: _dropped, ...rest } = out;
|
|
387
431
|
out = rest;
|
|
388
432
|
}
|
|
389
433
|
// The per-role thinking switch is known only to cores advertising `roleThinkingControl`.
|
|
390
|
-
if (capabilities?.roleThinkingControl !== 1 && (Object.values(out.agents ?? {}).some(agent => agent?.thinking !== undefined) || out.fixer?.thinking !== undefined)) {
|
|
434
|
+
if (capabilities?.roleThinkingControl !== 1 && ([...Object.values(out.agents ?? {}), ...Object.values(out.roles ?? {})].some(agent => agent?.thinking !== undefined) || out.fixer?.thinking !== undefined)) {
|
|
391
435
|
const strip = (agent) => { const { thinking: _t, ...rest } = agent; return rest; };
|
|
392
|
-
out = { ...out, ...(out.agents ? { agents: Object.fromEntries(Object.entries(out.agents).map(([role, agent]) => [role, strip(agent)])) } : {}), ...(out.fixer ? { fixer: strip(out.fixer) } : {}) };
|
|
436
|
+
out = { ...out, ...(out.agents ? { agents: Object.fromEntries(Object.entries(out.agents).map(([role, agent]) => [role, strip(agent)])) } : {}), ...(out.fixer ? { fixer: strip(out.fixer) } : {}), ...(out.roles ? { roles: Object.fromEntries(Object.entries(out.roles).map(([id, role]) => [id, strip(role)])) } : {}) };
|
|
393
437
|
}
|
|
394
438
|
return out;
|
|
395
439
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
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.nativeAgentFile = nativeAgentFile;
|
|
7
|
+
exports.nativeAgentsDirectory = nativeAgentsDirectory;
|
|
8
|
+
exports.listNativeAgentFiles = listNativeAgentFiles;
|
|
9
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
10
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
11
|
+
const providers_1 = require("../../../providers");
|
|
12
|
+
/** Provider-native role storage shared by Agent Studio and runtime projection. */
|
|
13
|
+
function nativeAgentFile(root, agentId, provider) {
|
|
14
|
+
const adapter = (0, providers_1.getAdapter)(provider);
|
|
15
|
+
return adapter.customRolePath?.(root, agentId) ?? node_path_1.default.join(root, adapter.projectDirName, 'agents', `${agentId}.md`);
|
|
16
|
+
}
|
|
17
|
+
function nativeAgentsDirectory(root, provider) {
|
|
18
|
+
const probe = nativeAgentFile(root, '__catalog_probe__', provider);
|
|
19
|
+
return node_path_1.default.basename(probe) === 'SKILL.md' ? node_path_1.default.dirname(node_path_1.default.dirname(probe)) : node_path_1.default.dirname(probe);
|
|
20
|
+
}
|
|
21
|
+
function listNativeAgentFiles(root, provider) {
|
|
22
|
+
const directory = nativeAgentsDirectory(root, provider);
|
|
23
|
+
if (!node_fs_1.default.existsSync(directory))
|
|
24
|
+
return [];
|
|
25
|
+
return node_fs_1.default.readdirSync(directory, { withFileTypes: true }).flatMap(entry => {
|
|
26
|
+
const id = entry.isDirectory() ? entry.name : entry.isFile() && entry.name.endsWith('.md') ? entry.name.slice(0, -3) : undefined;
|
|
27
|
+
if (!id)
|
|
28
|
+
return [];
|
|
29
|
+
const file = nativeAgentFile(root, id, provider);
|
|
30
|
+
return node_fs_1.default.existsSync(file) ? [{ id, file }] : [];
|
|
31
|
+
}).sort((a, b) => a.id.localeCompare(b.id));
|
|
32
|
+
}
|
|
@@ -12,6 +12,8 @@ const path_1 = __importDefault(require("path"));
|
|
|
12
12
|
const crypto_1 = require("crypto");
|
|
13
13
|
const tree_kill_1 = __importDefault(require("tree-kill"));
|
|
14
14
|
const agent_generator_1 = require("./agent-generator");
|
|
15
|
+
const agent_role_descriptor_1 = require("./agent-role-descriptor");
|
|
16
|
+
const kimi_skill_prompt_1 = require("../../../providers/kimi-skill-prompt");
|
|
15
17
|
const ai_invocations_1 = require("../../accounting/runtime/ai-invocations");
|
|
16
18
|
const result_event_1 = require("../../accounting/runtime/result-event");
|
|
17
19
|
const spawn_lifecycle_1 = require("../../execution/runtime/spawn-lifecycle");
|
|
@@ -199,6 +201,16 @@ class AgentRefineManager {
|
|
|
199
201
|
if (draftName && draftName !== currentName) {
|
|
200
202
|
return { ok: false, reason: 'name_changed' };
|
|
201
203
|
}
|
|
204
|
+
// Force only bypasses concurrent disk edits, never the execution contract.
|
|
205
|
+
try {
|
|
206
|
+
(0, agent_role_descriptor_1.projectCustomAgentRole)({ id: session.agent_id, content: session.draft_body }, { provider: this._adapter.id });
|
|
207
|
+
if (this._adapter.id === 'kimi' && (0, kimi_skill_prompt_1.validateKimiRoleDocument)(session.draft_body, session.agent_id, `${session.agent_id}/SKILL.md`).length > 0) {
|
|
208
|
+
return { ok: false, reason: 'invalid_agent_role' };
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
return { ok: false, reason: 'invalid_agent_role' };
|
|
213
|
+
}
|
|
202
214
|
fs_1.default.writeFileSync(file, session.draft_body, 'utf8');
|
|
203
215
|
const maxVersion = this._db
|
|
204
216
|
.prepare(`SELECT COALESCE(MAX(version), 0) AS v FROM agent_versions
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RUNTIME_ROLE_ID = void 0;
|
|
4
|
+
exports.projectCustomAgentRole = projectCustomAgentRole;
|
|
5
|
+
exports.projectCustomAgentRoles = projectCustomAgentRoles;
|
|
6
|
+
const js_yaml_1 = require("js-yaml");
|
|
7
|
+
exports.RUNTIME_ROLE_ID = /^[a-z][a-z0-9-]{0,63}$/;
|
|
8
|
+
const BUILTINS = new Set(['architect', 'developer', 'reviewer', 'fixer']);
|
|
9
|
+
const object = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
|
|
10
|
+
/** Pure frontmatter-to-role mapping; source access never follows model/prompt wording. */
|
|
11
|
+
function projectCustomAgentRole(document, fallback) {
|
|
12
|
+
const id = document.id.startsWith('custom-') ? document.id.slice(7) : '';
|
|
13
|
+
if (!exports.RUNTIME_ROLE_ID.test(id) || BUILTINS.has(id))
|
|
14
|
+
throw new Error(`Custom agent ${document.id} must map to a non-built-in role matching ${exports.RUNTIME_ROLE_ID.source}`);
|
|
15
|
+
const match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)([\s\S]*)$/.exec(document.content);
|
|
16
|
+
if (!match && document.content.startsWith('---'))
|
|
17
|
+
throw new Error(`Custom agent ${document.id} has incomplete YAML frontmatter`);
|
|
18
|
+
const metadata = match ? (0, js_yaml_1.load)(match[1], { schema: js_yaml_1.JSON_SCHEMA }) : {};
|
|
19
|
+
if (!object(metadata))
|
|
20
|
+
throw new Error(`Custom agent ${document.id} has invalid frontmatter`);
|
|
21
|
+
if (metadata.name !== undefined && metadata.name !== document.id)
|
|
22
|
+
throw new Error(`Custom agent ${document.id} frontmatter name differs from its file identity`);
|
|
23
|
+
const prompt = (match ? match[2] : document.content).trim();
|
|
24
|
+
if (!prompt || prompt.length > 20_000 || prompt.includes('\0'))
|
|
25
|
+
throw new Error(`Custom agent ${document.id} instructions must contain 1–20,000 characters`);
|
|
26
|
+
const access = metadata.access ?? 'read', artifacts = metadata.artifacts ?? 'none';
|
|
27
|
+
if (!['read', 'write'].includes(String(access)) || !['none', 'tasks-checkboxes', 'all'].includes(String(artifacts)))
|
|
28
|
+
throw new Error(`Custom agent ${document.id} declares invalid source or artifact access`);
|
|
29
|
+
if (metadata.openspecSkill !== undefined && !['openspec-ff-change', 'openspec-apply-change', 'openspec-verify-change'].includes(String(metadata.openspecSkill)))
|
|
30
|
+
throw new Error(`Custom agent ${document.id} declares an unsupported OpenSpec skill`);
|
|
31
|
+
const engine = metadata.engine === undefined ? {} : metadata.engine;
|
|
32
|
+
if (!object(engine) || Object.keys(engine).some(key => !['provider', 'model', 'effort', 'thinking', 'maxTurns', 'escalation'].includes(key)))
|
|
33
|
+
throw new Error(`Custom agent ${document.id} engine must contain only provider, model, effort, thinking, maxTurns and escalation`);
|
|
34
|
+
const provider = engine.provider ?? fallback.provider;
|
|
35
|
+
const model = engine.model ?? (metadata.model === 'inherit' ? undefined : metadata.model) ?? fallback.model;
|
|
36
|
+
const effort = engine.effort ?? metadata.effort ?? fallback.effort;
|
|
37
|
+
if (typeof provider !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(provider) ||
|
|
38
|
+
model !== undefined && (typeof model !== 'string' || !model || model.length > 256 || /^-|[\r\n\0]/.test(model)) ||
|
|
39
|
+
effort !== undefined && (typeof effort !== 'string' || !/^[a-z][a-z0-9_-]{0,31}$/.test(effort)) ||
|
|
40
|
+
engine.thinking !== undefined && !['on', 'off'].includes(String(engine.thinking)) ||
|
|
41
|
+
engine.maxTurns !== undefined && (!Number.isSafeInteger(engine.maxTurns) || engine.maxTurns < 1))
|
|
42
|
+
throw new Error(`Custom agent ${document.id} has invalid engine settings`);
|
|
43
|
+
const escalation = engine.escalation;
|
|
44
|
+
if (escalation !== undefined && (!object(escalation) || Object.keys(escalation).some(key => !['model', 'effort'].includes(key)) ||
|
|
45
|
+
typeof escalation.model !== 'string' || !escalation.model || escalation.model.length > 256 || /^-|[\r\n\0]/.test(escalation.model) ||
|
|
46
|
+
escalation.effort !== undefined && (typeof escalation.effort !== 'string' || !/^[a-z][a-z0-9_-]{0,31}$/.test(escalation.effort)) ||
|
|
47
|
+
!model || escalation.model === model && escalation.effort === effort))
|
|
48
|
+
throw new Error(`Custom agent ${document.id} escalation requires a valid, different model or effort and an explicit base model`);
|
|
49
|
+
return { id, role: { provider, ...(model === undefined ? {} : { model: model }), ...(effort === undefined ? {} : { effort: effort }),
|
|
50
|
+
access: access, artifacts: artifacts, prompt,
|
|
51
|
+
...(metadata.openspecSkill === undefined ? {} : { openspecSkill: metadata.openspecSkill }),
|
|
52
|
+
...(engine.thinking === undefined ? {} : { thinking: engine.thinking }), ...(engine.maxTurns === undefined ? {} : { maxTurns: engine.maxTurns }),
|
|
53
|
+
...(escalation === undefined ? {} : { escalation: escalation }) } };
|
|
54
|
+
}
|
|
55
|
+
function projectCustomAgentRoles(documents, fallback, explicit = {}) {
|
|
56
|
+
const roles = {};
|
|
57
|
+
for (const document of documents) {
|
|
58
|
+
const { id, role } = projectCustomAgentRole(document, fallback);
|
|
59
|
+
if (Object.hasOwn(roles, id))
|
|
60
|
+
throw new Error(`Duplicate custom agent role ${id}`);
|
|
61
|
+
roles[id] = { ...role, ...explicit[id] };
|
|
62
|
+
}
|
|
63
|
+
return { ...roles, ...Object.fromEntries(Object.entries(explicit).filter(([id]) => !Object.hasOwn(roles, id))) };
|
|
64
|
+
}
|
|
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.providerSupportsAgentStudioAutomation = providerSupportsAgentStudioAutomation;
|
|
7
7
|
exports.createProfilesRouter = createProfilesRouter;
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const agent_catalog_1 = require("./agent-catalog");
|
|
10
|
+
const agent_role_descriptor_1 = require("./agent-role-descriptor");
|
|
9
11
|
const core_runtime_1 = require("../../../core-runtime");
|
|
10
12
|
const path_1 = __importDefault(require("path"));
|
|
11
13
|
const express_1 = require("express");
|
|
@@ -60,38 +62,13 @@ function projectAdapter(project, provider) {
|
|
|
60
62
|
return (0, providers_1.getAdapter)(provider ?? project.provider ?? 'claude');
|
|
61
63
|
}
|
|
62
64
|
function agentFile(project, agentId, provider) {
|
|
63
|
-
|
|
64
|
-
const adapter = projectAdapter(project, provider);
|
|
65
|
-
return adapter.customRolePath?.(root, agentId)
|
|
66
|
-
?? path_1.default.join(root, adapter.projectDirName, 'agents', `${agentId}.md`);
|
|
65
|
+
return (0, agent_catalog_1.nativeAgentFile)(specRoot(project), agentId, provider ?? project.provider ?? 'claude');
|
|
67
66
|
}
|
|
68
|
-
/** The provider-native roles catalog directory. */
|
|
69
67
|
function agentsCatalogDir(project, provider) {
|
|
70
|
-
|
|
71
|
-
// File-based roles use `<catalog>/<id>.md`; skill-based roles (Kimi) use
|
|
72
|
-
// `<catalog>/<id>/SKILL.md`.
|
|
73
|
-
return path_1.default.basename(probe) === 'SKILL.md'
|
|
74
|
-
? path_1.default.dirname(path_1.default.dirname(probe))
|
|
75
|
-
: path_1.default.dirname(probe);
|
|
68
|
+
return (0, agent_catalog_1.nativeAgentsDirectory)(specRoot(project), provider ?? project.provider ?? 'claude');
|
|
76
69
|
}
|
|
77
70
|
function listAgentFiles(project, provider) {
|
|
78
|
-
|
|
79
|
-
if (!fs_1.default.existsSync(dir))
|
|
80
|
-
return [];
|
|
81
|
-
const out = [];
|
|
82
|
-
for (const entry of fs_1.default.readdirSync(dir, { withFileTypes: true })) {
|
|
83
|
-
const id = entry.isDirectory()
|
|
84
|
-
? entry.name
|
|
85
|
-
: entry.isFile() && entry.name.endsWith('.md')
|
|
86
|
-
? entry.name.slice(0, -3)
|
|
87
|
-
: null;
|
|
88
|
-
if (!id)
|
|
89
|
-
continue;
|
|
90
|
-
const file = agentFile(project, id, provider);
|
|
91
|
-
if (fs_1.default.existsSync(file))
|
|
92
|
-
out.push({ id, file });
|
|
93
|
-
}
|
|
94
|
-
return out;
|
|
71
|
+
return (0, agent_catalog_1.listNativeAgentFiles)(specRoot(project), provider ?? project.provider ?? 'claude');
|
|
95
72
|
}
|
|
96
73
|
const AGENTS_SECTION_ENABLED = process.env.SPECRAILS_AGENTS_SECTION !== 'false';
|
|
97
74
|
function handleError(res, err) {
|
|
@@ -135,9 +112,14 @@ function requireSafeStudioPolicy(res, provider) {
|
|
|
135
112
|
* leaf (fs/path/js-yaml only), so this direct import does not create a router /
|
|
136
113
|
* adapter cycle. */
|
|
137
114
|
function validateCustomRoleBody(provider, agentId, body) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
115
|
+
const errors = provider === 'kimi' ? (0, kimi_skill_prompt_1.validateKimiRoleDocument)(body, agentId, `${agentId}/SKILL.md`) : [];
|
|
116
|
+
try {
|
|
117
|
+
(0, agent_role_descriptor_1.projectCustomAgentRole)({ id: agentId, content: body }, { provider });
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
errors.push(error instanceof Error ? error.message : 'Invalid Core role descriptor');
|
|
121
|
+
}
|
|
122
|
+
return errors;
|
|
141
123
|
}
|
|
142
124
|
function createProfilesRouter() {
|
|
143
125
|
const router = (0, express_1.Router)({ mergeParams: true });
|
|
@@ -419,8 +401,18 @@ function createProfilesRouter() {
|
|
|
419
401
|
continue;
|
|
420
402
|
let description;
|
|
421
403
|
let model;
|
|
404
|
+
let projected = {};
|
|
422
405
|
try {
|
|
423
406
|
const body = fs_1.default.readFileSync(entry.file, 'utf8');
|
|
407
|
+
if (kind === 'custom') {
|
|
408
|
+
try {
|
|
409
|
+
const result = (0, agent_role_descriptor_1.projectCustomAgentRole)({ id, content: body }, { provider });
|
|
410
|
+
projected = { roleId: result.id, runtimeRoleDefaults: result.role };
|
|
411
|
+
}
|
|
412
|
+
catch (error) {
|
|
413
|
+
projected = { runtimeRoleError: error instanceof Error ? error.message : 'Invalid Core role descriptor' };
|
|
414
|
+
}
|
|
415
|
+
}
|
|
424
416
|
if (provider === 'kimi') {
|
|
425
417
|
// Use the same js-yaml metadata parser as validation/execution so
|
|
426
418
|
// folded/literal descriptions and quoted scalars render correctly.
|
|
@@ -466,7 +458,7 @@ function createProfilesRouter() {
|
|
|
466
458
|
catch {
|
|
467
459
|
// ignore unreadable files
|
|
468
460
|
}
|
|
469
|
-
agents.push({ id, kind, description, model });
|
|
461
|
+
agents.push({ id, kind, description, model, ...projected });
|
|
470
462
|
}
|
|
471
463
|
agents.sort((a, b) => a.id.localeCompare(b.id));
|
|
472
464
|
res.json({ agents });
|
|
@@ -517,7 +509,7 @@ function createProfilesRouter() {
|
|
|
517
509
|
}
|
|
518
510
|
const roleErrors = validateCustomRoleBody(provider, id, body);
|
|
519
511
|
if (roleErrors.length > 0) {
|
|
520
|
-
res.status(400).json({ error: 'invalid_kimi_skill', details: roleErrors });
|
|
512
|
+
res.status(400).json({ error: provider === 'kimi' ? 'invalid_kimi_skill' : 'invalid_agent_role', details: roleErrors });
|
|
521
513
|
return;
|
|
522
514
|
}
|
|
523
515
|
const file = agentFile(project, id, provider);
|
|
@@ -556,7 +548,7 @@ function createProfilesRouter() {
|
|
|
556
548
|
}
|
|
557
549
|
const roleErrors = validateCustomRoleBody(provider, agentId, body);
|
|
558
550
|
if (roleErrors.length > 0) {
|
|
559
|
-
res.status(400).json({ error: 'invalid_kimi_skill', details: roleErrors });
|
|
551
|
+
res.status(400).json({ error: provider === 'kimi' ? 'invalid_kimi_skill' : 'invalid_agent_role', details: roleErrors });
|
|
560
552
|
return;
|
|
561
553
|
}
|
|
562
554
|
const file = agentFile(project, agentId, provider);
|