@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,345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safe, single-task mutations for the server.
|
|
3
|
+
*
|
|
4
|
+
* The CLI mutates by rebuilding the whole index then writing — fine for a
|
|
5
|
+
* one-shot process. A long-lived server with multiple writers (you + agents)
|
|
6
|
+
* needs to avoid clobbering: between the moment the server read a task and the
|
|
7
|
+
* moment it writes, the file may have changed on disk (an agent edited the
|
|
8
|
+
* body, say). So we re-read immediately before writing and merge the requested
|
|
9
|
+
* field changes onto the CURRENT on-disk state, rather than onto a possibly
|
|
10
|
+
* stale in-memory copy.
|
|
11
|
+
*
|
|
12
|
+
* Because status lives in per-task files (never a shared queue file), the only
|
|
13
|
+
* conflict surface is concurrent writes to the SAME task — which this handles.
|
|
14
|
+
*/
|
|
15
|
+
import { readFileSync, writeFileSync, existsSync, unlinkSync } from "node:fs";
|
|
16
|
+
import { execFileSync } from "node:child_process";
|
|
17
|
+
import { join, resolve, sep, relative, basename } from "node:path";
|
|
18
|
+
import { STATUSES } from "../core/types.js";
|
|
19
|
+
import { parseTask, serializeTask, recordChange, utcTimestamp, extractSection, removeSection, ACTIVITY_HEADING, SCREENSHOTS_HEADING, ORIGINAL_PROMPT_HEADING, } from "../core/task.js";
|
|
20
|
+
import { commitTaskFile } from "../core/git.js";
|
|
21
|
+
import { appendScreenshotsSection } from "./attachments.js";
|
|
22
|
+
/**
|
|
23
|
+
* Body sections that are user-owned or append-only: they live in the task body
|
|
24
|
+
* but must survive a wholesale body replacement. The freeform PM "flesh it out"
|
|
25
|
+
* flow runs `repoos update --body`, which otherwise silently drops the user's
|
|
26
|
+
* screenshots, their original prompt, and the entire activity history (#0317).
|
|
27
|
+
* When a patch supplies a new body that is silent about one of these sections,
|
|
28
|
+
* it's carried over verbatim from the current on-disk copy. Order is
|
|
29
|
+
* canonical — they always sit at the end of the body in this order.
|
|
30
|
+
*/
|
|
31
|
+
const PROTECTED_SECTIONS = [
|
|
32
|
+
ORIGINAL_PROMPT_HEADING,
|
|
33
|
+
SCREENSHOTS_HEADING,
|
|
34
|
+
ACTIVITY_HEADING,
|
|
35
|
+
];
|
|
36
|
+
/**
|
|
37
|
+
* Sections in PROTECTED_SECTIONS where the caller's own copy, if the patch
|
|
38
|
+
* body explicitly includes one, wins over the on-disk version instead of
|
|
39
|
+
* being silently discarded. Screenshots and Activity are system-managed
|
|
40
|
+
* (via `addScreenshot` / `recordChange`) and must never be settable by a
|
|
41
|
+
* plain body replacement, so they stay force-preserved-from-disk regardless
|
|
42
|
+
* of what a caller's body happens to contain. Original Prompt is the one
|
|
43
|
+
* exception: it's the durable record of what the user actually asked for
|
|
44
|
+
* (#0345 — a malformed PM response wiped it with no way to restore it short
|
|
45
|
+
* of hand-editing the file, which AGENTS.md forbids), so a caller that
|
|
46
|
+
* deliberately includes an updated one — e.g. a hotfix restoring lost
|
|
47
|
+
* content via `repoos update --body` — must be able to set it.
|
|
48
|
+
*/
|
|
49
|
+
const CALLER_OVERRIDABLE_SECTIONS = [ORIGINAL_PROMPT_HEADING];
|
|
50
|
+
export class WriteError extends Error {
|
|
51
|
+
}
|
|
52
|
+
/** Thrown when a delete target resolves outside the configured work dir. */
|
|
53
|
+
export class PathGuardError extends WriteError {
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Apply a patch to a task file safely. `absPath` is the file to edit. Returns
|
|
57
|
+
* the freshly re-parsed Task. Throws WriteError on bad input or missing file.
|
|
58
|
+
*/
|
|
59
|
+
export function patchTaskFile(config, absPath, patch, opts = {}) {
|
|
60
|
+
if (!existsSync(absPath)) {
|
|
61
|
+
throw new WriteError(`Task file not found: ${absPath}`);
|
|
62
|
+
}
|
|
63
|
+
if (patch.status !== undefined && !STATUSES.includes(patch.status)) {
|
|
64
|
+
throw new WriteError(`Invalid status "${patch.status}". Valid: ${STATUSES.join(", ")}`);
|
|
65
|
+
}
|
|
66
|
+
// Re-read CURRENT on-disk state right before writing.
|
|
67
|
+
const current = parseTask({
|
|
68
|
+
content: readFileSync(absPath, "utf8"),
|
|
69
|
+
absPath,
|
|
70
|
+
root: config.root,
|
|
71
|
+
defaultStatus: config.defaultStatus,
|
|
72
|
+
defaultAssignee: config.defaultAssignee,
|
|
73
|
+
});
|
|
74
|
+
// Track changes for activity log
|
|
75
|
+
const changes = [];
|
|
76
|
+
// Merge requested fields onto the current state.
|
|
77
|
+
if (patch.status !== undefined) {
|
|
78
|
+
if (patch.status !== current.status) {
|
|
79
|
+
changes.push(`status ${current.status}→${patch.status}`);
|
|
80
|
+
opts.onStatusChange?.(current, current.status, patch.status);
|
|
81
|
+
}
|
|
82
|
+
current.status = patch.status;
|
|
83
|
+
}
|
|
84
|
+
if (patch.needsInput !== undefined) {
|
|
85
|
+
if (patch.needsInput !== current.needsInput)
|
|
86
|
+
changes.push("needs_input");
|
|
87
|
+
current.needsInput = patch.needsInput;
|
|
88
|
+
// A cleared flag has no reason to carry forward — serializeTask would drop
|
|
89
|
+
// it anyway (only written while needsInput is true), but clearing it here
|
|
90
|
+
// too keeps the in-memory Task consistent with what gets written.
|
|
91
|
+
if (!patch.needsInput)
|
|
92
|
+
current.needsInputReason = undefined;
|
|
93
|
+
}
|
|
94
|
+
if (patch.needsInputReason !== undefined) {
|
|
95
|
+
current.needsInputReason = patch.needsInputReason ?? undefined;
|
|
96
|
+
}
|
|
97
|
+
if (patch.needsMerge !== undefined) {
|
|
98
|
+
if (patch.needsMerge !== current.needsMerge)
|
|
99
|
+
changes.push("needs_merge");
|
|
100
|
+
current.needsMerge = patch.needsMerge;
|
|
101
|
+
}
|
|
102
|
+
if (patch.title !== undefined) {
|
|
103
|
+
if (patch.title !== current.title)
|
|
104
|
+
changes.push("title");
|
|
105
|
+
current.title = patch.title;
|
|
106
|
+
}
|
|
107
|
+
if (patch.priority !== undefined) {
|
|
108
|
+
if (patch.priority !== current.priority)
|
|
109
|
+
changes.push("priority");
|
|
110
|
+
current.priority = patch.priority;
|
|
111
|
+
}
|
|
112
|
+
if (patch.area !== undefined) {
|
|
113
|
+
if (patch.area !== current.area)
|
|
114
|
+
changes.push("area");
|
|
115
|
+
current.area = patch.area;
|
|
116
|
+
}
|
|
117
|
+
if (patch.branch !== undefined) {
|
|
118
|
+
if (patch.branch !== current.branch)
|
|
119
|
+
changes.push("branch");
|
|
120
|
+
current.branch = patch.branch;
|
|
121
|
+
}
|
|
122
|
+
if (patch.type !== undefined) {
|
|
123
|
+
if (patch.type !== current.type)
|
|
124
|
+
changes.push("type");
|
|
125
|
+
current.type = patch.type;
|
|
126
|
+
}
|
|
127
|
+
if (patch.assignedTo !== undefined) {
|
|
128
|
+
if (patch.assignedTo !== current.assignedTo)
|
|
129
|
+
changes.push("assigned_to");
|
|
130
|
+
current.assignedTo = patch.assignedTo;
|
|
131
|
+
current.assignee =
|
|
132
|
+
patch.assignedTo.toLowerCase() === "ai" ? "ai" : patch.assignedTo ? "human" : "unassigned";
|
|
133
|
+
}
|
|
134
|
+
if (patch.body !== undefined) {
|
|
135
|
+
// Carry user-owned / append-only sections over from the on-disk copy so a
|
|
136
|
+
// caller that replaced the whole body (freeform PM rewrites do) can't drop
|
|
137
|
+
// them — UNLESS the caller's own body already includes that section and
|
|
138
|
+
// it's caller-overridable, in which case the caller's version wins (see
|
|
139
|
+
// CALLER_OVERRIDABLE_SECTIONS). Anything not kept from the caller's own
|
|
140
|
+
// body is stripped first, so nothing duplicates.
|
|
141
|
+
const preserved = PROTECTED_SECTIONS.map((h) => {
|
|
142
|
+
const fromCaller = extractSection(patch.body, h);
|
|
143
|
+
if (fromCaller !== null && CALLER_OVERRIDABLE_SECTIONS.includes(h))
|
|
144
|
+
return null;
|
|
145
|
+
return extractSection(current.body, h);
|
|
146
|
+
}).filter((s) => s !== null);
|
|
147
|
+
let nextBody = patch.body;
|
|
148
|
+
for (const h of PROTECTED_SECTIONS) {
|
|
149
|
+
if (CALLER_OVERRIDABLE_SECTIONS.includes(h) && extractSection(patch.body, h) !== null) {
|
|
150
|
+
continue; // caller's version is kept in place below, not stripped.
|
|
151
|
+
}
|
|
152
|
+
nextBody = removeSection(nextBody, h);
|
|
153
|
+
}
|
|
154
|
+
nextBody = [nextBody.replace(/\s+$/, ""), ...preserved].filter(Boolean).join("\n\n");
|
|
155
|
+
if (nextBody !== current.body)
|
|
156
|
+
changes.push("body");
|
|
157
|
+
current.body = nextBody;
|
|
158
|
+
}
|
|
159
|
+
if (patch.addScreenshot) {
|
|
160
|
+
current.body = appendScreenshotsSection(current.body, [patch.addScreenshot]);
|
|
161
|
+
changes.push("screenshots");
|
|
162
|
+
}
|
|
163
|
+
if (patch.addScreenshots && patch.addScreenshots.length > 0) {
|
|
164
|
+
current.body = appendScreenshotsSection(current.body, patch.addScreenshots);
|
|
165
|
+
changes.push("screenshots");
|
|
166
|
+
}
|
|
167
|
+
if (patch.agentOverride !== undefined) {
|
|
168
|
+
if (patch.agentOverride !== current.agentOverride)
|
|
169
|
+
changes.push("agent_override");
|
|
170
|
+
current.agentOverride = patch.agentOverride;
|
|
171
|
+
}
|
|
172
|
+
if (patch.cliOverride !== undefined) {
|
|
173
|
+
if (patch.cliOverride !== current.cliOverride)
|
|
174
|
+
changes.push("cli_override");
|
|
175
|
+
current.cliOverride = patch.cliOverride;
|
|
176
|
+
}
|
|
177
|
+
if (patch.modelOverride !== undefined) {
|
|
178
|
+
if (patch.modelOverride !== current.modelOverride)
|
|
179
|
+
changes.push("model_override");
|
|
180
|
+
current.modelOverride = patch.modelOverride;
|
|
181
|
+
}
|
|
182
|
+
if (patch.pmAgentOverride !== undefined) {
|
|
183
|
+
if (patch.pmAgentOverride !== current.pmAgentOverride)
|
|
184
|
+
changes.push("pm_agent_override");
|
|
185
|
+
current.pmAgentOverride = patch.pmAgentOverride;
|
|
186
|
+
}
|
|
187
|
+
if (patch.pmCliOverride !== undefined) {
|
|
188
|
+
if (patch.pmCliOverride !== current.pmCliOverride)
|
|
189
|
+
changes.push("pm_cli_override");
|
|
190
|
+
current.pmCliOverride = patch.pmCliOverride;
|
|
191
|
+
}
|
|
192
|
+
if (patch.pmModelOverride !== undefined) {
|
|
193
|
+
if (patch.pmModelOverride !== current.pmModelOverride)
|
|
194
|
+
changes.push("pm_model_override");
|
|
195
|
+
current.pmModelOverride = patch.pmModelOverride;
|
|
196
|
+
}
|
|
197
|
+
if (patch.reviewAgentOverride !== undefined) {
|
|
198
|
+
if (patch.reviewAgentOverride !== current.reviewAgentOverride)
|
|
199
|
+
changes.push("review_agent_override");
|
|
200
|
+
current.reviewAgentOverride = patch.reviewAgentOverride;
|
|
201
|
+
}
|
|
202
|
+
if (patch.reviewCliOverride !== undefined) {
|
|
203
|
+
if (patch.reviewCliOverride !== current.reviewCliOverride)
|
|
204
|
+
changes.push("review_cli_override");
|
|
205
|
+
current.reviewCliOverride = patch.reviewCliOverride;
|
|
206
|
+
}
|
|
207
|
+
if (patch.reviewModelOverride !== undefined) {
|
|
208
|
+
if (patch.reviewModelOverride !== current.reviewModelOverride)
|
|
209
|
+
changes.push("review_model_override");
|
|
210
|
+
current.reviewModelOverride = patch.reviewModelOverride;
|
|
211
|
+
}
|
|
212
|
+
if (patch.hotfix !== undefined) {
|
|
213
|
+
if (patch.hotfix !== current.hotfix)
|
|
214
|
+
changes.push("hotfix");
|
|
215
|
+
current.hotfix = patch.hotfix;
|
|
216
|
+
}
|
|
217
|
+
if (patch.hotfixTarget !== undefined) {
|
|
218
|
+
if (patch.hotfixTarget !== current.hotfixTarget)
|
|
219
|
+
changes.push("hotfix_target");
|
|
220
|
+
current.hotfixTarget = patch.hotfixTarget;
|
|
221
|
+
}
|
|
222
|
+
// A note is an additive activity entry, not a task field: it surfaces in the
|
|
223
|
+
// timeline (and therefore in the UI and to AI reviewers) without rewriting
|
|
224
|
+
// the body. It can accompany a status transition in the same patch. Entries
|
|
225
|
+
// are appended status-first then note, matching the core `updateStatus` path,
|
|
226
|
+
// so the timeline reads identically regardless of entry path.
|
|
227
|
+
//
|
|
228
|
+
// Newlines are collapsed to spaces (defense-in-depth): a multi-line note
|
|
229
|
+
// from the UI textarea must not inject raw line breaks into the `## Activity`
|
|
230
|
+
// list, which would break the single-line `- ts · entry` structure that
|
|
231
|
+
// consumers (e.g. DebugPanel.parseActivity) rely on.
|
|
232
|
+
const note = typeof patch.note === "string" ? patch.note.replace(/\r?\n/g, " ").trim() : "";
|
|
233
|
+
const entries = [];
|
|
234
|
+
if (changes.length)
|
|
235
|
+
entries.push(changes.join(", "));
|
|
236
|
+
if (note)
|
|
237
|
+
entries.push(`note: ${note}`);
|
|
238
|
+
if (entries.length) {
|
|
239
|
+
for (const entry of entries)
|
|
240
|
+
recordChange(current, entry);
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
current.updated_at = utcTimestamp();
|
|
244
|
+
}
|
|
245
|
+
writeFileSync(absPath, serializeTask(current));
|
|
246
|
+
// Keep the task file committed in main so a later close-out merge never
|
|
247
|
+
// aborts on an untracked or dirty copy. Fail-soft: the write itself already
|
|
248
|
+
// succeeded; a git failure only means a future merge must commit first.
|
|
249
|
+
commitTaskFile(config.root, absPath, `docs(${current.id}): update task`);
|
|
250
|
+
// Re-parse so the returned object reflects exactly what's on disk.
|
|
251
|
+
return parseTask({
|
|
252
|
+
content: readFileSync(absPath, "utf8"),
|
|
253
|
+
absPath,
|
|
254
|
+
root: config.root,
|
|
255
|
+
defaultStatus: config.defaultStatus,
|
|
256
|
+
defaultAssignee: config.defaultAssignee,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Mark the successful end of the review-to-done flow in the task's existing
|
|
261
|
+
* append-only activity log. This is deliberately separate from TaskPatch so a
|
|
262
|
+
* normal status edit cannot make an unmerged task appear in release history.
|
|
263
|
+
*/
|
|
264
|
+
export function markTaskReleased(config, absPath) {
|
|
265
|
+
if (!existsSync(absPath))
|
|
266
|
+
throw new WriteError(`Task file not found: ${absPath}`);
|
|
267
|
+
const task = parseTask({
|
|
268
|
+
content: readFileSync(absPath, "utf8"),
|
|
269
|
+
absPath,
|
|
270
|
+
root: config.root,
|
|
271
|
+
defaultStatus: config.defaultStatus,
|
|
272
|
+
defaultAssignee: config.defaultAssignee,
|
|
273
|
+
});
|
|
274
|
+
// A close-out retry after the successful marker was written must not create a
|
|
275
|
+
// second release or move the timeline entry. Checked against the task's
|
|
276
|
+
// CURRENT status, not `task.releasedAt` — that field is derived from the
|
|
277
|
+
// most recent "release:success" entry anywhere in the append-only Activity
|
|
278
|
+
// log (releasedAtFromActivity), which never clears once written. A task
|
|
279
|
+
// reopened after release (done→ready, a legitimate action — e.g. "went done
|
|
280
|
+
// with no real work, moved back to active to redo it properly") still shows
|
|
281
|
+
// a truthy releasedAt from its FIRST release forever, so the old check here
|
|
282
|
+
// silently no-op'd every subsequent close-out (#0195, 2026-08-15): main got
|
|
283
|
+
// the merge, but the task sat published-and-still-review indefinitely.
|
|
284
|
+
// `status === "done"` is only true for an actually-current release.
|
|
285
|
+
if (task.status === "done")
|
|
286
|
+
return task;
|
|
287
|
+
const previousStatus = task.status;
|
|
288
|
+
task.status = "done";
|
|
289
|
+
// A finished task is never "waiting on human input" — leaving a stale flag
|
|
290
|
+
// here (e.g. from an earlier failed review that got fixed on retry) makes a
|
|
291
|
+
// completed task show a permanent "needs input" badge for no reason (#0293
|
|
292
|
+
// follow-up: confirmed live on #0253, which released with needs_input still
|
|
293
|
+
// set from a since-resolved merge conflict retry).
|
|
294
|
+
task.needsInput = false;
|
|
295
|
+
task.needsInputReason = undefined;
|
|
296
|
+
recordChange(task, `status ${previousStatus}→done, release:success`);
|
|
297
|
+
writeFileSync(absPath, serializeTask(task));
|
|
298
|
+
commitTaskFile(config.root, absPath, `docs(${task.id}): set status done`);
|
|
299
|
+
return parseTask({
|
|
300
|
+
content: readFileSync(absPath, "utf8"),
|
|
301
|
+
absPath,
|
|
302
|
+
root: config.root,
|
|
303
|
+
defaultStatus: config.defaultStatus,
|
|
304
|
+
defaultAssignee: config.defaultAssignee,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Remove a task file. `absPath` must resolve inside the configured work dir —
|
|
309
|
+
* this mirrors the `safeRepoFile` guard and prevents deleting arbitrary repo
|
|
310
|
+
* files through the API. Throws PathGuardError when the target is outside the
|
|
311
|
+
* work dir, and WriteError when the file is already gone (callers treat the
|
|
312
|
+
* latter as an idempotent 404).
|
|
313
|
+
*/
|
|
314
|
+
export function deleteTaskFile(config, absPath) {
|
|
315
|
+
const workDir = resolve(join(config.root, config.workDir));
|
|
316
|
+
const abs = resolve(absPath);
|
|
317
|
+
if (!(abs.startsWith(workDir + sep) || abs === workDir)) {
|
|
318
|
+
throw new PathGuardError(`Refusing to delete outside work dir: ${abs}`);
|
|
319
|
+
}
|
|
320
|
+
if (!existsSync(abs)) {
|
|
321
|
+
throw new WriteError(`Task file not found: ${abs}`);
|
|
322
|
+
}
|
|
323
|
+
unlinkSync(abs);
|
|
324
|
+
// Tracked task files must not linger as staged deletions — commit the
|
|
325
|
+
// removal (fail-soft) so main stays mergeable. Untracked files need nothing.
|
|
326
|
+
const rel = relative(config.root, abs);
|
|
327
|
+
if (gitTracked(config.root, rel)) {
|
|
328
|
+
commitTaskFile(config.root, abs, `docs(${basename(abs).split("-")[0]}): delete task`);
|
|
329
|
+
}
|
|
330
|
+
return abs;
|
|
331
|
+
}
|
|
332
|
+
/** Whether git tracks a (relative) path in the given checkout. */
|
|
333
|
+
function gitTracked(root, rel) {
|
|
334
|
+
try {
|
|
335
|
+
execFileSync("git", ["ls-files", "--error-unmatch", "--", rel], {
|
|
336
|
+
cwd: root,
|
|
337
|
+
stdio: "ignore",
|
|
338
|
+
timeout: 4000,
|
|
339
|
+
});
|
|
340
|
+
return true;
|
|
341
|
+
}
|
|
342
|
+
catch {
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.built-in-interactive-hint[data-v-dc10e962]{border:1px dashed var(--border-bright);color:var(--txt-secondary);border-radius:8px;align-items:center;gap:8px;padding:9px 12px;font-size:12.5px;line-height:1.4;display:flex}.built-in-interactive-dot[data-v-dc10e962]{background:var(--green);width:8px;height:8px;box-shadow:0 0 8px var(--green);border-radius:50%;flex:none}.built-in-last-run[data-v-dc10e962]{color:var(--txt-faint);font-family:JetBrains Mono,monospace;font-size:11px}.built-in-status-field[data-v-dc10e962]{grid-column:1/-1}.built-in-status[data-v-dc10e962]{border-radius:4px;margin-top:4px;padding:8px 12px;font-size:12px;line-height:1.3}.built-in-status.success[data-v-dc10e962]{color:var(--green);background:#22c55e1a}.built-in-status.error[data-v-dc10e962]{color:var(--red);background:#ef44441a}.playground[data-v-20dd17ec]{gap:16px;height:100%;min-height:0;padding:16px 18px 20px;display:flex}.playground-sidebar[data-v-20dd17ec]{flex-direction:column;flex:1 1 0;gap:10px;min-width:0;min-height:0;display:flex}.playground-sidebar-head[data-v-20dd17ec]{justify-content:space-between;align-items:center;gap:8px;padding-bottom:2px;display:flex}.playground-filters[data-v-20dd17ec]{flex-direction:column;flex:none;gap:8px;display:flex}.playground-filters input[data-v-20dd17ec],.playground-filters select[data-v-20dd17ec]{border:1px solid var(--border);background:var(--panel-solid);width:100%;color:var(--txt);font:12px var(--font-sans);border-radius:9px;outline:0;padding:7px 10px;transition:all .15s}.playground-filters input[data-v-20dd17ec]:focus,.playground-filters select[data-v-20dd17ec]:focus{border-color:var(--border-bright)}.playground-filters input[data-v-20dd17ec]::placeholder{color:var(--txt-faint)}.playground-filter-row[data-v-20dd17ec]{gap:8px;display:flex}.playground-filter-row select[data-v-20dd17ec]{flex:1;min-width:0}.playground-list[data-v-20dd17ec]{flex-direction:column;flex:1;gap:10px;min-height:0;padding-right:4px;display:flex;overflow-y:auto}.playground-no-match[data-v-20dd17ec]{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.playground-filter-clear[data-v-20dd17ec]{border:1px solid var(--border);background:var(--panel);color:var(--txt-dim);font:500 10.5px var(--font-sans);cursor:pointer;border-radius:8px;padding:4px 10px;transition:all .15s}.playground-filter-clear[data-v-20dd17ec]:hover{border-color:var(--border-bright);color:var(--txt)}.playground-error[data-v-20dd17ec],.playground-loading[data-v-20dd17ec]{color:var(--txt-dim);padding:4px 2px;font-size:11.5px}.playground-provider-group[data-v-20dd17ec]{flex-direction:column;gap:8px;display:flex}.playground-provider-label[data-v-20dd17ec]{letter-spacing:.08em;text-transform:uppercase;color:var(--txt-faint);margin:4px 2px 0;font:600 10px JetBrains Mono,monospace}.playground-provider-error[data-v-20dd17ec]{color:var(--amber);padding:0 2px;font-size:11px}.playground-skeletons[data-v-20dd17ec]{flex-direction:column;gap:8px;display:flex}.playground-skeleton[data-v-20dd17ec]{border:1px solid var(--border);background:var(--panel);border-radius:11px;flex-direction:column;gap:6px;padding:11px;display:flex}.playground-skeleton-line[data-v-20dd17ec]{background:linear-gradient(90deg, var(--panel) 0%, var(--border) 50%, var(--panel) 100%);background-size:200% 100%;border-radius:5px;height:9px;animation:1.4s ease-in-out infinite playground-shimmer-20dd17ec}.playground-skeleton-line.w-70[data-v-20dd17ec]{width:70%}.playground-skeleton-line.w-90[data-v-20dd17ec]{width:90%}.playground-skeleton-line.w-45[data-v-20dd17ec]{width:45%}.playground-model-card[data-v-20dd17ec]{text-align:left;border:1px solid var(--border);background:var(--panel);color:var(--txt);cursor:pointer;border-radius:11px;flex-direction:column;gap:4px;padding:10px 11px;transition:all .15s;display:flex}.playground-model-card[data-v-20dd17ec]:hover{border-color:var(--border-bright)}.playground-model-card[data-v-20dd17ec]:disabled{opacity:.5;cursor:default}.playground-model-card.active[data-v-20dd17ec]{border-color:var(--cyan);box-shadow:var(--card-glow)}.playground-model-name[data-v-20dd17ec]{font-size:12.5px;font-weight:600}.playground-model-reason[data-v-20dd17ec]{color:var(--txt-dim);font-size:11px;line-height:1.4}.playground-model-meta[data-v-20dd17ec]{color:var(--txt-faint);gap:10px;font:500 10px JetBrains Mono,monospace;display:flex}.playground-chat[data-v-20dd17ec]{border:1px solid var(--border);background:var(--panel-solid);border-radius:14px;flex-direction:column;flex:1 1 0;min-width:0;min-height:0;display:flex;overflow:hidden}.playground-chat-head[data-v-20dd17ec]{border-bottom:1px solid var(--border);background:var(--topbar-bg);align-items:center;gap:9px;padding:12px 14px;display:flex}.playground-active-dot[data-v-20dd17ec]{background:var(--green);width:8px;height:8px;box-shadow:0 0 8px var(--green);border-radius:50%;flex:none}.playground-active-info[data-v-20dd17ec]{flex-direction:column;gap:2px;min-width:0;display:flex}.playground-active-info strong[data-v-20dd17ec]{letter-spacing:-.01em;text-overflow:ellipsis;white-space:nowrap;font-size:13px;overflow:hidden}.playground-active-info span[data-v-20dd17ec]{color:var(--txt-dim);font:500 10px JetBrains Mono,monospace}.playground-clear[data-v-20dd17ec]{border:1px solid var(--border);background:var(--panel);color:var(--txt-dim);font:500 10.5px var(--font-sans);cursor:pointer;border-radius:8px;flex:none;margin-left:auto;padding:5px 11px;transition:all .15s}.playground-clear[data-v-20dd17ec]:hover{border-color:var(--border-bright);color:var(--txt)}.playground-clear[data-v-20dd17ec]:disabled{opacity:.5;cursor:default}.playground-log[data-v-20dd17ec]{flex-direction:column;flex:1;gap:11px;min-height:0;padding:16px;display:flex;overflow-y:auto}.playground-empty[data-v-20dd17ec]{color:var(--txt-dim);flex:1;place-items:center;padding:40px 16px;font-size:12.5px;display:grid}.playground-welcome[data-v-20dd17ec]{text-align:center;color:var(--txt-dim);margin:auto 0;padding:22px 12px}.playground-welcome strong[data-v-20dd17ec]{color:var(--txt);margin-bottom:6px;font-size:14px;display:block}.playground-welcome p[data-v-20dd17ec]{max-width:320px;margin:0 auto;font-size:11.5px;line-height:1.55}.playground-starters[data-v-20dd17ec]{flex-wrap:wrap;justify-content:center;gap:7px;margin-top:14px;display:flex}.playground-starters button[data-v-20dd17ec]{border:1px solid var(--border);background:var(--panel);color:var(--txt-dim);font:500 10.5px var(--font-sans);cursor:pointer;border-radius:999px;padding:6px 10px}.playground-starters button[data-v-20dd17ec]:hover{border-color:var(--border-bright);color:var(--txt)}.playground-row[data-v-20dd17ec]{display:flex}.playground-row-user[data-v-20dd17ec]{justify-content:flex-end}.playground-bubble[data-v-20dd17ec]{overflow-wrap:anywhere;border-radius:13px;max-width:84%;padding:9px 11px;font-size:12.5px;line-height:1.55}.playground-bubble-user[data-v-20dd17ec]{color:var(--btn-primary-color);background:var(--btn-primary-bg);border:1px solid var(--border-bright);border-bottom-right-radius:4px}.playground-bubble-assistant[data-v-20dd17ec]{color:var(--txt);background:var(--panel);border:1px solid var(--border);border-bottom-left-radius:4px}.playground-markdown[data-v-20dd17ec] p{margin:0 0 7px}.playground-markdown[data-v-20dd17ec] p:last-child{margin-bottom:0}.playground-markdown[data-v-20dd17ec] code{background:var(--md-body-bg);border-radius:4px;padding:1px 4px;font:10.5px JetBrains Mono,monospace}.playground-markdown[data-v-20dd17ec] pre{background:var(--md-body-bg);border-radius:7px;margin:7px 0;padding:8px;overflow:auto}.playground-markdown[data-v-20dd17ec] pre code{background:0 0;padding:0}.playground-send-error[data-v-20dd17ec]{color:var(--red);align-self:center;font-size:11px}.playground-thinking[data-v-20dd17ec]{border:1px solid var(--border);background:var(--panel);border-radius:13px;align-self:flex-start;gap:4px;padding:9px 12px;display:flex}.playground-thinking span[data-v-20dd17ec]{background:var(--txt-faint);border-radius:50%;width:5px;height:5px;animation:1.2s infinite playground-bounce-20dd17ec}.playground-thinking span[data-v-20dd17ec]:nth-child(2){animation-delay:.15s}.playground-thinking span[data-v-20dd17ec]:nth-child(3){animation-delay:.3s}.playground-compose[data-v-20dd17ec]{border:1px solid var(--border);background:var(--panel);border-radius:13px;align-items:flex-end;gap:8px;margin:12px;padding:8px 9px 8px 12px;display:flex}.playground-compose[data-v-20dd17ec]:focus-within{border-color:var(--border-bright);box-shadow:0 0 0 3px var(--cyan-dim)}.playground-compose textarea[data-v-20dd17ec]{resize:none;min-height:24px;max-height:120px;color:var(--txt);font:12.5px/1.55 var(--font-sans);background:0 0;border:0;outline:0;flex:1;overflow-y:auto}.playground-compose textarea[data-v-20dd17ec]::placeholder{color:var(--txt-faint)}.playground-compose textarea[data-v-20dd17ec]:disabled{opacity:.6}.playground-compose button[data-v-20dd17ec]{background:var(--btn-primary-bg);color:var(--cyan);font:600 11.5px var(--font-sans);cursor:pointer;border:0;border-radius:9px;flex:none;padding:7px 14px}.playground-compose button[data-v-20dd17ec]:disabled{opacity:.4;cursor:default}@keyframes playground-bounce-20dd17ec{0%,70%,to{opacity:.4;transform:translateY(0)}35%{opacity:1;transform:translateY(-3px)}}@keyframes playground-shimmer-20dd17ec{0%{background-position:200% 0}to{background-position:-200% 0}}@media (width<=860px){.playground[data-v-20dd17ec]{flex-direction:column;height:auto}.playground-sidebar[data-v-20dd17ec]{max-height:320px}.playground-chat[data-v-20dd17ec]{width:100%;min-height:420px}}@media (prefers-reduced-motion:reduce){.playground-thinking span[data-v-20dd17ec],.playground-skeleton-line[data-v-20dd17ec]{animation:none}}.mp-panel[data-v-70f2ebda]{margin-bottom:16px;padding:0 18px 14px}.mp-row[data-v-70f2ebda]{border-top:1px solid var(--border);padding:14px 0 12px}.mp-row.first[data-v-70f2ebda]{border-top:0;padding-top:6px}.mp-row-head[data-v-70f2ebda]{align-items:center;gap:10px;display:flex}.mp-row-title[data-v-70f2ebda]{align-items:center;gap:8px;min-width:0;display:flex}.mp-pill[data-v-70f2ebda]{letter-spacing:.07em;text-transform:uppercase;border:1px solid var(--border);color:var(--txt-dim);border-radius:999px;flex:none;padding:2px 7px;font:600 9px JetBrains Mono,monospace}.mp-pill.pill-live[data-v-70f2ebda]{color:var(--green);border-color:color-mix(in srgb, var(--green) 35%, transparent)}.mp-dash-link[data-v-70f2ebda]{color:var(--cyan);flex:none;margin-left:auto;font:500 10.5px JetBrains Mono,monospace;text-decoration:none}.mp-dash-link[data-v-70f2ebda]:hover{text-decoration:underline}.mp-note[data-v-70f2ebda]{color:var(--txt-dim);margin-top:2px;font-size:11px;line-height:1.5}.mp-key-form[data-v-70f2ebda]{flex-wrap:wrap;align-items:center;gap:8px;margin-top:10px;display:flex}.mp-key-form input[data-v-70f2ebda]{border:1px solid var(--border);background:var(--panel);min-width:0;color:var(--txt);font:12px var(--font-sans);border-radius:9px;outline:0;flex:220px;padding:7px 10px;transition:all .15s}.mp-key-form input[data-v-70f2ebda]:focus{border-color:var(--border-bright)}.mp-key-hint[data-v-70f2ebda]{color:var(--txt-faint);flex-basis:100%;font-size:10.5px}.mp-key-hint code[data-v-70f2ebda],.mp-error code[data-v-70f2ebda]{font:10px JetBrains Mono,monospace}.mp-data[data-v-70f2ebda]{flex-direction:column;gap:10px;margin-top:12px;display:flex}.mp-stat-hero[data-v-70f2ebda]{border:1px solid var(--border);background:var(--panel);border-radius:11px;align-items:baseline;gap:10px;padding:10px 12px;display:flex}.mp-stat-hero .mp-stat-value[data-v-70f2ebda]{font-size:20px}.mp-stat-sub[data-v-70f2ebda]{color:var(--txt-faint);font-size:10.5px}.mp-stat-row[data-v-70f2ebda]{flex-wrap:wrap;gap:8px;display:flex}.mp-stat[data-v-70f2ebda]{border:1px solid var(--border);background:var(--panel);border-radius:11px;flex-direction:column;gap:2px;min-width:90px;padding:8px 11px;display:flex}.mp-stat-value[data-v-70f2ebda]{color:var(--txt);font:600 13px JetBrains Mono,monospace}.mp-stat-value.sm[data-v-70f2ebda]{font-size:12.5px}.mp-stat-label[data-v-70f2ebda]{letter-spacing:.06em;text-transform:uppercase;color:var(--txt-faint);font:500 9.5px JetBrains Mono,monospace}.mp-window[data-v-70f2ebda]{border:1px solid var(--border);background:var(--panel);border-radius:11px;flex-direction:column;gap:6px;padding:10px 12px;display:flex}.mp-window-head[data-v-70f2ebda]{flex-wrap:wrap;justify-content:space-between;align-items:baseline;gap:8px;display:flex}.mp-window-pct[data-v-70f2ebda]{color:var(--txt-dim);font:500 10.5px JetBrains Mono,monospace}.mp-bar[data-v-70f2ebda]{background:var(--border);border-radius:999px;height:5px;overflow:hidden}.mp-bar-fill[data-v-70f2ebda]{background:var(--cyan);border-radius:999px;height:100%;transition:width .3s}.mp-window-reset[data-v-70f2ebda]{color:var(--txt-faint);font-size:10px}.mp-actions[data-v-70f2ebda]{gap:6px;margin-top:10px;display:flex}.mp-loading[data-v-70f2ebda]{color:var(--txt-dim);margin-top:10px;font-size:11.5px}.mp-error[data-v-70f2ebda]{color:var(--red);margin-top:8px;font-size:11.5px}.mp-error .mp-retry[data-v-70f2ebda]{border:1px solid var(--border);background:var(--panel);color:var(--txt-dim);font:500 10.5px var(--font-sans);cursor:pointer;border-radius:7px;margin-left:6px;padding:2px 8px}.mp-error .mp-retry[data-v-70f2ebda]:hover{color:var(--txt);border-color:var(--border-bright)}.mp-part-error[data-v-70f2ebda]{color:var(--amber);font-size:11px}.mp-part-error a[data-v-70f2ebda]{color:inherit}@media (prefers-reduced-motion:reduce){.mp-bar-fill[data-v-70f2ebda]{transition:none}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{$ as e,B as t,C as n,D as r,E as i,G as a,I as o,O as s,S as c,St as l,Tt as u,U as d,V as f,_ as p,b as m,bt as h,d as g,dt as _,f as v,h as y,i as b,it as x,m as S,p as C,pt as w,r as T,rt as E,w as D,wt as O,x as k}from"./vendor-vue-CobgyEJp.js";import{a as A,i as ee,t as j}from"./button-lbikqSph.js";import{A as M,D as N,E as te,I as P,L as F,N as I,O as L,S as R,T as ne,c as re,d as z,f as ie,g as ae,k as oe,l as se,m as B,n as V,p as ce,r as le,s as H,u as U,w as W,x as ue,y as de}from"./index-BOQ-ust6.js";var G={class:`agent-head`},fe={class:`agent-title`},pe={class:`agent-name`},me={class:`agent-body`},he={class:`agent-field`},ge={key:0,class:`agent-field`},_e={key:1,class:`agent-field`},ve={class:`agent-field`},ye={class:`agent-test-actions`},be={key:0,class:`built-in-last-run`},xe={key:2,class:`agent-field built-in-status-field`},Se={key:0,class:`built-in-status success`},Ce={key:1,class:`built-in-status error`},K=I(s({__name:`BuiltInAgentCard`,props:{agent:{},interactive:{type:Boolean}},setup(t){let a=t,o=P(),s=m(()=>o.agentsMeta.clis[0]??`opencode`),c=m(()=>o.agentsMeta.models[0]??`default`),f=w({enabled:!1,schedule:`manual`,cli:``,model:``});e(()=>o.data?.builtInAgents,e=>{let t=e?.[a.agent];t&&(f.value={enabled:t.enabled??!1,schedule:t.schedule??`manual`,lastRunAt:t.lastRunAt,cli:t.cli||s.value,model:t.model||c.value})},{immediate:!0,deep:!0});let p=m(()=>o.agentsMeta.clis??[]),g=o.modelsFor,_=w(!1),v=w(``),y=w(``),b=m(()=>a.agent===`debugger`?{name:`Debugger Agent`,description:`Paste a bug, stack trace, or error and get a clear diagnosis — the root cause plus a suggested fix. Chat with him from his floating head next to Ross and the CTO.`,icon:`🐞`}:a.agent===`tech-debt`?{name:`Tech Debt Agent`,description:`Scans your repository for technical debt patterns including outdated dependencies, code duplication, high-complexity files, unused code, and deprecated APIs. Creates tasks in your inbox for each issue found.`,icon:`🔧`}:a.agent===`performance`?{name:`Performance Agent`,description:`Keeps your app fast by scanning for performance issues like slow functions, blocking operations, deeply nested loops, unbounded memory growth, and duplicate computations. Creates tasks in your inbox for each issue found.`,icon:`⚡`}:a.agent===`architect`?{name:`Architect Agent`,description:`Analyzes your codebase architecture — detects tight coupling, missing abstractions, scalability risks, and over-engineering. Generates a detailed markdown report saved to docs/agents/Architect/ with recommendations.`,icon:`🏛`}:a.agent===`design`?{name:`Design Agent`,description:`Reviews your web UI's quality — layout, styling consistency, accessibility, and interaction flows. Flags UI bugs and UX friction and proposes concrete fixes and design improvements, saved as a markdown report to docs/agents/Design/.`,icon:`🎨`}:a.agent===`docs-debt`?{name:`Docs Debt Agent`,description:`Checks that AGENTS.md, docs/, and user-docs/ still tell the truth about the code — verifying file paths, symbols, scripts, and stated constraints against the real repo. Applies small mechanical fixes directly and bundles anything needing a human decision into one task.`,icon:`📖`}:null),x=m(()=>f.value.lastRunAt?new Date(f.value.lastRunAt).toLocaleDateString(`en-US`,{month:`short`,day:`numeric`,hour:`2-digit`,minute:`2-digit`}):`Never`),S=m(()=>f.value.cli||s.value),C=m(()=>f.value.model||c.value);async function T(){try{let e=o.data?.builtInAgents||{},t={enabled:f.value.enabled,schedule:f.value.schedule};f.value.lastRunAt&&(t.lastRunAt=f.value.lastRunAt),f.value.cli&&(t.cli=f.value.cli),f.value.model&&(t.model=f.value.model),await A(`/api/config`,ee(`PATCH`,{builtInAgents:{...e,[a.agent]:t}}));let n=await A(`/api/config`);o.data=n.config}catch(e){v.value=e instanceof Error?e.message:`Failed to save configuration`}}function O(e){f.value.enabled=e,T()}function M(e){f.value.cli=e,T()}function N(e){f.value.model=e,T()}async function te(e){e&&(e===`daily`||e===`weekly`||e===`manual`)&&(f.value.schedule=e,await T())}async function F(){if(!_.value){_.value=!0,v.value=``,y.value=``;try{let e=await A(`/api/agents/built-in/${a.agent}/run`,ee(`POST`,{}));if(e.ok){if(f.value.lastRunAt=new Date().toISOString(),e.failed&&e.failed>0)v.value=`${e.taskCount} task(s) created, ${e.failed} failed — ${(e.errors??[]).join(`; `)||`unknown write error`}`;else if(a.agent===`design`)y.value=`Review complete — ${e.findingsFound??0} design finding(s) found (${e.scannedFiles??0} files scanned). Report saved to docs/agents/Design/.`;else if(a.agent===`architect`)y.value=`Review complete — ${e.issuesFound??0} architecture issue(s) found (${e.scannedFiles??0} files scanned). Report saved to docs/agents/Architect/.`;else if(a.agent===`docs-debt`){let t=e.trivialFixesApplied??0,n=t>0?`applied ${t} small fix(es); `:``;y.value=(e.findingsFound??0)>0?`Check complete — ${n}${e.findingsFound??0} claim(s) need a human decision, bundled into one task (${e.scannedFiles??0} docs scanned).`:`Check complete — ${n}docs match the code (${e.scannedFiles??0} docs scanned).`}else if(e.taskCount>0){let t=a.agent===`performance`?`performance`:`tech debt`;y.value=`Scan complete — ${e.taskCount} ${t} task(s) created from ${e.issuesFound??0} issue(s).`}else{let t=a.agent===`performance`?`performance`:`tech debt`;y.value=`Scan complete — no ${t} issues found (${e.scannedFiles??0} files scanned).`}await T()}else v.value=`Failed to run agent`}catch(e){v.value=e instanceof Error?e.message:`Failed to run agent`}finally{_.value=!1}}}return(e,a)=>b.value?(d(),D(`div`,{key:0,class:l([`agent-card`,{off:!f.value.enabled}])},[k(`div`,G,[k(`div`,fe,[a[0]||=k(`span`,{class:`agent-dot`},null,-1),k(`span`,pe,u(b.value.icon)+` `+u(b.value.name),1),a[1]||=k(`span`,{class:`agent-badge`},`built-in`,-1)]),r(V,{checked:f.value.enabled,"onUpdate:checked":O},null,8,[`checked`])]),k(`div`,me,[k(`div`,he,[a[2]||=k(`label`,null,`Coding agent + Model`,-1),r(H,{"cli-options":p.value,"model-options":h(g)(S.value,C.value),cli:S.value,model:C.value,"memory-key":`builtin:`+t.agent,"onUpdate:cli":M,"onUpdate:model":N},null,8,[`cli-options`,`model-options`,`cli`,`model`,`memory-key`])]),t.interactive?(d(),D(`div`,_e,[...a[7]||=[k(`label`,null,`Interaction`,-1),k(`div`,{class:`built-in-interactive-hint`},[k(`span`,{class:`built-in-interactive-dot`}),i(` Chat from floating head `)],-1)]])):(d(),D(`div`,ge,[a[6]||=k(`label`,null,`Run schedule`,-1),r(ce,{"model-value":f.value.schedule,"onUpdate:modelValue":te},{default:E(()=>[r(U,{class:`h-[34px] w-full rounded-[9px] px-[11px]`},{default:E(()=>[r(se)]),_:1}),r(ie,{position:`popper`},{default:E(()=>[r(re,{class:`min-w-[var(--radix-select-trigger-width)]`},{default:E(()=>[r(z,{value:`daily`},{default:E(()=>[...a[3]||=[i(`Daily`,-1)]]),_:1}),r(z,{value:`weekly`},{default:E(()=>[...a[4]||=[i(`Weekly`,-1)]]),_:1}),r(z,{value:`manual`},{default:E(()=>[...a[5]||=[i(`Manual only`,-1)]]),_:1})]),_:1})]),_:1})]),_:1},8,[`model-value`])])),k(`div`,ve,[a[8]||=k(`label`,null,`Actions`,-1),k(`div`,ye,[r(j,{variant:`outline`,size:`sm`,disabled:_.value||!f.value.enabled,onClick:F},{default:E(()=>[i(u(_.value?`Running…`:`Run now`),1)]),_:1},8,[`disabled`]),f.value.lastRunAt?(d(),D(`span`,be,` Last: `+u(x.value),1)):n(``,!0)])]),y.value||v.value?(d(),D(`div`,xe,[y.value?(d(),D(`div`,Se,u(y.value),1)):n(``,!0),v.value?(d(),D(`div`,Ce,u(v.value),1)):n(``,!0)])):n(``,!0)])],2)):n(``,!0)}}),[[`__scopeId`,`data-v-dc10e962`]]),we={class:`playground`},Te=[`aria-busy`],Ee={class:`playground-sidebar-head`},De={class:`playground-filters`},Oe={class:`playground-filter-row`},ke=[`value`],q=[`value`],J={key:0,class:`playground-error`},Ae={class:`playground-list`},Y={key:0,class:`playground-skeletons`,"aria-hidden":`true`},X={key:1,class:`playground-loading playground-no-match`},je={key:2,class:`playground-loading`},Me={key:0,class:`playground-provider-group`},Ne={class:`playground-provider-label`},Pe={key:0,class:`playground-provider-error`},Fe=[`disabled`,`onClick`],Ie={class:`playground-model-name`},Le={class:`playground-model-reason`},Re={class:`playground-model-meta`},ze={key:0},Be={class:`playground-chat`},Ve={class:`playground-chat-head`},Z={class:`playground-active-info`},Q=[`disabled`],He=[`aria-label`],$={key:0,class:`playground-welcome`},Ue={class:`playground-starters`},We=[`onClick`],Ge=[`innerHTML`],Ke={key:1},qe={key:1,class:`playground-thinking`,"aria-label":`Model is responding`},Je={key:2,class:`playground-send-error`},Ye=[`disabled`,`placeholder`,`aria-label`],Xe=[`disabled`],Ze={key:1,class:`playground-empty`},Qe={key:0},$e=I(s({__name:`ModelPlaygroundPanel`,setup(e){let s=[`What's this repo about?`,`Explain this codebase`,`What would you improve here first?`],c=w([]),f=w(!1),_=w(``),b=w(!1),S=w(null),C=w([]),T=w(``),O=w(!1),M=w(``),N=w(null),te=w(null),P=m(()=>c.value.flatMap(e=>e.models.map(t=>({...t,providerLabel:e.label})))),F=w(``),I=w(``),L=w(``),ne=[.5,1,2,5,10];function re(e){let t=F.value.trim().toLowerCase();if(t&&!e.name.toLowerCase().includes(t))return!1;let n=L.value===``?null:Number(L.value);if(n!=null){let t=e.inputPricePerM??e.outputPricePerM;if(t!=null&&t>n)return!1}return!0}let z=m(()=>c.value.filter(e=>!I.value||e.id===I.value).map(e=>({...e,models:e.models.filter(re)})).filter(e=>e.models.length>0||e.error)),ie=m(()=>z.value.reduce((e,t)=>e+t.models.length,0)),ae=m(()=>F.value.trim()!==``||I.value!==``||L.value!==``);function oe(){F.value=``,I.value=``,L.value=``}function se(e){return e==null?`—`:e<1?`$${e.toFixed(3)}`:`$${e.toFixed(2)}`}async function B(e=!1){f.value=!0,_.value=``;try{let t=await A(`/api/playground/models${e?`?refresh=1`:``}`);c.value=t.providers;let n=P.value;if(S.value){let e=n.find(e=>e.runId===S.value?.runId);S.value=e??S.value}else n.length&&(S.value=n[0])}catch(e){_.value=e instanceof Error?e.message:`Could not load the model catalog.`}finally{f.value=!1,b.value=!0}}function V(e){O.value||S.value?.runId===e.runId||(S.value=e,C.value=[],M.value=``,T.value=``)}function ce(){O.value||(C.value=[],M.value=``,T.value=``)}function le(){o(()=>{N.value&&(N.value.scrollTop=N.value.scrollHeight)})}async function H(e){let t=(e??T.value).trim();if(!t||O.value||!S.value)return;let n=S.value;C.value=[...C.value,{role:`user`,text:t}],T.value=``,M.value=``,O.value=!0,le();try{let e=await A(`/api/playground/chat`,ee(`POST`,{runId:n.runId,messages:C.value}));C.value=[...C.value,{role:`assistant`,text:e.text}]}catch(e){M.value=e instanceof Error?e.message:`The model did not respond.`}finally{O.value=!1,le()}}function U(e){e.key!==`Enter`||e.shiftKey||e.isComposing||(e.preventDefault(),H())}return t(()=>{B()}),(e,t)=>(d(),D(`div`,we,[k(`aside`,{class:`playground-sidebar`,"aria-label":`Models worth trying`,"aria-busy":f.value},[k(`div`,Ee,[t[7]||=k(`span`,{class:`sec-label`},[k(`span`,{class:`live-dot`}),i(`Models worth trying`)],-1),r(j,{variant:`outline`,size:`sm`,disabled:f.value,onClick:t[0]||=e=>B(!0)},{default:E(()=>[i(u(f.value?`Refreshing…`:`Refresh`),1)]),_:1},8,[`disabled`])]),k(`div`,De,[x(k(`input`,{"onUpdate:modelValue":t[1]||=e=>F.value=e,type:`search`,class:`playground-search`,placeholder:`Search models…`,"aria-label":`Search models by name`},null,512),[[v,F.value]]),k(`div`,Oe,[x(k(`select`,{"onUpdate:modelValue":t[2]||=e=>I.value=e,class:`playground-provider-select`,"aria-label":`Filter by provider`},[t[8]||=k(`option`,{value:``},`All providers`,-1),(d(!0),D(p,null,a(c.value,e=>(d(),D(`option`,{key:e.id,value:e.id},u(e.label),9,ke))),128))],512),[[g,I.value]]),x(k(`select`,{"onUpdate:modelValue":t[3]||=e=>L.value=e,class:`playground-cost-select`,"aria-label":`Filter by maximum token cost`},[t[9]||=k(`option`,{value:``},`Any cost`,-1),(d(),D(p,null,a(ne,e=>k(`option`,{key:e,value:String(e)},` ≤ `+u(se(e))+` / 1M `,9,q)),64))],512),[[g,L.value]])])]),_.value?(d(),D(`div`,J,u(_.value),1)):n(``,!0),k(`div`,Ae,[f.value&&!P.value.length?(d(),D(`div`,Y,[(d(),D(p,null,a(3,e=>k(`div`,{key:e,class:`playground-skeleton`},[...t[10]||=[k(`div`,{class:`playground-skeleton-line w-70`},null,-1),k(`div`,{class:`playground-skeleton-line w-90`},null,-1),k(`div`,{class:`playground-skeleton-line w-45`},null,-1)]])),64))])):b.value&&!_.value&&P.value.length&&!ie.value?(d(),D(`div`,X,[t[11]||=i(` No models match your filters. `,-1),ae.value?(d(),D(`button`,{key:0,type:`button`,class:`playground-filter-clear`,onClick:oe},` Clear filters `)):n(``,!0)])):b.value&&!P.value.length&&!_.value?(d(),D(`div`,je,` No models available right now. `)):n(``,!0),(d(!0),D(p,null,a(z.value,e=>(d(),D(p,{key:e.id},[e.models.length||e.error?(d(),D(`div`,Me,[k(`div`,Ne,u(e.label),1),e.error?(d(),D(`div`,Pe,u(e.error),1)):n(``,!0),(d(!0),D(p,null,a(e.models,t=>(d(),D(`button`,{key:t.runId,type:`button`,class:l([`playground-model-card`,{active:S.value?.runId===t.runId}]),disabled:O.value&&S.value?.runId!==t.runId,onClick:n=>V({...t,providerLabel:e.label})},[k(`div`,Ie,u(t.name),1),k(`div`,Le,u(t.reason),1),k(`div`,Re,[k(`span`,null,u(se(t.inputPricePerM))+` / `+u(se(t.outputPricePerM))+` per 1M`,1),t.contextWindow?(d(),D(`span`,ze,u(h(R)(t.contextWindow))+` ctx`,1)):n(``,!0)])],10,Fe))),128))])):n(``,!0)],64))),128))])],8,Te),k(`section`,Be,[S.value?(d(),D(p,{key:0},[k(`header`,Ve,[t[12]||=k(`span`,{class:`playground-active-dot`,"aria-hidden":`true`},null,-1),k(`div`,Z,[k(`strong`,null,u(S.value.name),1),k(`span`,null,u(S.value.providerLabel)+` · active model`,1)]),C.value.length?(d(),D(`button`,{key:0,type:`button`,class:`playground-clear`,disabled:O.value,"aria-label":`Clear conversation`,onClick:t[4]||=e=>ce()},` Clear `,8,Q)):n(``,!0)]),k(`div`,{ref_key:`log`,ref:N,class:`playground-log`,role:`log`,"aria-live":`polite`,"aria-label":`Conversation with ${S.value.name}`},[C.value.length?n(``,!0):(d(),D(`div`,$,[k(`strong`,null,`Try `+u(S.value.name),1),k(`p`,null,u(S.value.reason),1),k(`div`,Ue,[(d(),D(p,null,a(s,e=>k(`button`,{key:e,type:`button`,onClick:t=>H(e)},u(e),9,We)),64))])])),(d(!0),D(p,null,a(C.value,(e,t)=>(d(),D(`div`,{key:t,class:l([`playground-row`,`playground-row-${e.role}`])},[k(`div`,{class:l([`playground-bubble`,`playground-bubble-${e.role}`])},[e.role===`assistant`?(d(),D(`div`,{key:0,class:`playground-markdown`,innerHTML:h(W)(e.text)},null,8,Ge)):(d(),D(`span`,Ke,u(e.text),1))],2)],2))),128)),O.value?(d(),D(`div`,qe,[...t[13]||=[k(`span`,null,null,-1),k(`span`,null,null,-1),k(`span`,null,null,-1)]])):n(``,!0),M.value?(d(),D(`div`,Je,u(M.value),1)):n(``,!0)],8,He),k(`form`,{class:`playground-compose`,onSubmit:t[6]||=y(e=>H(),[`prevent`])},[x(k(`textarea`,{ref_key:`draftTextarea`,ref:te,"onUpdate:modelValue":t[5]||=e=>T.value=e,rows:`1`,disabled:O.value,placeholder:`Message ${S.value.name}…`,"aria-label":`Message ${S.value.name}`,onKeydown:U},null,40,Ye),[[v,T.value]]),k(`button`,{type:`submit`,disabled:!T.value.trim()||O.value,"aria-label":`Send message`},` Send `,8,Xe)],32)],64)):(d(),D(`div`,Ze,[f.value?n(``,!0):(d(),D(`p`,Qe,`Pick a model from the sidebar to start chatting.`))]))])]))}}),[[`__scopeId`,`data-v-20dd17ec`]]),et={key:0,class:`mp-error`},tt={key:1,class:`agent-empty`},nt={class:`mp-row-head`},rt={class:`mp-row-title`},it={class:`agent-name`},at=[`href`],ot={class:`mp-note`},st={key:0,class:`mp-key-form`},ct=[`onUpdate:modelValue`,`placeholder`,`aria-label`,`onKeyup`],lt={key:1,class:`mp-error`},ut={key:0,class:`mp-loading`},dt={key:1,class:`mp-error`},ft=[`onClick`],pt={key:2,class:`mp-data`},mt={key:0,class:`mp-stat mp-stat-hero`},ht={class:`mp-stat-value`},gt={key:0,class:`mp-stat-sub`},_t={key:1,class:`mp-part-error`},vt={key:2,class:`mp-stat-row`},yt={class:`mp-stat`},bt={class:`mp-stat-value sm`},xt={class:`mp-stat`},St={class:`mp-stat-value sm`},Ct={class:`mp-stat`},wt={class:`mp-stat-value sm`},Tt={key:0,class:`mp-stat`},Et={class:`mp-stat-value sm`},Dt={key:3,class:`mp-part-error`},Ot={key:3,class:`mp-data`},kt={class:`mp-window-head`},At={class:`mp-stat-label`},jt={class:`mp-window-pct`},Mt=[`aria-valuenow`,`aria-label`],Nt={key:1,class:`mp-window-reset`},Pt={key:1,class:`mp-part-error`},Ft=[`href`],It={key:2,class:`mp-part-error`},Lt={key:4,class:`mp-actions`},Rt=I(s({__name:`ModelProvidersPanel`,setup(e){let o=w([]),s=w(!1),f=w(``),m=_({}),h=_({}),g=_({}),y=_({}),b=_({});function C(e){return m[e]||(m[e]={usage:null,loading:!1,error:``}),m[e]}async function T(){s.value=!0,f.value=``;try{let e=await A(`/api/model-providers`);o.value=e.providers;for(let t of e.providers)t.kind===`live`&&t.hasKey&&!m[t.id]?.usage&&M(t.id)}catch(e){f.value=e instanceof Error?e.message:`Could not load the provider list.`}finally{s.value=!1}}async function M(e){let t=C(e);if(!t.loading){t.loading=!0,t.error=``;try{t.usage=await A(`/api/model-providers/${e}/usage`)}catch(e){t.error=e instanceof Error?e.message:`Could not load usage.`}finally{t.loading=!1}}}async function N(e){if(!g[e.id]){g[e.id]=!0,b[e.id]=``;try{let t=await A(`/api/model-providers/${e.id}/key`,ee(`POST`,{key:h[e.id]??``}));e.hasKey=t.hasKey,h[e.id]=``,y[e.id]=!1,t.hasKey?M(e.id):C(e.id).usage=null}catch(t){b[e.id]=t instanceof Error?t.message:`Could not save the key.`}finally{g[e.id]=!1}}}function te(e){h[e.id]=``,N(e)}function P(e){return e==null?`—`:`$${e.toLocaleString(`en-US`,{minimumFractionDigits:2,maximumFractionDigits:2})}`}function F(e){if(!e)return``;let t=new Date(e);return Number.isNaN(t.getTime())?``:t.toLocaleString(`en-US`,{month:`short`,day:`numeric`,hour:`numeric`,minute:`2-digit`})}function I(e){return e===`openrouter`||e===`opencode-go`}let L=e=>e?.kind===`openrouter`?e:null,R=e=>e?.kind===`opencode-go`?e:null;return t(()=>{T()}),(e,t)=>(d(),c(B,{class:`mp-panel`},{default:E(()=>[t[11]||=k(`div`,{class:`sec-label`,style:{"padding-top":`16px`,"margin-bottom":`4px`}},[k(`span`,{class:`live-dot`}),i(`Model providers `)],-1),t[12]||=k(`div`,{class:`agent-desc`},` Spend and usage per model provider, without leaving RepoOS. Two providers report live numbers behind an API key; the rest link straight to their dashboard. `,-1),f.value?(d(),D(`div`,et,u(f.value),1)):s.value&&!o.value.length?(d(),D(`div`,tt,`Loading providers…`)):n(``,!0),(d(!0),D(p,null,a(o.value,(e,o)=>(d(),D(`div`,{key:e.id,class:l([`mp-row`,{first:o===0}])},[k(`div`,nt,[k(`div`,rt,[k(`span`,it,u(e.label),1),k(`span`,{class:l([`mp-pill`,e.kind===`live`?`pill-live`:`pill-link`])},u(e.kind===`live`?`live`:`dashboard only`),3)]),k(`a`,{class:`mp-dash-link`,href:e.dashboardUrl,target:`_blank`,rel:`noopener noreferrer`},` Open dashboard ↗ `,8,at)]),k(`div`,ot,u(e.note),1),I(e.id)?(d(),D(p,{key:0},[!e.hasKey||y[e.id]?(d(),D(`div`,st,[x(k(`input`,{"onUpdate:modelValue":t=>h[e.id]=t,type:`password`,autocomplete:`off`,placeholder:`Paste your ${e.label} API key`,"aria-label":`${e.label} API key`,onKeyup:S(t=>N(e),[`enter`])},null,40,ct),[[v,h[e.id]]]),r(j,{variant:`outline`,size:`sm`,disabled:g[e.id],onClick:t=>N(e)},{default:E(()=>[i(u(g[e.id]?`Saving…`:`Save key`),1)]),_:2},1032,[`disabled`,`onClick`]),e.hasKey?(d(),c(j,{key:0,variant:`ghost`,size:`sm`,disabled:g[e.id],onClick:t=>y[e.id]=!1},{default:E(()=>[...t[0]||=[i(` Cancel `,-1)]]),_:1},8,[`disabled`,`onClick`])):n(``,!0),t[1]||=k(`div`,{class:`mp-key-hint`},[i(` Stored in `),k(`code`,null,`.env`),i(` on this machine (gitignored) — never committed, never logged. `)],-1),b[e.id]?(d(),D(`div`,lt,u(b[e.id]),1)):n(``,!0)])):(d(),D(p,{key:1},[C(e.id).loading?(d(),D(`div`,ut,`Checking…`)):C(e.id).error?(d(),D(`div`,dt,[i(u(C(e.id).error)+` `,1),k(`button`,{class:`mp-retry`,onClick:t=>M(e.id)},`Retry`,8,ft)])):L(C(e.id).usage)?(d(),D(`div`,pt,[L(C(e.id).usage).credits?(d(),D(`div`,mt,[t[2]||=k(`span`,{class:`mp-stat-label`},`Remaining credits`,-1),k(`span`,ht,u(P(L(C(e.id).usage).credits.remaining)),1),L(C(e.id).usage).credits.totalCredits==null?n(``,!0):(d(),D(`span`,gt,` of `+u(P(L(C(e.id).usage).credits.totalCredits))+` purchased `,1))])):n(``,!0),L(C(e.id).usage).creditsError?(d(),D(`div`,_t,` Balance unavailable: `+u(L(C(e.id).usage).creditsError),1)):n(``,!0),L(C(e.id).usage).key?(d(),D(`div`,vt,[k(`div`,yt,[t[3]||=k(`span`,{class:`mp-stat-label`},`Today`,-1),k(`span`,bt,u(P(L(C(e.id).usage).key.usageDaily)),1)]),k(`div`,xt,[t[4]||=k(`span`,{class:`mp-stat-label`},`This week`,-1),k(`span`,St,u(P(L(C(e.id).usage).key.usageWeekly)),1)]),k(`div`,Ct,[t[5]||=k(`span`,{class:`mp-stat-label`},`This month`,-1),k(`span`,wt,u(P(L(C(e.id).usage).key.usageMonthly)),1)]),L(C(e.id).usage).key.rateLimit?.requests==null?n(``,!0):(d(),D(`div`,Tt,[t[6]||=k(`span`,{class:`mp-stat-label`},`Rate limit`,-1),k(`span`,Et,u(L(C(e.id).usage).key.rateLimit.requests)+` req / `+u(L(C(e.id).usage).key.rateLimit.interval),1)]))])):n(``,!0),L(C(e.id).usage).keyError?(d(),D(`div`,Dt,` Key usage unavailable: `+u(L(C(e.id).usage).keyError),1)):n(``,!0)])):R(C(e.id).usage)?(d(),D(`div`,Ot,[R(C(e.id).usage).windows.length?(d(!0),D(p,{key:0},a(R(C(e.id).usage).windows,e=>(d(),D(`div`,{key:e.id,class:`mp-window`},[k(`div`,kt,[k(`span`,At,u(e.label),1),k(`span`,jt,[i(u(e.usedPct==null?`—`:`${Math.round(e.usedPct)}% used`)+` `,1),e.usedUsd!=null&&e.limitUsd!=null?(d(),D(p,{key:0},[i(` · `+u(P(e.usedUsd))+` of `+u(P(e.limitUsd)),1)],64)):n(``,!0)])]),e.usedPct==null?n(``,!0):(d(),D(`div`,{key:0,class:`mp-bar`,role:`progressbar`,"aria-valuenow":Math.round(e.usedPct),"aria-valuemin":`0`,"aria-valuemax":`100`,"aria-label":`${e.label} usage`},[k(`div`,{class:`mp-bar-fill`,style:O({width:`${Math.min(100,Math.max(0,e.usedPct))}%`})},null,4)],8,Mt)),F(e.resetsAt)?(d(),D(`div`,Nt,` resets `+u(F(e.resetsAt)),1)):n(``,!0)]))),128)):R(C(e.id).usage).unrecognized?(d(),D(`div`,Pt,[t[7]||=i(` Live usage responded, but in a format this build doesn't recognize — check the `,-1),k(`a`,{href:e.dashboardUrl,target:`_blank`,rel:`noopener noreferrer`},`console`,8,Ft),t[8]||=i(`. `,-1)])):(d(),D(`div`,It,`No usage reported yet.`))])):n(``,!0),e.hasKey&&!y[e.id]?(d(),D(`div`,Lt,[r(j,{variant:`outline`,size:`sm`,disabled:C(e.id).loading,onClick:t=>M(e.id)},{default:E(()=>[i(u(C(e.id).loading?`Refreshing…`:`Refresh`),1)]),_:2},1032,[`disabled`,`onClick`]),r(j,{variant:`ghost`,size:`sm`,onClick:t=>y[e.id]=!0},{default:E(()=>[...t[9]||=[i(`Replace key`,-1)]]),_:1},8,[`onClick`]),r(j,{variant:`ghost`,size:`sm`,disabled:g[e.id],onClick:t=>te(e)},{default:E(()=>[...t[10]||=[i(` Clear `,-1)]]),_:1},8,[`disabled`,`onClick`])])):n(``,!0)],64))],64)):n(``,!0)],2))),128))]),_:1}))}}),[[`__scopeId`,`data-v-70f2ebda`]]),zt={class:`agents-page`},Bt={class:`page-desc`},Vt={key:0},Ht={key:1,class:`save-msg err`},Ut={key:2,class:`save-msg ok`},Wt={key:0,class:`spin`},Gt={class:`agent-tabs`},Kt=[`onClick`],qt={class:`agents-tab-content`},Jt={class:`sec-label`,style:{"padding-top":`16px`,"margin-bottom":`4px`}},Yt={class:`agent-head`},Xt={class:`agent-title`},Zt={class:`agent-name`},Qt={class:`agent-body`},$t={class:`agent-field`},en={class:`agent-field agent-test-result`},tn={class:`agent-test-actions`},nn={key:0,class:`model-test-spinner`},rn=[`title`],an={class:`agent-field agent-instr-field`},on={class:`instr-header`},sn=[`value`,`onInput`,`onBlur`],cn={key:0,class:`agent-field agent-skills-field`},ln={class:`instr-header`},un={class:`agent-skills-summary`},dn={class:`agent-add`},fn={key:0,class:`agent-empty`},pn={class:`agent-head`},mn={class:`agent-title`},hn={style:{display:`flex`,"align-items":`center`,gap:`10px`}},gn={class:`agent-body`},_n={class:`agent-field`},vn={class:`agent-field agent-test-result`},yn={class:`agent-test-actions`},bn={key:0,class:`model-test-spinner`},xn=[`title`],Sn={class:`agent-field agent-instr-field`},Cn={class:`instr-header`},wn=[`value`,`onInput`,`onBlur`],Tn={key:0,class:`agent-field agent-skills-field`},En={class:`instr-header`},Dn={class:`agent-skills-summary`},On={class:`agent-head`},kn={class:`agent-title`},An={class:`agent-name`},jn={class:`agent-body`},Mn={class:`agent-field`},Nn={class:`agent-field agent-test-result`},Pn={class:`agent-test-actions`},Fn={key:0,class:`model-test-spinner`},In=[`title`],Ln={class:`agent-field agent-instr-field`},Rn={class:`instr-header`},zn=[`value`,`onInput`,`onBlur`],Bn={key:0,class:`agent-field agent-skills-field`},Vn={class:`instr-header`},Hn={class:`agent-skills-summary`},Un={key:0,class:`detect-loading`},Wn={key:1,class:`agent-empty`},Gn={class:`detect-row-left`},Kn={class:`agent-name`},qn={class:`detect-row-right`},Jn={class:`detect-bin`},Yn=[`title`],Xn={key:1,class:`detect-ver`},Zn={key:2,class:`detect-hint`},Qn=[`onClick`],$n={class:`detect-bin`},er={class:`detect-hint`},tr=[`onClick`],nr={class:`detect-foot`},rr={class:`am-modal-head`},ir={key:0,class:`agent-skill-modal-list`},ar=[`checked`,`onChange`],or={key:0},sr=`docs/agent-model-recommendations.md`,cr=`docs/opencode-models.md`,lr=s({__name:`AgentsView`,setup(o){let s=P(),g=b(),_=T(),v=F(),y={default:`Default Agents`,custom:`Custom Agents`,team:`Build Your Team`,detected:`Detected Coding Agents`,playground:`Model Playground`,providers:`Model providers`},I=[`default`,`custom`,`team`,`detected`,`playground`,`providers`],R=w(`default`),re=w(!1),z=w(!1);e(R,e=>{e===`playground`&&(re.value=!0),e===`providers`&&(z.value=!0)});let ie=()=>{let e=_.query.tab;return typeof e==`string`&&I.includes(e)?e:`default`};e(()=>_.query.tab,()=>{let e=ie();e!==R.value&&(R.value=e)},{immediate:!0}),e(R,e=>{ie()!==e&&g.replace({query:{..._.query,tab:e}})});function se(){v.loadDoc(sr),g.push({name:`repo`})}function ce(){v.loadDoc(cr),g.push({name:`repo`})}let U=w([]),W=w(``),G=w(null),fe=!1,pe,me=!1,he=!1;function ge(){fe=!0,U.value=s.agents.map(e=>({...e})),fe=!1}e(()=>s.loaded,e=>{e&&ge()},{immediate:!0});let _e=m(()=>s.agentsMeta.defaults.map(e=>e.name.toLowerCase())),ve=e=>_e.value.includes(e.toLowerCase()),ye=[`ross`,`cto`],be=e=>ye.includes(e.toLowerCase()),xe=m(()=>U.value.filter(e=>ve(e.name)&&!be(e.name))),Se=m(()=>U.value.filter(e=>ve(e.name)&&be(e.name))),Ce=m(()=>U.value.filter(e=>!ve(e.name))),we={"claude code":`Claude Code`,"github copilot":`GitHub Copilot CLI`,"qwen code":`qwen code`,codex:`codex`},Te=new Map,Ee=new Map;function De(e,t){let n=Te.get(e);n&&ae(n,t)}function Oe(e,t){let n=Ee.get(e);n&&ae(n,t)}m(()=>s.agentsMeta.clis.map(e=>({value:e,label:we[e]??e})));let ke=m(()=>s.agentsMeta.clis??[]),q=w({}),J=w({});s.modelsFor;let Ae=m(()=>s.modelsLoading);function Y(e){return`${e.name}\u0000${e.cli}\u0000${e.model}`}function X(e){return q.value[Y(e)]}async function je(e){let t=Y(e);if(J.value[t])return;J.value={...J.value,[t]:!0};let n=e.cli,r=e.model;try{let e=await A(`/api/models/test`,ee(`POST`,{cli:n,model:r}));q.value={...q.value,[t]:e.result}}catch(e){q.value={...q.value,[t]:{cli:n,model:r,status:`failed`,durationMs:0,error:e instanceof Error?e.message:`Model compatibility test failed.`}}}finally{let e={...J.value};delete e[t],J.value=e}}let Me=(e=!1)=>s.loadModels(e);function Ne(){let e=W.value.trim();if(e){if(U.value.some(t=>t.name.toLowerCase()===e.toLowerCase())){s.error=`An agent named "${e}" already exists.`;return}U.value.push({name:e,cli:s.agentsMeta.clis[0]??`opencode`,model:s.agentsMeta.models[1]??`big pickle`,enabled:!0,instructions:``}),W.value=``,s.error=``}}function Pe(e){U.value=U.value.filter(t=>t!==e)}function Fe(e,t){e.instructions=t.target.value}function Ie(e){let t=document.activeElement;t instanceof HTMLTextAreaElement&&t.value!==e.instructions&&(e.instructions=t.value)}function Le(e,t,n){let r=new Set(e.skills??[]);n?r.add(t):r.delete(t),e.skills=[...r]}function Re(e){G.value=e}function ze(){let e=new Set;for(let t of U.value){let n=t.name.trim().toLowerCase();if(!n){s.error=`Every agent needs a name.`;return}if(e.has(n)){s.error=`Duplicate agent name "${t.name}".`;return}e.add(n)}return U.value.map(e=>({...e,name:e.name.trim()}))}async function Be(){if(me){he=!0;return}let e=ze();if(e){me=!0,he=!1;try{await s.saveAgents(e)}catch{}finally{me=!1,he&&Ve(0)}}}function Ve(e=450){clearTimeout(pe),pe=setTimeout(()=>void Be(),e)}e(U,()=>{fe||!s.loaded||(s.msg=``,s.error=``,me&&(he=!0),Ve())},{deep:!0,flush:`sync`});let Z=w([]),Q=w(!1),He=w(!1),$=w(``),Ue=m(()=>Z.value.map(e=>e.installed?e.headless===!1?{agent:e,status:`desktop`,statusLabel:`desktop only`,color:`var(--amber)`}:{agent:e,status:`ok`,statusLabel:`ready`,color:`var(--green)`}:{agent:e,status:`missing`,statusLabel:`not installed`,color:`var(--red)`}));async function We(){Q.value=!0,He.value=!1,$.value=``;try{let e=await A(`/api/agents/detect`);Z.value=e.agents}catch{He.value=!0,Z.value=[]}finally{Q.value=!1}}function Ge(e){le(e),$.value=e,setTimeout(()=>{$.value===e&&($.value=``)},1500)}return t(()=>{We(),Me()}),f(()=>{clearTimeout(pe)}),(e,t)=>(d(),D(`div`,zt,[t[41]||=k(`div`,{class:`page-title agents-page-title`},`Agents`,-1),k(`div`,Bt,[t[3]||=i(` The AI agents that work this repo · `,-1),k(`button`,{class:`model-pricing-link`,onClick:se},` View the full agent & model selection guide → `),h(s).saving?(d(),D(`span`,Vt,` · Saving…`)):h(s).error?(d(),D(`span`,Ht,` · `+u(h(s).error),1)):h(s).msg?(d(),D(`span`,Ut,` · Saved`)):n(``,!0)]),h(s).loaded?(d(),D(p,{key:1},[k(`div`,Gt,[(d(),D(p,null,a(I,e=>k(`button`,{key:e,type:`button`,class:l([`tab-btn`,{active:R.value===e}]),onClick:t=>R.value=e},u(y[e]),11,Kt)),64))]),k(`div`,qt,[x(r(B,{style:{padding:`0 18px 6px`,"margin-bottom":`16px`}},{default:E(()=>[k(`div`,Jt,[t[4]||=k(`span`,{class:`live-dot`},null,-1),t[5]||=i(`Default agents `,-1),k(`button`,{class:`model-pricing-link`,onClick:ce},` Model pricing & use cases → `),r(j,{variant:`outline`,size:`sm`,style:{"margin-left":`auto`},disabled:Ae.value,title:`Re-probe opencode's live model list (opencode models --refresh)`,onClick:t[0]||=e=>Me(!0)},{default:E(()=>[i(u(Ae.value?`Refreshing…`:`Refresh models`),1)]),_:1},8,[`disabled`])]),t[14]||=k(`div`,{class:`agent-desc`},` Headless task-engine roles that run the roadmap. Toggle them on or off and pick their coding agent and model. `,-1),(d(!0),D(p,null,a(xe.value,e=>(d(),D(`div`,{key:e.name,class:l([`agent-card`,{off:!e.enabled}])},[k(`div`,Yt,[k(`div`,Xt,[t[6]||=k(`span`,{class:`agent-dot`},null,-1),k(`span`,Zt,u(e.name),1),t[7]||=k(`span`,{class:`agent-badge`},`default`,-1)]),r(V,{checked:e.enabled,"onUpdate:checked":t=>e.enabled=t},null,8,[`checked`,`onUpdate:checked`])]),k(`div`,Qt,[k(`div`,$t,[t[8]||=k(`label`,null,`Coding agent + Model`,-1),r(H,{"cli-options":ke.value,"model-options":h(s).modelsFor(e.cli,e.model),"memory-key":`headless:`+e.name,cli:e.cli,"onUpdate:cli":t=>e.cli=t,model:e.model,"onUpdate:model":t=>e.model=t},null,8,[`cli-options`,`model-options`,`memory-key`,`cli`,`onUpdate:cli`,`model`,`onUpdate:model`])]),k(`div`,en,[t[9]||=k(`label`,null,`Compatibility`,-1),k(`div`,tn,[r(j,{variant:`outline`,size:`sm`,disabled:!!J.value[Y(e)],onClick:t=>je(e)},{default:E(()=>[J.value[Y(e)]?(d(),D(`span`,nn)):n(``,!0),i(` `+u(J.value[Y(e)]?`Testing…`:X(e)?`Test again`:`Test`),1)]),_:2},1032,[`disabled`,`onClick`]),X(e)?(d(),D(`span`,{key:0,class:l(`model-test model-test-`+X(e).status),title:X(e).error},u(X(e).status.replace(`_`,` `)),11,rn)):n(``,!0)])]),k(`div`,an,[k(`div`,on,[t[10]||=k(`label`,null,`Instructions`,-1),r(de,{onTranscribed:t=>De(e.name,t)},null,8,[`onTranscribed`])]),k(`textarea`,{ref_for:!0,ref:t=>h(Te).set(e.name,t),value:e.instructions??``,class:`agent-instr`,rows:`2`,placeholder:`Optional — how this agent should behave`,onInput:t=>Fe(e,t),onBlur:t=>Ie(e)},null,40,sn)]),h(s).agentsMeta.skills.length?(d(),D(`div`,cn,[k(`div`,ln,[t[12]||=k(`label`,null,`Enabled skills`,-1),r(j,{variant:`outline`,size:`sm`,onClick:t=>Re(e)},{default:E(()=>[...t[11]||=[i(`Add skills to agent`,-1)]]),_:1},8,[`onClick`])]),t[13]||=k(`div`,{class:`agent-skills-help`},` ⓘ Skills are selected dynamically for each task/run from repository skills; these are this agent's preferred candidates. `,-1),k(`div`,un,u((e.skills??[]).join(`, `)||`No default candidates`),1)])):n(``,!0)])],2))),128))]),_:1},512),[[C,R.value==="default"]]),x(r(B,{style:{padding:`0 18px 6px`,"margin-bottom":`16px`}},{default:E(()=>[t[24]||=k(`div`,{class:`sec-label`,style:{"padding-top":`16px`,"margin-bottom":`4px`}},[k(`span`,{class:`live-dot`,style:{background:`var(--violet, var(--cyan))`}}),i(`Custom agents `)],-1),t[25]||=k(`div`,{class:`agent-desc`},` Your own roles — data analyst, refactor agent, anything you need. `,-1),k(`div`,dn,[r(ue,{modelValue:W.value,"onUpdate:modelValue":t[1]||=e=>W.value=e,placeholder:`e.g. data analyst`,class:`w-[220px]`,onKeyup:S(Ne,[`enter`])},null,8,[`modelValue`]),r(j,{variant:`outline`,size:`sm`,disabled:!W.value.trim(),onClick:Ne},{default:E(()=>[...t[15]||=[i(` Add agent `,-1)]]),_:1},8,[`disabled`])]),Ce.value.length?n(``,!0):(d(),D(`div`,fn,` No custom agents yet — add one above. `)),(d(!0),D(p,null,a(Ce.value,e=>(d(),D(`div`,{key:e.name,class:l([`agent-card`,{off:!e.enabled}])},[k(`div`,pn,[k(`div`,mn,[t[16]||=k(`span`,{class:`agent-dot`},null,-1),r(ue,{"model-value":e.name,class:`w-[180px] h-[30px]`,"onUpdate:modelValue":t=>e.name=String(t??``)},null,8,[`model-value`,`onUpdate:modelValue`])]),k(`div`,hn,[r(j,{variant:`ghost`,size:`sm`,class:`agent-remove`,onClick:t=>Pe(e)},{default:E(()=>[...t[17]||=[i(` Remove `,-1)]]),_:1},8,[`onClick`]),r(V,{checked:e.enabled,"onUpdate:checked":t=>e.enabled=t},null,8,[`checked`,`onUpdate:checked`])])]),k(`div`,gn,[k(`div`,_n,[t[18]||=k(`label`,null,`Coding agent + Model`,-1),r(H,{"cli-options":ke.value,"model-options":h(s).modelsFor(e.cli,e.model),"memory-key":`custom:`+e.name,cli:e.cli,"onUpdate:cli":t=>e.cli=t,model:e.model,"onUpdate:model":t=>e.model=t},null,8,[`cli-options`,`model-options`,`memory-key`,`cli`,`onUpdate:cli`,`model`,`onUpdate:model`])]),k(`div`,vn,[t[19]||=k(`label`,null,`Compatibility`,-1),k(`div`,yn,[r(j,{variant:`outline`,size:`sm`,disabled:!!J.value[Y(e)],onClick:t=>je(e)},{default:E(()=>[J.value[Y(e)]?(d(),D(`span`,bn)):n(``,!0),i(` `+u(J.value[Y(e)]?`Testing…`:X(e)?`Test again`:`Test`),1)]),_:2},1032,[`disabled`,`onClick`]),X(e)?(d(),D(`span`,{key:0,class:l(`model-test model-test-`+X(e).status),title:X(e).error},u(X(e).status.replace(`_`,` `)),11,xn)):n(``,!0)])]),k(`div`,Sn,[k(`div`,Cn,[t[20]||=k(`label`,null,`Instructions`,-1),r(de,{onTranscribed:t=>Oe(e.name,t)},null,8,[`onTranscribed`])]),k(`textarea`,{ref_for:!0,ref:t=>h(Ee).set(e.name,t),value:e.instructions??``,class:`agent-instr`,rows:`2`,placeholder:`Optional — how this agent should behave`,onInput:t=>Fe(e,t),onBlur:t=>Ie(e)},null,40,wn)]),h(s).agentsMeta.skills.length?(d(),D(`div`,Tn,[k(`div`,En,[t[22]||=k(`label`,null,`Enabled skills`,-1),r(j,{variant:`outline`,size:`sm`,onClick:t=>Re(e)},{default:E(()=>[...t[21]||=[i(`Add skills to agent`,-1)]]),_:1},8,[`onClick`])]),t[23]||=k(`div`,{class:`agent-skills-help`},` ⓘ Skills are selected dynamically for each task/run from repository skills; these are this agent's preferred candidates. `,-1),k(`div`,Dn,u((e.skills??[]).join(`, `)||`No default candidates`),1)])):n(``,!0)])],2))),128))]),_:1},512),[[C,R.value===`custom`]]),x(r(B,{style:{padding:`0 18px 6px`,"margin-bottom":`16px`}},{default:E(()=>[t[34]||=k(`div`,{class:`sec-label`,style:{"padding-top":`16px`,"margin-bottom":`4px`}},[k(`span`,{class:`live-dot`,style:{background:`var(--green)`}}),i(`Build your team `)],-1),t[35]||=k(`div`,{class:`agent-desc`},` The agents that talk back or extend RepoOS. Enable them to add new capabilities. `,-1),(d(!0),D(p,null,a(Se.value,e=>(d(),D(`div`,{key:`team-`+e.name,class:l([`agent-card`,{off:!e.enabled}])},[k(`div`,On,[k(`div`,kn,[t[26]||=k(`span`,{class:`agent-dot`},null,-1),k(`span`,An,u(e.name),1),t[27]||=k(`span`,{class:`agent-badge`},`team`,-1)]),r(V,{checked:e.enabled,"onUpdate:checked":t=>e.enabled=t},null,8,[`checked`,`onUpdate:checked`])]),k(`div`,jn,[k(`div`,Mn,[t[28]||=k(`label`,null,`Coding agent + Model`,-1),r(H,{"cli-options":ke.value,"model-options":h(s).modelsFor(e.cli,e.model),"memory-key":`team:`+e.name,cli:e.cli,"onUpdate:cli":t=>e.cli=t,model:e.model,"onUpdate:model":t=>e.model=t},null,8,[`cli-options`,`model-options`,`memory-key`,`cli`,`onUpdate:cli`,`model`,`onUpdate:model`])]),k(`div`,Nn,[t[29]||=k(`label`,null,`Compatibility`,-1),k(`div`,Pn,[r(j,{variant:`outline`,size:`sm`,disabled:!!J.value[Y(e)],onClick:t=>je(e)},{default:E(()=>[J.value[Y(e)]?(d(),D(`span`,Fn)):n(``,!0),i(` `+u(J.value[Y(e)]?`Testing…`:X(e)?`Test again`:`Test`),1)]),_:2},1032,[`disabled`,`onClick`]),X(e)?(d(),D(`span`,{key:0,class:l(`model-test model-test-`+X(e).status),title:X(e).error},u(X(e).status.replace(`_`,` `)),11,In)):n(``,!0)])]),k(`div`,Ln,[k(`div`,Rn,[t[30]||=k(`label`,null,`Instructions`,-1),r(de,{onTranscribed:t=>De(e.name,t)},null,8,[`onTranscribed`])]),k(`textarea`,{ref_for:!0,ref:t=>h(Te).set(e.name,t),value:e.instructions??``,class:`agent-instr`,rows:`2`,placeholder:`Optional — how this agent should behave`,onInput:t=>Fe(e,t),onBlur:t=>Ie(e)},null,40,zn)]),h(s).agentsMeta.skills.length?(d(),D(`div`,Bn,[k(`div`,Vn,[t[32]||=k(`label`,null,`Enabled skills`,-1),r(j,{variant:`outline`,size:`sm`,onClick:t=>Re(e)},{default:E(()=>[...t[31]||=[i(`Add skills to agent`,-1)]]),_:1},8,[`onClick`])]),t[33]||=k(`div`,{class:`agent-skills-help`},` ⓘ Skills are selected dynamically for each task/run from repository skills; these are this agent's preferred candidates. `,-1),k(`div`,Hn,u((e.skills??[]).join(`, `)||`No default candidates`),1)])):n(``,!0)])],2))),128)),r(K,{agent:`debugger`,interactive:``}),r(K,{agent:`tech-debt`}),r(K,{agent:`performance`}),r(K,{agent:`architect`}),r(K,{agent:`design`}),r(K,{agent:`docs-debt`})]),_:1},512),[[C,R.value===`team`]]),He.value?n(``,!0):x((d(),c(B,{key:0,style:{padding:`0 18px 6px`,"margin-bottom":`16px`}},{default:E(()=>[t[37]||=k(`div`,{class:`sec-label`,style:{"padding-top":`16px`,"margin-bottom":`4px`}},[k(`span`,{class:`live-dot`,style:{background:`var(--violet, var(--cyan))`}}),i(` Detected coding agents `)],-1),t[38]||=k(`div`,{class:`agent-desc`},` What's on this machine's PATH — installed & headless-ready, desktop-only, or missing. Click a hint to copy it. `,-1),Q.value&&!Z.value.length?(d(),D(`div`,Un,`Probing PATH…`)):Z.value.length?(d(),D(p,{key:2},[(d(!0),D(p,null,a(Ue.value,e=>(d(),D(`div`,{key:e.agent.id,class:`detect-row`},[k(`div`,Gn,[k(`span`,{class:`detect-badge`,style:O({background:e.color,boxShadow:`0 0 8px `+e.color})},null,4),k(`span`,Kn,u(e.agent.name),1),k(`span`,{class:`detect-pill`,style:O({color:e.color})},u(e.statusLabel),5),k(`span`,{class:l([`agent-badge`,e.agent.drivable?`detect-driver-yes`:`detect-driver-no`])},u(e.agent.drivable?`RepoOS driver`:`detected only`),3)]),k(`div`,qn,[e.agent.installed?(d(),D(p,{key:0},[k(`span`,Jn,u(e.agent.binary),1),e.agent.path?(d(),D(`span`,{key:0,class:`detect-path`,title:e.agent.path},u(e.agent.path),9,Yn)):n(``,!0),e.agent.version?(d(),D(`span`,Xn,u(e.agent.version),1)):n(``,!0),e.agent.headless?n(``,!0):(d(),D(`span`,Zn,[t[36]||=i(` Desktop app shadows PATH — install headless CLI: `,-1),k(`code`,null,u(e.agent.installHint),1),k(`button`,{class:`detect-copy`,onClick:t=>Ge(e.agent.installHint)},u($.value===e.agent.installHint?`copied`:`copy`),9,Qn)]))],64)):(d(),D(p,{key:1},[k(`span`,$n,u(e.agent.binary),1),k(`span`,er,[k(`code`,null,u(e.agent.installHint),1),k(`button`,{class:`detect-copy`,onClick:t=>Ge(e.agent.installHint)},u($.value===e.agent.installHint?`copied`:`copy`),9,tr)])],64))])]))),128)),k(`div`,nr,[r(j,{variant:`outline`,size:`sm`,disabled:Q.value,onClick:We},{default:E(()=>[i(u(Q.value?`Checking…`:`Check again`),1)]),_:1},8,[`disabled`])])],64)):(d(),D(`div`,Wn,` No known coding agents detected on PATH. `))]),_:1},512)),[[C,R.value===`detected`]]),re.value?x((d(),c($e,{key:1},null,512)),[[C,R.value===`playground`]]):n(``,!0),z.value?x((d(),c(Rt,{key:2},null,512)),[[C,R.value===`providers`]]):n(``,!0)])],64)):(d(),D(`div`,Wt)),r(M,{open:!!G.value,"onUpdate:open":t[2]||=e=>{e||(G.value=null)}},{default:E(()=>[r(te),r(L,{class:`am-modal`},{default:E(()=>[k(`div`,rr,[r(ne,null,{default:E(()=>[i(`Skills for `+u(G.value?.name),1)]),_:1}),r(oe,{class:`close-x`},{default:E(()=>[...t[39]||=[i(`×`,-1)]]),_:1})]),r(N,{class:`am-modal-desc`},{default:E(()=>[...t[40]||=[i(`Choose preferred candidates for this agent. RepoOS still selects only task-relevant skills on each run.`,-1)]]),_:1}),G.value?(d(),D(`div`,ir,[(d(!0),D(p,null,a(h(s).agentsMeta.skills,e=>(d(),D(`label`,{key:e.path,class:`agent-skill-option`},[k(`input`,{type:`checkbox`,checked:(G.value.skills??[]).includes(e.name),onChange:t=>Le(G.value,e.name,t.target.checked)},null,40,ar),k(`span`,null,[k(`strong`,null,u(e.name),1),e.description?(d(),D(`small`,or,u(e.description),1)):n(``,!0)])]))),128))])):n(``,!0)]),_:1})]),_:1},8,[`open`])]))}});export{lr as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.ff-textarea[data-v-4849f9ae],.doc-textarea[data-v-4849f9ae]{border:1px solid var(--border);resize:vertical;background:var(--bg-secondary);width:100%;color:var(--txt);border-radius:8px;padding:10px;font-family:monospace;font-size:12px}.ff-agent-bar[data-v-4849f9ae]{background:var(--bg-secondary);border-radius:8px;flex-direction:column;gap:12px;margin:12px 0;padding:12px;display:flex}.agent-pick-grid[data-v-4849f9ae]{grid-template-columns:1fr 1fr 1fr;gap:8px;display:grid}.agent-field[data-v-4849f9ae]{flex-direction:column;gap:4px;display:flex}.agent-field label[data-v-4849f9ae]{color:var(--txt-secondary);font-size:12px;font-weight:500}.ff-notice[data-v-4849f9ae]{background:var(--info-alpha);color:var(--info);border-radius:6px;margin:12px 0;padding:10px;font-size:13px}.ff-notice a[data-v-4849f9ae]{color:inherit;text-decoration:underline}.ff-error[data-v-4849f9ae]{background:var(--red-alpha);color:var(--red);border-radius:6px;margin:12px 0;padding:10px;font-size:13px}.ff-stream[data-v-4849f9ae]{background:var(--bg-secondary);border-radius:8px;margin-top:16px;padding:12px}.ff-stream-head[data-v-4849f9ae]{color:var(--txt-secondary);align-items:center;gap:8px;margin-bottom:8px;font-size:12px;font-weight:600;display:flex}.ff-stream-log[data-v-4849f9ae]{max-height:200px;font-family:monospace;font-size:11px;line-height:1.5;overflow-y:auto}.ff-stream-line[data-v-4849f9ae]{color:var(--txt-faint);word-break:break-all}.ff-stream-line.err[data-v-4849f9ae]{color:var(--red)}.btn-row[data-v-4849f9ae]{justify-content:flex-end;gap:8px;display:flex}.field[data-v-4849f9ae]{flex-direction:column;gap:6px;margin-bottom:12px;display:flex}.field-header[data-v-4849f9ae]{justify-content:space-between;align-items:center;gap:8px;display:flex}.field label[data-v-4849f9ae]{color:var(--txt-secondary);font-size:13px;font-weight:500}.upload-input[data-v-4849f9ae]{border:1px solid var(--border);background:var(--bg-secondary);color:var(--txt);cursor:pointer;border-radius:8px;padding:8px 10px;font-size:13px}.upload-input[data-v-4849f9ae]:hover{border-color:var(--border-focus)}.upload-file-info[data-v-4849f9ae]{background:var(--bg-secondary);color:var(--txt-secondary);border-radius:6px;margin-top:8px;padding:8px 10px;font-size:12px}.upload-dest[data-v-4849f9ae]{font-family:var(--font-mono,monospace);color:var(--txt-tertiary,var(--txt-secondary));margin-left:6px}.ff-textarea[data-v-a348ce84],.doc-textarea[data-v-a348ce84]{border:1px solid var(--border);resize:vertical;background:var(--bg-secondary);width:100%;color:var(--txt);border-radius:8px;padding:10px;font-family:monospace;font-size:12px}.hint[data-v-a348ce84]{color:var(--txt-faint);font-family:monospace;font-size:11px}.ff-agent-bar[data-v-a348ce84]{margin:12px 0;display:flex}.ff-notice[data-v-a348ce84]{background:var(--info-alpha);color:var(--info);border-radius:6px;margin:12px 0;padding:10px;font-size:13px}.ff-notice a[data-v-a348ce84]{color:inherit;text-decoration:underline}.ff-error[data-v-a348ce84]{background:var(--red-alpha);color:var(--red);border-radius:6px;margin:12px 0;padding:10px;font-size:13px}.ff-stream[data-v-a348ce84]{background:var(--bg-secondary);border-radius:8px;margin-top:16px;padding:12px}.ff-stream-head[data-v-a348ce84]{color:var(--txt-secondary);align-items:center;gap:8px;margin-bottom:8px;font-size:12px;font-weight:600;display:flex}.ff-stream-log[data-v-a348ce84]{max-height:200px;font-family:monospace;font-size:11px;line-height:1.5;overflow-y:auto}.ff-stream-line[data-v-a348ce84]{color:var(--txt-faint);word-break:break-all}.ff-stream-line.err[data-v-a348ce84]{color:var(--red)}.btn-row[data-v-a348ce84]{justify-content:flex-end;gap:8px;display:flex}.field[data-v-a348ce84]{flex-direction:column;gap:6px;margin-bottom:12px;display:flex}.field label[data-v-a348ce84]{color:var(--txt-secondary);font-size:13px;font-weight:500}.upload-input[data-v-a348ce84]{border:1px solid var(--border);background:var(--bg-secondary);color:var(--txt);cursor:pointer;border-radius:8px;padding:8px 10px;font-size:13px}.upload-input[data-v-a348ce84]:hover{border-color:var(--border-focus)}.upload-file-info[data-v-a348ce84]{background:var(--bg-secondary);color:var(--txt-secondary);border-radius:6px;margin-top:8px;padding:8px 10px;font-size:12px}.ctx-refresh-btn[data-v-6925ffc2]{margin-left:auto}.ctx-discover-head[data-v-6925ffc2]{color:var(--txt-muted);gap:5px;padding:12px;font-size:12px;display:grid}.ctx-discover-head strong[data-v-6925ffc2]{color:var(--txt);font-size:13px}.ctx-skill-search[data-v-6925ffc2]{border:1px solid var(--border);background:var(--bg);width:100%;color:var(--txt);border-radius:6px;margin-top:5px;padding:7px 9px}.ctx-skill-meta[data-v-6925ffc2]{color:var(--txt-faint);font-size:11px}.ctx-installed[data-v-6925ffc2]{color:var(--green);font-size:11px;font-weight:700}.ctx-catalog-skill[data-v-6925ffc2]{text-align:left;width:100%;color:inherit;font:inherit;background:0 0;border:0}.ctx-detail-meta[data-v-6925ffc2]{color:var(--txt-muted);margin-top:10px;font-size:12px}.ctx-detail-copy[data-v-6925ffc2]{color:var(--txt-muted);max-width:54ch;margin-top:18px;line-height:1.55}.ctx-detail-actions[data-v-6925ffc2]{gap:8px;margin-top:20px;display:flex}.ctx-refresh-btn[data-v-6925ffc2] svg{transition:transform .2s}.ctx-refresh-btn[data-v-6925ffc2] svg.refreshing{animation:1s linear infinite spin-6925ffc2}@keyframes spin-6925ffc2{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.doc-tree[data-v-6925ffc2]{padding:8px 0}.tree-item[data-v-6925ffc2]{-webkit-user-select:none;user-select:none}.tree-dir[data-v-6925ffc2],.tree-file[data-v-6925ffc2]{cursor:pointer;border-radius:4px;align-items:center;gap:8px;padding:6px 8px;font-size:13px;transition:background-color .15s;display:flex}.tree-dir[data-v-6925ffc2]:hover,.tree-file[data-v-6925ffc2]:hover{background-color:var(--bg-overlay)}.tree-file.sel[data-v-6925ffc2]{background-color:var(--bg-accent-soft);font-weight:500}.dir-name[data-v-6925ffc2]{color:var(--txt-primary);font-weight:500}.chevron[data-v-6925ffc2]{color:var(--txt-secondary);flex-shrink:0;transition:transform .15s}.ctx-refresh-error[data-v-6925ffc2]{background:var(--red-tint);border:1px solid var(--red-border-tint);color:var(--txt);border-radius:8px;margin:4px 8px 8px;padding:8px 12px;font-size:12px}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/mermaid.core-BUUkChHW.js","assets/src-BH-TyZbA.js","assets/chunk-Y2CYZVJY-DsF7k-Jl.js","assets/index-BOQ-ust6.js","assets/vendor-vue-CobgyEJp.js","assets/button-lbikqSph.js","assets/vendor-ui-DPm7zLxi.js","assets/index-BACBfnga.css","assets/chunk-DU6HZSFF-DfdNNqwa.js","assets/chunk-75Z2AOVW-5GuBxfsL.js","assets/dist-DTg6UBE_.js","assets/chunk-PWAF6VOD-DfoTLtxn.js","assets/chunk-GMAD6QVW-DGWvSKj5.js","assets/chunk-P2QGCYS3-C74X4AQX.js","assets/chunk-4HAMMTFA-D1YR8lF_.js","assets/rough.esm-By172zw-.js","assets/chunk-GVQU2GXP-D6Aw75wJ.js","assets/chunk-OSK3NFVY-B7r9w2UW.js","assets/line-KAyfuul4.js","assets/path-COt_16Va.js","assets/array-BifhSqXX.js","assets/graphlib-DS17s2tU.js","assets/chunk-L3NEJ4N5-D5OJuXYE.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{$ as e,B as t,C as n,D as r,E as i,G as a,I as o,O as s,S as c,St as l,Tt as u,U as d,_ as f,b as p,bt as m,dt as h,f as ee,h as te,it as g,m as _,pt as v,q as y,r as b,rt as x,s as S,u as C,w,wt as ne,x as T}from"./vendor-vue-CobgyEJp.js";import{a as re,i as E,t as D}from"./button-lbikqSph.js";import{C as O,F as k,K as A,nt as j,rt as M}from"./vendor-ui-DPm7zLxi.js";import{A as ie,B as N,D as ae,E as P,I as oe,L as se,N as F,O as I,T as L,W as ce,b as R,c as z,d as B,f as V,g as H,k as U,l as W,m as G,p as le,s as ue,t as K,u as de,w as q,x as J,y as Y}from"./index-BOQ-ust6.js";var X=null;function Z(){let e=document.documentElement.getAttribute(`data-theme`);return e===`dark`?`dark`:e===`light`?`default`:window.matchMedia(`(prefers-color-scheme: dark)`).matches?`dark`:`default`}async function Q(){return X||=K(async()=>{let{default:e}=await import(`./mermaid.core-BUUkChHW.js`);return{default:e}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22])).then(({default:e})=>(e.initialize({startOnLoad:!1,securityLevel:`strict`,maxTextSize:5e4,maxEdges:1e3,theme:Z()}),e)),X}async function fe(e){let t=e.querySelectorAll(`.md-mermaid:not([data-processed])`);if(t.length)try{await(await Q()).run({nodes:t,suppressErrors:!0})}catch{}}function pe(e){let t={};for(let n of e){if(!n.path)continue;let e=n.path.split(`/`),r=t;for(let t=0;t<e.length;t++){let i=e[t],a=t===e.length-1,o=e.slice(0,t+1).join(`/`);r[i]||(r[i]={name:i,key:o,isFile:a,path:a?n.path:void 0,children:{}}),a||(r=r[i].children)}}let n=e=>Object.values(e).sort((e,t)=>e.isFile===t.isFile?e.name.localeCompare(t.name):e.isFile?1:-1).map(e=>{let t={name:e.name,key:e.key,isFile:e.isFile,path:e.path},r=n(e.children);return r.length&&(t.children=r),t});return n(t)}function me(e,t){let n=[],r=(e,i)=>{for(let a of e)n.push({key:a.key,name:a.name,isFile:a.isFile,path:a.path,depth:i}),!a.isFile&&a.children&&t.has(a.key)&&r(a.children,i+1)};return r(e,0),n}var he={class:`drawer-head`},ge={class:`drawer-tabs`},_e={class:`drawer-body`},ve={class:`field`},ye={class:`field-header`},be={class:`ff-agent-bar`},xe={class:`agent-pick-grid`},Se={class:`agent-field`},Ce={class:`agent-field`,style:{"grid-column":`1 / -1`}},we={key:0,class:`ff-notice`},Te={key:1,class:`ff-error`},Ee={class:`btn-row`,style:{"margin-top":`20px`}},De={key:2,class:`ff-stream`},Oe={class:`ff-stream-head`},ke={class:`field`},Ae={class:`field`},je={class:`field-header`},Me={class:`btn-row`,style:{"margin-top":`20px`}},Ne={class:`field`},Pe={class:`field`},Fe={key:0,class:`upload-file-info`},Ie={key:0,class:`upload-dest`},Le={key:0,class:`ff-error`},Re={class:`btn-row`,style:{"margin-top":`20px`}},ze=F(s({__name:`NewDocPanel`,setup(t){let s=ce(),b=N(),S=oe(),C=se(),re=p(()=>s.isNewDoc);function E(e){e||s.close()}function k(e){s.isNewDoc&&(e.preventDefault(),requestAnimationFrame(()=>{let e;e=A.value===`freeform`?`nd-freeform`:A.value===`upload`?`nd-upload-path`:`nd-path`,document.getElementById(e)?.focus()}))}let A=v(`freeform`),j=v(``),M=v(``),F=v(!1),G=v(null),K=v(null),q=v(``),X=v(``),Z=p(()=>{let e=q.value.trim();return e?/\/\s*$/.test(e)&&K.value?e.replace(/\s*$/,``)+K.value.name:e:``}),Q=p(()=>!S.loaded||(S.agents??[]).some(e=>e.name===`pm`&&e.enabled));e(()=>s.isNewDoc,e=>{e&&(A.value=S.form.defaultTaskMode===`manual`?`manual`:`freeform`,j.value=``,M.value=``,K.value=null,q.value=``,X.value=``,Ge())});async function fe(){let e=j.value.trim();if(e){s.saving=!0,F.value=!0,M.value=``,G.value&&b.clearOutput(G.value),G.value=crypto.randomUUID();try{let t=Ke.value?{agent:$.agent,cli:$.cli,model:$.model}:void 0,n=await b.createFreeformDocument(e,G.value,t);s.close(),j.value=``,await b.refresh(),await C.loadDocs(),n.path&&await C.loadDoc(n.path)}catch(e){M.value=e instanceof Error?e.message:String(e)}finally{F.value=!1,G.value=null,s.saving=!1}}}async function pe(){if(!(!s.nd.path||!s.nd.content)){s.saving=!0;try{let e=s.nd.path;await b.createDocument({path:e,content:s.nd.content}),s.close(),s.nd.path=``,s.nd.content=``,await b.refresh(),await C.loadDocs(),await C.loadDoc(e)}catch(e){b.onError(e)}finally{s.saving=!1}}}function me(e){return new Promise((t,n)=>{let r=new FileReader;r.onload=()=>t(String(r.result).split(`,`)[1]??``),r.onerror=()=>n(r.error??Error(`could not read file`)),r.readAsDataURL(e)})}async function ze(){if(!(!K.value||!q.value.trim())){s.saving=!0,X.value=``;try{let e=K.value,t=Z.value,n=await me(e);await b.createDocument({path:t,contentBase64:n}),s.close(),K.value=null,q.value=``,await b.refresh(),await C.loadDocs(),/\.(md|markdown|txt|svg)$/i.test(t)&&await C.loadDoc(t)}catch(e){X.value=e instanceof Error?e.message:String(e)}finally{s.saving=!1}}}function Be(e){let t=e.target.files;t&&t.length>0&&(K.value=t[0])}let Ve=p(()=>(S.agents??[]).filter(e=>e.enabled)),He=p(()=>S.agentsMeta.clis??[]),Ue=p(()=>S.modelsFor($.cli,$.model||void 0)),We=p(()=>(S.agents?.length?S.agents:[]).find(e=>e.enabled&&e.name===`pm`)??null),$=h({agent:``,cli:``,model:``});function Ge(){let e=We.value;$.agent=e?.name||``,$.cli=e?.cli||``,$.model=e?.model||``}let Ke=p(()=>{let e=We.value;return e?$.agent!==e.name||$.cli!==e.cli||$.model!==e.model:!1}),qe=p(()=>(G.value?b.outputs[G.value]??[]:[]).map(e=>`type`in e?{s:`out`,d:e.type===`text`?e.text:e.d??``}:{s:e.s===`err`?`err`:`out`,d:e.d})),Je=v(null);e(qe,()=>{o(()=>{let e=Je.value;e&&(e.scrollTop=e.scrollHeight)})});let Ye=v(null),Xe=v(null);function Ze(e){Ye.value&&H(Ye.value,e)}function Qe(e){Xe.value&&H(Xe.value,e)}return(e,t)=>{let o=y(`router-link`);return d(),c(ie,{open:re.value,"onUpdate:open":E},{default:x(()=>[r(P),r(I,{style:ne({width:m(s).drawerWidth+`px`,"max-width":`100vw`}),onOpenAutoFocus:k},{default:x(()=>[T(`div`,{class:`drawer-resize`,onMousedown:t[0]||=te((...e)=>m(s).startResize&&m(s).startResize(...e),[`prevent`])},null,32),T(`div`,he,[r(L,null,{default:x(()=>[...t[15]||=[i(`New doc`,-1)]]),_:1}),r(ae,{class:`sr-only`},{default:x(()=>[...t[16]||=[i(`Create a new document`,-1)]]),_:1}),r(U,{class:`close-x`},{default:x(()=>[r(m(O),{class:`size-[15px]`})]),_:1})]),T(`div`,ge,[T(`button`,{type:`button`,class:l([`tab-btn`,{active:A.value===`freeform`}]),onClick:t[1]||=e=>A.value=`freeform`},` Freeform `,2),T(`button`,{type:`button`,class:l([`tab-btn`,{active:A.value===`manual`}]),onClick:t[2]||=e=>A.value=`manual`},` Manual `,2),T(`button`,{type:`button`,class:l([`tab-btn`,{active:A.value===`upload`}]),onClick:t[3]||=e=>A.value=`upload`},` Upload `,2)]),T(`div`,_e,[A.value===`freeform`?(d(),w(f,{key:0},[T(`div`,ve,[T(`div`,ye,[t[17]||=T(`label`,{for:`nd-freeform`},`Describe the document`,-1),r(Y,{onTranscribed:Ze})]),g(T(`textarea`,{id:`nd-freeform`,ref_key:`freeformTextarea`,ref:Ye,"onUpdate:modelValue":t[4]||=e=>j.value=e,class:`ff-textarea`,rows:`10`,placeholder:`Type the document description — like explaining what should be documented. The PM agent writes the document and chooses an appropriate path.`},null,512),[[ee,j.value]])]),T(`div`,be,[T(`div`,xe,[T(`div`,Se,[t[18]||=T(`label`,null,`Role`,-1),r(le,{modelValue:$.agent,"onUpdate:modelValue":t[5]||=e=>$.agent=e,disabled:F.value},{default:x(()=>[r(de,{class:`h-[34px] w-full rounded-[9px] px-[11px]`},{default:x(()=>[r(W,{placeholder:`agent`})]),_:1}),r(V,{position:`popper`},{default:x(()=>[r(z,{class:`min-w-[var(--radix-select-trigger-width)]`},{default:x(()=>[(d(!0),w(f,null,a(Ve.value,e=>(d(),c(B,{key:e.name,value:e.name},{default:x(()=>[i(u(e.name),1)]),_:2},1032,[`value`]))),128))]),_:1})]),_:1})]),_:1},8,[`modelValue`,`disabled`])]),T(`div`,Ce,[r(ue,{"cli-options":He.value,"model-options":Ue.value,"memory-key":`panel:new-doc`,cli:$.cli,"onUpdate:cli":t[6]||=e=>$.cli=e,model:$.model,"onUpdate:model":t[7]||=e=>$.model=e,disabled:F.value},null,8,[`cli-options`,`model-options`,`cli`,`model`,`disabled`])])])]),Q.value?n(``,!0):(d(),w(`div`,we,[t[20]||=i(` No PM agent is configured. `,-1),r(o,{to:{name:`agents`},onClick:t[8]||=e=>m(s).close()},{default:x(()=>[...t[19]||=[i(` Set one up on the Agents page `,-1)]]),_:1}),t[21]||=i(` — until then use the Manual doc tab. `,-1)])),M.value?(d(),w(`div`,Te,u(M.value),1)):n(``,!0),T(`div`,Ee,[r(D,{variant:`outline`,onClick:t[9]||=e=>m(s).close()},{default:x(()=>[...t[22]||=[i(`Cancel`,-1)]]),_:1}),r(D,{variant:`default`,onClick:fe,disabled:m(s).saving||!j.value.trim()},{default:x(()=>[F.value?(d(),c(R,{key:0})):n(``,!0),i(` `+u(F.value?`Asking the PM agent…`:`Create document`),1)]),_:1},8,[`disabled`])]),qe.value.length?(d(),w(`div`,De,[T(`div`,Oe,[r(R),t[23]||=i(` PM agent `,-1)]),T(`div`,{class:`ff-stream-log`,ref_key:`ffLogEl`,ref:Je},[(d(!0),w(f,null,a(qe.value,(e,t)=>(d(),w(`div`,{key:t,class:l([`ff-stream-line`,e.s===`err`?`err`:``])},u(e.d),3))),128))],512)])):n(``,!0)],64)):A.value===`manual`?(d(),w(f,{key:1},[T(`div`,ke,[t[24]||=T(`label`,{for:`nd-path`},`File path`,-1),r(J,{id:`nd-path`,modelValue:m(s).nd.path,"onUpdate:modelValue":t[10]||=e=>m(s).nd.path=e,placeholder:`docs/my-document.md`,onKeyup:_(pe,[`enter`])},null,8,[`modelValue`])]),T(`div`,Ae,[T(`div`,je,[t[25]||=T(`label`,{for:`nd-content`},`Content`,-1),r(Y,{onTranscribed:Qe})]),g(T(`textarea`,{id:`nd-content`,ref_key:`docBodyTextarea`,ref:Xe,"onUpdate:modelValue":t[11]||=e=>m(s).nd.content=e,class:`doc-textarea`,rows:`15`,placeholder:`Enter the document content in Markdown format...`},null,512),[[ee,m(s).nd.content]])]),T(`div`,Me,[r(D,{variant:`outline`,onClick:t[12]||=e=>m(s).close()},{default:x(()=>[...t[26]||=[i(`Cancel`,-1)]]),_:1}),r(D,{variant:`default`,onClick:pe,disabled:m(s).saving||!m(s).nd.path||!m(s).nd.content},{default:x(()=>[...t[27]||=[i(` Create `,-1)]]),_:1},8,[`disabled`])])],64)):A.value===`upload`?(d(),w(f,{key:2},[T(`div`,Ne,[t[28]||=T(`label`,{for:`nd-upload-path`},`File path`,-1),r(J,{id:`nd-upload-path`,modelValue:q.value,"onUpdate:modelValue":t[13]||=e=>q.value=e,placeholder:`docs/my-document.md — or docs/design/assets/ to keep the filename`},null,8,[`modelValue`])]),T(`div`,Pe,[t[29]||=T(`label`,{for:`nd-upload-file`},`Select file`,-1),T(`input`,{id:`nd-upload-file`,type:`file`,class:`upload-input`,onChange:Be},null,32),K.value?(d(),w(`div`,Fe,[i(u(K.value.name)+` (`+u((K.value.size/1024).toFixed(1))+` KB) `,1),Z.value?(d(),w(`span`,Ie,`→ `+u(Z.value),1)):n(``,!0)])):n(``,!0)]),X.value?(d(),w(`div`,Le,u(X.value),1)):n(``,!0),T(`div`,Re,[r(D,{variant:`outline`,onClick:t[14]||=e=>m(s).close()},{default:x(()=>[...t[30]||=[i(`Cancel`,-1)]]),_:1}),r(D,{variant:`default`,onClick:ze,disabled:m(s).saving||!K.value||!q.value.trim()},{default:x(()=>[...t[31]||=[i(` Upload `,-1)]]),_:1},8,[`disabled`])])],64)):n(``,!0)])]),_:1},8,[`style`])]),_:1},8,[`open`])}}}),[[`__scopeId`,`data-v-4849f9ae`]]),Be={class:`drawer-head`},Ve={class:`drawer-tabs`},He={class:`drawer-body`},Ue={class:`field`},We={class:`ff-agent-bar`},$={key:0,class:`ff-notice`},Ge={key:1,class:`ff-error`},Ke={class:`btn-row`,style:{"margin-top":`20px`}},qe={key:2,class:`ff-stream`},Je={class:`ff-stream-head`},Ye={class:`field`},Xe={key:0,class:`hint`},Ze={class:`field`},Qe={class:`field`},$e={key:0,class:`ff-error`},et={class:`btn-row`,style:{"margin-top":`20px`}},tt={class:`field`},nt={key:0,class:`hint`},rt={class:`field`},it={key:0,class:`upload-file-info`},at={key:0,class:`ff-error`},ot={class:`btn-row`,style:{"margin-top":`20px`}},st=F(s({__name:`NewSkillPanel`,setup(t){let s=ce(),_=N(),b=oe(),S=se(),C=p(()=>s.isNewSkill);function re(e){e||s.close()}let E=v(`freeform`),k=v(``),A=v(``),j=v(!1),M=v(null),F=v(``),z=v(null),B=v(``),V=p(()=>!b.loaded||(b.agents??[]).some(e=>e.name===`pm`&&e.enabled)),H=p(()=>(b.agents??[]).find(e=>e.enabled&&e.name===`pm`)??null),W=h({cli:``,model:``});function G(){W.cli=H.value?.cli||``,W.model=H.value?.model||``}let le=p(()=>{let e=H.value;return e?W.cli!==e.cli||W.model!==e.model:!1}),K=p(()=>b.agentsMeta.clis??[]),de=p(()=>b.modelsFor(W.cli,W.model||void 0)),q=p(()=>s.ns.name.trim().toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``));e(()=>s.isNewSkill,e=>{e&&(E.value=`freeform`,k.value=``,A.value=``,F.value=``,z.value=null,B.value=``,G())});async function Y(e){s.close(),await _.refresh(),await S.loadSkills(),e&&await S.loadSkill(e)}async function X(){let e=k.value.trim();if(e){s.saving=!0,j.value=!0,A.value=``,M.value&&_.clearOutput(M.value),M.value=crypto.randomUUID();try{let t=le.value?{cli:W.cli,model:W.model}:void 0,n=await _.createFreeformSkill(e,M.value,t);k.value=``,await Y(n.path)}catch(e){A.value=e instanceof Error?e.message:String(e)}finally{j.value=!1,M.value=null,s.saving=!1}}}async function Z(){if(!(!s.ns.name.trim()||!s.ns.description.trim()||!s.ns.content.trim())){s.saving=!0,F.value=``;try{await Y((await _.createSkill({name:s.ns.name.trim(),description:s.ns.description.trim(),body:s.ns.content})).path)}catch(e){F.value=e instanceof Error?e.message:String(e)}finally{s.saving=!1}}}async function Q(){if(!(!z.value||!s.ns.name.trim())){s.saving=!0,B.value=``;try{let e=await z.value.text();await Y((await _.createSkill({name:s.ns.name.trim(),content:e})).path)}catch(e){B.value=e instanceof Error?e.message:String(e)}finally{s.saving=!1}}}function fe(e){let t=e.target.files;t&&t.length>0&&(z.value=t[0])}let pe=p(()=>(M.value?_.outputs[M.value]??[]:[]).map(e=>`type`in e?{s:`out`,d:e.type===`text`?e.text:e.d??``}:{s:e.s===`err`?`err`:`out`,d:e.d})),me=v(null);return e(pe,()=>{o(()=>{let e=me.value;e&&(e.scrollTop=e.scrollHeight)})}),(e,t)=>{let o=y(`router-link`);return d(),c(ie,{open:C.value,"onUpdate:open":re},{default:x(()=>[r(P),r(I,{style:ne({width:m(s).drawerWidth+`px`,"max-width":`100vw`})},{default:x(()=>[T(`div`,{class:`drawer-resize`,onMousedown:t[0]||=te((...e)=>m(s).startResize&&m(s).startResize(...e),[`prevent`])},null,32),T(`div`,Be,[r(L,null,{default:x(()=>[...t[15]||=[i(`New skill`,-1)]]),_:1}),r(ae,{class:`sr-only`},{default:x(()=>[...t[16]||=[i(`Create a new skill`,-1)]]),_:1}),r(U,{class:`close-x`},{default:x(()=>[r(m(O),{class:`size-[15px]`})]),_:1})]),T(`div`,Ve,[T(`button`,{type:`button`,class:l([`tab-btn`,{active:E.value===`freeform`}]),onClick:t[1]||=e=>E.value=`freeform`},` Freeform `,2),T(`button`,{type:`button`,class:l([`tab-btn`,{active:E.value===`manual`}]),onClick:t[2]||=e=>E.value=`manual`},` Manual `,2),T(`button`,{type:`button`,class:l([`tab-btn`,{active:E.value===`upload`}]),onClick:t[3]||=e=>E.value=`upload`},` Upload `,2)]),T(`div`,He,[E.value===`freeform`?(d(),w(f,{key:0},[T(`div`,Ue,[t[17]||=T(`label`,{for:`ns-freeform`},`Describe the skill`,-1),g(T(`textarea`,{id:`ns-freeform`,"onUpdate:modelValue":t[4]||=e=>k.value=e,class:`ff-textarea`,rows:`10`,placeholder:`Describe what the skill should do and when an agent should reach for it. The PM agent writes the SKILL.md and picks the skills/<name>/ folder.`},null,512),[[ee,k.value]])]),T(`div`,We,[r(ue,{"cli-options":K.value,"model-options":de.value,"memory-key":`panel:new-skill`,cli:W.cli,"onUpdate:cli":t[5]||=e=>W.cli=e,model:W.model,"onUpdate:model":t[6]||=e=>W.model=e,disabled:j.value},null,8,[`cli-options`,`model-options`,`cli`,`model`,`disabled`])]),V.value?n(``,!0):(d(),w(`div`,$,[t[19]||=i(` No PM agent is configured. `,-1),r(o,{to:{name:`agents`},onClick:t[7]||=e=>m(s).close()},{default:x(()=>[...t[18]||=[i(` Set one up on the Agents page `,-1)]]),_:1}),t[20]||=i(` — until then use the Manual tab. `,-1)])),A.value?(d(),w(`div`,Ge,u(A.value),1)):n(``,!0),T(`div`,Ke,[r(D,{variant:`outline`,onClick:t[8]||=e=>m(s).close()},{default:x(()=>[...t[21]||=[i(`Cancel`,-1)]]),_:1}),r(D,{variant:`default`,onClick:X,disabled:m(s).saving||!k.value.trim()},{default:x(()=>[j.value?(d(),c(R,{key:0})):n(``,!0),i(` `+u(j.value?`Asking the PM agent…`:`Create skill`),1)]),_:1},8,[`disabled`])]),pe.value.length?(d(),w(`div`,qe,[T(`div`,Je,[r(R),t[22]||=i(` PM agent `,-1)]),T(`div`,{class:`ff-stream-log`,ref_key:`ffLogEl`,ref:me},[(d(!0),w(f,null,a(pe.value,(e,t)=>(d(),w(`div`,{key:t,class:l([`ff-stream-line`,e.s===`err`?`err`:``])},u(e.d),3))),128))],512)])):n(``,!0)],64)):E.value===`manual`?(d(),w(f,{key:1},[T(`div`,Ye,[t[23]||=T(`label`,{for:`ns-name`},`Skill name`,-1),r(J,{id:`ns-name`,modelValue:m(s).ns.name,"onUpdate:modelValue":t[9]||=e=>m(s).ns.name=e,placeholder:`my-skill`},null,8,[`modelValue`]),q.value?(d(),w(`div`,Xe,`→ skills/`+u(q.value)+`/SKILL.md`,1)):n(``,!0)]),T(`div`,Ze,[t[24]||=T(`label`,{for:`ns-desc`},`Description`,-1),r(J,{id:`ns-desc`,modelValue:m(s).ns.description,"onUpdate:modelValue":t[10]||=e=>m(s).ns.description=e,placeholder:`One line: when should an agent use this skill?`},null,8,[`modelValue`])]),T(`div`,Qe,[t[25]||=T(`label`,{for:`ns-body`},`Instructions (Markdown)`,-1),g(T(`textarea`,{id:`ns-body`,"onUpdate:modelValue":t[11]||=e=>m(s).ns.content=e,class:`doc-textarea`,rows:`14`,placeholder:`# My skill
|
|
3
|
+
|
|
4
|
+
What the agent should do when this skill is active...`},null,512),[[ee,m(s).ns.content]])]),F.value?(d(),w(`div`,$e,u(F.value),1)):n(``,!0),T(`div`,et,[r(D,{variant:`outline`,onClick:t[12]||=e=>m(s).close()},{default:x(()=>[...t[26]||=[i(`Cancel`,-1)]]),_:1}),r(D,{variant:`default`,onClick:Z,disabled:m(s).saving||!m(s).ns.name.trim()||!m(s).ns.description.trim()||!m(s).ns.content.trim()},{default:x(()=>[...t[27]||=[i(` Create `,-1)]]),_:1},8,[`disabled`])])],64)):(d(),w(f,{key:2},[T(`div`,tt,[t[28]||=T(`label`,{for:`ns-upload-name`},`Skill name`,-1),r(J,{id:`ns-upload-name`,modelValue:m(s).ns.name,"onUpdate:modelValue":t[13]||=e=>m(s).ns.name=e,placeholder:`my-skill`},null,8,[`modelValue`]),q.value?(d(),w(`div`,nt,`→ skills/`+u(q.value)+`/SKILL.md`,1)):n(``,!0)]),T(`div`,rt,[t[29]||=T(`label`,{for:`ns-upload-file`},`Select SKILL.md`,-1),T(`input`,{id:`ns-upload-file`,type:`file`,class:`upload-input`,onChange:fe},null,32),z.value?(d(),w(`div`,it,u(z.value.name)+` (`+u((z.value.size/1024).toFixed(1))+` KB) `,1)):n(``,!0)]),B.value?(d(),w(`div`,at,u(B.value),1)):n(``,!0),T(`div`,ot,[r(D,{variant:`outline`,onClick:t[14]||=e=>m(s).close()},{default:x(()=>[...t[30]||=[i(`Cancel`,-1)]]),_:1}),r(D,{variant:`default`,onClick:Q,disabled:m(s).saving||!z.value||!m(s).ns.name.trim()},{default:x(()=>[...t[31]||=[i(` Upload `,-1)]]),_:1},8,[`disabled`])])],64))])]),_:1},8,[`style`])]),_:1},8,[`open`])}}}),[[`__scopeId`,`data-v-a348ce84`]]),ct={class:`ctx-page`},lt={style:{display:`flex`,"align-items":`flex-end`,"justify-content":`space-between`,"margin-bottom":`20px`}},ut={class:`ctx-tabs`},dt={class:`repo-grid`},ft={key:0,class:`ctx-empty`},pt={key:1,class:`doc-tree`},mt={key:0,class:`ctx-refresh-error`},ht=[`onClick`],gt=[`onClick`],_t={class:`dir-name`},vt={key:0,class:`ctx-empty`},yt=[`onClick`],bt={class:`skill-name`},xt={key:0,class:`skill-desc`},St={class:`ctx-discover-head`},Ct={key:0,class:`ctx-refresh-error`},wt={key:1,class:`ctx-empty`},Tt=[`onClick`],Et={class:`skill-name`},Dt={class:`ctx-skill-meta`},Ot={key:0,class:`ctx-installed`},kt={key:0},At={class:`doc-title`},jt={class:`doc-path`},Mt=[`innerHTML`],Nt={key:1,style:{color:`var(--txt-faint)`}},Pt={key:0},Ft={class:`doc-title`},It={class:`doc-path`},Lt={key:0,class:`skill-desc-line`},Rt=[`innerHTML`],zt={key:1,style:{color:`var(--txt-faint)`}},Bt={class:`doc-title`},Vt={class:`ctx-detail-meta`},Ht={class:`ctx-detail-copy`},Ut={key:0,class:`ctx-detail-copy`},Wt={class:`ctx-detail-copy`},Gt={key:1,class:`ctx-review-check`},Kt={class:`ctx-detail-actions`},qt=F(s({__name:`ContextView`,setup(s){let h=se(),te=ce(),{docs:_,selDoc:y,docContent:O,docTitle:ie,skills:N,selSkill:ae,skillContent:P,skillName:oe,skillDesc:F}=S(h),I=v(`docs`),L=v(``),R=v([]),z=v(!1),B=v(``),V=v(null),H=v(null),U=v(!1),W=v(!1),le=p(()=>new Set(N.value.map(e=>e.name)));async function ue(){z.value=!0,B.value=``;try{let e=L.value.trim().length>=2?`/api/skill-registry/search?q=${encodeURIComponent(L.value.trim())}`:`/api/skill-registry/curated`;R.value=(await re(e)).skills}catch(e){B.value=e instanceof Error?e.message:`Skills.sh is unavailable`}finally{z.value=!1}}async function K(e){try{let t=await re(`/api/skill-registry/detail?id=${encodeURIComponent(e.id)}`);V.value=t.detail,H.value=t.audit,U.value=!1}catch(e){B.value=e instanceof Error?e.message:`Could not load skill details`}}async function de(){if(!(!V.value||W.value)){W.value=!0,B.value=``;try{await re(`/api/skill-registry/install`,E(`POST`,{id:V.value.id})),await h.loadSkills()}catch(e){B.value=e instanceof Error?e.message:`Could not install skill`}finally{W.value=!1}}}function J(e){let t=N.value.find(t=>t.name===e);t&&(I.value=`skills`,h.loadSkill(t.path))}let Y=v(new Set),X=v(!1),Z=v(``),Q=v(null),he=e=>!!e&&/\.md$/i.test(e),ge=p(()=>q(O.value)),_e=p(()=>q(P.value));async function ve(){await o(),Q.value&&await fe(Q.value)}e([O,P,I],()=>void ve(),{flush:`post`}),t(()=>void ve()),e(I,e=>{e===`discover`&&!R.value.length&&ue()});let ye;e(L,()=>{clearTimeout(ye),ye=setTimeout(()=>void ue(),250)});let be=p(()=>me(pe(_.value),Y.value));function xe(e){Y.value.has(e)?Y.value.delete(e):Y.value.add(e)}function Se(e){return{paddingLeft:`${8+e*16}px`}}async function Ce(){X.value=!0,Z.value=``;try{await h.loadDocs()?y.value&&!_.value.some(e=>e.path===y.value)&&(_.value.length?h.loadDoc(_.value[0].path):(y.value=null,O.value=``)):Z.value=`Could not refresh docs.`}finally{X.value=!1}}let we=b();return e(_,e=>{let t=typeof we.query.doc==`string`?we.query.doc:null;t&&e.some(e=>e.path===t)&&y.value!==t&&h.loadDoc(t)},{immediate:!0}),(e,t)=>(d(),w(`div`,ct,[T(`div`,lt,[t[8]||=T(`div`,null,[T(`div`,{class:`page-title`},`Repo Context`),T(`div`,{class:`page-desc`,style:{margin:`3px 0 0`}},`AI-readable docs · ADRs · skills`)],-1),r(D,{variant:`accent`,class:`new-btn`,onClick:t[0]||=e=>I.value===`docs`?m(te).openNewDoc():m(te).openNewSkill()},{default:x(()=>[t[7]||=T(`svg`,{viewBox:`0 0 24 24`,fill:`none`},[T(`path`,{d:`M12 5v14M5 12h14`,stroke:`currentColor`,"stroke-width":`2`,"stroke-linecap":`round`})],-1),i(` `+u(I.value===`docs`?`New doc`:`New skill`),1)]),_:1})]),T(`div`,ut,[T(`button`,{class:l([`ctx-tab`,{on:I.value===`docs`}]),onClick:t[1]||=e=>I.value=`docs`},`Docs`,2),T(`button`,{class:l([`ctx-tab`,{on:I.value===`skills`}]),onClick:t[2]||=e=>I.value=`skills`},` Skills `,2),T(`button`,{class:l([`ctx-tab`,{on:I.value===`discover`}]),onClick:t[3]||=e=>I.value=`discover`},` Discover `,2),I.value===`docs`?(d(),c(D,{key:0,variant:`ghost`,size:`sm`,class:`ctx-refresh-btn`,disabled:X.value,title:`Refresh documentation`,onClick:Ce},{default:x(()=>[r(m(k),{class:l([`size-4`,{refreshing:X.value}])},null,8,[`class`])]),_:1},8,[`disabled`])):n(``,!0)]),T(`div`,dt,[r(G,{class:`doc-list`},{default:x(()=>[I.value===`docs`?(d(),w(f,{key:0},[m(_).length?(d(),w(`div`,pt,[Z.value?(d(),w(`div`,mt,u(Z.value),1)):n(``,!0),(d(!0),w(f,null,a(be.value,e=>(d(),w(f,{key:e.key},[e.isFile?(d(),w(`div`,{key:0,class:l([`tree-item tree-file`,{sel:m(y)===e.path}]),style:ne(Se(e.depth)),onClick:t=>m(h).loadDoc(e.path)},[r(m(A),{class:`size-4`}),T(`span`,null,u(e.name),1)],14,ht)):(d(),w(`div`,{key:1,class:`tree-item tree-dir`,style:ne(Se(e.depth)),onClick:t=>xe(e.key)},[Y.value.has(e.key)?(d(),c(m(M),{key:0,class:`size-4 chevron`})):(d(),c(m(j),{key:1,class:`size-4 chevron`})),T(`span`,_t,u(e.name),1)],12,gt))],64))),128))])):(d(),w(`div`,ft,`No docs found.`))],64)):I.value===`skills`?(d(),w(f,{key:1},[m(N).length?n(``,!0):(d(),w(`div`,vt,[...t[9]||=[i(` No skills yet — add a `,-1),T(`code`,null,`skills/<name>/SKILL.md`,-1),i(`. `,-1)]])),(d(!0),w(f,null,a(m(N),e=>(d(),w(`div`,{key:e.path,class:l([`skill-row`,{sel:m(ae)===e.path}]),onClick:t=>m(h).loadSkill(e.path)},[T(`span`,bt,[t[10]||=T(`svg`,{viewBox:`0 0 24 24`,fill:`none`},[T(`path`,{d:`M13 2L4.5 13.5H11L9.5 22 19.5 10H13L13 2z`,stroke:`currentColor`,"stroke-width":`1.8`,"stroke-linejoin":`round`})],-1),i(` `+u(e.name),1)]),e.description?(d(),w(`span`,xt,u(e.description),1)):n(``,!0)],10,yt))),128))],64)):(d(),w(f,{key:2},[T(`div`,St,[t[11]||=T(`strong`,null,`Skills.sh curated catalog`,-1),t[12]||=T(`span`,null,`Inspect files and audits before installing into this project.`,-1),g(T(`input`,{"onUpdate:modelValue":t[4]||=e=>L.value=e,class:`ctx-skill-search`,placeholder:`Search skills`},null,512),[[ee,L.value]])]),B.value?(d(),w(`div`,Ct,u(B.value),1)):z.value?(d(),w(`div`,wt,`Loading Skills.sh…`)):n(``,!0),(d(!0),w(f,null,a(R.value,e=>(d(),w(`button`,{key:e.id,type:`button`,class:l([`skill-row ctx-catalog-skill`,{sel:V.value?.id===e.id}]),onClick:t=>K(e)},[T(`span`,Et,u(e.name),1),T(`span`,Dt,u(e.source)+` · `+u(e.installs.toLocaleString())+` installs`,1),le.value.has(e.slug)?(d(),w(`span`,Ot,`Installed`)):n(``,!0)],10,Tt))),128))],64))]),_:1}),r(G,{class:`doc-view`},{default:x(()=>[I.value===`docs`?(d(),w(f,{key:0},[m(O)?(d(),w(`div`,kt,[T(`div`,At,u(m(ie)),1),T(`div`,jt,u(m(y)),1),he(m(y))?(d(),w(`div`,{key:0,ref_key:`markdownRoot`,ref:Q,class:`md-rendered`,innerHTML:ge.value},null,8,Mt)):(d(),w(f,{key:1},[i(u(m(O)),1)],64))])):(d(),w(`div`,Nt,`Select a document.`))],64)):I.value===`skills`?(d(),w(f,{key:1},[m(P)?(d(),w(`div`,Pt,[T(`div`,Ft,u(m(oe)),1),T(`div`,It,u(m(ae)),1),m(F)?(d(),w(`div`,Lt,u(m(F)),1)):n(``,!0),he(m(ae))?(d(),w(`div`,{key:1,ref_key:`markdownRoot`,ref:Q,class:`md-rendered`,innerHTML:_e.value},null,8,Rt)):(d(),w(f,{key:2},[i(u(m(P)),1)],64))])):(d(),w(`div`,zt,`Select a skill.`))],64)):(d(),w(f,{key:2},[V.value?(d(),w(f,{key:0},[T(`div`,Bt,u(V.value.slug),1),T(`div`,Vt,u(V.value.source)+` · `+u(V.value.installs.toLocaleString())+` installs · `+u(V.value.hash??`unhashed`),1),T(`div`,Ht,[i(u(V.value.files?.length??0)+` files will be copied into `,1),T(`code`,null,`skills/`+u(V.value.slug)+`/`,1),t[13]||=i(` and locked in `,-1),t[14]||=T(`code`,null,`skills.lock.json`,-1),t[15]||=i(`. `,-1)]),H.value?.audits?.length?(d(),w(`div`,Ut,[t[17]||=T(`strong`,null,`Security audits`,-1),t[18]||=T(`br`,null,null,-1),(d(!0),w(f,null,a(H.value.audits,e=>(d(),w(`span`,{key:e.provider},[i(u(e.provider)+`: `+u(e.status)+` — `+u(e.summary),1),t[16]||=T(`br`,null,null,-1)]))),128))])):n(``,!0),T(`details`,Wt,[t[19]||=T(`summary`,null,`Review files before installing`,-1),(d(!0),w(f,null,a(V.value.files,e=>(d(),w(`pre`,{key:e.path},[T(`strong`,null,u(e.path),1),i(`\\n`+u(e.contents),1)]))),128))]),le.value.has(V.value.slug)?n(``,!0):(d(),w(`label`,Gt,[g(T(`input`,{"onUpdate:modelValue":t[5]||=e=>U.value=e,type:`checkbox`},null,512),[[C,U.value]]),t[20]||=i(` I reviewed these files and want to add this skill to the project. `,-1)])),T(`div`,Kt,[le.value.has(V.value.slug)?(d(),c(D,{key:0,variant:`accent`,onClick:t[6]||=e=>J(V.value.slug)},{default:x(()=>[...t[21]||=[i(`Open installed skill`,-1)]]),_:1})):(d(),c(D,{key:1,variant:`accent`,disabled:W.value||!U.value,onClick:de},{default:x(()=>[i(u(W.value?`Installing…`:`Install to project`),1)]),_:1},8,[`disabled`]))])],64)):(d(),w(f,{key:1},[t[22]||=T(`div`,{class:`doc-title`},`Discover skills`,-1),t[23]||=T(`div`,{class:`skill-desc-line`},` Select a skill to inspect its exact files, content hash, publisher, and security audit before installing it. `,-1)],64))],64))]),_:1})]),r(ze),r(st)]))}}),[[`__scopeId`,`data-v-6925ffc2`]]);export{qt as default};
|