@repo-os/repoos 0.5.45 → 0.5.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -3
- package/dist/.build-info.json +2 -2
- package/dist/.build-stamp.json +1 -1
- package/dist/cli/index.js +6 -0
- package/dist/commands/uninstall.d.ts +13 -0
- package/dist/commands/uninstall.js +111 -0
- package/dist/server/integration-orchestrator.d.ts +27 -0
- package/dist/server/integration-orchestrator.js +97 -30
- package/dist/ui/assets/AgentsView-7zA87rTf.js +1 -0
- package/dist/ui/assets/{AgentsView-CF4wRvHh.css → AgentsView-CdTKjw_Y.css} +1 -1
- package/dist/ui/assets/{ContextView-DsOqAdyE.js → ContextView-MigaqOfe.js} +2 -2
- package/dist/ui/assets/{DashboardView-BOhsIJqO.js → DashboardView-Dcrwlrwn.js} +1 -1
- package/dist/ui/assets/{DeploymentsView-DXu_FYR2.js → DeploymentsView-DxCQsZvb.js} +1 -1
- package/dist/ui/assets/{InputsView-24HVbVPk.js → InputsView-C1A3fbei.js} +1 -1
- package/dist/ui/assets/{LoginView-BqupI0Lt.js → LoginView-DRMjCnGr.js} +1 -1
- package/dist/ui/assets/{ReleasesView-CAgMuxpe.js → ReleasesView-jG4d0Mo5.js} +1 -1
- package/dist/ui/assets/SettingsView-w8HbTZnf.js +3 -0
- package/dist/ui/assets/WorkView-BURSyjUL.js +1 -0
- package/dist/ui/assets/{abnfDiagram-VCTEODGH-J5lkSnEE.js → abnfDiagram-VCTEODGH-B3HDyW1L.js} +1 -1
- package/dist/ui/assets/architecture-7GRP2DOG-B-YNUE4u.js +1 -0
- package/dist/ui/assets/{architectureDiagram-5GKGNRK7-C3k89uKX.js → architectureDiagram-5GKGNRK7-CF1NMjye.js} +1 -1
- package/dist/ui/assets/{blockDiagram-I7D4REHJ-AWNoBzop.js → blockDiagram-I7D4REHJ-NN5i_rnJ.js} +1 -1
- package/dist/ui/assets/{c4Diagram-7LVT6UL2-DKG1D5gd.js → c4Diagram-7LVT6UL2-CIIOAuP6.js} +1 -1
- package/dist/ui/assets/channel-ByPPwpr0.js +1 -0
- package/dist/ui/assets/{chunk-4HAMMTFA-D1YR8lF_.js → chunk-4HAMMTFA-l4djRUYV.js} +1 -1
- package/dist/ui/assets/{chunk-75Z2AOVW-5GuBxfsL.js → chunk-75Z2AOVW-DyrFYAG_.js} +1 -1
- package/dist/ui/assets/{chunk-DU6HZSFF-DfdNNqwa.js → chunk-DU6HZSFF-CItRm7J1.js} +1 -1
- package/dist/ui/assets/{chunk-F27PBJKO-BPZzinQ4.js → chunk-F27PBJKO-DaczqqTE.js} +1 -1
- package/dist/ui/assets/{chunk-GMAD6QVW-DGWvSKj5.js → chunk-GMAD6QVW-CB0tZHa7.js} +1 -1
- package/dist/ui/assets/{chunk-GVQU2GXP-D6Aw75wJ.js → chunk-GVQU2GXP-C-cDJVm0.js} +1 -1
- package/dist/ui/assets/{chunk-IMKFNOWR-B8mMBKCW.js → chunk-IMKFNOWR-OA75ThJF.js} +1 -1
- package/dist/ui/assets/{chunk-L3NEJ4N5-D5OJuXYE.js → chunk-L3NEJ4N5-CBE4DSCk.js} +1 -1
- package/dist/ui/assets/{chunk-OSK3NFVY-B7r9w2UW.js → chunk-OSK3NFVY-BuXhb1_B.js} +1 -1
- package/dist/ui/assets/{chunk-P2QGCYS3-C74X4AQX.js → chunk-P2QGCYS3-BGBBMTyP.js} +1 -1
- package/dist/ui/assets/{chunk-POPQ4Y6H-C5_u1gUS.js → chunk-POPQ4Y6H-D0ZTnRsC.js} +1 -1
- package/dist/ui/assets/{chunk-PWAF6VOD-DfoTLtxn.js → chunk-PWAF6VOD-ByX-zr35.js} +1 -1
- package/dist/ui/assets/{chunk-SHT3W25Y-D40m2eqz.js → chunk-SHT3W25Y-Bh_gkUMX.js} +1 -1
- package/dist/ui/assets/{chunk-SVP7TREG-euxi0Kap.js → chunk-SVP7TREG-DW3_jpLk.js} +1 -1
- package/dist/ui/assets/{chunk-TICWLB2K-fkdxngzN.js → chunk-TICWLB2K-DdzwBMkK.js} +1 -1
- package/dist/ui/assets/classDiagram-ZZMXUADV-Dl8H1P8I.js +1 -0
- package/dist/ui/assets/classDiagram-v2-VYDZK3BY-Dl8H1P8I.js +1 -0
- package/dist/ui/assets/{cynefin-OW5HDTMX-B5m_COsS.js → cynefin-OW5HDTMX-HRsrbC5X.js} +1 -1
- package/dist/ui/assets/{cynefinDiagram-5FMLGOSQ-C-AG6CGe.js → cynefinDiagram-5FMLGOSQ-BygrCWJt.js} +1 -1
- package/dist/ui/assets/{dagre-GXQ25YYZ-DDfDnp8L.js → dagre-GXQ25YYZ-unKY8vsX.js} +1 -1
- package/dist/ui/assets/{diagram-S7CK7UJ4-DjQZAlEY.js → diagram-S7CK7UJ4-bBTGuKeX.js} +1 -1
- package/dist/ui/assets/{diagram-UQ7AKVKN-DAZ9yp1B.js → diagram-UQ7AKVKN-DhSz2err.js} +1 -1
- package/dist/ui/assets/{diagram-VSXAHHWV-BWepUKJD.js → diagram-VSXAHHWV-D_1IlJ5N.js} +1 -1
- package/dist/ui/assets/{diagram-VX7I27RA-EcV1J81b.js → diagram-VX7I27RA-DcJu9i5Y.js} +1 -1
- package/dist/ui/assets/{diagram-Z3DM3KII-Dbz7XU_K.js → diagram-Z3DM3KII-BegKxxS3.js} +1 -1
- package/dist/ui/assets/{ebnfDiagram-PWID7BFC-BUyQw8Mm.js → ebnfDiagram-PWID7BFC-B2W_iiID.js} +1 -1
- package/dist/ui/assets/{erDiagram-RLTQ6QDP-WVf8ukKt.js → erDiagram-RLTQ6QDP-DgQmNV6c.js} +1 -1
- package/dist/ui/assets/eventmodeling-NTZA5JFV-DG7FAHfq.js +1 -0
- package/dist/ui/assets/flowDiagram-HODETNUW-BW1KIkAC.js +1 -0
- package/dist/ui/assets/{ganttDiagram-EL5Y4UJY-rB4MZuB-.js → ganttDiagram-EL5Y4UJY-1Q0-GyM3.js} +1 -1
- package/dist/ui/assets/{gitGraph-4MIJSDKK-BOTWM8dY.js → gitGraph-4MIJSDKK-BR7WCjO-.js} +1 -1
- package/dist/ui/assets/{gitGraphDiagram-WWUBYQGX-eYscuhtP.js → gitGraphDiagram-WWUBYQGX-yNQ1AZdE.js} +1 -1
- package/dist/ui/assets/{index-BACBfnga.css → index-BqPcSMLi.css} +1 -1
- package/dist/ui/assets/index-KCn__xLG.js +26 -0
- package/dist/ui/assets/{info-A6RAGUB7-_67wOORe.js → info-A6RAGUB7-CqP9o5kc.js} +1 -1
- package/dist/ui/assets/{infoDiagram-27XIBGKW-XVXbddTA.js → infoDiagram-27XIBGKW-CQXLSaWm.js} +1 -1
- package/dist/ui/assets/{ishikawaDiagram-5VMMS53U-ClLNiEru.js → ishikawaDiagram-5VMMS53U-B9xRfvdR.js} +1 -1
- package/dist/ui/assets/{journeyDiagram-3NMN7TZE-NRawjR6i.js → journeyDiagram-3NMN7TZE-CLecupNd.js} +1 -1
- package/dist/ui/assets/{kanban-definition-UXKFOSKX-BgSzBfIx.js → kanban-definition-UXKFOSKX-Bgh0O41s.js} +1 -1
- package/dist/ui/assets/{line-KAyfuul4.js → line-D-TkCLYl.js} +1 -1
- package/dist/ui/assets/{mermaid-parser.core-CgXZk1iN.js → mermaid-parser.core-DuQ04aZW.js} +3 -3
- package/dist/ui/assets/{mermaid.core-BUUkChHW.js → mermaid.core-BBpIvweb.js} +4 -4
- package/dist/ui/assets/{mindmap-definition-YA3MSWOX-Cpn7vW4r.js → mindmap-definition-YA3MSWOX-DSHjdhEw.js} +1 -1
- package/dist/ui/assets/{packet-AYTQ26CC-0lZwM-d6.js → packet-AYTQ26CC-BDfW3rtB.js} +1 -1
- package/dist/ui/assets/{pegDiagram-XKGWAZYB-impy0inn.js → pegDiagram-XKGWAZYB-rMIAYGZz.js} +1 -1
- package/dist/ui/assets/{pie-WAS4IAKB-CqfdGHYg.js → pie-WAS4IAKB-DfYZwArG.js} +1 -1
- package/dist/ui/assets/{pieDiagram-E7YTZNPT-CxjL4I1h.js → pieDiagram-E7YTZNPT-CuQsR7e8.js} +1 -1
- package/dist/ui/assets/{quadrantDiagram-AXDQQJYC-Cjd1QMIe.js → quadrantDiagram-AXDQQJYC-Dt2tyjxB.js} +1 -1
- package/dist/ui/assets/{radar-RG4KPBEZ-CRkQIwiv.js → radar-RG4KPBEZ-DVzWY-M9.js} +1 -1
- package/dist/ui/assets/{railroad-74A4TZTK-i67XSWTB.js → railroad-74A4TZTK-Cu6stMtw.js} +1 -1
- package/dist/ui/assets/railroad-abnf-HS5TGJTU-D05JnF_u.js +1 -0
- package/dist/ui/assets/railroad-ebnf-LZEXJU2U-Dwp8jJ0X.js +1 -0
- package/dist/ui/assets/railroad-peg-WCYAUIDC-lqOiNYZz.js +1 -0
- package/dist/ui/assets/{railroadDiagram-O6MQD6OU-_pK0qyaY.js → railroadDiagram-O6MQD6OU-DdPLKXLv.js} +1 -1
- package/dist/ui/assets/{requirementDiagram-BXWQKSXE-CRrFX-yw.js → requirementDiagram-BXWQKSXE-Ced7kyzl.js} +1 -1
- package/dist/ui/assets/{sankeyDiagram-P5KCCOFB-X_xFRj9E.js → sankeyDiagram-P5KCCOFB-O7BvVpMl.js} +1 -1
- package/dist/ui/assets/{sequenceDiagram-WJ2MYXX4-Byb49lKf.js → sequenceDiagram-WJ2MYXX4-CcgW2ANH.js} +1 -1
- package/dist/ui/assets/{stateDiagram-D77RDMKH-CzaPrqYF.js → stateDiagram-D77RDMKH-9LFja-bW.js} +1 -1
- package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-DkIUWCT9.js +1 -0
- package/dist/ui/assets/{swimlanes-42K2YHIH-Cx_1lnqr.js → swimlanes-42K2YHIH--Qka2jcY.js} +1 -1
- package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-D_VVVLM0.js +8 -0
- package/dist/ui/assets/{timeline-definition-24CTP7MA-B1IbZPQ-.js → timeline-definition-24CTP7MA-Ddok2Czn.js} +1 -1
- package/dist/ui/assets/{treeView-Q6P3EWNA-DFWhVE3d.js → treeView-Q6P3EWNA-CsnID5mj.js} +1 -1
- package/dist/ui/assets/{treemap-WGGIJYW6-BmbYPThn.js → treemap-WGGIJYW6-BLo8xcAp.js} +1 -1
- package/dist/ui/assets/{vennDiagram-4TSXK5OY-Ae2AtRpt.js → vennDiagram-4TSXK5OY-mHJwXX5J.js} +1 -1
- package/dist/ui/assets/{wardley-WFR3VGLG-BtD4X4tL.js → wardley-WFR3VGLG-DKxzocuy.js} +1 -1
- package/dist/ui/assets/{wardleyDiagram-VM6X3IG4-B3YN2fTd.js → wardleyDiagram-VM6X3IG4-DSraOQ5a.js} +1 -1
- package/dist/ui/assets/{xychartDiagram-S5SC5T6Z-CIzJfMKA.js → xychartDiagram-S5SC5T6Z-DvcL8eBl.js} +1 -1
- package/dist/ui/index.html +2 -2
- package/dist/ui/sw.js +2 -2
- package/package.json +1 -1
- package/dist/ui/assets/AgentsView-D-myL-kA.js +0 -1
- package/dist/ui/assets/SettingsView-O3iZSnjg.js +0 -3
- package/dist/ui/assets/WorkView-D8Tl6qwy.js +0 -1
- package/dist/ui/assets/architecture-7GRP2DOG-pLdFt-xS.js +0 -1
- package/dist/ui/assets/channel-gA4qBv3A.js +0 -1
- package/dist/ui/assets/classDiagram-ZZMXUADV-BzW8bq2P.js +0 -1
- package/dist/ui/assets/classDiagram-v2-VYDZK3BY-BzW8bq2P.js +0 -1
- package/dist/ui/assets/eventmodeling-NTZA5JFV-DHqyLOAn.js +0 -1
- package/dist/ui/assets/flowDiagram-HODETNUW-CYk_ze5K.js +0 -1
- package/dist/ui/assets/index-BOQ-ust6.js +0 -26
- package/dist/ui/assets/railroad-abnf-HS5TGJTU-Cv9m5aS3.js +0 -1
- package/dist/ui/assets/railroad-ebnf-LZEXJU2U-C5ZIn-Jh.js +0 -1
- package/dist/ui/assets/railroad-peg-WCYAUIDC-CGra9Oq-.js +0 -1
- package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-BCXckz7K.js +0 -1
- package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-54qsKi6A.js +0 -8
package/README.md
CHANGED
|
@@ -38,13 +38,52 @@ first-class participants, but humans always hold the gate.
|
|
|
38
38
|
|
|
39
39
|
## Install
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
Choose one installation method:
|
|
42
|
+
|
|
43
|
+
### curl
|
|
44
|
+
|
|
45
|
+
Install the standalone `repoos` command. This is the quickest option when you
|
|
46
|
+
want a self-contained release build:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
curl -fsSL https://repoos.org/install.sh | bash
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
It runs on Bun when available (recommended), otherwise requires Node.js >=
|
|
53
|
+
20.6.0. It installs to `~/.repoos` and links `repoos` into `~/.local/bin`.
|
|
54
|
+
|
|
55
|
+
### npm
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install -g @repo-os/repoos
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Bun
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
bun add -g @repo-os/repoos
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### pnpm
|
|
42
68
|
|
|
43
69
|
```bash
|
|
44
|
-
|
|
70
|
+
pnpm add -g @repo-os/repoos
|
|
45
71
|
```
|
|
46
72
|
|
|
47
|
-
|
|
73
|
+
### mise
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
mise use --global npm:@repo-os/repoos
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
This uses mise's built-in npm backend and records RepoOS in your global mise
|
|
80
|
+
configuration. Make sure [mise shell activation](https://mise.jdx.dev/getting-started.html)
|
|
81
|
+
is enabled so its `repoos` shim is on your PATH.
|
|
82
|
+
|
|
83
|
+
Use the same tool to update a package-manager install: `npm update -g
|
|
84
|
+
@repo-os/repoos`, `bun update -g @repo-os/repoos`, `pnpm update -g
|
|
85
|
+
@repo-os/repoos`, or `mise upgrade npm:@repo-os/repoos`. A standalone install
|
|
86
|
+
updates with `repoos upgrade` and removes with `repoos uninstall`.
|
|
48
87
|
|
|
49
88
|
Then in any repo:
|
|
50
89
|
|
package/dist/.build-info.json
CHANGED
package/dist/.build-stamp.json
CHANGED
package/dist/cli/index.js
CHANGED
|
@@ -12,6 +12,7 @@ import { cmdServe, serveProcessTitle, setServeProcessTitle } from "../commands/s
|
|
|
12
12
|
import { cmdStop } from "../commands/stop.js";
|
|
13
13
|
import { cmdTunnel } from "../commands/tunnel.js";
|
|
14
14
|
import { cmdUpgrade } from "../commands/upgrade.js";
|
|
15
|
+
import { cmdUninstall } from "../commands/uninstall.js";
|
|
15
16
|
import { cmdStatus } from "../commands/status.js";
|
|
16
17
|
import { checkBuild } from "../core/build.js";
|
|
17
18
|
import { loadConfig } from "../core/config.js";
|
|
@@ -74,6 +75,7 @@ function help() {
|
|
|
74
75
|
${c.cyan("upgrade")} [--channel beta|canary|rc]
|
|
75
76
|
Self-update a standalone (curl-installed) repoos to the latest release
|
|
76
77
|
(stable by default; --channel tracks a prerelease line instead)
|
|
78
|
+
${c.cyan("uninstall")} [--yes] Remove the standalone (curl-installed) repoos from this machine
|
|
77
79
|
|
|
78
80
|
${c.bold("EXAMPLES")}
|
|
79
81
|
${c.dim("$")} repoos init
|
|
@@ -121,6 +123,7 @@ function main() {
|
|
|
121
123
|
"--help",
|
|
122
124
|
"-h",
|
|
123
125
|
"upgrade",
|
|
126
|
+
"uninstall",
|
|
124
127
|
]);
|
|
125
128
|
if (!skipCheck.has(cmd)) {
|
|
126
129
|
const result = checkBuild();
|
|
@@ -201,6 +204,9 @@ function main() {
|
|
|
201
204
|
case "upgrade":
|
|
202
205
|
void cmdUpgrade(rest);
|
|
203
206
|
break;
|
|
207
|
+
case "uninstall":
|
|
208
|
+
void cmdUninstall(rest);
|
|
209
|
+
break;
|
|
204
210
|
case "version":
|
|
205
211
|
case "--version":
|
|
206
212
|
case "-v":
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface StandaloneUninstallPlan {
|
|
2
|
+
installDir: string;
|
|
3
|
+
launcherPath: string | null;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Return the files owned by a default curl install, or null for every other
|
|
7
|
+
* kind of execution (source checkout, npm/Bun, custom installation, etc.).
|
|
8
|
+
*
|
|
9
|
+
* The launcher is removed only when its exact contents match the launcher this
|
|
10
|
+
* installation owns. A user's replacement launcher is never deleted.
|
|
11
|
+
*/
|
|
12
|
+
export declare function standaloneUninstallPlan(entryPath: string, home?: string, binDir?: string): StandaloneUninstallPlan | null;
|
|
13
|
+
export declare function cmdUninstall(args: string[]): Promise<void>;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `repoos uninstall` — remove a standalone install created by install.sh.
|
|
3
|
+
*
|
|
4
|
+
* This deliberately has a narrow scope. It never removes a source checkout or
|
|
5
|
+
* a package-manager install, and it leaves project data and user configuration
|
|
6
|
+
* alone. Package-manager installs must be removed by their package manager.
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync, readFileSync, rmSync } from "node:fs";
|
|
9
|
+
import { homedir } from "node:os";
|
|
10
|
+
import { dirname, join } from "node:path";
|
|
11
|
+
import { createInterface } from "node:readline/promises";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
import { c } from "../cli/colors.js";
|
|
14
|
+
import { launcherScript } from "./upgrade.js";
|
|
15
|
+
/**
|
|
16
|
+
* Return the files owned by a default curl install, or null for every other
|
|
17
|
+
* kind of execution (source checkout, npm/Bun, custom installation, etc.).
|
|
18
|
+
*
|
|
19
|
+
* The launcher is removed only when its exact contents match the launcher this
|
|
20
|
+
* installation owns. A user's replacement launcher is never deleted.
|
|
21
|
+
*/
|
|
22
|
+
export function standaloneUninstallPlan(entryPath, home = homedir(), binDir = join(home, ".local", "bin")) {
|
|
23
|
+
const installDir = dirname(dirname(entryPath));
|
|
24
|
+
const expectedInstallDir = join(home, ".repoos");
|
|
25
|
+
if (installDir !== expectedInstallDir || !existsSync(join(installDir, "cli", "index.js"))) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const launcherPath = join(binDir, "repoos");
|
|
29
|
+
let ownsLauncher = false;
|
|
30
|
+
try {
|
|
31
|
+
ownsLauncher =
|
|
32
|
+
existsSync(launcherPath) &&
|
|
33
|
+
readFileSync(launcherPath, "utf8") === launcherScript(join(installDir, "cli", "index.js"));
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// A launcher we cannot read is not safe to remove.
|
|
37
|
+
}
|
|
38
|
+
return { installDir, launcherPath: ownsLauncher ? launcherPath : null };
|
|
39
|
+
}
|
|
40
|
+
async function confirm() {
|
|
41
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
42
|
+
try {
|
|
43
|
+
const answer = (await rl.question(" Remove the standalone RepoOS install? [y/N] "))
|
|
44
|
+
.trim()
|
|
45
|
+
.toLowerCase();
|
|
46
|
+
return answer === "y" || answer === "yes";
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
rl.close();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function printPackageManagerRemoval() {
|
|
53
|
+
console.log(c.yellow(" repoos was installed via a package manager."));
|
|
54
|
+
console.log(c.dim(" Remove it with the same package manager:"));
|
|
55
|
+
console.log(c.dim(" npm uninstall -g @repo-os/repoos"));
|
|
56
|
+
console.log(c.dim(" bun remove -g @repo-os/repoos"));
|
|
57
|
+
console.log(c.dim(" pnpm remove -g @repo-os/repoos"));
|
|
58
|
+
console.log(c.dim(" mise unuse --global npm:@repo-os/repoos"));
|
|
59
|
+
}
|
|
60
|
+
function printSourceRemoval() {
|
|
61
|
+
console.log(c.yellow(" repoos appears to be running from a source checkout, not a standalone install."));
|
|
62
|
+
console.log(c.dim(" There is nothing for RepoOS to uninstall. Remove the checkout only if you no longer need it."));
|
|
63
|
+
}
|
|
64
|
+
export async function cmdUninstall(args) {
|
|
65
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
66
|
+
console.log("\n Usage: repoos uninstall [--yes]\n\n Remove the default standalone install created by install.sh.\n Project data and user configuration are left untouched.\n");
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
const entryPath = fileURLToPath(import.meta.url);
|
|
70
|
+
const root = dirname(dirname(entryPath));
|
|
71
|
+
if (root.includes("node_modules")) {
|
|
72
|
+
printPackageManagerRemoval();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const plan = standaloneUninstallPlan(entryPath);
|
|
76
|
+
if (!plan) {
|
|
77
|
+
printSourceRemoval();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const yes = args.includes("--yes") || args.includes("-y");
|
|
81
|
+
if (!yes) {
|
|
82
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
83
|
+
console.error(c.red(" Refusing to uninstall without confirmation in a non-interactive terminal."));
|
|
84
|
+
console.error(c.dim(" Re-run with: repoos uninstall --yes"));
|
|
85
|
+
process.exitCode = 1;
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (!(await confirm())) {
|
|
89
|
+
console.log(c.dim(" Kept the standalone RepoOS install."));
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
if (plan.launcherPath)
|
|
95
|
+
rmSync(plan.launcherPath, { force: true });
|
|
96
|
+
rmSync(plan.installDir, { recursive: true, force: true });
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
console.error(c.red(" Failed to remove the standalone install: " + e.message));
|
|
100
|
+
process.exitCode = 1;
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
console.log(c.green(" Removed the standalone RepoOS install."));
|
|
104
|
+
if (plan.launcherPath) {
|
|
105
|
+
console.log(c.dim(` Removed launcher: ${plan.launcherPath}`));
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
console.log(c.dim(" Kept ~/.local/bin/repoos because it is not the launcher this install created."));
|
|
109
|
+
}
|
|
110
|
+
console.log(c.dim(" Your RepoOS projects and user configuration were not changed."));
|
|
111
|
+
}
|
|
@@ -14,6 +14,33 @@ import type { Logger } from "../core/logger.js";
|
|
|
14
14
|
import type { DoneStep } from "./done.js";
|
|
15
15
|
import type { RemoteValidator } from "./remote-validation.js";
|
|
16
16
|
import type { TaskCheckManager, TaskCheckListener } from "./task-check.js";
|
|
17
|
+
/**
|
|
18
|
+
* Is main's advance between `baseMainSha` and `currentMainSha` purely
|
|
19
|
+
* non-code churn?
|
|
20
|
+
*
|
|
21
|
+
* The publish phase normally discards a validated candidate and resyncs from
|
|
22
|
+
* scratch whenever main moved, because a code change on main could invalidate
|
|
23
|
+
* the candidate's validation. That is correct for a competing feature merge;
|
|
24
|
+
* it is pure waste for bookkeeping-only drift, which is auto-resolved to
|
|
25
|
+
* main's copy at publish time and cannot affect a build or test result.
|
|
26
|
+
*
|
|
27
|
+
* This is the root cause of #0376/#0382's unbounded resync loops: git log for
|
|
28
|
+
* both incident windows showed a burst of `docs(<id>): update task` commits
|
|
29
|
+
* across UNRELATED tasks, not competing feature merges. Skipping the resync
|
|
30
|
+
* for exactly that case lets the candidate land directly instead of
|
|
31
|
+
* rebuilding a byte-identical tree and hoping to win a race it never had to
|
|
32
|
+
* run. A drift touching any real source/config path still resyncs (bounded by
|
|
33
|
+
* MAX_PUBLISH_DRIFT_RETRIES).
|
|
34
|
+
*
|
|
35
|
+
* Fails closed: a git error, or any path that is not bookkeeping/generated,
|
|
36
|
+
* returns false so the caller takes the existing, capped resync path.
|
|
37
|
+
*/
|
|
38
|
+
export declare function mainDriftIsBookkeepingOnly(opts: {
|
|
39
|
+
root: string;
|
|
40
|
+
baseMainSha: string;
|
|
41
|
+
currentMainSha: string;
|
|
42
|
+
workDir: string;
|
|
43
|
+
}): Promise<boolean>;
|
|
17
44
|
/**
|
|
18
45
|
* The merge that just ran left the candidate at exactly base main — it added
|
|
19
46
|
* nothing. That is legitimate when the feature branch was already fully
|
|
@@ -36,6 +36,50 @@ const MAX_PUBLISH_DRIFT_RETRIES = 5;
|
|
|
36
36
|
function candidateBranchName(taskId) {
|
|
37
37
|
return `${CANDIDATE_BRANCH_PREFIX}${taskId}`;
|
|
38
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* A path whose change on main can never invalidate a build/test run that
|
|
41
|
+
* already passed on the candidate: task bookkeeping under the work dir, or
|
|
42
|
+
* generated `dist/`+`screenshots/` output. The publish merge auto-resolves
|
|
43
|
+
* (or ignores) all three, so they are non-code drift by construction.
|
|
44
|
+
*/
|
|
45
|
+
function isNonCodePublishDrift(path, workPrefix) {
|
|
46
|
+
return path.startsWith(workPrefix) || path.startsWith("dist/") || path.startsWith("screenshots/");
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Is main's advance between `baseMainSha` and `currentMainSha` purely
|
|
50
|
+
* non-code churn?
|
|
51
|
+
*
|
|
52
|
+
* The publish phase normally discards a validated candidate and resyncs from
|
|
53
|
+
* scratch whenever main moved, because a code change on main could invalidate
|
|
54
|
+
* the candidate's validation. That is correct for a competing feature merge;
|
|
55
|
+
* it is pure waste for bookkeeping-only drift, which is auto-resolved to
|
|
56
|
+
* main's copy at publish time and cannot affect a build or test result.
|
|
57
|
+
*
|
|
58
|
+
* This is the root cause of #0376/#0382's unbounded resync loops: git log for
|
|
59
|
+
* both incident windows showed a burst of `docs(<id>): update task` commits
|
|
60
|
+
* across UNRELATED tasks, not competing feature merges. Skipping the resync
|
|
61
|
+
* for exactly that case lets the candidate land directly instead of
|
|
62
|
+
* rebuilding a byte-identical tree and hoping to win a race it never had to
|
|
63
|
+
* run. A drift touching any real source/config path still resyncs (bounded by
|
|
64
|
+
* MAX_PUBLISH_DRIFT_RETRIES).
|
|
65
|
+
*
|
|
66
|
+
* Fails closed: a git error, or any path that is not bookkeeping/generated,
|
|
67
|
+
* returns false so the caller takes the existing, capped resync path.
|
|
68
|
+
*/
|
|
69
|
+
export async function mainDriftIsBookkeepingOnly(opts) {
|
|
70
|
+
const { root, baseMainSha, currentMainSha, workDir } = opts;
|
|
71
|
+
const res = await runGit(root, ["diff", "--name-only", `${baseMainSha}..${currentMainSha}`], 10_000);
|
|
72
|
+
if (res.status !== 0)
|
|
73
|
+
return false;
|
|
74
|
+
const workPrefix = `${workDir || "work"}/`;
|
|
75
|
+
// No net tree change (e.g. main advanced only via an empty/merge commit) is
|
|
76
|
+
// trivially safe to publish past.
|
|
77
|
+
return res.stdout
|
|
78
|
+
.split("\n")
|
|
79
|
+
.map((s) => s.trim())
|
|
80
|
+
.filter(Boolean)
|
|
81
|
+
.every((p) => isNonCodePublishDrift(p, workPrefix));
|
|
82
|
+
}
|
|
39
83
|
/**
|
|
40
84
|
* The merge that just ran left the candidate at exactly base main — it added
|
|
41
85
|
* nothing. That is legitimate when the feature branch was already fully
|
|
@@ -1022,37 +1066,60 @@ export class CloseOutOrchestrator {
|
|
|
1022
1066
|
}
|
|
1023
1067
|
const currentMainSha = currentMainRes.stdout.trim();
|
|
1024
1068
|
if (job.baseMainSha !== currentMainSha) {
|
|
1025
|
-
//
|
|
1026
|
-
//
|
|
1027
|
-
//
|
|
1028
|
-
//
|
|
1029
|
-
//
|
|
1030
|
-
//
|
|
1031
|
-
//
|
|
1032
|
-
//
|
|
1033
|
-
const
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1069
|
+
// Root-cause escape hatch (#0386): if main only picked up
|
|
1070
|
+
// bookkeeping/generated churn since the candidate was validated
|
|
1071
|
+
// (typically a burst of `docs(<id>): update task` commits for
|
|
1072
|
+
// unrelated tasks), no code the candidate was tested against moved.
|
|
1073
|
+
// Resyncing would rebuild a byte-identical tree and throw away a clean
|
|
1074
|
+
// validation — the actual driver of #0376/#0382's loops. Publish
|
|
1075
|
+
// directly onto the new main instead, recording the new base so the
|
|
1076
|
+
// job state matches what was merged.
|
|
1077
|
+
const bookkeepingOnly = job.baseMainSha
|
|
1078
|
+
? await mainDriftIsBookkeepingOnly({
|
|
1079
|
+
root,
|
|
1080
|
+
baseMainSha: job.baseMainSha,
|
|
1081
|
+
currentMainSha,
|
|
1082
|
+
workDir: this.config.workDir,
|
|
1083
|
+
})
|
|
1084
|
+
: false;
|
|
1085
|
+
if (bookkeepingOnly) {
|
|
1086
|
+
this.logger?.integration(job.taskId, "info", "main advanced with bookkeeping-only commits — publishing without a resync", { from: job.baseMainSha, to: currentMainSha });
|
|
1087
|
+
this.coordinator.updateJob(job.taskId, { baseMainSha: currentMainSha });
|
|
1088
|
+
}
|
|
1089
|
+
else {
|
|
1090
|
+
// Main advanced with a real code change between validation and
|
|
1091
|
+
// publishing. Every OTHER retry path in this close-out pipeline is
|
|
1092
|
+
// capped (#0216's validate-phase 2-attempt cap; handoff.ts's
|
|
1093
|
+
// MAX_*_RETRY_ATTEMPTS for merge-conflict/check-failure/handoff-
|
|
1094
|
+
// signal repairs) — this one wasn't, so a task whose
|
|
1095
|
+
// sync→validate→publish cycle takes longer than the interval
|
|
1096
|
+
// between OTHER tasks landing on main could retry forever, never
|
|
1097
|
+
// winning the race. Reproduced live twice in one session (#0376,
|
|
1098
|
+
// #0382): 3-4 consecutive resets, ~2 minutes each, on a busy board.
|
|
1099
|
+
const driftCount = (job.publishDriftCount ?? 0) + 1;
|
|
1100
|
+
if (driftCount > MAX_PUBLISH_DRIFT_RETRIES) {
|
|
1101
|
+
// Deliberately do NOT set phase: "syncing" here — leaving it
|
|
1102
|
+
// unchanged (still "publishing") means processJob's own existing
|
|
1103
|
+
// `currentJob.phase === "syncing"` check below is false, so it
|
|
1104
|
+
// falls through to failOrReconcile exactly the way a genuine
|
|
1105
|
+
// publish failure already does. No new give-up path needed; this
|
|
1106
|
+
// reuses the one that's already there.
|
|
1107
|
+
return {
|
|
1108
|
+
ok: false,
|
|
1109
|
+
reason: `main advanced ${driftCount} times in a row while trying to publish — giving up ` +
|
|
1110
|
+
"rather than retrying forever. The branch itself is fine, it's just losing the race " +
|
|
1111
|
+
"to land; retry Move-to-done once main quiets down.",
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1114
|
+
removeWorktree(root, branch);
|
|
1115
|
+
this.coordinator.updateJob(job.taskId, {
|
|
1116
|
+
phase: "syncing",
|
|
1117
|
+
baseMainSha: null,
|
|
1118
|
+
candidateSha: null,
|
|
1119
|
+
publishDriftCount: driftCount,
|
|
1120
|
+
});
|
|
1121
|
+
return { ok: false, reason: "main advanced, revalidating" };
|
|
1047
1122
|
}
|
|
1048
|
-
removeWorktree(root, branch);
|
|
1049
|
-
this.coordinator.updateJob(job.taskId, {
|
|
1050
|
-
phase: "syncing",
|
|
1051
|
-
baseMainSha: null,
|
|
1052
|
-
candidateSha: null,
|
|
1053
|
-
publishDriftCount: driftCount,
|
|
1054
|
-
});
|
|
1055
|
-
return { ok: false, reason: "main advanced, revalidating" };
|
|
1056
1123
|
}
|
|
1057
1124
|
// Ensure the main checkout is on the actual main branch before merging.
|
|
1058
1125
|
// A branch-mode hotfix leaves the main checkout on its hotfix branch
|
|
@@ -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 B,n as V,p as se,r as ce,s as H,u as U,w as W,x as le,y as ue}from"./index-KCn__xLG.js";var G={class:`agent-head`},de={class:`agent-title`},fe={class:`agent-name`},pe={class:`agent-body`},me={class:`agent-field`},he={key:0,class:`agent-field`},ge={key:1,class:`agent-field`},_e={class:`agent-field`},ve={class:`agent-test-actions`},ye={key:0,class:`built-in-last-run`},be={key:2,class:`agent-field built-in-status-field`},xe={key:0,class:`built-in-status success`},Se={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`,de,[a[0]||=k(`span`,{class:`agent-dot`},null,-1),k(`span`,fe,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`,pe,[k(`div`,me,[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`,ge,[...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`,he,[a[6]||=k(`label`,null,`Run schedule`,-1),r(se,{"model-value":f.value.schedule,"onUpdate:modelValue":te},{default:E(()=>[r(U,{class:`h-[34px] w-full rounded-[9px] px-[11px]`},{default:E(()=>[r(B)]),_: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`,_e,[a[8]||=k(`label`,null,`Actions`,-1),k(`div`,ve,[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`,ye,` Last: `+u(x.value),1)):n(``,!0)])]),y.value||v.value?(d(),D(`div`,be,[y.value?(d(),D(`div`,xe,u(y.value),1)):n(``,!0),v.value?(d(),D(`div`,Se,u(v.value),1)):n(``,!0)])):n(``,!0)])],2)):n(``,!0)}}),[[`__scopeId`,`data-v-dc10e962`]]),Ce={class:`playground`},we=[`aria-busy`],Te={class:`playground-sidebar-head`},Ee={class:`playground-filters`},De={class:`playground-filter-row`},Oe=[`value`],q=[`value`],J={key:0,class:`playground-error`},ke={class:`playground-list`},Y={key:0,class:`playground-skeletons`,"aria-hidden":`true`},X={key:1,class:`playground-loading playground-no-match`},Ae={key:2,class:`playground-loading`},je={key:0,class:`playground-provider-group`},Me={class:`playground-provider-label`},Ne={key:0,class:`playground-provider-error`},Pe=[`disabled`,`onClick`],Fe={class:`playground-model-name`},Ie={class:`playground-model-reason`},Le={class:`playground-model-meta`},Re={key:0},ze={class:`playground-chat`},Be={class:`playground-chat-head`},Z={class:`playground-active-info`},Q=[`disabled`],Ve=[`aria-label`],$={key:0,class:`playground-welcome`},He={class:`playground-starters`},Ue=[`onClick`],We=[`innerHTML`],Ge={key:1},Ke={key:1,class:`playground-thinking`,"aria-label":`Model is responding`},qe={key:2,class:`playground-send-error`},Je=[`disabled`,`placeholder`,`aria-label`],Ye=[`disabled`],Xe={key:1,class:`playground-empty`},Ze={key:0},Qe=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 B(e){return e==null?`—`:e<1?`$${e.toFixed(3)}`:`$${e.toFixed(2)}`}async function V(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 se(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 H(){o(()=>{N.value&&(N.value.scrollTop=N.value.scrollHeight)})}async function U(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,H();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,H()}}function le(e){e.key!==`Enter`||e.shiftKey||e.isComposing||(e.preventDefault(),U())}return t(()=>{V()}),(e,t)=>(d(),D(`div`,Ce,[k(`aside`,{class:`playground-sidebar`,"aria-label":`Models worth trying`,"aria-busy":f.value},[k(`div`,Te,[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=>V(!0)},{default:E(()=>[i(u(f.value?`Refreshing…`:`Refresh`),1)]),_:1},8,[`disabled`])]),k(`div`,Ee,[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`,De,[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,Oe))),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(B(e))+` / 1M `,9,q)),64))],512),[[g,L.value]])])]),_.value?(d(),D(`div`,J,u(_.value),1)):n(``,!0),k(`div`,ke,[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`,Ae,` 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`,je,[k(`div`,Me,u(e.label),1),e.error?(d(),D(`div`,Ne,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=>se({...t,providerLabel:e.label})},[k(`div`,Fe,u(t.name),1),k(`div`,Ie,u(t.reason),1),k(`div`,Le,[k(`span`,null,u(B(t.inputPricePerM))+` / `+u(B(t.outputPricePerM))+` per 1M`,1),t.contextWindow?(d(),D(`span`,Re,u(h(R)(t.contextWindow))+` ctx`,1)):n(``,!0)])],10,Pe))),128))])):n(``,!0)],64))),128))])],8,we),k(`section`,ze,[S.value?(d(),D(p,{key:0},[k(`header`,Be,[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`,He,[(d(),D(p,null,a(s,e=>k(`button`,{key:e,type:`button`,onClick:t=>U(e)},u(e),9,Ue)),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,We)):(d(),D(`span`,Ge,u(e.text),1))],2)],2))),128)),O.value?(d(),D(`div`,Ke,[...t[13]||=[k(`span`,null,null,-1),k(`span`,null,null,-1),k(`span`,null,null,-1)]])):n(``,!0),M.value?(d(),D(`div`,qe,u(M.value),1)):n(``,!0)],8,Ve),k(`form`,{class:`playground-compose`,onSubmit:t[6]||=y(e=>U(),[`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:le},null,40,Je),[[v,T.value]]),k(`button`,{type:`submit`,disabled:!T.value.trim()||O.value,"aria-label":`Send message`},` Send `,8,Ye)],32)],64)):(d(),D(`div`,Xe,[f.value?n(``,!0):(d(),D(`p`,Ze,`Pick a model from the sidebar to start chatting.`))]))])]))}}),[[`__scopeId`,`data-v-20dd17ec`]]),$e={class:`mp-panel agent-tab-panel`},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(),D(`div`,$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=>(d(),D(`div`,{key:e.id,class:`mp-row`},[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)]))),128))]))}}),[[`__scopeId`,`data-v-454cf721`]]),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:`agent-tab-panel`,style:{padding:`0 18px 6px`,"margin-bottom":`16px`}},Yt={class:`sec-label`,style:{"padding-top":`16px`,"margin-bottom":`4px`}},Xt={class:`agent-head`},Zt={class:`agent-title`},Qt={class:`agent-name`},$t={class:`agent-body`},en={class:`agent-field`},tn={class:`agent-field agent-test-result`},nn={class:`agent-test-actions`},rn={key:0,class:`model-test-spinner`},an=[`title`],on={class:`agent-field agent-instr-field`},sn={class:`instr-header`},cn=[`value`,`onInput`,`onBlur`],ln={key:0,class:`agent-field agent-skills-field`},un={class:`instr-header`},dn={class:`agent-skills-summary`},fn={class:`agent-tab-panel`,style:{padding:`0 18px 6px`,"margin-bottom":`16px`}},pn={class:`agent-add`},mn={key:0,class:`agent-empty`},hn={class:`agent-head`},gn={class:`agent-title`},_n={style:{display:`flex`,"align-items":`center`,gap:`10px`}},vn={class:`agent-body`},yn={class:`agent-field`},bn={class:`agent-field agent-test-result`},xn={class:`agent-test-actions`},Sn={key:0,class:`model-test-spinner`},Cn=[`title`],wn={class:`agent-field agent-instr-field`},Tn={class:`instr-header`},En=[`value`,`onInput`,`onBlur`],Dn={key:0,class:`agent-field agent-skills-field`},On={class:`instr-header`},kn={class:`agent-skills-summary`},An={class:`agent-tab-panel`,style:{padding:`0 18px 6px`,"margin-bottom":`16px`}},jn={class:`agent-head`},Mn={class:`agent-title`},Nn={class:`agent-name`},Pn={class:`agent-body`},Fn={class:`agent-field`},In={class:`agent-field agent-test-result`},Ln={class:`agent-test-actions`},Rn={key:0,class:`model-test-spinner`},zn=[`title`],Bn={class:`agent-field agent-instr-field`},Vn={class:`instr-header`},Hn=[`value`,`onInput`,`onBlur`],Un={key:0,class:`agent-field agent-skills-field`},Wn={class:`instr-header`},Gn={class:`agent-skills-summary`},Kn={key:0,class:`agent-tab-panel`,style:{padding:`0 18px 6px`,"margin-bottom":`16px`}},qn={key:0,class:`detect-loading`},Jn={key:1,class:`agent-empty`},Yn={class:`detect-row-left`},Xn={class:`agent-name`},Zn={class:`detect-row-right`},Qn={class:`detect-bin`},$n=[`title`],er={key:1,class:`detect-ver`},tr={key:2,class:`detect-hint`},nr=[`onClick`],rr={class:`detect-bin`},ir={class:`detect-hint`},ar=[`onClick`],or={class:`detect-foot`},sr={class:`am-modal-head`},cr={key:0,class:`agent-skill-modal-list`},lr=[`checked`,`onChange`],ur={key:0},dr=`docs/agent-model-recommendations.md`,fr=`docs/opencode-models.md`,pr=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 B(){v.loadDoc(dr),g.push({name:`repo`})}function se(){v.loadDoc(fr),g.push({name:`repo`})}let U=w([]),W=w(``),G=w(null),de=!1,fe,pe=!1,me=!1;function he(){de=!0,U.value=s.agents.map(e=>({...e})),de=!1}e(()=>s.loaded,e=>{e&&he()},{immediate:!0});let ge=m(()=>s.agentsMeta.defaults.map(e=>e.name.toLowerCase())),_e=e=>ge.value.includes(e.toLowerCase()),ve=[`ross`,`cto`],ye=e=>ve.includes(e.toLowerCase()),be=m(()=>U.value.filter(e=>_e(e.name)&&!ye(e.name))),xe=m(()=>U.value.filter(e=>_e(e.name)&&ye(e.name))),Se=m(()=>U.value.filter(e=>!_e(e.name))),Ce={"claude code":`Claude Code`,"github copilot":`GitHub Copilot CLI`,"qwen code":`qwen code`,codex:`codex`},we=new Map,Te=new Map;function Ee(e,t){let n=we.get(e);n&&ae(n,t)}function De(e,t){let n=Te.get(e);n&&ae(n,t)}m(()=>s.agentsMeta.clis.map(e=>({value:e,label:Ce[e]??e})));let Oe=m(()=>s.agentsMeta.clis??[]),q=w({}),J=w({});s.modelsFor;let ke=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 Ae(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 je=(e=!1)=>s.loadModels(e);function Me(){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 Ne(e){U.value=U.value.filter(t=>t!==e)}function Pe(e,t){e.instructions=t.target.value}function Fe(e){let t=document.activeElement;t instanceof HTMLTextAreaElement&&t.value!==e.instructions&&(e.instructions=t.value)}function Ie(e,t,n){let r=new Set(e.skills??[]);n?r.add(t):r.delete(t),e.skills=[...r]}function Le(e){G.value=e}function Re(){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 ze(){if(pe){me=!0;return}let e=Re();if(e){pe=!0,me=!1;try{await s.saveAgents(e)}catch{}finally{pe=!1,me&&Be(0)}}}function Be(e=450){clearTimeout(fe),fe=setTimeout(()=>void ze(),e)}e(U,()=>{de||!s.loaded||(s.msg=``,s.error=``,pe&&(me=!0),Be())},{deep:!0,flush:`sync`});let Z=w([]),Q=w(!1),Ve=w(!1),$=w(``),He=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 Ue(){Q.value=!0,Ve.value=!1,$.value=``;try{let e=await A(`/api/agents/detect`);Z.value=e.agents}catch{Ve.value=!0,Z.value=[]}finally{Q.value=!1}}function We(e){ce(e),$.value=e,setTimeout(()=>{$.value===e&&($.value=``)},1500)}return t(()=>{Ue(),je()}),f(()=>{clearTimeout(fe)}),(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:B},` 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(k(`div`,Jt,[k(`div`,Yt,[t[4]||=k(`span`,{class:`live-dot`},null,-1),t[5]||=i(`Default agents `,-1),k(`button`,{class:`model-pricing-link`,onClick:se},` Model pricing & use cases → `),r(j,{variant:`outline`,size:`sm`,style:{"margin-left":`auto`},disabled:ke.value,title:`Re-probe opencode's live model list (opencode models --refresh)`,onClick:t[0]||=e=>je(!0)},{default:E(()=>[i(u(ke.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(be.value,e=>(d(),D(`div`,{key:e.name,class:l([`agent-card`,{off:!e.enabled}])},[k(`div`,Xt,[k(`div`,Zt,[t[6]||=k(`span`,{class:`agent-dot`},null,-1),k(`span`,Qt,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`,$t,[k(`div`,en,[t[8]||=k(`label`,null,`Coding agent + Model`,-1),r(H,{"cli-options":Oe.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`,tn,[t[9]||=k(`label`,null,`Compatibility`,-1),k(`div`,nn,[r(j,{variant:`outline`,size:`sm`,disabled:!!J.value[Y(e)],onClick:t=>Ae(e)},{default:E(()=>[J.value[Y(e)]?(d(),D(`span`,rn)):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,an)):n(``,!0)])]),k(`div`,on,[k(`div`,sn,[t[10]||=k(`label`,null,`Instructions`,-1),r(ue,{onTranscribed:t=>Ee(e.name,t)},null,8,[`onTranscribed`])]),k(`textarea`,{ref_for:!0,ref:t=>h(we).set(e.name,t),value:e.instructions??``,class:`agent-instr`,rows:`2`,placeholder:`Optional — how this agent should behave`,onInput:t=>Pe(e,t),onBlur:t=>Fe(e)},null,40,cn)]),h(s).agentsMeta.skills.length?(d(),D(`div`,ln,[k(`div`,un,[t[12]||=k(`label`,null,`Enabled skills`,-1),r(j,{variant:`outline`,size:`sm`,onClick:t=>Le(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`,dn,u((e.skills??[]).join(`, `)||`No default candidates`),1)])):n(``,!0)])],2))),128))],512),[[C,R.value==="default"]]),x(k(`div`,fn,[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`,pn,[r(le,{modelValue:W.value,"onUpdate:modelValue":t[1]||=e=>W.value=e,placeholder:`e.g. data analyst`,class:`w-[220px]`,onKeyup:S(Me,[`enter`])},null,8,[`modelValue`]),r(j,{variant:`outline`,size:`sm`,disabled:!W.value.trim(),onClick:Me},{default:E(()=>[...t[15]||=[i(` Add agent `,-1)]]),_:1},8,[`disabled`])]),Se.value.length?n(``,!0):(d(),D(`div`,mn,` No custom agents yet — add one above. `)),(d(!0),D(p,null,a(Se.value,e=>(d(),D(`div`,{key:e.name,class:l([`agent-card`,{off:!e.enabled}])},[k(`div`,hn,[k(`div`,gn,[t[16]||=k(`span`,{class:`agent-dot`},null,-1),r(le,{"model-value":e.name,class:`w-[180px] h-[30px]`,"onUpdate:modelValue":t=>e.name=String(t??``)},null,8,[`model-value`,`onUpdate:modelValue`])]),k(`div`,_n,[r(j,{variant:`ghost`,size:`sm`,class:`agent-remove`,onClick:t=>Ne(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`,vn,[k(`div`,yn,[t[18]||=k(`label`,null,`Coding agent + Model`,-1),r(H,{"cli-options":Oe.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`,bn,[t[19]||=k(`label`,null,`Compatibility`,-1),k(`div`,xn,[r(j,{variant:`outline`,size:`sm`,disabled:!!J.value[Y(e)],onClick:t=>Ae(e)},{default:E(()=>[J.value[Y(e)]?(d(),D(`span`,Sn)):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,Cn)):n(``,!0)])]),k(`div`,wn,[k(`div`,Tn,[t[20]||=k(`label`,null,`Instructions`,-1),r(ue,{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=>Pe(e,t),onBlur:t=>Fe(e)},null,40,En)]),h(s).agentsMeta.skills.length?(d(),D(`div`,Dn,[k(`div`,On,[t[22]||=k(`label`,null,`Enabled skills`,-1),r(j,{variant:`outline`,size:`sm`,onClick:t=>Le(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`,kn,u((e.skills??[]).join(`, `)||`No default candidates`),1)])):n(``,!0)])],2))),128))],512),[[C,R.value===`custom`]]),x(k(`div`,An,[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(xe.value,e=>(d(),D(`div`,{key:`team-`+e.name,class:l([`agent-card`,{off:!e.enabled}])},[k(`div`,jn,[k(`div`,Mn,[t[26]||=k(`span`,{class:`agent-dot`},null,-1),k(`span`,Nn,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`,Pn,[k(`div`,Fn,[t[28]||=k(`label`,null,`Coding agent + Model`,-1),r(H,{"cli-options":Oe.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`,In,[t[29]||=k(`label`,null,`Compatibility`,-1),k(`div`,Ln,[r(j,{variant:`outline`,size:`sm`,disabled:!!J.value[Y(e)],onClick:t=>Ae(e)},{default:E(()=>[J.value[Y(e)]?(d(),D(`span`,Rn)):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,zn)):n(``,!0)])]),k(`div`,Bn,[k(`div`,Vn,[t[30]||=k(`label`,null,`Instructions`,-1),r(ue,{onTranscribed:t=>Ee(e.name,t)},null,8,[`onTranscribed`])]),k(`textarea`,{ref_for:!0,ref:t=>h(we).set(e.name,t),value:e.instructions??``,class:`agent-instr`,rows:`2`,placeholder:`Optional — how this agent should behave`,onInput:t=>Pe(e,t),onBlur:t=>Fe(e)},null,40,Hn)]),h(s).agentsMeta.skills.length?(d(),D(`div`,Un,[k(`div`,Wn,[t[32]||=k(`label`,null,`Enabled skills`,-1),r(j,{variant:`outline`,size:`sm`,onClick:t=>Le(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`,Gn,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`})],512),[[C,R.value===`team`]]),Ve.value?n(``,!0):x((d(),D(`div`,Kn,[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`,qn,`Probing PATH…`)):Z.value.length?(d(),D(p,{key:2},[(d(!0),D(p,null,a(He.value,e=>(d(),D(`div`,{key:e.agent.id,class:`detect-row`},[k(`div`,Yn,[k(`span`,{class:`detect-badge`,style:O({background:e.color,boxShadow:`0 0 8px `+e.color})},null,4),k(`span`,Xn,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`,Zn,[e.agent.installed?(d(),D(p,{key:0},[k(`span`,Qn,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,$n)):n(``,!0),e.agent.version?(d(),D(`span`,er,u(e.agent.version),1)):n(``,!0),e.agent.headless?n(``,!0):(d(),D(`span`,tr,[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=>We(e.agent.installHint)},u($.value===e.agent.installHint?`copied`:`copy`),9,nr)]))],64)):(d(),D(p,{key:1},[k(`span`,rr,u(e.agent.binary),1),k(`span`,ir,[k(`code`,null,u(e.agent.installHint),1),k(`button`,{class:`detect-copy`,onClick:t=>We(e.agent.installHint)},u($.value===e.agent.installHint?`copied`:`copy`),9,ar)])],64))])]))),128)),k(`div`,or,[r(j,{variant:`outline`,size:`sm`,disabled:Q.value,onClick:Ue},{default:E(()=>[i(u(Q.value?`Checking…`:`Check again`),1)]),_:1},8,[`disabled`])])],64)):(d(),D(`div`,Jn,` No known coding agents detected on PATH. `))],512)),[[C,R.value===`detected`]]),re.value?x((d(),c(Qe,{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`,sr,[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`,cr,[(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=>Ie(G.value,e.name,t.target.checked)},null,40,lr),k(`span`,null,[k(`strong`,null,u(e.name),1),e.description?(d(),D(`small`,ur,u(e.description),1)):n(``,!0)])]))),128))])):n(``,!0)]),_:1})]),_:1},8,[`open`])]))}});export{pr as default};
|
|
@@ -1 +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}}
|
|
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-454cf721]{margin-bottom:16px;padding:0 18px 14px}.mp-row[data-v-454cf721]{border:1px solid var(--border);background:var(--panel-solid);border-radius:10px;padding:14px 16px}.mp-row+.mp-row[data-v-454cf721]{margin-top:12px}.mp-row-head[data-v-454cf721]{align-items:center;gap:10px;display:flex}.mp-row-title[data-v-454cf721]{align-items:center;gap:8px;min-width:0;display:flex}.mp-pill[data-v-454cf721]{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-454cf721]{color:var(--green);border-color:color-mix(in srgb, var(--green) 35%, transparent)}.mp-dash-link[data-v-454cf721]{color:var(--cyan);flex:none;margin-left:auto;font:500 10.5px JetBrains Mono,monospace;text-decoration:none}.mp-dash-link[data-v-454cf721]:hover{text-decoration:underline}.mp-note[data-v-454cf721]{color:var(--txt-dim);margin-top:2px;font-size:11px;line-height:1.5}.mp-key-form[data-v-454cf721]{flex-wrap:wrap;align-items:center;gap:8px;margin-top:10px;display:flex}.mp-key-form input[data-v-454cf721]{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-454cf721]:focus{border-color:var(--border-bright)}.mp-key-hint[data-v-454cf721]{color:var(--txt-faint);flex-basis:100%;font-size:10.5px}.mp-key-hint code[data-v-454cf721],.mp-error code[data-v-454cf721]{font:10px JetBrains Mono,monospace}.mp-data[data-v-454cf721]{flex-direction:column;gap:10px;margin-top:12px;display:flex}.mp-stat-hero[data-v-454cf721]{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-454cf721]{font-size:20px}.mp-stat-sub[data-v-454cf721]{color:var(--txt-faint);font-size:10.5px}.mp-stat-row[data-v-454cf721]{flex-wrap:wrap;gap:8px;display:flex}.mp-stat[data-v-454cf721]{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-454cf721]{color:var(--txt);font:600 13px JetBrains Mono,monospace}.mp-stat-value.sm[data-v-454cf721]{font-size:12.5px}.mp-stat-label[data-v-454cf721]{letter-spacing:.06em;text-transform:uppercase;color:var(--txt-faint);font:500 9.5px JetBrains Mono,monospace}.mp-window[data-v-454cf721]{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-454cf721]{flex-wrap:wrap;justify-content:space-between;align-items:baseline;gap:8px;display:flex}.mp-window-pct[data-v-454cf721]{color:var(--txt-dim);font:500 10.5px JetBrains Mono,monospace}.mp-bar[data-v-454cf721]{background:var(--border);border-radius:999px;height:5px;overflow:hidden}.mp-bar-fill[data-v-454cf721]{background:var(--cyan);border-radius:999px;height:100%;transition:width .3s}.mp-window-reset[data-v-454cf721]{color:var(--txt-faint);font-size:10px}.mp-actions[data-v-454cf721]{gap:6px;margin-top:10px;display:flex}.mp-loading[data-v-454cf721]{color:var(--txt-dim);margin-top:10px;font-size:11.5px}.mp-error[data-v-454cf721]{color:var(--red);margin-top:8px;font-size:11.5px}.mp-error .mp-retry[data-v-454cf721]{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-454cf721]:hover{color:var(--txt);border-color:var(--border-bright)}.mp-part-error[data-v-454cf721]{color:var(--amber);font-size:11px}.mp-part-error a[data-v-454cf721]{color:inherit}@media (prefers-reduced-motion:reduce){.mp-bar-fill[data-v-454cf721]{transition:none}}
|