@repo-os/repoos 0.5.45
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/LICENSE.md +110 -0
- package/README.md +272 -0
- package/dist/.build-info.json +4 -0
- package/dist/.build-stamp.json +3 -0
- package/dist/cli/colors.d.ts +13 -0
- package/dist/cli/colors.js +37 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +221 -0
- package/dist/commands/check.d.ts +170 -0
- package/dist/commands/check.js +1227 -0
- package/dist/commands/docs.d.ts +2 -0
- package/dist/commands/docs.js +70 -0
- package/dist/commands/gc.d.ts +1 -0
- package/dist/commands/gc.js +57 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.js +699 -0
- package/dist/commands/screenshots.d.ts +7 -0
- package/dist/commands/screenshots.js +77 -0
- package/dist/commands/serve.d.ts +55 -0
- package/dist/commands/serve.js +204 -0
- package/dist/commands/status.d.ts +140 -0
- package/dist/commands/status.js +569 -0
- package/dist/commands/stop.d.ts +1 -0
- package/dist/commands/stop.js +59 -0
- package/dist/commands/tasks.d.ts +47 -0
- package/dist/commands/tasks.js +334 -0
- package/dist/commands/tunnel.d.ts +1 -0
- package/dist/commands/tunnel.js +1271 -0
- package/dist/commands/ui-harness.d.ts +53 -0
- package/dist/commands/ui-harness.js +62 -0
- package/dist/commands/ui-smoke.d.ts +6 -0
- package/dist/commands/ui-smoke.js +220 -0
- package/dist/commands/upgrade.d.ts +15 -0
- package/dist/commands/upgrade.js +188 -0
- package/dist/core/auth-store.d.ts +81 -0
- package/dist/core/auth-store.js +530 -0
- package/dist/core/auth.d.ts +75 -0
- package/dist/core/auth.js +124 -0
- package/dist/core/bootstrap.d.ts +41 -0
- package/dist/core/bootstrap.js +236 -0
- package/dist/core/build.d.ts +92 -0
- package/dist/core/build.js +249 -0
- package/dist/core/canary.d.ts +10 -0
- package/dist/core/canary.js +14 -0
- package/dist/core/check-failure-summary.d.ts +10 -0
- package/dist/core/check-failure-summary.js +34 -0
- package/dist/core/config.d.ts +160 -0
- package/dist/core/config.js +1288 -0
- package/dist/core/context-pack.d.ts +74 -0
- package/dist/core/context-pack.js +778 -0
- package/dist/core/db.d.ts +236 -0
- package/dist/core/db.js +747 -0
- package/dist/core/detect.d.ts +69 -0
- package/dist/core/detect.js +251 -0
- package/dist/core/docs.d.ts +76 -0
- package/dist/core/docs.js +225 -0
- package/dist/core/frontmatter.d.ts +29 -0
- package/dist/core/frontmatter.js +215 -0
- package/dist/core/git.d.ts +505 -0
- package/dist/core/git.js +1453 -0
- package/dist/core/indexer.d.ts +33 -0
- package/dist/core/indexer.js +282 -0
- package/dist/core/input.d.ts +66 -0
- package/dist/core/input.js +222 -0
- package/dist/core/logger.d.ts +70 -0
- package/dist/core/logger.js +138 -0
- package/dist/core/models.d.ts +45 -0
- package/dist/core/models.js +291 -0
- package/dist/core/net-probe.d.ts +4 -0
- package/dist/core/net-probe.js +20 -0
- package/dist/core/providers/deepinfra.d.ts +23 -0
- package/dist/core/providers/deepinfra.js +44 -0
- package/dist/core/providers/index.d.ts +24 -0
- package/dist/core/providers/index.js +59 -0
- package/dist/core/providers/openrouter.d.ts +28 -0
- package/dist/core/providers/openrouter.js +82 -0
- package/dist/core/providers/spend.d.ts +86 -0
- package/dist/core/providers/spend.js +286 -0
- package/dist/core/providers/types.d.ts +56 -0
- package/dist/core/providers/types.js +39 -0
- package/dist/core/repoos.d.ts +59 -0
- package/dist/core/repoos.js +221 -0
- package/dist/core/runtime.d.ts +35 -0
- package/dist/core/runtime.js +167 -0
- package/dist/core/skills-registry.d.ts +39 -0
- package/dist/core/skills-registry.js +148 -0
- package/dist/core/skills-registry.test.d.ts +1 -0
- package/dist/core/skills-registry.test.js +52 -0
- package/dist/core/sysmem.d.ts +7 -0
- package/dist/core/sysmem.js +55 -0
- package/dist/core/tailscale.d.ts +2 -0
- package/dist/core/tailscale.js +19 -0
- package/dist/core/task.d.ts +53 -0
- package/dist/core/task.js +310 -0
- package/dist/core/toml-line.d.ts +20 -0
- package/dist/core/toml-line.js +52 -0
- package/dist/core/toml-validate.d.ts +44 -0
- package/dist/core/toml-validate.js +335 -0
- package/dist/core/tunnel-assistant.d.ts +30 -0
- package/dist/core/tunnel-assistant.js +65 -0
- package/dist/core/tunnel-registry.d.ts +96 -0
- package/dist/core/tunnel-registry.js +267 -0
- package/dist/core/tunnel-registry.test.d.ts +1 -0
- package/dist/core/tunnel-registry.test.js +309 -0
- package/dist/core/tunnel.d.ts +103 -0
- package/dist/core/tunnel.js +320 -0
- package/dist/core/types.d.ts +811 -0
- package/dist/core/types.js +27 -0
- package/dist/core/worktree-gc.d.ts +57 -0
- package/dist/core/worktree-gc.js +194 -0
- package/dist/server/__tests__/integration-job.test.d.ts +1 -0
- package/dist/server/__tests__/integration-job.test.js +129 -0
- package/dist/server/agents.d.ts +1020 -0
- package/dist/server/agents.js +4070 -0
- package/dist/server/attachments.d.ts +51 -0
- package/dist/server/attachments.js +130 -0
- package/dist/server/auto-engineering.d.ts +45 -0
- package/dist/server/auto-engineering.js +275 -0
- package/dist/server/branchless-release.d.ts +22 -0
- package/dist/server/branchless-release.js +67 -0
- package/dist/server/built-in-agents.d.ts +305 -0
- package/dist/server/built-in-agents.js +1838 -0
- package/dist/server/cto-monitor.d.ts +35 -0
- package/dist/server/cto-monitor.js +281 -0
- package/dist/server/cto.d.ts +125 -0
- package/dist/server/cto.js +590 -0
- package/dist/server/deployments.d.ts +119 -0
- package/dist/server/deployments.js +325 -0
- package/dist/server/diff-snapshot.d.ts +20 -0
- package/dist/server/diff-snapshot.js +73 -0
- package/dist/server/done.d.ts +160 -0
- package/dist/server/done.js +488 -0
- package/dist/server/freeform.d.ts +55 -0
- package/dist/server/freeform.js +179 -0
- package/dist/server/handoff.d.ts +99 -0
- package/dist/server/handoff.js +575 -0
- package/dist/server/hetzner.d.ts +45 -0
- package/dist/server/hetzner.js +117 -0
- package/dist/server/icons.d.ts +8 -0
- package/dist/server/icons.js +195 -0
- package/dist/server/integration-job.d.ts +75 -0
- package/dist/server/integration-job.js +144 -0
- package/dist/server/integration-orchestrator.d.ts +211 -0
- package/dist/server/integration-orchestrator.js +1299 -0
- package/dist/server/integration-status.d.ts +48 -0
- package/dist/server/integration-status.js +71 -0
- package/dist/server/live-index.d.ts +295 -0
- package/dist/server/live-index.js +452 -0
- package/dist/server/model-test.d.ts +20 -0
- package/dist/server/model-test.js +100 -0
- package/dist/server/ntfy.d.ts +57 -0
- package/dist/server/ntfy.js +112 -0
- package/dist/server/pm-attachments.d.ts +35 -0
- package/dist/server/pm-attachments.js +181 -0
- package/dist/server/pm-runs.d.ts +58 -0
- package/dist/server/pm-runs.js +80 -0
- package/dist/server/preview.d.ts +174 -0
- package/dist/server/preview.js +641 -0
- package/dist/server/release.d.ts +88 -0
- package/dist/server/release.js +449 -0
- package/dist/server/reload.d.ts +194 -0
- package/dist/server/reload.js +586 -0
- package/dist/server/remote-validation.d.ts +132 -0
- package/dist/server/remote-validation.js +478 -0
- package/dist/server/repo-lock.d.ts +36 -0
- package/dist/server/repo-lock.js +141 -0
- package/dist/server/review-guard.d.ts +14 -0
- package/dist/server/review-guard.js +159 -0
- package/dist/server/review.d.ts +243 -0
- package/dist/server/review.js +1211 -0
- package/dist/server/routes/agents.d.ts +6 -0
- package/dist/server/routes/agents.js +28 -0
- package/dist/server/routes/auth.d.ts +60 -0
- package/dist/server/routes/auth.js +755 -0
- package/dist/server/routes/config.d.ts +20 -0
- package/dist/server/routes/config.js +347 -0
- package/dist/server/routes/debugger.d.ts +33 -0
- package/dist/server/routes/debugger.js +360 -0
- package/dist/server/routes/deployments.d.ts +3 -0
- package/dist/server/routes/deployments.js +16 -0
- package/dist/server/routes/docs.d.ts +8 -0
- package/dist/server/routes/docs.js +135 -0
- package/dist/server/routes/helpers.d.ts +21 -0
- package/dist/server/routes/helpers.js +171 -0
- package/dist/server/routes/index.d.ts +19 -0
- package/dist/server/routes/index.js +18 -0
- package/dist/server/routes/info.d.ts +17 -0
- package/dist/server/routes/info.js +177 -0
- package/dist/server/routes/inputs.d.ts +7 -0
- package/dist/server/routes/inputs.js +125 -0
- package/dist/server/routes/model-providers.d.ts +27 -0
- package/dist/server/routes/model-providers.js +94 -0
- package/dist/server/routes/models.d.ts +3 -0
- package/dist/server/routes/models.js +36 -0
- package/dist/server/routes/notify.d.ts +2 -0
- package/dist/server/routes/notify.js +17 -0
- package/dist/server/routes/playground.d.ts +29 -0
- package/dist/server/routes/playground.js +81 -0
- package/dist/server/routes/release.d.ts +20 -0
- package/dist/server/routes/release.js +86 -0
- package/dist/server/routes/router.d.ts +12 -0
- package/dist/server/routes/router.js +32 -0
- package/dist/server/routes/skill-registry.d.ts +5 -0
- package/dist/server/routes/skill-registry.js +51 -0
- package/dist/server/routes/tasks.d.ts +58 -0
- package/dist/server/routes/tasks.js +1442 -0
- package/dist/server/routes/transcribe.d.ts +2 -0
- package/dist/server/routes/transcribe.js +124 -0
- package/dist/server/routes/types.d.ts +68 -0
- package/dist/server/routes/types.js +1 -0
- package/dist/server/routes/ui.d.ts +5 -0
- package/dist/server/routes/ui.js +81 -0
- package/dist/server/routes/utils.d.ts +3 -0
- package/dist/server/routes/utils.js +23 -0
- package/dist/server/serve-reaper.d.ts +135 -0
- package/dist/server/serve-reaper.js +491 -0
- package/dist/server/server.d.ts +49 -0
- package/dist/server/server.js +2171 -0
- package/dist/server/supervisor.d.ts +89 -0
- package/dist/server/supervisor.js +231 -0
- package/dist/server/system.d.ts +198 -0
- package/dist/server/system.js +480 -0
- package/dist/server/task-check.d.ts +45 -0
- package/dist/server/task-check.js +71 -0
- package/dist/server/task-transitions.d.ts +51 -0
- package/dist/server/task-transitions.js +78 -0
- package/dist/server/task-watchdog.d.ts +158 -0
- package/dist/server/task-watchdog.js +681 -0
- package/dist/server/test-run.d.ts +28 -0
- package/dist/server/test-run.js +81 -0
- package/dist/server/watcher.d.ts +21 -0
- package/dist/server/watcher.js +194 -0
- package/dist/server/write.d.ts +94 -0
- package/dist/server/write.js +345 -0
- package/dist/ui/assets/AgentsView-CF4wRvHh.css +1 -0
- package/dist/ui/assets/AgentsView-D-myL-kA.js +1 -0
- package/dist/ui/assets/ContextView-D3TC-RSp.css +1 -0
- package/dist/ui/assets/ContextView-DsOqAdyE.js +4 -0
- package/dist/ui/assets/DashboardView-BOhsIJqO.js +1 -0
- package/dist/ui/assets/DashboardView-Ck9o0RP2.css +1 -0
- package/dist/ui/assets/DeploymentsView--iIUVfEH.css +1 -0
- package/dist/ui/assets/DeploymentsView-DXu_FYR2.js +1 -0
- package/dist/ui/assets/InputsView-24HVbVPk.js +1 -0
- package/dist/ui/assets/InputsView-BLb7GHtx.css +1 -0
- package/dist/ui/assets/LoginView-6QlGg6cx.css +1 -0
- package/dist/ui/assets/LoginView-BqupI0Lt.js +1 -0
- package/dist/ui/assets/ReleasesView-BEG1A0YH.css +1 -0
- package/dist/ui/assets/ReleasesView-CAgMuxpe.js +3 -0
- package/dist/ui/assets/SettingsView-CA-NYSMK.css +1 -0
- package/dist/ui/assets/SettingsView-O3iZSnjg.js +3 -0
- package/dist/ui/assets/WorkView-D8Tl6qwy.js +1 -0
- package/dist/ui/assets/WorkView-DMYL2s3W.css +1 -0
- package/dist/ui/assets/abnfDiagram-VCTEODGH-J5lkSnEE.js +1 -0
- package/dist/ui/assets/arc-BHZnmhhM.js +1 -0
- package/dist/ui/assets/architecture-7GRP2DOG-pLdFt-xS.js +1 -0
- package/dist/ui/assets/architectureDiagram-5GKGNRK7-C3k89uKX.js +36 -0
- package/dist/ui/assets/array-BifhSqXX.js +1 -0
- package/dist/ui/assets/blockDiagram-I7D4REHJ-AWNoBzop.js +129 -0
- package/dist/ui/assets/button-lbikqSph.js +1 -0
- package/dist/ui/assets/c4Diagram-7LVT6UL2-DKG1D5gd.js +38 -0
- package/dist/ui/assets/channel-gA4qBv3A.js +1 -0
- package/dist/ui/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- package/dist/ui/assets/chunk-4HAMMTFA-D1YR8lF_.js +62 -0
- package/dist/ui/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- package/dist/ui/assets/chunk-75Z2AOVW-5GuBxfsL.js +2 -0
- package/dist/ui/assets/chunk-DU6HZSFF-DfdNNqwa.js +127 -0
- package/dist/ui/assets/chunk-F27PBJKO-BPZzinQ4.js +1 -0
- package/dist/ui/assets/chunk-FOHPRMQF-l2z4K2jD.js +161 -0
- package/dist/ui/assets/chunk-GMAD6QVW-DGWvSKj5.js +72 -0
- package/dist/ui/assets/chunk-GVQU2GXP-D6Aw75wJ.js +1 -0
- package/dist/ui/assets/chunk-IMKFNOWR-B8mMBKCW.js +231 -0
- package/dist/ui/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- package/dist/ui/assets/chunk-L3NEJ4N5-D5OJuXYE.js +1 -0
- package/dist/ui/assets/chunk-OSK3NFVY-B7r9w2UW.js +10 -0
- package/dist/ui/assets/chunk-P2QGCYS3-C74X4AQX.js +1 -0
- package/dist/ui/assets/chunk-POPQ4Y6H-C5_u1gUS.js +1 -0
- package/dist/ui/assets/chunk-PWAF6VOD-DfoTLtxn.js +1 -0
- package/dist/ui/assets/chunk-SHT3W25Y-D40m2eqz.js +168 -0
- package/dist/ui/assets/chunk-SVP7TREG-euxi0Kap.js +88 -0
- package/dist/ui/assets/chunk-TICWLB2K-fkdxngzN.js +206 -0
- package/dist/ui/assets/chunk-XXDRQBXY-DFBUG-OT.js +1 -0
- package/dist/ui/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- package/dist/ui/assets/classDiagram-ZZMXUADV-BzW8bq2P.js +1 -0
- package/dist/ui/assets/classDiagram-v2-VYDZK3BY-BzW8bq2P.js +1 -0
- package/dist/ui/assets/cose-bilkent-JH36ORCC-BTcgMon1.js +1 -0
- package/dist/ui/assets/cynefin-OW5HDTMX-B5m_COsS.js +1 -0
- package/dist/ui/assets/cynefinDiagram-5FMLGOSQ-C-AG6CGe.js +62 -0
- package/dist/ui/assets/cytoscape.esm-FBntH-9t.js +321 -0
- package/dist/ui/assets/dagre-GXQ25YYZ-DDfDnp8L.js +4 -0
- package/dist/ui/assets/dagre-PrKaheQc.js +1 -0
- package/dist/ui/assets/defaultLocale-BFoDCU3G.js +1 -0
- package/dist/ui/assets/diagram-S7CK7UJ4-DjQZAlEY.js +30 -0
- package/dist/ui/assets/diagram-UQ7AKVKN-DAZ9yp1B.js +41 -0
- package/dist/ui/assets/diagram-VSXAHHWV-BWepUKJD.js +3 -0
- package/dist/ui/assets/diagram-VX7I27RA-EcV1J81b.js +24 -0
- package/dist/ui/assets/diagram-Z3DM3KII-Dbz7XU_K.js +24 -0
- package/dist/ui/assets/dist-DTg6UBE_.js +1 -0
- package/dist/ui/assets/ebnfDiagram-PWID7BFC-BUyQw8Mm.js +1 -0
- package/dist/ui/assets/erDiagram-RLTQ6QDP-WVf8ukKt.js +99 -0
- package/dist/ui/assets/eventmodeling-NTZA5JFV-DHqyLOAn.js +1 -0
- package/dist/ui/assets/flowDiagram-HODETNUW-CYk_ze5K.js +1 -0
- package/dist/ui/assets/ganttDiagram-EL5Y4UJY-rB4MZuB-.js +292 -0
- package/dist/ui/assets/gitGraph-4MIJSDKK-BOTWM8dY.js +1 -0
- package/dist/ui/assets/gitGraphDiagram-WWUBYQGX-eYscuhtP.js +106 -0
- package/dist/ui/assets/graphlib-DS17s2tU.js +1 -0
- package/dist/ui/assets/index-BACBfnga.css +1 -0
- package/dist/ui/assets/index-BOQ-ust6.js +26 -0
- package/dist/ui/assets/info-A6RAGUB7-_67wOORe.js +1 -0
- package/dist/ui/assets/infoDiagram-27XIBGKW-XVXbddTA.js +2 -0
- package/dist/ui/assets/init-C-OQMol4.js +1 -0
- package/dist/ui/assets/ishikawaDiagram-5VMMS53U-ClLNiEru.js +70 -0
- package/dist/ui/assets/journeyDiagram-3NMN7TZE-NRawjR6i.js +139 -0
- package/dist/ui/assets/kanban-definition-UXKFOSKX-BgSzBfIx.js +89 -0
- package/dist/ui/assets/katex-DolUETbr.js +257 -0
- package/dist/ui/assets/line-KAyfuul4.js +1 -0
- package/dist/ui/assets/linear-cCCPOpu7.js +1 -0
- package/dist/ui/assets/mermaid-parser.core-CgXZk1iN.js +7 -0
- package/dist/ui/assets/mermaid.core-BUUkChHW.js +44 -0
- package/dist/ui/assets/mindmap-definition-YA3MSWOX-Cpn7vW4r.js +96 -0
- package/dist/ui/assets/ordinal-BDEzSJ7C.js +1 -0
- package/dist/ui/assets/packet-AYTQ26CC-0lZwM-d6.js +1 -0
- package/dist/ui/assets/path-COt_16Va.js +1 -0
- package/dist/ui/assets/pegDiagram-XKGWAZYB-impy0inn.js +1 -0
- package/dist/ui/assets/pie-WAS4IAKB-CqfdGHYg.js +1 -0
- package/dist/ui/assets/pieDiagram-E7YTZNPT-CxjL4I1h.js +39 -0
- package/dist/ui/assets/quadrantDiagram-AXDQQJYC-Cjd1QMIe.js +7 -0
- package/dist/ui/assets/radar-RG4KPBEZ-CRkQIwiv.js +1 -0
- package/dist/ui/assets/railroad-74A4TZTK-i67XSWTB.js +1 -0
- package/dist/ui/assets/railroad-abnf-HS5TGJTU-Cv9m5aS3.js +1 -0
- package/dist/ui/assets/railroad-ebnf-LZEXJU2U-C5ZIn-Jh.js +1 -0
- package/dist/ui/assets/railroad-peg-WCYAUIDC-CGra9Oq-.js +1 -0
- package/dist/ui/assets/railroadDiagram-O6MQD6OU-_pK0qyaY.js +1 -0
- package/dist/ui/assets/releases-B0WNV-SY.js +1 -0
- package/dist/ui/assets/repoos-cto-square.webp +0 -0
- package/dist/ui/assets/repoos-helpful-pm-square.webp +0 -0
- package/dist/ui/assets/repoos-orchestrator-square.webp +0 -0
- package/dist/ui/assets/repoos-performance-agent-square.webp +0 -0
- package/dist/ui/assets/repoos-ross-from-friends-square.webp +0 -0
- package/dist/ui/assets/repoos-tech-debt-agent-square.webp +0 -0
- package/dist/ui/assets/requirementDiagram-BXWQKSXE-CRrFX-yw.js +84 -0
- package/dist/ui/assets/rough.esm-By172zw-.js +1 -0
- package/dist/ui/assets/sankeyDiagram-P5KCCOFB-X_xFRj9E.js +40 -0
- package/dist/ui/assets/sequenceDiagram-WJ2MYXX4-Byb49lKf.js +162 -0
- package/dist/ui/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
- package/dist/ui/assets/src-BH-TyZbA.js +1 -0
- package/dist/ui/assets/stateDiagram-D77RDMKH-CzaPrqYF.js +1 -0
- package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-BCXckz7K.js +1 -0
- package/dist/ui/assets/swimlanes-42K2YHIH-Cx_1lnqr.js +1 -0
- package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-54qsKi6A.js +8 -0
- package/dist/ui/assets/timeline-definition-24CTP7MA-B1IbZPQ-.js +120 -0
- package/dist/ui/assets/treeView-Q6P3EWNA-DFWhVE3d.js +1 -0
- package/dist/ui/assets/treemap-WGGIJYW6-BmbYPThn.js +1 -0
- package/dist/ui/assets/vendor-ui-DPm7zLxi.js +3 -0
- package/dist/ui/assets/vendor-vue-CobgyEJp.js +1 -0
- package/dist/ui/assets/vennDiagram-4TSXK5OY-Ae2AtRpt.js +34 -0
- package/dist/ui/assets/wardley-WFR3VGLG-BtD4X4tL.js +1 -0
- package/dist/ui/assets/wardleyDiagram-VM6X3IG4-B3YN2fTd.js +78 -0
- package/dist/ui/assets/xychartDiagram-S5SC5T6Z-CIzJfMKA.js +7 -0
- package/dist/ui/favicon.svg +11 -0
- package/dist/ui/index.html +49 -0
- package/dist/ui/sw.js +48 -0
- package/package.json +91 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import { json, readBody } from "./utils.js";
|
|
2
|
+
import { debuggerAgent, debuggerSessionId, deriveBranch, resolveAgentForTask, resolvePmAgent, taskPmPrompt, } from "../agents.js";
|
|
3
|
+
import { patchTaskFile } from "../write.js";
|
|
4
|
+
import { getCurrentUser } from "./auth.js";
|
|
5
|
+
import { ensureWorktree } from "../../core/git.js";
|
|
6
|
+
import { bootstrap } from "../../core/bootstrap.js";
|
|
7
|
+
import { generateContextPack, resumePreamble } from "../../core/context-pack.js";
|
|
8
|
+
export const getDebugger = (ctx, _req, res) => {
|
|
9
|
+
const { config, runner } = ctx;
|
|
10
|
+
const state = config.builtInAgents?.debugger ?? {};
|
|
11
|
+
const enabled = Boolean(state.enabled);
|
|
12
|
+
const session = runner.output(debuggerSessionId);
|
|
13
|
+
return json(res, 200, {
|
|
14
|
+
ok: true,
|
|
15
|
+
agent: debuggerAgent(fromPersisted(state)),
|
|
16
|
+
enabled,
|
|
17
|
+
lines: session?.lines ?? [],
|
|
18
|
+
running: runner.isRunning(debuggerSessionId),
|
|
19
|
+
stats: runner.stats(debuggerSessionId),
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
/** Persisted cli/model overrides for the Debugger, sanitized to non-empty strings. */
|
|
23
|
+
function fromPersisted(state) {
|
|
24
|
+
const cli = typeof state.cli === "string" && state.cli.trim() ? state.cli.trim() : undefined;
|
|
25
|
+
const model = typeof state.model === "string" && state.model.trim() ? state.model.trim() : undefined;
|
|
26
|
+
return { cli, model };
|
|
27
|
+
}
|
|
28
|
+
export const sendDebuggerMessage = async (ctx, req, res) => {
|
|
29
|
+
const { config, index, runner } = ctx;
|
|
30
|
+
const state = config.builtInAgents?.debugger ?? {};
|
|
31
|
+
if (!state.enabled) {
|
|
32
|
+
return json(res, 400, {
|
|
33
|
+
error: "Debugger is disabled — enable it on the Agents page to chat",
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
const body = (await readBody(req));
|
|
37
|
+
const text = typeof body?.text === "string" ? body.text.trim() : "";
|
|
38
|
+
if (!text)
|
|
39
|
+
return json(res, 400, { error: "message text is required" });
|
|
40
|
+
const agent = debuggerAgent(fromPersisted(state));
|
|
41
|
+
const context = repoContextForDebugger(index);
|
|
42
|
+
const existing = runner.output(debuggerSessionId);
|
|
43
|
+
const result = existing
|
|
44
|
+
? runner.send(debuggerSessionId, text, agent, {
|
|
45
|
+
resumePreamble: `Updated repository context:\n${context}`,
|
|
46
|
+
})
|
|
47
|
+
: runner.startChat(debuggerSessionId, text, agent, context);
|
|
48
|
+
if (!result.ok) {
|
|
49
|
+
const reason = result.reason ?? "could not send message";
|
|
50
|
+
// Both a busy turn (`busy`) and the concurrency race where another request
|
|
51
|
+
// created the session between the output check above and startChat
|
|
52
|
+
// ("conversation already exists") mean the conversation is in flight — the
|
|
53
|
+
// caller should surface a retry, not a hard failure.
|
|
54
|
+
if (result.busy || reason.includes("already exists")) {
|
|
55
|
+
return json(res, 409, {
|
|
56
|
+
error: "Debugger is busy — wait for the current turn to finish",
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return json(res, 400, { error: reason });
|
|
60
|
+
}
|
|
61
|
+
return json(res, 200, { ok: true });
|
|
62
|
+
};
|
|
63
|
+
/** Interrupt a running Debugger response. Idempotent. */
|
|
64
|
+
export const interruptDebugger = (ctx, _req, res) => {
|
|
65
|
+
const result = ctx.runner.interrupt(debuggerSessionId);
|
|
66
|
+
return json(res, 200, { ok: true, ...result });
|
|
67
|
+
};
|
|
68
|
+
/** Hand an explicit debugger diagnosis to the task's existing engineering session. */
|
|
69
|
+
export const repairWithDebugger = async (ctx, req, res) => {
|
|
70
|
+
const { config, index, runner } = ctx;
|
|
71
|
+
const body = (await readBody(req));
|
|
72
|
+
const taskId = typeof body.taskId === "string" ? body.taskId : "";
|
|
73
|
+
const diagnosis = typeof body.diagnosis === "string" ? body.diagnosis.trim() : "";
|
|
74
|
+
const task = index.getTask(taskId);
|
|
75
|
+
if (!task)
|
|
76
|
+
return json(res, 404, { error: "Task not found" });
|
|
77
|
+
if (task.status !== "review")
|
|
78
|
+
return json(res, 400, { error: "Only review tasks can be repaired" });
|
|
79
|
+
if (!diagnosis)
|
|
80
|
+
return json(res, 400, { error: "Debugger diagnosis is required" });
|
|
81
|
+
const engineer = resolveAgentForTask(config, task);
|
|
82
|
+
if (!engineer)
|
|
83
|
+
return json(res, 400, { error: "No enabled engineer is configured" });
|
|
84
|
+
const sent = runner.send(task.id, [
|
|
85
|
+
"The Debugger diagnosed a failed Move-to-done operation. Apply the smallest safe repair in this existing worktree, run repoos check, then hand off to review.",
|
|
86
|
+
diagnosis,
|
|
87
|
+
].join("\n\n"), engineer, { skipBoardDivergence: true });
|
|
88
|
+
if (!sent.ok)
|
|
89
|
+
return json(res, sent.busy ? 409 : 400, { error: sent.reason ?? "Could not start engineer" });
|
|
90
|
+
const updated = patchTaskFile(config, task.absPath, { status: "active" });
|
|
91
|
+
index.applyFileChange(updated.absPath);
|
|
92
|
+
return json(res, 200, { ok: true, task: index.getTask(task.id) });
|
|
93
|
+
};
|
|
94
|
+
/** Minimal repository context for the Debugger (bug paste vs. config surface). */
|
|
95
|
+
function repoContextForDebugger(index) {
|
|
96
|
+
const tasks = index.getTasks();
|
|
97
|
+
const lines = tasks.map((t) => `#${t.id} ${t.title} (${t.status})`);
|
|
98
|
+
return [
|
|
99
|
+
`RepoOS repository with ${tasks.length} task(s).`,
|
|
100
|
+
...(lines.length ? lines : ["No tasks yet."]),
|
|
101
|
+
].join("\n");
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Per-task Debugger chat (task #0337). The session is keyed by
|
|
105
|
+
* `debugger:<taskId>` so it lives alongside — but does not collide with — the
|
|
106
|
+
* global bug-paste Debugger (`__repoos-debugger__`) and the task's own
|
|
107
|
+
* engineer/PM/reviewer sessions.
|
|
108
|
+
*/
|
|
109
|
+
export const taskDebuggerSessionId = (taskId) => `debugger:${taskId}`;
|
|
110
|
+
/**
|
|
111
|
+
* Redact obvious secrets/credentials from text before it is handed to the
|
|
112
|
+
* Debugger. The agent is instructed never to surface secrets too, but defense
|
|
113
|
+
* in depth: a stray API key or password in a log line should never reach the
|
|
114
|
+
* model's prompt (and therefore the user's screen).
|
|
115
|
+
*/
|
|
116
|
+
function redactSecrets(text) {
|
|
117
|
+
return text
|
|
118
|
+
.replace(/sk-[A-Za-z0-9_-]{20,}/g, "***REDACTED***")
|
|
119
|
+
.replace(/AKIA[0-9A-Z]{16}/g, "***REDACTED***")
|
|
120
|
+
.replace(/gh[pousr]_[A-Za-z0-9]{20,}/g, "***REDACTED***")
|
|
121
|
+
.replace(/\bBearer\s+[A-Za-z0-9._\-]+/gi, "Bearer ***REDACTED***")
|
|
122
|
+
.replace(/\b(api[_-]?key|apikey|secret|access[_-]?token|auth[_-]?token|client[_-]?secret|private[_-]?key|password|passwd|token)\b\s*[:=]\s*['"]?[^\s'"`}]{6,}/gi, (m) => {
|
|
123
|
+
const eq = m.match(/[:=]\s*['"]?/);
|
|
124
|
+
const sep = eq ? eq[0] : ": ";
|
|
125
|
+
const key = m.slice(0, m.length - (eq ? eq[0].length : 0));
|
|
126
|
+
return `${key}${sep}***REDACTED***`;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
/** Render one agent transcript entry to a single-line-ish readable string. */
|
|
130
|
+
function entryText(e) {
|
|
131
|
+
if ("type" in e) {
|
|
132
|
+
switch (e.type) {
|
|
133
|
+
case "human":
|
|
134
|
+
return `User: ${e.text}`;
|
|
135
|
+
case "text":
|
|
136
|
+
return `Assistant: ${e.text}`;
|
|
137
|
+
case "sys":
|
|
138
|
+
return `[system] ${e.d}`;
|
|
139
|
+
case "tool": {
|
|
140
|
+
const input = e.input ? `\n input: ${e.input}` : "";
|
|
141
|
+
const output = e.output ? `\n output: ${e.output}` : "";
|
|
142
|
+
const state = e.state ? ` (${e.state})` : "";
|
|
143
|
+
return `[tool ${e.tool}${state}]${input}${output}`;
|
|
144
|
+
}
|
|
145
|
+
case "step":
|
|
146
|
+
return "";
|
|
147
|
+
default:
|
|
148
|
+
return "";
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return e.s === "sys" ? `[system] ${e.d}` : e.d;
|
|
152
|
+
}
|
|
153
|
+
function transcriptFor(label, session) {
|
|
154
|
+
if (!session || !session.lines || session.lines.length === 0) {
|
|
155
|
+
return `(${label}: no conversation yet)`;
|
|
156
|
+
}
|
|
157
|
+
return session.lines.map(entryText).filter(Boolean).join("\n");
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Aggregate the full task context the Debugger reasons over: the task's
|
|
161
|
+
* metadata/body, every agent conversation thread (engineer/developer, PM,
|
|
162
|
+
* reviewer), and the task's own logs. Secrets are redacted before returning.
|
|
163
|
+
*/
|
|
164
|
+
function buildTaskDebuggerContext(ctx, taskId, currentUserEmail) {
|
|
165
|
+
const task = ctx.index.getTask(taskId);
|
|
166
|
+
if (!task)
|
|
167
|
+
return "(task not found)";
|
|
168
|
+
const parts = [];
|
|
169
|
+
parts.push(`# Task #${task.id}: ${task.title}`);
|
|
170
|
+
parts.push(`Status: ${task.status} | Priority: ${task.priority ?? "unset"} | Area: ${task.area ?? "unset"} | Type: ${task.type ?? "unset"}`);
|
|
171
|
+
if (task.branch)
|
|
172
|
+
parts.push(`Branch: ${task.branch}`);
|
|
173
|
+
if (task.body)
|
|
174
|
+
parts.push(`\n## Task specification\n${task.body}`);
|
|
175
|
+
const logs = ctx.logger.getTaskLogs(taskId, 800);
|
|
176
|
+
if (logs.length) {
|
|
177
|
+
const rendered = logs
|
|
178
|
+
.map((l) => `[${l.timestamp}] ${l.level}: ${l.message}${l.context ? " " + JSON.stringify(l.context) : ""}`)
|
|
179
|
+
.join("\n");
|
|
180
|
+
parts.push(`\n## Task logs (most recent first)\n${rendered}`);
|
|
181
|
+
}
|
|
182
|
+
parts.push(`\n## Engineer (developer) conversation\n${transcriptFor("engineer", ctx.runner.output(task.id))}`);
|
|
183
|
+
const pmSessionId = currentUserEmail
|
|
184
|
+
? `pm-task-v2:${task.id}::${currentUserEmail}`
|
|
185
|
+
: `pm-task-v2:${task.id}`;
|
|
186
|
+
parts.push(`\n## PM (product manager) conversation\n${transcriptFor("PM", ctx.runner.output(pmSessionId))}`);
|
|
187
|
+
parts.push(`\n## Reviewer conversation\n${transcriptFor("reviewer", ctx.runner.output(`review:${task.id}`))}`);
|
|
188
|
+
return redactSecrets(parts.join("\n"));
|
|
189
|
+
}
|
|
190
|
+
/** Read the Debugger's enabled state for a specific task's debug chat. */
|
|
191
|
+
export const getTaskDebugger = (ctx, _req, res, params) => {
|
|
192
|
+
const id = params.param1;
|
|
193
|
+
const task = ctx.index.getTask(id);
|
|
194
|
+
if (!task)
|
|
195
|
+
return json(res, 404, { error: `Task #${id} not found` });
|
|
196
|
+
const state = ctx.config.builtInAgents?.debugger ?? {};
|
|
197
|
+
const enabled = Boolean(state.enabled);
|
|
198
|
+
const sessionId = taskDebuggerSessionId(id);
|
|
199
|
+
const session = ctx.runner.output(sessionId);
|
|
200
|
+
return json(res, 200, {
|
|
201
|
+
ok: true,
|
|
202
|
+
enabled,
|
|
203
|
+
lines: session?.lines ?? [],
|
|
204
|
+
running: ctx.runner.isRunning(sessionId),
|
|
205
|
+
});
|
|
206
|
+
};
|
|
207
|
+
/** Start or continue a task-scoped Debugger conversation with full context. */
|
|
208
|
+
export const sendTaskDebuggerMessage = async (ctx, req, res, params) => {
|
|
209
|
+
const { config, index, runner } = ctx;
|
|
210
|
+
const id = params.param1;
|
|
211
|
+
const state = config.builtInAgents?.debugger ?? {};
|
|
212
|
+
if (!state.enabled) {
|
|
213
|
+
return json(res, 400, {
|
|
214
|
+
error: "Debugger is disabled — enable it on the Agents page to chat",
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
const task = index.getTask(id);
|
|
218
|
+
if (!task)
|
|
219
|
+
return json(res, 404, { error: `Task #${id} not found` });
|
|
220
|
+
const body = (await readBody(req));
|
|
221
|
+
const text = typeof body?.text === "string" ? body.text.trim() : "";
|
|
222
|
+
if (!text)
|
|
223
|
+
return json(res, 400, { error: "message text is required" });
|
|
224
|
+
const agent = debuggerAgent(fromPersisted(state));
|
|
225
|
+
const currentUserEmail = getCurrentUser(req, config)?.email;
|
|
226
|
+
const context = buildTaskDebuggerContext(ctx, id, currentUserEmail);
|
|
227
|
+
const sessionId = taskDebuggerSessionId(id);
|
|
228
|
+
const existing = runner.output(sessionId);
|
|
229
|
+
const result = existing
|
|
230
|
+
? runner.send(sessionId, text, agent, {
|
|
231
|
+
resumePreamble: `Latest task context:\n${context}`,
|
|
232
|
+
})
|
|
233
|
+
: runner.startChat(sessionId, text, agent, context);
|
|
234
|
+
if (!result.ok) {
|
|
235
|
+
if (result.busy) {
|
|
236
|
+
return json(res, 409, { error: "Debugger is busy — wait for the current turn to finish" });
|
|
237
|
+
}
|
|
238
|
+
return json(res, 400, { error: result.reason ?? "could not send message" });
|
|
239
|
+
}
|
|
240
|
+
return json(res, 200, { ok: true });
|
|
241
|
+
};
|
|
242
|
+
/** Interrupt a running task-scoped Debugger response. Idempotent. */
|
|
243
|
+
export const interruptTaskDebugger = (ctx, _req, res, params) => {
|
|
244
|
+
const result = ctx.runner.interrupt(taskDebuggerSessionId(params.param1));
|
|
245
|
+
return json(res, 200, { ok: true, ...result });
|
|
246
|
+
};
|
|
247
|
+
/**
|
|
248
|
+
* Dispatch a follow-up instruction from the task Debugger chat straight to the
|
|
249
|
+
* engineer: resume the task's existing engineering session with the instruction,
|
|
250
|
+
* or start the engineer fresh when it has never run. Sets the task `active` so
|
|
251
|
+
* the agent can act on the diagnosis.
|
|
252
|
+
*/
|
|
253
|
+
export const sendTaskDebuggerToEngineer = async (ctx, req, res, params) => {
|
|
254
|
+
const { config, index, runner, onServerStatusChange } = ctx;
|
|
255
|
+
const id = params.param1;
|
|
256
|
+
const task = index.getTask(id);
|
|
257
|
+
if (!task)
|
|
258
|
+
return json(res, 404, { error: `Task #${id} not found` });
|
|
259
|
+
const body = (await readBody(req));
|
|
260
|
+
const text = typeof body?.text === "string" ? body.text.trim() : "";
|
|
261
|
+
if (!text)
|
|
262
|
+
return json(res, 400, { error: "instruction text is required" });
|
|
263
|
+
const engineer = resolveAgentForTask(config, task);
|
|
264
|
+
if (!engineer) {
|
|
265
|
+
return json(res, 400, { error: "No enabled engineer agent is configured on the Agents page" });
|
|
266
|
+
}
|
|
267
|
+
const existing = runner.output(id);
|
|
268
|
+
if (existing) {
|
|
269
|
+
if (task.status !== "active") {
|
|
270
|
+
const updated = patchTaskFile(config, task.absPath, { status: "active" });
|
|
271
|
+
index.applyFileChange(updated.absPath);
|
|
272
|
+
}
|
|
273
|
+
const sent = runner.send(id, text, engineer, { skipBoardDivergence: true });
|
|
274
|
+
if (!sent.ok) {
|
|
275
|
+
return json(res, sent.busy ? 409 : 400, { error: sent.reason ?? "Could not reach engineer" });
|
|
276
|
+
}
|
|
277
|
+
return json(res, 200, { ok: true, task: index.getTask(id) });
|
|
278
|
+
}
|
|
279
|
+
// Engineer never ran for this task — boot it fresh with the instruction.
|
|
280
|
+
if (task.status !== "ready" && task.status !== "active") {
|
|
281
|
+
return json(res, 400, {
|
|
282
|
+
error: `Only ready or active tasks can be started (#${id} is ${task.status})`,
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
if (runner.isRunning(id)) {
|
|
286
|
+
return json(res, 400, { error: `Task #${id} is already running` });
|
|
287
|
+
}
|
|
288
|
+
const branch = task.branch || deriveBranch(task.title);
|
|
289
|
+
const patch = { status: "active", needsInput: false };
|
|
290
|
+
if (!task.branch)
|
|
291
|
+
patch.branch = branch;
|
|
292
|
+
const updated = patchTaskFile(config, task.absPath, patch, {
|
|
293
|
+
onStatusChange: onServerStatusChange,
|
|
294
|
+
});
|
|
295
|
+
const wtRes = ensureWorktree(config.root, branch);
|
|
296
|
+
index.applyFileChange(updated.absPath);
|
|
297
|
+
index.refreshBranches();
|
|
298
|
+
const cwd = wtRes.ok ? wtRes.path : config.root;
|
|
299
|
+
const taskForLaunch = index.getTask(updated.id) ?? updated;
|
|
300
|
+
const bootResult = await bootstrap(config, taskForLaunch, branch, cwd);
|
|
301
|
+
if (!bootResult.ok) {
|
|
302
|
+
return json(res, 500, { error: `Bootstrap failed: ${bootResult.reason ?? "unknown error"}` });
|
|
303
|
+
}
|
|
304
|
+
const pack = generateContextPack(config, taskForLaunch, branch, cwd, bootResult);
|
|
305
|
+
const resumeContext = !task.branch || !wtRes.ok ? undefined : resumePreamble(config, taskForLaunch, branch, cwd);
|
|
306
|
+
const preamble = [resumeContext, text].filter(Boolean).join("\n\n") || undefined;
|
|
307
|
+
const spawnRes = runner.start(taskForLaunch, branch, engineer, {
|
|
308
|
+
cwd,
|
|
309
|
+
contextPack: pack.content,
|
|
310
|
+
resumePreamble: preamble,
|
|
311
|
+
});
|
|
312
|
+
return json(res, 200, {
|
|
313
|
+
ok: true,
|
|
314
|
+
task: index.getTask(updated.id),
|
|
315
|
+
branch,
|
|
316
|
+
spawn: { ok: spawnRes.ok, pid: spawnRes.pid, queued: spawnRes.queued, reason: spawnRes.reason },
|
|
317
|
+
});
|
|
318
|
+
};
|
|
319
|
+
/**
|
|
320
|
+
* Dispatch a follow-up instruction from the task Debugger chat to the PM. Opens
|
|
321
|
+
* (or resumes) the task's PM conversation with the instruction and the full
|
|
322
|
+
* task context, so the PM can update the task on the diagnosis.
|
|
323
|
+
*/
|
|
324
|
+
export const sendTaskDebuggerToPm = async (ctx, req, res, params) => {
|
|
325
|
+
const { config, index, runner } = ctx;
|
|
326
|
+
const id = params.param1;
|
|
327
|
+
const existing = index.getTask(id);
|
|
328
|
+
if (!existing)
|
|
329
|
+
return json(res, 404, { error: `Task #${id} not found` });
|
|
330
|
+
const body = (await readBody(req));
|
|
331
|
+
const text = typeof body?.text === "string" ? body.text.trim() : "";
|
|
332
|
+
if (!text)
|
|
333
|
+
return json(res, 400, { error: "instruction text is required" });
|
|
334
|
+
const pm = resolvePmAgent(config);
|
|
335
|
+
if (!pm) {
|
|
336
|
+
return json(res, 400, { error: "PM agent is not configured — enable it on the Agents page" });
|
|
337
|
+
}
|
|
338
|
+
const currentUserEmail = getCurrentUser(req, config)?.email;
|
|
339
|
+
const pmSessionId = currentUserEmail
|
|
340
|
+
? `pm-task-v2:${id}::${currentUserEmail}`
|
|
341
|
+
: `pm-task-v2:${id}`;
|
|
342
|
+
const taskContext = `Task #${id}: ${existing.title}
|
|
343
|
+
Status: ${existing.status}
|
|
344
|
+
Priority: ${existing.priority || "unset"}
|
|
345
|
+
Area: ${existing.area || "unset"}
|
|
346
|
+
Type: ${existing.type || "unset"}
|
|
347
|
+
|
|
348
|
+
Description:
|
|
349
|
+
${existing.body || "(no description)"}`;
|
|
350
|
+
const result = runner.output(pmSessionId)
|
|
351
|
+
? runner.send(pmSessionId, text, pm, { resumePreamble: `Task context:\n${taskContext}` })
|
|
352
|
+
: runner.startChat(pmSessionId, text, pm, taskContext, taskPmPrompt);
|
|
353
|
+
if (!result.ok && result.busy) {
|
|
354
|
+
return json(res, 409, { error: result.reason ?? "PM is busy" });
|
|
355
|
+
}
|
|
356
|
+
if (!result.ok) {
|
|
357
|
+
return json(res, 400, { error: result.reason ?? "could not send message to PM" });
|
|
358
|
+
}
|
|
359
|
+
return json(res, 200, { ok: true });
|
|
360
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { json, readBody } from "./utils.js";
|
|
2
|
+
import { deployBranch, getDeploymentsStatus } from "../deployments.js";
|
|
3
|
+
export const getDeployments = async (ctx, _req, res) => json(res, 200, await getDeploymentsStatus(ctx.config));
|
|
4
|
+
export const postDeploy = async (ctx, req, res) => {
|
|
5
|
+
const body = (await readBody(req));
|
|
6
|
+
if (typeof body.branch !== "string" || !body.branch.trim())
|
|
7
|
+
return json(res, 400, { error: "branch is required" });
|
|
8
|
+
const result = await deployBranch(ctx.config, body.branch.trim());
|
|
9
|
+
// 409 (not 400) for the refusal cases: the request was well-formed but the
|
|
10
|
+
// repository state — dirty tree, diverged branches, moved remote — refused it.
|
|
11
|
+
// The refusal text is ALSO carried in `error`, not just `output`: the
|
|
12
|
+
// browser's api() wrapper only surfaces `body.error`/`body.reason` on a
|
|
13
|
+
// non-2xx, so without this the carefully-assembled git refusal ("Nothing
|
|
14
|
+
// was force-pushed", git's stderr) would reach the user as "Conflict".
|
|
15
|
+
return json(res, result.ok ? 200 : 409, { ...result, error: result.output });
|
|
16
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Document routes: manual create + PM-agent-backed freeform create.
|
|
3
|
+
*/
|
|
4
|
+
import type { RouteHandler } from "./types.js";
|
|
5
|
+
export declare const createDoc: RouteHandler;
|
|
6
|
+
export declare const createSkillRoute: RouteHandler;
|
|
7
|
+
export declare const createFreeformSkillRoute: RouteHandler;
|
|
8
|
+
export declare const createFreeformDoc: RouteHandler;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { json, readBody } from "./utils.js";
|
|
2
|
+
import { resolvePmAgent, runPrompt, recordOneShotSession } from "../agents.js";
|
|
3
|
+
/** Apply optional `cliOverride` / `modelOverride` from a request body onto the base PM agent. */
|
|
4
|
+
function pmWithOverrides(base, body) {
|
|
5
|
+
const cli = typeof body?.cliOverride === "string" && body.cliOverride ? body.cliOverride : undefined;
|
|
6
|
+
const model = typeof body?.modelOverride === "string" && body.modelOverride ? body.modelOverride : undefined;
|
|
7
|
+
return { ...base, ...(cli ? { cli } : {}), ...(model ? { model } : {}) };
|
|
8
|
+
}
|
|
9
|
+
import { createDocument, createFreeformDocument, createSkill, createFreeformSkill, docFreeformPrompt, skillFreeformPrompt, parseGeneratedDocument, } from "../../core/docs.js";
|
|
10
|
+
export const createDoc = async (ctx, req, res) => {
|
|
11
|
+
const { config } = ctx;
|
|
12
|
+
const body = (await readBody(req));
|
|
13
|
+
// `content` is a utf8 string (manual create, text upload); `contentBase64` is
|
|
14
|
+
// base64-encoded raw bytes (binary upload — images, PDFs, fonts).
|
|
15
|
+
const isBase64 = typeof body.contentBase64 === "string";
|
|
16
|
+
const content = isBase64 ? body.contentBase64 : body.content;
|
|
17
|
+
if (typeof content !== "string") {
|
|
18
|
+
return json(res, 400, { error: "content or contentBase64 is required" });
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const result = createDocument(config, {
|
|
22
|
+
path: body.path,
|
|
23
|
+
content,
|
|
24
|
+
encoding: isBase64 ? "base64" : "utf8",
|
|
25
|
+
});
|
|
26
|
+
return json(res, 201, { ok: true, path: result.path });
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
return json(res, 400, { error: err.message });
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
export const createSkillRoute = async (ctx, req, res) => {
|
|
33
|
+
const { config } = ctx;
|
|
34
|
+
const body = (await readBody(req));
|
|
35
|
+
const name = typeof body.name === "string" ? body.name.trim() : "";
|
|
36
|
+
if (!name) {
|
|
37
|
+
return json(res, 400, { error: "name is required" });
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const result = createSkill(config, {
|
|
41
|
+
name,
|
|
42
|
+
description: typeof body.description === "string" ? body.description : "",
|
|
43
|
+
body: typeof body.body === "string" ? body.body : "",
|
|
44
|
+
content: typeof body.content === "string" ? body.content : undefined,
|
|
45
|
+
});
|
|
46
|
+
return json(res, 201, { ok: true, path: result.path });
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
return json(res, 400, { error: err.message });
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
export const createFreeformSkillRoute = async (ctx, req, res) => {
|
|
53
|
+
const { config, emitEvent } = ctx;
|
|
54
|
+
const body = (await readBody(req));
|
|
55
|
+
const description = typeof body?.description === "string" ? body.description.trim() : "";
|
|
56
|
+
if (!description) {
|
|
57
|
+
return json(res, 400, { ok: false, reason: "description is required" });
|
|
58
|
+
}
|
|
59
|
+
const runId = typeof body?.runId === "string" && body.runId ? body.runId : null;
|
|
60
|
+
const pmBase = resolvePmAgent(config);
|
|
61
|
+
if (!pmBase) {
|
|
62
|
+
return json(res, 400, { ok: false, reason: "No PM agent is configured" });
|
|
63
|
+
}
|
|
64
|
+
const pm = pmWithOverrides(pmBase, body);
|
|
65
|
+
try {
|
|
66
|
+
const skillResult = await createFreeformSkill(config, description, async (desc) => {
|
|
67
|
+
const result = await runPrompt(pm, skillFreeformPrompt(desc), {
|
|
68
|
+
cwd: config.root,
|
|
69
|
+
onLine: runId
|
|
70
|
+
? (line) => {
|
|
71
|
+
emitEvent({
|
|
72
|
+
type: "agent.output",
|
|
73
|
+
id: runId,
|
|
74
|
+
entry: { s: "out", d: line },
|
|
75
|
+
stream: "out",
|
|
76
|
+
at: new Date().toISOString(),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
: undefined,
|
|
80
|
+
});
|
|
81
|
+
recordOneShotSession(config.root, pm, result, { sessionType: "pm", taskId: null });
|
|
82
|
+
if (!result.ok || !result.output) {
|
|
83
|
+
throw new Error(result.error ?? "the PM agent returned no usable output");
|
|
84
|
+
}
|
|
85
|
+
return parseGeneratedDocument(result.output);
|
|
86
|
+
});
|
|
87
|
+
return json(res, 201, { ok: true, path: skillResult.path });
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
return json(res, 400, { ok: false, reason: err.message });
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
export const createFreeformDoc = async (ctx, req, res) => {
|
|
94
|
+
const { config, emitEvent } = ctx;
|
|
95
|
+
const body = (await readBody(req));
|
|
96
|
+
const description = typeof body?.description === "string" ? body.description.trim() : "";
|
|
97
|
+
if (!description) {
|
|
98
|
+
return json(res, 400, { ok: false, reason: "description is required" });
|
|
99
|
+
}
|
|
100
|
+
const runId = typeof body?.runId === "string" && body.runId ? body.runId : null;
|
|
101
|
+
const pmBase = resolvePmAgent(config);
|
|
102
|
+
if (!pmBase) {
|
|
103
|
+
return json(res, 400, { ok: false, reason: "No PM agent is configured" });
|
|
104
|
+
}
|
|
105
|
+
// The New doc panel sends cliOverride / modelOverride from its agent picker.
|
|
106
|
+
const pm = pmWithOverrides(pmBase, body);
|
|
107
|
+
try {
|
|
108
|
+
const docResult = await createFreeformDocument(config, description, async (desc) => {
|
|
109
|
+
const result = await runPrompt(pm, docFreeformPrompt(desc), {
|
|
110
|
+
cwd: config.root,
|
|
111
|
+
onLine: runId
|
|
112
|
+
? (line) => {
|
|
113
|
+
emitEvent({
|
|
114
|
+
type: "agent.output",
|
|
115
|
+
id: runId,
|
|
116
|
+
entry: { s: "out", d: line },
|
|
117
|
+
stream: "out",
|
|
118
|
+
at: new Date().toISOString(),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
: undefined,
|
|
122
|
+
});
|
|
123
|
+
// Freeform doc authoring is real PM spend that belongs to no task (0311).
|
|
124
|
+
recordOneShotSession(config.root, pm, result, { sessionType: "pm", taskId: null });
|
|
125
|
+
if (!result.ok || !result.output) {
|
|
126
|
+
throw new Error(result.error ?? "the PM agent returned no usable output");
|
|
127
|
+
}
|
|
128
|
+
return parseGeneratedDocument(result.output);
|
|
129
|
+
});
|
|
130
|
+
return json(res, 201, { ok: true, path: docResult.path });
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
return json(res, 400, { ok: false, reason: err.message });
|
|
134
|
+
}
|
|
135
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { RepoOSConfig, Task } from "../../core/types.js";
|
|
2
|
+
export declare const UI_MIME: Record<string, string>;
|
|
3
|
+
export declare function serveStaticUi(res: any, uiDir: string, urlPath: string): boolean;
|
|
4
|
+
export declare function safeRepoFile(root: string, urlPath: string): string | null;
|
|
5
|
+
export declare function findUiDir(root: string): string | null;
|
|
6
|
+
export declare function findPackageRoot(): string | null;
|
|
7
|
+
export declare function loadBuildInfo(): {
|
|
8
|
+
version: string | null;
|
|
9
|
+
buildAt: string | null;
|
|
10
|
+
};
|
|
11
|
+
export declare function skillField(text: string, field: string): string | null;
|
|
12
|
+
export declare function listDocs(config: RepoOSConfig): {
|
|
13
|
+
path: string;
|
|
14
|
+
title: string;
|
|
15
|
+
}[];
|
|
16
|
+
export declare function listSkills(config: RepoOSConfig): {
|
|
17
|
+
path: string;
|
|
18
|
+
name: string;
|
|
19
|
+
description: string;
|
|
20
|
+
}[];
|
|
21
|
+
export declare function repoGuideContext(config: RepoOSConfig, tasks: Task[]): string;
|