crewswarm 0.9.5 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +56 -7
  2. package/apps/dashboard/dist/assets/{index-D-sRshvg.css → index-C5-vlIwl.css} +1 -1
  3. package/apps/dashboard/dist/assets/index-CSooN9fi.js +2 -0
  4. package/apps/dashboard/dist/assets/index-CSooN9fi.js.br +0 -0
  5. package/apps/dashboard/dist/assets/tab-spending-tab-DcXD5TQY.js +1 -0
  6. package/apps/dashboard/dist/assets/tab-spending-tab-DcXD5TQY.js.br +0 -0
  7. package/apps/dashboard/dist/assets/tab-testing-tab-Ea5K-rsb.js +1 -0
  8. package/apps/dashboard/dist/index.html +83 -7
  9. package/apps/dashboard/dist/index.html.br +0 -0
  10. package/contrib/openclaw-plugin/index.ts +20 -11
  11. package/lib/autoharness/index.mjs +151 -1
  12. package/lib/chat/history.mjs +1 -1
  13. package/lib/contacts/identity-linker.mjs +24 -3
  14. package/lib/contacts/index.mjs +2 -1
  15. package/lib/crew-lead/chat-handler.mjs +56 -33
  16. package/lib/crew-lead/llm-caller.mjs +71 -14
  17. package/lib/crew-lead/prompts.mjs +4 -2
  18. package/lib/engines/rt-envelope.mjs +4 -1
  19. package/package.json +5 -3
  20. package/scripts/dashboard.mjs +216 -25
  21. package/scripts/health-check.mjs +70 -28
  22. package/scripts/restart-all-from-repo.sh +25 -21
  23. package/scripts/start.mjs +35 -15
  24. package/apps/dashboard/dist/assets/chat-core-uXb_C0GM.js.br +0 -0
  25. package/apps/dashboard/dist/assets/cli-process-CNZ_UBCt.js.br +0 -0
  26. package/apps/dashboard/dist/assets/components-BS9fQjE_.js.br +0 -0
  27. package/apps/dashboard/dist/assets/core-utils-CmOkXgzi.js.br +0 -0
  28. package/apps/dashboard/dist/assets/index-BeVllEj_.js +0 -2
  29. package/apps/dashboard/dist/assets/index-BeVllEj_.js.br +0 -0
  30. package/apps/dashboard/dist/assets/index-D-sRshvg.css.br +0 -0
  31. package/apps/dashboard/dist/assets/orchestration-Ca2DLWN-.js.br +0 -0
  32. package/apps/dashboard/dist/assets/setup-wizard-CA0Or47w.js.br +0 -0
  33. package/apps/dashboard/dist/assets/tab-agents-tab-BgpIsjkw.js.br +0 -0
  34. package/apps/dashboard/dist/assets/tab-benchmarks-tab-BHjKCPm3.js.br +0 -0
  35. package/apps/dashboard/dist/assets/tab-comms-tab-kguqTIzD.js.br +0 -0
  36. package/apps/dashboard/dist/assets/tab-contacts-tab-DiOyMYth.js.br +0 -0
  37. package/apps/dashboard/dist/assets/tab-engines-tab-BsdZVvU0.js.br +0 -0
  38. package/apps/dashboard/dist/assets/tab-memory-tab-Cu6u13EQ.js.br +0 -0
  39. package/apps/dashboard/dist/assets/tab-models-tab-dNRgsTOO.js.br +0 -0
  40. package/apps/dashboard/dist/assets/tab-pm-loop-tab-DiAPTJXu.js.br +0 -0
  41. package/apps/dashboard/dist/assets/tab-projects-tab-SFH4E--a.js.br +0 -0
  42. package/apps/dashboard/dist/assets/tab-prompts-tab-DVkUNaJd.js.br +0 -0
  43. package/apps/dashboard/dist/assets/tab-services-tab-DU_LH3uG.js.br +0 -0
  44. package/apps/dashboard/dist/assets/tab-settings-tab-CuvH_Fj_.js.br +0 -0
  45. package/apps/dashboard/dist/assets/tab-skills-tab-DR7PJ7NB.js.br +0 -0
  46. package/apps/dashboard/dist/assets/tab-spending-tab-DEccQHnt.js +0 -1
  47. package/apps/dashboard/dist/assets/tab-spending-tab-DEccQHnt.js.br +0 -0
  48. package/apps/dashboard/dist/assets/tab-swarm-chat-tab-BNrd88-r.js.br +0 -0
  49. package/apps/dashboard/dist/assets/tab-swarm-tab-B1AcjL1W.js.br +0 -0
  50. package/apps/dashboard/dist/assets/tab-testing-tab-CezZOZcJ.js +0 -1
  51. package/apps/dashboard/dist/assets/tab-testing-tab-CezZOZcJ.js.br +0 -0
  52. package/apps/dashboard/dist/assets/tab-usage-tab-BIOOnB-Y.js.br +0 -0
  53. package/apps/dashboard/dist/assets/tab-waves-tab-SaJDkb4x.js.br +0 -0
  54. package/apps/dashboard/dist/assets/tab-workflows-tab-B-soSy1k.js.br +0 -0
  55. package/apps/dashboard/dist/index.html.gz +0 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # crewswarm
2
2
 
3
- **The only multi-engine AI coding platform.** Switch between Claude Code, Cursor, Gemini, Codex, and OpenCode mid-conversation. Parallel agents. Persistent sessions. No vendor lock-in.
3
+ **A multi-engine AI coding platform.** Switch between Claude Code, Cursor, Gemini, Codex, OpenCode, and crew-cli mid-conversation. Parallel agents. Persistent sessions. No vendor lock-in.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/crewswarm)](https://www.npmjs.com/package/crewswarm)
6
6
  [![Release Check](https://img.shields.io/badge/release_check-required-blue)](https://github.com/crewswarm/crewswarm)
@@ -17,7 +17,7 @@
17
17
 
18
18
  **Rate limits are real.** Every $20/month AI coding plan has them. Claude, Cursor, Codex — you'll hit the wall mid-feature.
19
19
 
20
- crewswarm is the only tool where you seamlessly switch to another engine and keep your session context. Or pick the best CLI for each job:
20
+ crewswarm lets you switch engines without throwing away your working context. Or pick the best CLI for each job:
21
21
 
22
22
  | Engine | Best for | Key strength |
23
23
  |---|---|---|
@@ -26,7 +26,53 @@ crewswarm is the only tool where you seamlessly switch to another engine and kee
26
26
  | **Gemini CLI** | Research, SEO, free fallback | Free: 60 req/min, Google Search built in |
27
27
  | **Codex CLI** | Backend, fast iteration | Full sandbox, no approval prompts |
28
28
  | **OpenCode** | Provider flexibility | Any model (Groq/DeepSeek/Ollama) |
29
- | **crew-cli** | Orchestration, quality workflows | 20+ agents, sandbox, 3x parallel speedup |
29
+ | **crew-cli** | Execution engine, any model | 40+ models, 16 providers, sandbox, parallel workers |
30
+
31
+ ---
32
+
33
+ ## crew-cli: the execution engine
34
+
35
+ crew-cli is the built-in execution engine. It runs standalone or as one of crewswarm's 6 engines. Unlike other AI coding CLIs that lock you to one provider, crew-cli works with any model:
36
+
37
+ | Provider | Models | Driver |
38
+ |---|---|---|
39
+ | **OpenAI** | GPT-5.4, GPT-5.2, GPT-4.1, o3-mini, o4-mini | OpenAI API |
40
+ | **Anthropic** | Claude Opus/Sonnet/Haiku (API + OAuth) | Anthropic API + CCH |
41
+ | **Google** | Gemini 2.5 Flash, Gemini 3 Pro | Gemini API |
42
+ | **xAI** | Grok 4.20, Grok 4-1, Grok 3, grok-code-fast | OpenAI-compatible |
43
+ | **DeepSeek** | DeepSeek Chat, DeepSeek Reasoner | OpenAI-compatible |
44
+ | **Groq** | Llama 4 Scout, Kimi K2, Qwen3-32B, GPT-OSS | OpenAI-compatible |
45
+ | **Fireworks** | DeepSeek v3, GLM-5, Kimi K2.5, GPT-OSS | OpenAI-compatible |
46
+ | **Mistral** | Mistral Large, Codestral, Devstral | OpenAI-compatible |
47
+ | **Cerebras** | Qwen 3-235B, Llama 3.1 | OpenAI-compatible |
48
+ | **NVIDIA** | Llama 3.3-70B | OpenAI-compatible |
49
+ | **OpenCode/Zen** | 39 models (GPT-5.x, Claude, Gemini, GLM, Kimi, MiniMax, Qwen, Nemotron) | OpenAI-compatible |
50
+ | **OpenRouter** | 100+ models | OpenAI-compatible |
51
+ | **Ollama** | Any local model | OpenAI-compatible |
52
+
53
+ Three API formats, one engine. Bring your own keys, use OAuth from Claude Code / Codex / Gemini CLI, or run free models via Groq / Ollama / OpenRouter.
54
+
55
+ ### Benchmark: free models match Claude Opus
56
+
57
+ Single-model pipeline testing — same model handles routing, planning, execution, review, and fixing. All tests pass on 6 TypeScript coding tasks (bugfix, feature, refactor, multi-file).
58
+
59
+ | Model | Provider | Result | ~Cost/Task |
60
+ |---|---|---|---|
61
+ | Qwen 3.5 (397B) | Ollama cloud | **All tests pass** | FREE |
62
+ | GLM-5.1 | Ollama cloud | **All tests pass** | FREE |
63
+ | Claude Sonnet 4.6 | Anthropic OAuth | **All tests pass** | ~$0.06 |
64
+ | Claude Opus 4.6 | Anthropic OAuth | **All tests pass** | ~$0.07 |
65
+ | GPT-5.4 | OpenAI OAuth | **All tests pass** | ~$0.13 |
66
+
67
+ Two free local models (Qwen 3.5, GLM-5.1 via Ollama) pass every test that Claude Opus does. [Full results →](https://crewswarm.ai/benchmarks.html)
68
+
69
+ **What makes crew-cli different from other AI coding CLIs:**
70
+ - **Failure memory** — blocks repeated bad moves, forces new approaches
71
+ - **Verification-first** — won't declare success until proof is shown
72
+ - **Patch critic** — evaluates every edit for quality in real time
73
+ - **Parallel workers** — splits multi-file tasks into concurrent work units
74
+ - **Sandbox preview** — all changes staged before writing to disk
75
+ - **Smart delegation** — picks the right model tier for each subtask
30
76
 
31
77
  ---
32
78
 
@@ -85,11 +131,11 @@ Use Docker when you want stronger isolation, easier restarts, or a shared server
85
131
 
86
132
  1. **You write a requirement** — one sentence, one paragraph, or a full spec
87
133
  2. **crew-pm plans it** — breaks work into phases, assigns specialists
88
- 3. **Agents execute in parallel** — backend, frontend, tests built simultaneously (3x faster)
134
+ 3. **Agents execute in parallel** — backend, frontend, and tests can run simultaneously
89
135
  4. **Done. Files on disk.** — real files, real tests, real output
90
136
 
91
137
  ```
92
- Dashboard / Vibe IDE / crew-cli / Telegram / MCP
138
+ Dashboard / Vibe IDE / crew-cli / crewchat / Telegram / WhatsApp / OpenClaw / MCP
93
139
  |
94
140
  crew-lead (router)
95
141
  |
@@ -110,8 +156,11 @@ Dashboard / Vibe IDE / crew-cli / Telegram / MCP
110
156
 
111
157
  - **Dashboard** — web control plane at `localhost:4319` (agents, engines, models, build, sessions)
112
158
  - **Vibe IDE** — browser-based editor + terminal + chat at `localhost:3333`
113
- - **crew-cli** — terminal-first with 34+ built-in tools
159
+ - **crew-cli** — execution engine: 40+ models, 16 providers, 41 built-in tools
160
+ - **crewchat** — conversational interface for quick tasks
114
161
  - **Telegram** — chat with your crew from your phone
162
+ - **WhatsApp** — mobile messaging bridge
163
+ - **OpenClaw plugin** — use crewswarm as the engineering backend for OpenClaw desktop apps (`npm i crewswarm-openclaw-plugin`)
115
164
  - **MCP server** — plug crewswarm into any MCP-compatible editor
116
165
 
117
166
  ---
@@ -172,7 +221,7 @@ crewswarm # Start full stack: RT bus, crew-lead, bridges, the
172
221
  crewswarm pm-loop # Run autonomous PM loop
173
222
  npm run doctor # Preflight check
174
223
  npm run restart-all # Restart the stack
175
- npm test # 4,530 tests, 100% passing
224
+ npm test # Run the core test suites
176
225
  npm run test:report # View test results summary
177
226
  crew exec "Build X" # Send task via CLI
178
227
  ```
@@ -1 +1 @@
1
- :root{--bg: #060a10;--bg-0: #040810;--bg-1: #0d1420;--bg-2: #111827;--bg-card: #0d1420;--bg-card2: #111827;--bg-hover: #141e2e;--surface-2: #16202e;--border: rgba(255, 255, 255, .07);--border-hi: rgba(56, 189, 248, .35);--text: #f0f6ff;--text-1: #f0f6ff;--text-2: #a0b3cc;--text-3: #7a8a9f;--accent: #38bdf8;--accent2: #818cf8;--purple: #818cf8;--green: #34d399;--red: #f87171;--yellow: #fbbf24;--amber: #f59e0b;--green-hi: #22c55e;--red-hi: #ef4444;--sky: #38bdf8;--blue: #4a7ab5;--teal: #0f766e;--warning: #f59e0b;--radius: 10px}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,sans-serif;background:var(--bg);color:var(--text);display:flex;height:100vh;overflow:hidden;font-size:14px;touch-action:manipulation}.skip-link{position:absolute;top:-40px;left:0;background:var(--accent);color:#000;padding:8px 16px;text-decoration:none;font-weight:600;border-radius:0 0 4px;z-index:9999}.skip-link:focus{top:0}*:focus-visible{outline:3px solid var(--accent);outline-offset:2px}button:focus-visible,a:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{outline:3px solid var(--accent);outline-offset:2px}.sidebar{width:216px;min-width:216px;background:var(--bg-card);border-right:1px solid var(--border);display:flex;flex-direction:column;overflow-y:auto}.sidebar-brand{display:flex;align-items:center;gap:10px;padding:18px 16px 14px;border-bottom:1px solid var(--border);text-decoration:none}.brand-icon{width:24px;height:24px;object-fit:contain;display:block}.brand-name{font-size:15px;font-weight:800;color:var(--text);letter-spacing:.06em;text-transform:uppercase}.brand-name span{color:var(--accent)}.sidebar-status{display:flex;align-items:center;gap:8px;padding:10px 16px;border-bottom:1px solid var(--border)}.status-dot{width:7px;height:7px;border-radius:50%;background:var(--text-3);flex-shrink:0}.status-dot.online{background:var(--green);box-shadow:0 0 6px var(--green)}.status-dot.error{background:var(--red)}#status{font-size:12px;color:var(--text-2)}.nav-section{padding:12px 8px 4px}.nav-label{font-size:10px;font-weight:600;color:var(--text-3);letter-spacing:.08em;text-transform:uppercase;padding:0 8px 6px}.nav-item{display:flex;align-items:center;gap:9px;width:100%;padding:8px 10px;border-radius:7px;border:none;background:transparent;color:var(--text-2);font-size:13px;font-weight:500;cursor:pointer;text-align:left;transition:background .12s,color .12s;font-family:inherit}.stab{padding:7px 16px;border:none;background:transparent;color:var(--text-2);font-size:13px;font-weight:500;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;font-family:inherit;transition:color .12s,border-color .12s;white-space:nowrap}.stab:hover{color:var(--text-1)}.stab.active{color:var(--accent);border-bottom-color:var(--accent)}.nav-item:hover{background:var(--bg-hover);color:var(--text)}.nav-item.active{background:#38bdf81a;color:var(--accent)}.nav-item .nav-icon{font-size:15px;width:18px;text-align:center}.nav-badge{margin-left:auto;background:var(--red);color:#fff;font-size:10px;font-weight:700;padding:1px 6px;border-radius:999px;min-width:18px;text-align:center}.nav-badge.hidden{display:none}.sidebar-bottom{margin-top:auto;padding:12px 8px;border-top:1px solid var(--border)}.main-wrap{flex:1;display:flex;flex-direction:column;overflow:hidden}.view{display:none;flex:1;overflow-y:auto;padding:24px}.view.active{display:block}.view-sessions{display:none;flex:1;overflow:hidden}.view-sessions.active{display:grid;grid-template-columns:34% 66%}.view-sessions>section{padding:16px;overflow-y:auto}.view-sessions>section+section{border-left:1px solid var(--border)}.msg-bar{padding:10px 16px;border-top:1px solid var(--border);background:var(--bg-card);display:flex;gap:8px;align-items:center;flex-shrink:0}.card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:16px;margin-bottom:12px}.card-title{font-size:15px;font-weight:600;margin-bottom:4px}.status-badge{display:inline-flex;align-items:center;gap:5px;font-size:12px;font-weight:600;padding:4px 10px;border-radius:20px;letter-spacing:.02em}.status-active,.status-running{background:#22c55e26;color:var(--green-hi);border:1px solid rgba(34,197,94,.3)}.status-stopped{background:#ef44441f;color:var(--red-hi);border:1px solid rgba(239,68,68,.25)}.meta{font-size:12px;color:var(--text-2)}.page-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:20px}.page-title{font-size:18px;font-weight:700;letter-spacing:-.3px}.page-sub{font-size:13px;color:var(--text-2);margin-top:3px}h3{font-size:14px;font-weight:600;margin-bottom:8px}.msg{border:1px solid var(--border);border-radius:var(--radius);padding:10px 12px;margin-bottom:8px;background:var(--bg-card)}.msg.u{border-left:3px solid var(--accent);background:#38bdf812;margin-left:40px}.msg.a{border-left:3px solid var(--green);background:#34d3990a}.dlq-item{border-left:3px solid var(--red)!important}.t{white-space:pre-wrap;font-size:13px;line-height:1.5;font-family:SF Mono,Fira Code,monospace}.chat-bubble{background:var(--surface-2);border-radius:10px;padding:12px 14px;font-size:14px;line-height:1.6;white-space:pre-wrap;word-break:break-word;max-width:85%;will-change:contents;contain:layout style paint}.chat-bubble.user{background:#38bdf81a;border:1px solid rgba(56,189,248,.2);margin-left:auto}.chat-bubble.assistant{background:var(--bg-card);border:1px solid var(--border)}#chatProjectTabs{scrollbar-width:thin;scrollbar-color:var(--border) transparent}#chatProjectTabs::-webkit-scrollbar{height:4px}#chatProjectTabs::-webkit-scrollbar-track{background:transparent}#chatProjectTabs::-webkit-scrollbar-thumb{background:var(--border);border-radius:2px}.project-tab{padding:6px 14px;border-radius:6px;font-size:12px;white-space:nowrap;cursor:pointer;border:none;background:#ffffff0a;color:var(--text-2);font-weight:500;transition:all .2s;font-family:inherit}.project-tab:hover{background:#ffffff14}.project-tab.active{background:var(--accent);color:var(--bg);font-weight:600}.row{padding:10px 12px;border:1px solid var(--border);border-radius:var(--radius);margin-bottom:8px;cursor:pointer;background:var(--bg-card);transition:border-color .12s,background .12s}.row:hover{background:var(--bg-hover)}.row.active{border-color:var(--accent);background:#38bdf80f}button{background:var(--accent);color:#000;border:none;border-radius:7px;padding:7px 14px;cursor:pointer;font-weight:600;font-size:13px;font-family:inherit;transition:opacity .12s}button:hover{opacity:.85}.btn-ghost{background:transparent;color:var(--text-2);border:1px solid var(--border)}.btn-ghost:hover{background:var(--bg-hover);color:var(--text)}.btn-green{background:var(--green);color:#000}.btn-sky{background:#0ea5e9;color:#000;border:1px solid #0ea5e9}.btn-sky:hover{background:var(--accent)}.btn-red{background:var(--red);color:#fff}.btn-yellow{background:var(--yellow);color:#000}.btn-purple{background:var(--accent2);color:#fff}.btn-muted{background:var(--bg-card2);color:var(--text-2);border:1px solid var(--border)}.reply-btn{font-size:11px;padding:3px 8px;background:var(--accent2);color:#fff;margin-left:8px}.replay-btn{font-size:11px;padding:3px 8px;background:var(--yellow);color:#000;margin-left:8px}.send-btn{background:var(--green);color:#000}.emoji-btn{width:46px;height:46px;font-size:22px;background:#ffffff0a;border:1px solid rgba(255,255,255,.1);border-radius:var(--radius);cursor:pointer;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:border-color .15s,background .15s;color:inherit}.emoji-btn:hover{border-color:var(--accent);background:#38bdf814}.emoji-picker-wrap{position:relative;flex-shrink:0}.emoji-picker-panel{display:none;position:absolute;top:50px;right:0;z-index:200;background:var(--bg-card);border:1px solid var(--border-hi);border-radius:var(--radius);padding:10px;box-shadow:0 8px 32px #00000080;width:260px}.emoji-picker-panel.open{display:block}.emoji-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:6px}.emoji-opt{font-size:22px;width:36px;height:36px;display:flex;align-items:center;justify-content:center;cursor:pointer;border-radius:6px;transition:background .1s}.emoji-opt:hover{background:#38bdf826}.file-row{display:flex;align-items:center;gap:10px;padding:8px 12px;background:var(--bg-card);border:1px solid var(--border);border-radius:6px;transition:border-color .15s}.file-row:hover{border-color:var(--accent)}.file-info{flex:1;min-width:0}.file-name{display:block;font-size:13px;color:var(--text);font-family:SF Mono,Fira Code,monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.file-meta{font-size:11px;color:var(--text-2)}.file-actions{display:flex;gap:5px;flex-shrink:0}.file-btn{font-size:11px;padding:3px 8px;border-radius:4px;border:1px solid var(--border);background:var(--bg-card2);color:var(--text-2);cursor:pointer;text-decoration:none;transition:all .15s;white-space:nowrap}.file-btn:hover{color:var(--text);border-color:var(--accent)}.file-btn-cursor{border-color:#6366f166;color:#818cf8}.file-btn-cursor:hover{background:#6366f126}.file-btn-opencode{border-color:#34d39966;color:#34d399}.file-btn-opencode:hover{background:#34d3991a}select,input[type=text],input[type=password],input[type=number],input[type=email],input:not([type]),textarea{background:var(--bg-1);color:var(--text-1);border:1px solid var(--border);border-radius:6px;padding:6px 10px;font-size:13px;font-family:inherit;outline:none;transition:border-color .15s,background .15s,box-shadow .15s;width:100%;box-sizing:border-box}select:focus,input:not([type]):focus,input[type=text]:focus,input[type=password]:focus,input[type=number]:focus,input[type=email]:focus,textarea:focus{border-color:var(--accent);background:#38bdf80a;box-shadow:0 0 0 3px #38bdf814}select{cursor:pointer}::placeholder{color:var(--text-3);opacity:1}input[type=text]{flex:1}textarea{resize:vertical;width:100%}input,textarea,select{user-select:text;-webkit-user-select:text;cursor:text}.inp-sm{padding:5px 8px!important;font-size:12px!important}.inp-xs{padding:3px 6px!important;font-size:12px!important;width:auto!important}.inp-mono{font-family:SF Mono,Fira Code,ui-monospace,monospace!important}.inp-flex{flex:1;width:auto!important}.notification{position:fixed;top:20px;right:20px;background:var(--green);color:#000;padding:12px 20px;border-radius:8px;box-shadow:0 4px 20px #0006;z-index:1000;animation:slideIn .25s ease;font-weight:600;font-size:13px}.notification.error{background:var(--red);color:#fff}.notification.warning{background:var(--amber);color:#000}@keyframes slideIn{0%{transform:translate(120%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes pulse{0%,to{opacity:.3;transform:scale(.85)}50%{opacity:1;transform:scale(1.15)}}.log-block{background:var(--bg);border:1px solid var(--border);border-radius:var(--radius);padding:12px;font-family:SF Mono,Fira Code,monospace;font-size:12px;color:var(--accent);max-height:220px;overflow-y:auto;white-space:pre-wrap;line-height:1.5}.rm-textarea{width:100%;font-family:SF Mono,Fira Code,monospace;font-size:12px;background:var(--bg);color:var(--text-2);border:1px solid var(--border);border-radius:8px;padding:12px;line-height:1.6;resize:vertical;box-sizing:border-box}.log-block.green{color:var(--green);border-color:#34d39933}.log-block.mono{color:var(--text-2)}.provider-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;margin-bottom:10px}.provider-header{display:flex;align-items:center;gap:12px;padding:13px 16px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .12s}.provider-header:hover{background:var(--bg-hover)}.provider-badge{font-size:11px;padding:2px 8px;border-radius:999px;font-weight:600}.provider-body{display:none;padding:16px;border-top:1px solid var(--border);background:var(--bg)}.provider-body.open{display:block}.key-row{display:flex;gap:8px;align-items:center;margin-bottom:12px}.key-input{flex:1;font-family:SF Mono,Fira Code,ui-monospace,monospace}.model-tag{display:inline-block;background:var(--bg-card2);border:1px solid var(--border);border-radius:5px;padding:2px 8px;font-size:11px;margin:2px;font-family:SF Mono,monospace;color:var(--text-2)}.test-ok{color:var(--green);font-size:12px;margin-left:8px;font-weight:600}.test-err{color:var(--red);font-size:12px;margin-left:8px}.pm-badge{font-size:11px;padding:2px 10px;border-radius:999px;font-weight:600;margin-left:10px;background:var(--bg-card2);color:var(--text-2);border:1px solid var(--border)}.pm-badge.running{background:#34d3991a;color:var(--green);border-color:#34d3994d}.prog-bar{height:4px;background:var(--bg-card2);border-radius:2px;overflow:hidden;margin:8px 0}.prog-fill{height:100%;border-radius:2px;transition:width .3s}.divider{border:none;border-top:1px solid var(--border);margin:20px 0}.agent-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}.agent-card-header{display:flex;align-items:center;gap:12px;padding:14px 16px}.agent-avatar{width:38px;height:38px;border-radius:10px;background:var(--bg-card2);border:1px solid var(--border);display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0}.agent-meta{flex:1;min-width:0}.agent-id{font-weight:700;font-size:14px}.agent-model{font-size:12px;color:var(--text-2);font-family:SF Mono,monospace;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.agent-body{border-top:1px solid var(--border);padding:14px 16px;background:var(--bg);display:grid;gap:12px}.agent-row{display:grid;grid-template-columns:110px 1fr auto auto;gap:8px;align-items:center}.agent-row label{font-size:12px;color:var(--text-2);font-weight:500}.agent-badge{font-size:11px;padding:2px 8px;border-radius:999px;background:#38bdf81a;color:var(--accent);border:1px solid rgba(56,189,248,.2);font-weight:600}.agent-badge.online{background:#34d3991a;color:var(--green);border-color:#34d3994d}.field-label{font-size:11px;font-weight:600;color:var(--text-2);margin-bottom:5px;text-transform:uppercase;letter-spacing:.05em}.tool-profile-opt{cursor:pointer}.tool-profile-opt input[type=radio]{display:none}.tp-card{border:1px solid var(--border);border-radius:8px;padding:10px 12px;transition:border-color .12s,background .12s}.tool-profile-opt:hover .tp-card{border-color:var(--accent);background:var(--bg-hover)}.tool-profile-opt input:checked+.tp-card{border-color:var(--accent);background:#38bdf812}.tp-name{font-size:13px;font-weight:700;margin-bottom:4px;color:var(--text);font-family:SF Mono,monospace}.tp-desc{font-size:11px;color:var(--text-2);line-height:1.4}::-webkit-scrollbar{width:5px;height:5px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}#rtView::-webkit-scrollbar{width:8px}#rtView::-webkit-scrollbar-track{background:var(--bg-card);border-radius:4px}#rtView::-webkit-scrollbar-thumb{background:var(--accent);border-radius:4px;opacity:.7}#rtView::-webkit-scrollbar-thumb:hover{background:var(--accent);opacity:1}#rtView{scrollbar-width:thin;scrollbar-color:var(--accent) var(--bg-card)}@media(max-width:1100px){body{flex-direction:column}.sidebar{width:100%!important;min-width:0!important;flex-direction:row;flex-wrap:wrap;padding:8px 12px;gap:4px;border-right:none;border-bottom:1px solid var(--border)}.sidebar .nav-item{padding:6px 10px;font-size:12px}.sidebar .nav-section{display:flex;flex-wrap:wrap;padding:0;gap:4px}.sidebar .nav-label,.sidebar .sidebar-bottom{display:none}.main-wrap{min-width:0}}@media(max-width:768px){.sidebar .nav-label{display:none}.sidebar .nav-item{padding:8px;min-width:36px;justify-content:center}#servicesGrid,#agentsList,#projectsList,#runSkillsGrid{grid-template-columns:1fr!important}.chat-input-row{flex-wrap:wrap;gap:6px}.chat-input-row button{height:44px}#chatInput{min-height:44px}.page-header{flex-direction:column;align-items:flex-start;gap:8px}.page-header .actions{flex-wrap:wrap}.container,.dashboard-grid,.view,.card{width:100%;max-width:100%;padding:1rem}img,video{max-width:100%;height:auto}button,a,.nav-item,input,select,textarea{min-height:44px}}@media(max-width:480px){body{font-size:13px}.card{padding:12px}.card-title{font-size:14px}.page-title{font-size:18px}.tab-bar{flex-wrap:wrap;gap:4px}.stab{padding:4px 10px;font-size:11px}button{min-height:44px;font-size:16px;padding:8px 16px}input,select,textarea{font-size:16px;min-height:44px}input:focus,select:focus,textarea:focus{font-size:16px}}.prompt-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:16px;transition:all .2s}.prompt-card:hover{border-color:var(--border-hi);background:var(--bg-hover)}.prompt-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:12px;gap:12px}.prompt-preview{font-size:12px;color:var(--text-2);line-height:1.5;font-family:SF Mono,Monaco,monospace;white-space:pre-wrap;word-break:break-word}.prompt-edit-btn{flex-shrink:0}.agent-info-card{background:var(--bg-card);border:1px solid var(--border);border-radius:8px;padding:16px}.agent-info-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px}.agent-info-header h4{margin:0;font-size:16px;font-weight:600}.agent-status{padding:4px 10px;border-radius:12px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em}.agent-status.active{background:var(--green-hi);color:#000}.agent-status.idle{background:var(--bg-card2);color:var(--text-3)}.agent-info-details{display:flex;flex-direction:column;gap:8px}.detail-row{display:flex;justify-content:space-between;font-size:13px;align-items:center}.detail-row .label{color:var(--text-3);font-weight:600}.detail-row .value{color:var(--text-1);font-family:SF Mono,Monaco,monospace;font-size:12px}#agentChatMessages{display:flex;flex-direction:column;gap:12px}.user-message,.agent-message{padding:12px 16px;border-radius:12px;max-width:75%;word-wrap:break-word}.user-message{background:var(--accent);color:#fff;align-self:flex-end;border-bottom-right-radius:4px}.agent-message{background:var(--bg-card);border:1px solid var(--border);align-self:flex-start;border-bottom-left-radius:4px}.message-header{display:flex;justify-content:space-between;margin-bottom:6px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;opacity:.8}.message-time{color:var(--text-3);font-size:10px;font-weight:400;text-transform:none;letter-spacing:0}.message-content{font-size:14px;line-height:1.6}.message-content code{background:#0000004d;padding:2px 6px;border-radius:4px;font-family:SF Mono,Monaco,monospace;font-size:13px}.message-content pre{background:#0006;padding:12px;border-radius:6px;overflow-x:auto;margin:8px 0;border:1px solid var(--border)}.message-content pre code{background:none;padding:0}.message-content a{color:var(--accent);text-decoration:none}.message-content a:hover{text-decoration:underline}.process-card{background:var(--bg-card);padding:12px;border-radius:8px;margin-bottom:8px}.process-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px}.process-cli{font-weight:600;font-family:SF Mono,Monaco,monospace;font-size:13px}.process-status{text-transform:uppercase;font-size:11px;font-weight:700;color:var(--text-3);letter-spacing:.05em}.process-details{font-size:12px;color:var(--text-2);line-height:1.6;font-family:SF Mono,Monaco,monospace}.empty-state{text-align:center;padding:60px 20px;color:var(--text-3);font-size:14px}.process-status-empty{padding:12px;text-align:center;color:var(--text-3);font-size:12px;font-style:italic}#workflowsLayout{display:grid;grid-template-columns:minmax(260px,340px) minmax(420px,1fr);gap:16px;align-items:start}@media(max-width:980px){#workflowsLayout{grid-template-columns:1fr}}.setup-wizard-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:9999;display:flex;align-items:center;justify-content:center;background:#040810eb;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);opacity:0;transition:opacity .26s ease}.setup-wizard-overlay.visible{opacity:1}.setup-wizard-overlay.dismissing{opacity:0}.setup-wizard-card{width:100%;max-width:520px;margin:0 16px;background:var(--bg-card);border:1px solid var(--border);border-radius:16px;padding:40px 36px 32px;box-shadow:0 0 0 1px #ffffff0a,0 24px 64px #00000080;transform:translateY(12px) scale(.98);opacity:0;transition:transform .3s cubic-bezier(.16,1,.3,1),opacity .3s ease}.setup-wizard-card.visible{transform:translateY(0) scale(1);opacity:1}.setup-wizard-steps{display:flex;align-items:center;justify-content:center;gap:0;margin-bottom:32px}.setup-wizard-step{display:flex;flex-direction:column;align-items:center;gap:6px}.setup-wizard-step-dot{width:10px;height:10px;border-radius:50%;border:2px solid var(--text-3);background:transparent;padding:0;cursor:default;transition:background .2s ease,border-color .2s ease,box-shadow .2s ease}.setup-wizard-step-dot.active{border-color:var(--accent);background:var(--accent);box-shadow:0 0 8px #38bdf866}.setup-wizard-step-dot.completed{border-color:var(--green);background:var(--green)}.setup-wizard-step-label{font-size:11px;color:var(--text-3);font-weight:500;letter-spacing:.02em}.setup-wizard-step .active~.setup-wizard-step-label,.setup-wizard-step-dot.active+.setup-wizard-step-label{color:var(--accent)}.setup-wizard-step-dot.completed+.setup-wizard-step-label{color:var(--green)}.setup-wizard-step-line{width:48px;height:2px;background:var(--text-3);margin:0 12px 18px;border-radius:1px;transition:background .2s ease}.setup-wizard-step-line.completed{background:var(--green)}.setup-wizard-content{display:flex;flex-direction:column}.setup-wizard-hero{text-align:center;margin-bottom:28px}.setup-wizard-logo-ring{display:inline-flex;align-items:center;justify-content:center;width:64px;height:64px;border-radius:16px;background:var(--bg-card2);border:1px solid var(--border);margin-bottom:20px}.setup-wizard-logo{width:36px;height:36px}.setup-wizard-title{font-size:24px;font-weight:700;color:var(--text);line-height:1.2;margin-bottom:8px;letter-spacing:-.02em}.setup-wizard-subtitle{font-size:15px;color:var(--text-2);line-height:1.5}.setup-wizard-checklist{display:flex;flex-direction:column;gap:10px;padding:16px 20px;background:var(--bg-card2);border:1px solid var(--border);border-radius:10px;margin-bottom:28px}.setup-wizard-check-item{display:flex;align-items:center;gap:10px;font-size:14px;color:var(--text-2)}.setup-wizard-check-icon{width:20px;height:20px;display:flex;align-items:center;justify-content:center;border-radius:50%;font-size:12px;flex-shrink:0}.setup-wizard-check-icon.done{background:#34d39926;color:var(--green);border:1px solid rgba(52,211,153,.3)}.setup-wizard-check-icon.pending{background:var(--bg-card);color:var(--text-3);border:1px solid var(--border);font-size:8px}.setup-wizard-section-header{margin-bottom:20px}.setup-wizard-section-title{font-size:20px;font-weight:700;color:var(--text);line-height:1.2;margin-bottom:6px;letter-spacing:-.01em}.setup-wizard-section-desc{font-size:14px;color:var(--text-2);line-height:1.5}.setup-wizard-provider-list{display:flex;flex-direction:column;gap:8px;margin-bottom:20px;max-height:360px;overflow-y:auto}.setup-wizard-provider-row{display:flex;flex-direction:column;gap:6px;padding:12px 14px;background:var(--bg-card2);border:1px solid var(--border);border-radius:10px;transition:border-color .2s ease,background .2s ease}.setup-wizard-provider-row.has-key{border-color:#34d3994d;background:#34d3990a}.setup-wizard-provider-label{display:flex;align-items:center;gap:8px}.setup-wizard-provider-icon{font-size:16px;width:22px;text-align:center;flex-shrink:0}.setup-wizard-provider-name{font-size:14px;font-weight:600;color:var(--text)}.setup-wizard-provider-link{margin-left:auto;font-size:12px;color:var(--accent);text-decoration:none;opacity:.7;transition:opacity .15s ease}.setup-wizard-provider-link:hover{opacity:1;text-decoration:underline}.setup-wizard-provider-input-wrap{display:flex;align-items:center;gap:6px}.setup-wizard-provider-input{flex:1;background:var(--bg);border:1px solid var(--border);border-radius:7px;padding:8px 10px;color:var(--text);font-size:13px;font-family:inherit;outline:none;transition:border-color .2s ease}.setup-wizard-provider-input::placeholder{color:var(--text-3)}.setup-wizard-provider-input:focus{border-color:var(--accent)}.setup-wizard-toggle-vis{background:transparent;border:1px solid var(--border);border-radius:6px;padding:6px 8px;font-size:14px;cursor:pointer;color:var(--text-3);transition:color .15s ease}.setup-wizard-toggle-vis:hover{color:var(--text)}.setup-wizard-engine-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;margin-bottom:16px}.setup-wizard-engine-card{background:var(--bg);border:1px solid var(--border);border-radius:10px;padding:16px;display:flex;flex-direction:column;gap:6px;transition:border-color .15s ease,background .15s ease}.setup-wizard-engine-card.available{border-color:#34d3994d;background:#34d39908}.setup-wizard-engine-card:not(.available){opacity:.7}.setup-wizard-engine-badge{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em}.setup-wizard-engine-badge.installed{color:var(--green, #34d399)}.setup-wizard-engine-badge.missing{color:var(--text-3, #666)}.setup-wizard-engine-title{font-size:15px;font-weight:600;color:var(--text)}.setup-wizard-engine-cmd{font-size:12px;color:var(--text-3);background:var(--bg-card);padding:2px 8px;border-radius:4px;display:inline-block;width:fit-content;font-family:var(--font-mono, monospace)}.setup-wizard-engine-desc{font-size:12px;color:var(--text-2);line-height:1.4;margin:4px 0 8px}.setup-wizard-engine-action{margin-top:auto;display:flex;align-items:center;gap:6px;font-size:12px}.setup-wizard-engine-auth-label{color:var(--text-3)}.setup-wizard-engine-auth-cmd{font-size:11px;color:var(--accent);background:#6366f11a;padding:3px 8px;border-radius:4px;font-family:var(--font-mono, monospace)}.setup-wizard-engine-key-note{font-size:12px}.setup-wizard-engine-key-note.key-ok{color:var(--green, #34d399)}.setup-wizard-engine-key-note.key-missing{color:var(--yellow, #fbbf24)}.setup-wizard-engine-install-btn{font-size:12px;color:var(--accent);text-decoration:none;font-weight:500;padding:4px 12px;border:1px solid var(--accent);border-radius:6px;transition:background .15s ease}.setup-wizard-engine-install-btn:hover{background:#6366f11a}.setup-wizard-engine-hint{font-size:13px;color:var(--text-2);text-align:center;margin:8px 0}.setup-wizard-provider-icon{font-size:16px;width:24px;text-align:center;flex-shrink:0}.setup-wizard-preset-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:24px}.setup-wizard-preset-card{display:flex;flex-direction:column;align-items:center;text-align:center;padding:20px 12px;background:var(--bg-card2);border:2px solid var(--border);border-radius:12px;cursor:pointer;transition:border-color .2s ease,background .2s ease,transform .15s ease}.setup-wizard-preset-card:hover{background:var(--bg-hover);transform:translateY(-1px)}.setup-wizard-preset-card.selected{border-color:var(--accent);background:#38bdf80f}.setup-wizard-preset-icon{font-size:28px;margin-bottom:10px;line-height:1}.setup-wizard-preset-label{font-size:15px;font-weight:700;color:var(--text);margin-bottom:6px;letter-spacing:-.01em}.setup-wizard-preset-desc{font-size:12px;color:var(--text-2);line-height:1.4}.setup-wizard-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:8px}.setup-wizard-btn-primary{background:var(--accent);color:#000;border:none;border-radius:8px;padding:10px 24px;font-size:14px;font-weight:600;font-family:inherit;cursor:pointer;transition:opacity .15s ease,transform .1s ease}.setup-wizard-btn-primary:hover{opacity:.9}.setup-wizard-btn-primary:active{transform:scale(.98)}.setup-wizard-btn-primary:disabled{opacity:.4;cursor:not-allowed}.setup-wizard-btn-ghost{background:transparent;color:var(--text-2);border:1px solid var(--border);border-radius:8px;padding:10px 20px;font-size:14px;font-weight:500;font-family:inherit;cursor:pointer;transition:background .15s ease,color .15s ease}.setup-wizard-btn-ghost:hover{background:var(--bg-hover);color:var(--text)}.setup-wizard-error{padding:10px 14px;background:#f871711a;border:1px solid rgba(248,113,113,.25);border-radius:8px;color:var(--red);font-size:13px;margin-bottom:12px}.setup-wizard-error.hidden{display:none}@media(max-width:640px){.setup-wizard-card{padding:28px 20px 24px;margin:0 12px;border-radius:12px}.setup-wizard-engine-grid,.setup-wizard-preset-grid{grid-template-columns:1fr;gap:8px}.setup-wizard-preset-card{flex-direction:row;text-align:left;gap:12px;padding:14px 16px}.setup-wizard-preset-icon{font-size:22px;margin-bottom:0}.setup-wizard-preset-label{margin-bottom:2px}.setup-wizard-step-line{width:28px;margin:0 6px}.setup-wizard-actions{flex-direction:column-reverse}.setup-wizard-btn-primary,.setup-wizard-btn-ghost{width:100%;text-align:center}}.test-launch-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:10px;margin-bottom:20px}.test-launch-card{background:var(--bg-2, #1a1a2e);border:1px solid var(--border);border-left:3px solid;border-radius:8px;padding:12px 14px}.test-launch-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}.test-launch-name{font-size:14px;font-weight:700}.test-launch-btn{font-size:11px;padding:3px 10px;border-radius:5px;border:1px solid var(--border);background:var(--bg-2);color:var(--text-1);cursor:pointer;font-weight:600}.test-launch-btn:hover{background:#ffffff14}.test-launch-counts{display:flex;gap:12px;font-size:12px;color:var(--text-2)}.test-launch-files{font-weight:500}.test-launch-tests{color:var(--text-1);font-weight:600}.test-launch-total{background:#60a5fa0a}.test-suite-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:12px;margin-bottom:16px}.test-suite-card{background:var(--bg-2, #1a1a2e);border:1px solid var(--border);border-radius:10px;padding:16px}.test-suite-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}.test-suite-name{font-size:15px;font-weight:700}.test-suite-stats{display:flex;gap:16px;font-size:13px;margin-bottom:8px}.test-suite-stats div{color:var(--text-2)}.test-suite-stats span{font-weight:600}.test-suite-meta{font-size:11px;color:var(--text-2);margin-bottom:10px}.test-summary-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px}.test-summary-status{font-size:13px;font-weight:700;letter-spacing:.5px;padding:4px 12px;border-radius:6px}.test-status-pass{background:#34d3991f;color:#34d399}.test-status-fail{background:#f871711f;color:#f87171}.test-summary-meta{font-size:12px;color:var(--text-2)}.test-meta-sep{margin:0 6px;opacity:.4}.test-summary-stats{display:flex;gap:32px;margin-bottom:14px}.test-stat{text-align:center}.test-stat-value{font-size:24px;font-weight:700;line-height:1.2}.test-stat-label{font-size:11px;color:var(--text-2);text-transform:uppercase;letter-spacing:.3px}.test-color-pass{color:#34d399}.test-color-fail{color:#f87171}.test-color-skip{color:#fbbf24}.test-progress-bar{display:flex;height:6px;border-radius:3px;overflow:hidden;background:#ffffff0d}.test-progress-pass{background:#34d399}.test-progress-fail{background:#f87171}.test-progress-skip{background:#fbbf24}.test-actions{display:flex;gap:8px;margin-bottom:20px;flex-wrap:wrap}.test-section-title{font-size:13px;font-weight:600;color:var(--text-2);text-transform:uppercase;letter-spacing:.4px;margin:20px 0 10px}.test-groups-table{width:100%;border-collapse:collapse;font-size:13px;margin-bottom:16px}.test-groups-table th{text-align:left;font-size:11px;font-weight:600;color:var(--text-2);text-transform:uppercase;letter-spacing:.3px;padding:8px 10px;border-bottom:1px solid var(--border)}.test-groups-table th.num,.test-groups-table td.num{text-align:right;font-variant-numeric:tabular-nums}.test-groups-table td{padding:6px 10px;border-bottom:1px solid rgba(255,255,255,.03)}.test-groups-table tbody tr:hover{background:#ffffff05}.test-row-fail{background:#f871710a}.test-cat-badge{font-size:11px;padding:2px 8px;border-radius:4px;font-weight:500}.test-cat-unit{background:#6366f126;color:#818cf8}.test-cat-integration{background:#34d39926;color:#34d399}.test-cat-e2e{background:#fbbf2426;color:#fbbf24}.test-cat-other{background:#94a3b826;color:#94a3b8}.test-failure-card{background:#f871710a;border:1px solid rgba(248,113,113,.15);border-radius:8px;padding:14px;margin-bottom:10px}.test-failure-name{font-weight:600;font-size:13px;margin-bottom:4px}.test-failure-file{font-size:11px;color:var(--text-2);margin-bottom:6px}.test-failure-class{font-size:10px;padding:2px 6px;border-radius:3px;background:#f871711f;color:#f87171;font-weight:500}.test-failure-error{font-size:11px;background:#0000004d;border-radius:6px;padding:10px;margin-top:8px;overflow-x:auto;white-space:pre-wrap;word-break:break-word;color:var(--text-2);max-height:120px;overflow-y:auto}.test-failure-rerun{margin-top:8px}.test-failure-rerun code{font-size:10px;background:#ffffff0d;padding:4px 8px;border-radius:4px;display:inline-block;word-break:break-all}.test-progress-live{background:#60a5fa0f;border:1px solid rgba(96,165,250,.2);border-radius:10px;padding:14px 18px;margin-bottom:16px;animation:test-progress-pulse 2s ease-in-out infinite}.test-progress-done{animation:none;background:#34d3990f;border-color:#34d39933}@keyframes test-progress-pulse{0%,to{border-color:#60a5fa33}50%{border-color:#60a5fa80}}.test-progress-live-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.test-progress-live-status{font-weight:700;font-size:14px;color:var(--accent)}.test-progress-live-stats{display:flex;gap:16px;font-size:13px;font-weight:500;margin-bottom:4px}.test-progress-live-stats span{color:var(--text-2)}.test-progress-live-file{font-size:11px;color:var(--text-2);font-family:monospace;margin-top:4px}.test-skips-section{margin:12px 0}.test-skips-section[open] summary{margin-bottom:10px}.test-history-chart{display:flex;align-items:flex-end;gap:4px;padding:12px 0;min-height:90px}.test-history-bar{flex:1;display:flex;flex-direction:column;align-items:center;cursor:default;min-width:20px}.test-history-bar-inner{width:100%;max-width:28px;border-radius:3px;overflow:hidden;display:flex;flex-direction:column}.test-history-pass{background:#34d399}.test-history-fail{background:#f87171}.test-history-label{font-size:9px;color:var(--text-2);margin-top:4px;white-space:nowrap}.test-history-table{width:100%;border-collapse:collapse;font-size:12px;margin-top:12px}.test-history-table th{text-align:left;font-size:11px;font-weight:600;color:var(--text-2);text-transform:uppercase;letter-spacing:.3px;padding:6px 10px;border-bottom:1px solid var(--border)}.test-history-table th.num,.test-history-table td.num{text-align:right;font-variant-numeric:tabular-nums}.test-history-table td{padding:5px 10px;border-bottom:1px solid rgba(255,255,255,.03)}.test-history-table tbody tr:hover{background:#ffffff05}
1
+ :root{--bg: #060a10;--bg-0: #040810;--bg-1: #0d1420;--bg-2: #111827;--bg-card: #0d1420;--bg-card2: #111827;--bg-hover: #141e2e;--surface-2: #16202e;--border: rgba(255, 255, 255, .07);--border-hi: rgba(56, 189, 248, .35);--text: #f0f6ff;--text-1: #f0f6ff;--text-2: #a0b3cc;--text-3: #7a8a9f;--accent: #38bdf8;--accent2: #818cf8;--purple: #818cf8;--green: #34d399;--red: #f87171;--yellow: #fbbf24;--amber: #f59e0b;--green-hi: #22c55e;--red-hi: #ef4444;--sky: #38bdf8;--blue: #4a7ab5;--teal: #0f766e;--warning: #f59e0b;--radius: 10px}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,sans-serif;background:var(--bg);color:var(--text);display:flex;height:100vh;overflow:hidden;font-size:14px;touch-action:manipulation}.skip-link{position:absolute;top:-40px;left:0;background:var(--accent);color:#000;padding:8px 16px;text-decoration:none;font-weight:600;border-radius:0 0 4px;z-index:9999}.skip-link:focus{top:0}*:focus-visible{outline:3px solid var(--accent);outline-offset:2px}button:focus-visible,a:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{outline:3px solid var(--accent);outline-offset:2px}.sidebar{width:216px;min-width:216px;background:var(--bg-card);border-right:1px solid var(--border);display:flex;flex-direction:column;overflow-y:auto}.sidebar-brand{display:flex;align-items:center;gap:10px;padding:18px 16px 14px;border-bottom:1px solid var(--border);text-decoration:none}.brand-icon{width:24px;height:24px;object-fit:contain;display:block}.brand-name{font-size:15px;font-weight:800;color:var(--text);letter-spacing:.06em;text-transform:uppercase}.brand-name span{color:var(--accent)}.sidebar-status{display:flex;align-items:center;gap:8px;padding:10px 16px;border-bottom:1px solid var(--border)}.status-dot{width:7px;height:7px;border-radius:50%;background:var(--text-3);flex-shrink:0}.status-dot.online{background:var(--green);box-shadow:0 0 6px var(--green)}.status-dot.error{background:var(--red)}#status{font-size:12px;color:var(--text-2)}.nav-section{padding:12px 8px 4px}.nav-label{font-size:10px;font-weight:600;color:var(--text-3);letter-spacing:.08em;text-transform:uppercase;padding:0 8px 6px}.nav-item{display:flex;align-items:center;gap:9px;width:100%;padding:8px 10px;border-radius:7px;border:none;background:transparent;color:var(--text-2);font-size:13px;font-weight:500;cursor:pointer;text-align:left;transition:background .12s,color .12s;font-family:inherit}.stab{padding:7px 16px;border:none;background:transparent;color:var(--text-2);font-size:13px;font-weight:500;cursor:pointer;border-bottom:2px solid transparent;margin-bottom:-1px;font-family:inherit;transition:color .12s,border-color .12s;white-space:nowrap}.stab:hover{color:var(--text-1)}.stab.active{color:var(--accent);border-bottom-color:var(--accent)}.nav-item:hover{background:var(--bg-hover);color:var(--text)}.nav-item.active{background:#38bdf81a;color:var(--accent)}.nav-item .nav-icon{font-size:15px;width:18px;text-align:center}.nav-badge{margin-left:auto;background:var(--red);color:#fff;font-size:10px;font-weight:700;padding:1px 6px;border-radius:999px;min-width:18px;text-align:center}.nav-badge.hidden{display:none}.sidebar-bottom{margin-top:auto;padding:12px 8px;border-top:1px solid var(--border)}.main-wrap{flex:1;display:flex;flex-direction:column;overflow:hidden}.view{display:none;flex:1;overflow-y:auto;padding:24px}.view.active{display:block}.view-sessions{display:none;flex:1;overflow:hidden}.view-sessions.active{display:grid;grid-template-columns:34% 66%}.view-sessions>section{padding:16px;overflow-y:auto}.view-sessions>section+section{border-left:1px solid var(--border)}.msg-bar{padding:10px 16px;border-top:1px solid var(--border);background:var(--bg-card);display:flex;gap:8px;align-items:center;flex-shrink:0}.card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:16px;margin-bottom:12px}.card-title{font-size:15px;font-weight:600;margin-bottom:4px}.status-badge{display:inline-flex;align-items:center;gap:5px;font-size:12px;font-weight:600;padding:4px 10px;border-radius:20px;letter-spacing:.02em}.status-active,.status-running{background:#22c55e26;color:var(--green-hi);border:1px solid rgba(34,197,94,.3)}.status-stopped{background:#ef44441f;color:var(--red-hi);border:1px solid rgba(239,68,68,.25)}.meta{font-size:12px;color:var(--text-2)}.page-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:20px}.page-title{font-size:18px;font-weight:700;letter-spacing:-.3px}.page-sub{font-size:13px;color:var(--text-2);margin-top:3px}h3{font-size:14px;font-weight:600;margin-bottom:8px}.msg{border:1px solid var(--border);border-radius:var(--radius);padding:10px 12px;margin-bottom:8px;background:var(--bg-card)}.msg.u{border-left:3px solid var(--accent);background:#38bdf812;margin-left:40px}.msg.a{border-left:3px solid var(--green);background:#34d3990a}.dlq-item{border-left:3px solid var(--red)!important}.t{white-space:pre-wrap;font-size:13px;line-height:1.5;font-family:SF Mono,Fira Code,monospace}.chat-bubble{background:var(--surface-2);border-radius:10px;padding:12px 14px;font-size:14px;line-height:1.6;white-space:pre-wrap;word-break:break-word;max-width:85%;will-change:contents;contain:layout style paint}.chat-bubble.user{background:#38bdf81a;border:1px solid rgba(56,189,248,.2);margin-left:auto}.chat-bubble.assistant{background:var(--bg-card);border:1px solid var(--border)}#chatProjectTabs{scrollbar-width:thin;scrollbar-color:var(--border) transparent}#chatProjectTabs::-webkit-scrollbar{height:4px}#chatProjectTabs::-webkit-scrollbar-track{background:transparent}#chatProjectTabs::-webkit-scrollbar-thumb{background:var(--border);border-radius:2px}.project-tab{padding:6px 14px;border-radius:6px;font-size:12px;white-space:nowrap;cursor:pointer;border:none;background:#ffffff0a;color:var(--text-2);font-weight:500;transition:all .2s;font-family:inherit}.project-tab:hover{background:#ffffff14}.project-tab.active{background:var(--accent);color:var(--bg);font-weight:600}.row{padding:10px 12px;border:1px solid var(--border);border-radius:var(--radius);margin-bottom:8px;cursor:pointer;background:var(--bg-card);transition:border-color .12s,background .12s}.row:hover{background:var(--bg-hover)}.row.active{border-color:var(--accent);background:#38bdf80f}button{background:var(--accent);color:#000;border:none;border-radius:7px;padding:7px 14px;cursor:pointer;font-weight:600;font-size:13px;font-family:inherit;transition:opacity .12s}button:hover{opacity:.85}.btn-ghost{background:transparent;color:var(--text-2);border:1px solid var(--border)}.btn-ghost:hover{background:var(--bg-hover);color:var(--text)}.btn-green{background:var(--green);color:#000}.btn-sky{background:#0ea5e9;color:#000;border:1px solid #0ea5e9}.btn-sky:hover{background:var(--accent)}.btn-red{background:var(--red);color:#fff}.btn-yellow{background:var(--yellow);color:#000}.btn-purple{background:var(--accent2);color:#fff}.btn-muted{background:var(--bg-card2);color:var(--text-2);border:1px solid var(--border)}.reply-btn{font-size:11px;padding:3px 8px;background:var(--accent2);color:#fff;margin-left:8px}.replay-btn{font-size:11px;padding:3px 8px;background:var(--yellow);color:#000;margin-left:8px}.send-btn{background:var(--green);color:#000}.emoji-btn{width:46px;height:46px;font-size:22px;background:#ffffff0a;border:1px solid rgba(255,255,255,.1);border-radius:var(--radius);cursor:pointer;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:border-color .15s,background .15s;color:inherit}.emoji-btn:hover{border-color:var(--accent);background:#38bdf814}.emoji-picker-wrap{position:relative;flex-shrink:0}.emoji-picker-panel{display:none;position:absolute;top:50px;right:0;z-index:200;background:var(--bg-card);border:1px solid var(--border-hi);border-radius:var(--radius);padding:10px;box-shadow:0 8px 32px #00000080;width:260px}.emoji-picker-panel.open{display:block}.emoji-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:6px}.emoji-opt{font-size:22px;width:36px;height:36px;display:flex;align-items:center;justify-content:center;cursor:pointer;border-radius:6px;transition:background .1s}.emoji-opt:hover{background:#38bdf826}.file-row{display:flex;align-items:center;gap:10px;padding:8px 12px;background:var(--bg-card);border:1px solid var(--border);border-radius:6px;transition:border-color .15s}.file-row:hover{border-color:var(--accent)}.file-info{flex:1;min-width:0}.file-name{display:block;font-size:13px;color:var(--text);font-family:SF Mono,Fira Code,monospace;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.file-meta{font-size:11px;color:var(--text-2)}.file-actions{display:flex;gap:5px;flex-shrink:0}.file-btn{font-size:11px;padding:3px 8px;border-radius:4px;border:1px solid var(--border);background:var(--bg-card2);color:var(--text-2);cursor:pointer;text-decoration:none;transition:all .15s;white-space:nowrap}.file-btn:hover{color:var(--text);border-color:var(--accent)}.file-btn-cursor{border-color:#6366f166;color:#818cf8}.file-btn-cursor:hover{background:#6366f126}.file-btn-opencode{border-color:#34d39966;color:#34d399}.file-btn-opencode:hover{background:#34d3991a}select,input[type=text],input[type=password],input[type=number],input[type=email],input:not([type]),textarea{background:var(--bg-1);color:var(--text-1);border:1px solid var(--border);border-radius:6px;padding:6px 10px;font-size:13px;font-family:inherit;outline:none;transition:border-color .15s,background .15s,box-shadow .15s;width:100%;box-sizing:border-box}select:focus,input:not([type]):focus,input[type=text]:focus,input[type=password]:focus,input[type=number]:focus,input[type=email]:focus,textarea:focus{border-color:var(--accent);background:#38bdf80a;box-shadow:0 0 0 3px #38bdf814}select{cursor:pointer}::placeholder{color:var(--text-3);opacity:1}input[type=text]{flex:1}textarea{resize:vertical;width:100%}input,textarea,select{user-select:text;-webkit-user-select:text;cursor:text}.inp-sm{padding:5px 8px!important;font-size:12px!important}.inp-xs{padding:3px 6px!important;font-size:12px!important;width:auto!important}.inp-mono{font-family:SF Mono,Fira Code,ui-monospace,monospace!important}.inp-flex{flex:1;width:auto!important}.notification{position:fixed;top:20px;right:20px;background:var(--green);color:#000;padding:12px 20px;border-radius:8px;box-shadow:0 4px 20px #0006;z-index:1000;animation:slideIn .25s ease;font-weight:600;font-size:13px}.notification.error{background:var(--red);color:#fff}.notification.warning{background:var(--amber);color:#000}@keyframes slideIn{0%{transform:translate(120%);opacity:0}to{transform:translate(0);opacity:1}}@keyframes pulse{0%,to{opacity:.3;transform:scale(.85)}50%{opacity:1;transform:scale(1.15)}}.log-block{background:var(--bg);border:1px solid var(--border);border-radius:var(--radius);padding:12px;font-family:SF Mono,Fira Code,monospace;font-size:12px;color:var(--accent);max-height:220px;overflow-y:auto;white-space:pre-wrap;line-height:1.5}.rm-textarea{width:100%;font-family:SF Mono,Fira Code,monospace;font-size:12px;background:var(--bg);color:var(--text-2);border:1px solid var(--border);border-radius:8px;padding:12px;line-height:1.6;resize:vertical;box-sizing:border-box}.log-block.green{color:var(--green);border-color:#34d39933}.log-block.mono{color:var(--text-2)}.provider-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;margin-bottom:10px}.provider-header{display:flex;align-items:center;gap:12px;padding:13px 16px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .12s}.provider-header:hover{background:var(--bg-hover)}.provider-badge{font-size:11px;padding:2px 8px;border-radius:999px;font-weight:600}.provider-body{display:none;padding:16px;border-top:1px solid var(--border);background:var(--bg)}.provider-body.open{display:block}.key-row{display:flex;gap:8px;align-items:center;margin-bottom:12px}.key-input{flex:1;font-family:SF Mono,Fira Code,ui-monospace,monospace}.model-tag{display:inline-block;background:var(--bg-card2);border:1px solid var(--border);border-radius:5px;padding:2px 8px;font-size:11px;margin:2px;font-family:SF Mono,monospace;color:var(--text-2)}.test-ok{color:var(--green);font-size:12px;margin-left:8px;font-weight:600}.test-err{color:var(--red);font-size:12px;margin-left:8px}.pm-badge{font-size:11px;padding:2px 10px;border-radius:999px;font-weight:600;margin-left:10px;background:var(--bg-card2);color:var(--text-2);border:1px solid var(--border)}.pm-badge.running{background:#34d3991a;color:var(--green);border-color:#34d3994d}.prog-bar{height:4px;background:var(--bg-card2);border-radius:2px;overflow:hidden;margin:8px 0}.prog-fill{height:100%;border-radius:2px;transition:width .3s}.divider{border:none;border-top:1px solid var(--border);margin:20px 0}.agent-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}.agent-card-header{display:flex;align-items:center;gap:12px;padding:14px 16px}.agent-avatar{width:38px;height:38px;border-radius:10px;background:var(--bg-card2);border:1px solid var(--border);display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0}.agent-meta{flex:1;min-width:0}.agent-id{font-weight:700;font-size:14px}.agent-model{font-size:12px;color:var(--text-2);font-family:SF Mono,monospace;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.agent-body{border-top:1px solid var(--border);padding:14px 16px;background:var(--bg);display:grid;gap:12px}.agent-row{display:grid;grid-template-columns:110px 1fr auto auto;gap:8px;align-items:center}.agent-row label{font-size:12px;color:var(--text-2);font-weight:500}.agent-badge{font-size:11px;padding:2px 8px;border-radius:999px;background:#38bdf81a;color:var(--accent);border:1px solid rgba(56,189,248,.2);font-weight:600}.agent-badge.online{background:#34d3991a;color:var(--green);border-color:#34d3994d}.field-label{font-size:11px;font-weight:600;color:var(--text-2);margin-bottom:5px;text-transform:uppercase;letter-spacing:.05em}.tool-profile-opt{cursor:pointer}.tool-profile-opt input[type=radio]{display:none}.tp-card{border:1px solid var(--border);border-radius:8px;padding:10px 12px;transition:border-color .12s,background .12s}.tool-profile-opt:hover .tp-card{border-color:var(--accent);background:var(--bg-hover)}.tool-profile-opt input:checked+.tp-card{border-color:var(--accent);background:#38bdf812}.tp-name{font-size:13px;font-weight:700;margin-bottom:4px;color:var(--text);font-family:SF Mono,monospace}.tp-desc{font-size:11px;color:var(--text-2);line-height:1.4}::-webkit-scrollbar{width:5px;height:5px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}#rtView::-webkit-scrollbar{width:8px}#rtView::-webkit-scrollbar-track{background:var(--bg-card);border-radius:4px}#rtView::-webkit-scrollbar-thumb{background:var(--accent);border-radius:4px;opacity:.7}#rtView::-webkit-scrollbar-thumb:hover{background:var(--accent);opacity:1}#rtView{scrollbar-width:thin;scrollbar-color:var(--accent) var(--bg-card)}@media(max-width:1100px){body{flex-direction:column}.sidebar{width:100%!important;min-width:0!important;flex-direction:row;flex-wrap:wrap;padding:8px 12px;gap:4px;border-right:none;border-bottom:1px solid var(--border)}.sidebar .nav-item{padding:6px 10px;font-size:12px}.sidebar .nav-section{display:flex;flex-wrap:wrap;padding:0;gap:4px}.sidebar .nav-label,.sidebar .sidebar-bottom{display:none}.main-wrap{min-width:0}}@media(max-width:768px){.sidebar .nav-label{display:none}.sidebar .nav-item{padding:8px;min-width:36px;justify-content:center}#servicesGrid,#agentsList,#projectsList,#runSkillsGrid{grid-template-columns:1fr!important}.chat-input-row{flex-wrap:wrap;gap:6px}.chat-input-row button{height:44px}#chatInput{min-height:44px}.page-header{flex-direction:column;align-items:flex-start;gap:8px}.page-header .actions{flex-wrap:wrap}.container,.dashboard-grid,.view,.card{width:100%;max-width:100%;padding:1rem}img,video{max-width:100%;height:auto}button,a,.nav-item,input,select,textarea{min-height:44px}}@media(max-width:480px){body{font-size:13px}.card{padding:12px}.card-title{font-size:14px}.page-title{font-size:18px}.tab-bar{flex-wrap:wrap;gap:4px}.stab{padding:4px 10px;font-size:11px}button{min-height:44px;font-size:16px;padding:8px 16px}input,select,textarea{font-size:16px;min-height:44px}input:focus,select:focus,textarea:focus{font-size:16px}}.prompt-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:16px;transition:all .2s}.prompt-card:hover{border-color:var(--border-hi);background:var(--bg-hover)}.prompt-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:12px;gap:12px}.prompt-preview{font-size:12px;color:var(--text-2);line-height:1.5;font-family:SF Mono,Monaco,monospace;white-space:pre-wrap;word-break:break-word}.prompt-edit-btn{flex-shrink:0}.agent-info-card{background:var(--bg-card);border:1px solid var(--border);border-radius:8px;padding:16px}.agent-info-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px}.agent-info-header h4{margin:0;font-size:16px;font-weight:600}.agent-status{padding:4px 10px;border-radius:12px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em}.agent-status.active{background:var(--green-hi);color:#000}.agent-status.idle{background:var(--bg-card2);color:var(--text-3)}.agent-info-details{display:flex;flex-direction:column;gap:8px}.detail-row{display:flex;justify-content:space-between;font-size:13px;align-items:center}.detail-row .label{color:var(--text-3);font-weight:600}.detail-row .value{color:var(--text-1);font-family:SF Mono,Monaco,monospace;font-size:12px}#agentChatMessages{display:flex;flex-direction:column;gap:12px}.user-message,.agent-message{padding:12px 16px;border-radius:12px;max-width:75%;word-wrap:break-word}.user-message{background:var(--accent);color:#fff;align-self:flex-end;border-bottom-right-radius:4px}.agent-message{background:var(--bg-card);border:1px solid var(--border);align-self:flex-start;border-bottom-left-radius:4px}.message-header{display:flex;justify-content:space-between;margin-bottom:6px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;opacity:.8}.message-time{color:var(--text-3);font-size:10px;font-weight:400;text-transform:none;letter-spacing:0}.message-content{font-size:14px;line-height:1.6}.message-content code{background:#0000004d;padding:2px 6px;border-radius:4px;font-family:SF Mono,Monaco,monospace;font-size:13px}.message-content pre{background:#0006;padding:12px;border-radius:6px;overflow-x:auto;margin:8px 0;border:1px solid var(--border)}.message-content pre code{background:none;padding:0}.message-content a{color:var(--accent);text-decoration:none}.message-content a:hover{text-decoration:underline}.process-card{background:var(--bg-card);padding:12px;border-radius:8px;margin-bottom:8px}.process-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px}.process-cli{font-weight:600;font-family:SF Mono,Monaco,monospace;font-size:13px}.process-status{text-transform:uppercase;font-size:11px;font-weight:700;color:var(--text-3);letter-spacing:.05em}.process-details{font-size:12px;color:var(--text-2);line-height:1.6;font-family:SF Mono,Monaco,monospace}.empty-state{text-align:center;padding:60px 20px;color:var(--text-3);font-size:14px}.process-status-empty{padding:12px;text-align:center;color:var(--text-3);font-size:12px;font-style:italic}#workflowsLayout{display:grid;grid-template-columns:minmax(260px,340px) minmax(420px,1fr);gap:16px;align-items:start}@media(max-width:980px){#workflowsLayout{grid-template-columns:1fr}}.setup-wizard-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:9999;display:flex;align-items:center;justify-content:center;background:#040810eb;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);opacity:0;transition:opacity .26s ease}.setup-wizard-overlay.visible{opacity:1}.setup-wizard-overlay.dismissing{opacity:0}.setup-wizard-card{width:100%;max-width:520px;margin:0 16px;background:var(--bg-card);border:1px solid var(--border);border-radius:16px;padding:40px 36px 32px;box-shadow:0 0 0 1px #ffffff0a,0 24px 64px #00000080;transform:translateY(12px) scale(.98);opacity:0;transition:transform .3s cubic-bezier(.16,1,.3,1),opacity .3s ease}.setup-wizard-card.visible{transform:translateY(0) scale(1);opacity:1}.setup-wizard-steps{display:flex;align-items:center;justify-content:center;gap:0;margin-bottom:32px}.setup-wizard-step{display:flex;flex-direction:column;align-items:center;gap:6px}.setup-wizard-step-dot{width:10px;height:10px;border-radius:50%;border:2px solid var(--text-3);background:transparent;padding:0;cursor:default;transition:background .2s ease,border-color .2s ease,box-shadow .2s ease}.setup-wizard-step-dot.active{border-color:var(--accent);background:var(--accent);box-shadow:0 0 8px #38bdf866}.setup-wizard-step-dot.completed{border-color:var(--green);background:var(--green)}.setup-wizard-step-label{font-size:11px;color:var(--text-3);font-weight:500;letter-spacing:.02em}.setup-wizard-step .active~.setup-wizard-step-label,.setup-wizard-step-dot.active+.setup-wizard-step-label{color:var(--accent)}.setup-wizard-step-dot.completed+.setup-wizard-step-label{color:var(--green)}.setup-wizard-step-line{width:48px;height:2px;background:var(--text-3);margin:0 12px 18px;border-radius:1px;transition:background .2s ease}.setup-wizard-step-line.completed{background:var(--green)}.setup-wizard-content{display:flex;flex-direction:column}.setup-wizard-hero{text-align:center;margin-bottom:28px}.setup-wizard-logo-ring{display:inline-flex;align-items:center;justify-content:center;width:64px;height:64px;border-radius:16px;background:var(--bg-card2);border:1px solid var(--border);margin-bottom:20px}.setup-wizard-logo{width:36px;height:36px}.setup-wizard-title{font-size:24px;font-weight:700;color:var(--text);line-height:1.2;margin-bottom:8px;letter-spacing:-.02em}.setup-wizard-subtitle{font-size:15px;color:var(--text-2);line-height:1.5}.setup-wizard-checklist{display:flex;flex-direction:column;gap:10px;padding:16px 20px;background:var(--bg-card2);border:1px solid var(--border);border-radius:10px;margin-bottom:28px}.setup-wizard-check-item{display:flex;align-items:center;gap:10px;font-size:14px;color:var(--text-2)}.setup-wizard-check-icon{width:20px;height:20px;display:flex;align-items:center;justify-content:center;border-radius:50%;font-size:12px;flex-shrink:0}.setup-wizard-check-icon.done{background:#34d39926;color:var(--green);border:1px solid rgba(52,211,153,.3)}.setup-wizard-check-icon.pending{background:var(--bg-card);color:var(--text-3);border:1px solid var(--border);font-size:8px}.setup-wizard-section-header{margin-bottom:20px}.setup-wizard-section-title{font-size:20px;font-weight:700;color:var(--text);line-height:1.2;margin-bottom:6px;letter-spacing:-.01em}.setup-wizard-section-desc{font-size:14px;color:var(--text-2);line-height:1.5}.setup-wizard-provider-list{display:flex;flex-direction:column;gap:8px;margin-bottom:20px;max-height:360px;overflow-y:auto}.setup-wizard-provider-row{display:flex;flex-direction:column;gap:6px;padding:12px 14px;background:var(--bg-card2);border:1px solid var(--border);border-radius:10px;transition:border-color .2s ease,background .2s ease}.setup-wizard-provider-row.has-key{border-color:#34d3994d;background:#34d3990a}.setup-wizard-provider-label{display:flex;align-items:center;gap:8px}.setup-wizard-provider-icon{font-size:16px;width:22px;text-align:center;flex-shrink:0}.setup-wizard-provider-name{font-size:14px;font-weight:600;color:var(--text)}.setup-wizard-provider-link{margin-left:auto;font-size:12px;color:var(--accent);text-decoration:none;opacity:.7;transition:opacity .15s ease}.setup-wizard-provider-link:hover{opacity:1;text-decoration:underline}.setup-wizard-provider-input-wrap{display:flex;align-items:center;gap:6px}.setup-wizard-provider-input{flex:1;background:var(--bg);border:1px solid var(--border);border-radius:7px;padding:8px 10px;color:var(--text);font-size:13px;font-family:inherit;outline:none;transition:border-color .2s ease}.setup-wizard-provider-input::placeholder{color:var(--text-3)}.setup-wizard-provider-input:focus{border-color:var(--accent)}.setup-wizard-toggle-vis{background:transparent;border:1px solid var(--border);border-radius:6px;padding:6px 8px;font-size:14px;cursor:pointer;color:var(--text-3);transition:color .15s ease}.setup-wizard-toggle-vis:hover{color:var(--text)}.setup-wizard-engine-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:12px;margin-bottom:16px}.setup-wizard-engine-card{background:var(--bg);border:1px solid var(--border);border-radius:10px;padding:16px;display:flex;flex-direction:column;gap:6px;transition:border-color .15s ease,background .15s ease}.setup-wizard-engine-card.available{border-color:#34d3994d;background:#34d39908}.setup-wizard-engine-card:not(.available){opacity:.7}.setup-wizard-engine-badge{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em}.setup-wizard-engine-badge.installed{color:var(--green, #34d399)}.setup-wizard-engine-badge.missing{color:var(--text-3, #666)}.setup-wizard-engine-title{font-size:15px;font-weight:600;color:var(--text)}.setup-wizard-engine-cmd{font-size:12px;color:var(--text-3);background:var(--bg-card);padding:2px 8px;border-radius:4px;display:inline-block;width:fit-content;font-family:var(--font-mono, monospace)}.setup-wizard-engine-desc{font-size:12px;color:var(--text-2);line-height:1.4;margin:4px 0 8px}.setup-wizard-engine-action{margin-top:auto;display:flex;align-items:center;gap:6px;font-size:12px}.setup-wizard-engine-auth-label{color:var(--text-3)}.setup-wizard-engine-auth-cmd{font-size:11px;color:var(--accent);background:#6366f11a;padding:3px 8px;border-radius:4px;font-family:var(--font-mono, monospace)}.setup-wizard-engine-key-note{font-size:12px}.setup-wizard-engine-key-note.key-ok{color:var(--green, #34d399)}.setup-wizard-engine-key-note.key-missing{color:var(--yellow, #fbbf24)}.setup-wizard-engine-install-btn{font-size:12px;color:var(--accent);text-decoration:none;font-weight:500;padding:4px 12px;border:1px solid var(--accent);border-radius:6px;transition:background .15s ease}.setup-wizard-engine-install-btn:hover{background:#6366f11a}.setup-wizard-engine-hint{font-size:13px;color:var(--text-2);text-align:center;margin:8px 0}.setup-wizard-provider-icon{font-size:16px;width:24px;text-align:center;flex-shrink:0}.setup-wizard-preset-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:24px}.setup-wizard-preset-card{display:flex;flex-direction:column;align-items:center;text-align:center;padding:20px 12px;background:var(--bg-card2);border:2px solid var(--border);border-radius:12px;cursor:pointer;transition:border-color .2s ease,background .2s ease,transform .15s ease}.setup-wizard-preset-card:hover{background:var(--bg-hover);transform:translateY(-1px)}.setup-wizard-preset-card.selected{border-color:var(--accent);background:#38bdf80f}.setup-wizard-preset-icon{font-size:28px;margin-bottom:10px;line-height:1}.setup-wizard-preset-label{font-size:15px;font-weight:700;color:var(--text);margin-bottom:6px;letter-spacing:-.01em}.setup-wizard-preset-desc{font-size:12px;color:var(--text-2);line-height:1.4}.setup-wizard-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:8px}.setup-wizard-btn-primary{background:var(--accent);color:#000;border:none;border-radius:8px;padding:10px 24px;font-size:14px;font-weight:600;font-family:inherit;cursor:pointer;transition:opacity .15s ease,transform .1s ease}.setup-wizard-btn-primary:hover{opacity:.9}.setup-wizard-btn-primary:active{transform:scale(.98)}.setup-wizard-btn-primary:disabled{opacity:.4;cursor:not-allowed}.setup-wizard-btn-ghost{background:transparent;color:var(--text-2);border:1px solid var(--border);border-radius:8px;padding:10px 20px;font-size:14px;font-weight:500;font-family:inherit;cursor:pointer;transition:background .15s ease,color .15s ease}.setup-wizard-btn-ghost:hover{background:var(--bg-hover);color:var(--text)}.setup-wizard-error{padding:10px 14px;background:#f871711a;border:1px solid rgba(248,113,113,.25);border-radius:8px;color:var(--red);font-size:13px;margin-bottom:12px}.setup-wizard-error.hidden{display:none}@media(max-width:640px){.setup-wizard-card{padding:28px 20px 24px;margin:0 12px;border-radius:12px}.setup-wizard-engine-grid,.setup-wizard-preset-grid{grid-template-columns:1fr;gap:8px}.setup-wizard-preset-card{flex-direction:row;text-align:left;gap:12px;padding:14px 16px}.setup-wizard-preset-icon{font-size:22px;margin-bottom:0}.setup-wizard-preset-label{margin-bottom:2px}.setup-wizard-step-line{width:28px;margin:0 6px}.setup-wizard-actions{flex-direction:column-reverse}.setup-wizard-btn-primary,.setup-wizard-btn-ghost{width:100%;text-align:center}}.test-launch-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:10px;margin-bottom:20px}.test-launch-card{background:var(--bg-2, #1a1a2e);border:1px solid var(--border);border-left:3px solid;border-radius:8px;padding:12px 14px}.test-launch-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}.test-launch-name{font-size:14px;font-weight:700}.test-launch-btn{font-size:11px;padding:3px 10px;border-radius:5px;border:1px solid var(--border);background:var(--bg-2);color:var(--text-1);cursor:pointer;font-weight:600}.test-launch-btn:hover{background:#ffffff14}.test-stop-btn{font-size:11px;padding:3px 10px;border-radius:5px;border:1px solid #ef4444;background:#ef444426;color:#ef4444;cursor:pointer;font-weight:600}.test-stop-btn:hover{background:#ef44444d}.test-launch-counts{display:flex;gap:12px;font-size:12px;color:var(--text-2)}.test-launch-files{font-weight:500}.test-launch-tests{color:var(--text-1);font-weight:600}.test-launch-total{background:#60a5fa0a}.test-suite-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:12px;margin-bottom:16px}.test-suite-card{background:var(--bg-2, #1a1a2e);border:1px solid var(--border);border-radius:10px;padding:16px}.test-suite-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}.test-suite-name{font-size:15px;font-weight:700}.test-suite-stats{display:flex;gap:16px;font-size:13px;margin-bottom:8px}.test-suite-stats div{color:var(--text-2)}.test-suite-stats span{font-weight:600}.test-suite-meta{font-size:11px;color:var(--text-2);margin-bottom:10px}.test-summary-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px}.test-summary-status{font-size:13px;font-weight:700;letter-spacing:.5px;padding:4px 12px;border-radius:6px}.test-status-pass{background:#34d3991f;color:#34d399}.test-status-fail{background:#f871711f;color:#f87171}.test-summary-meta{font-size:12px;color:var(--text-2)}.test-meta-sep{margin:0 6px;opacity:.4}.test-summary-stats{display:flex;gap:32px;margin-bottom:14px}.test-stat{text-align:center}.test-stat-value{font-size:24px;font-weight:700;line-height:1.2}.test-stat-label{font-size:11px;color:var(--text-2);text-transform:uppercase;letter-spacing:.3px}.test-color-pass{color:#34d399}.test-color-fail{color:#f87171}.test-color-skip{color:#fbbf24}.test-progress-bar{display:flex;height:6px;border-radius:3px;overflow:hidden;background:#ffffff0d}.test-progress-pass{background:#34d399}.test-progress-fail{background:#f87171}.test-progress-skip{background:#fbbf24}.test-actions{display:flex;gap:8px;margin-bottom:20px;flex-wrap:wrap}.test-section-title{font-size:13px;font-weight:600;color:var(--text-2);text-transform:uppercase;letter-spacing:.4px;margin:20px 0 10px}.test-groups-table{width:100%;border-collapse:collapse;font-size:13px;margin-bottom:16px}.test-groups-table th{text-align:left;font-size:11px;font-weight:600;color:var(--text-2);text-transform:uppercase;letter-spacing:.3px;padding:8px 10px;border-bottom:1px solid var(--border)}.test-groups-table th.num,.test-groups-table td.num{text-align:right;font-variant-numeric:tabular-nums}.test-groups-table td{padding:6px 10px;border-bottom:1px solid rgba(255,255,255,.03)}.test-groups-table tbody tr:hover{background:#ffffff05}.test-row-fail{background:#f871710a}.test-cat-badge{font-size:11px;padding:2px 8px;border-radius:4px;font-weight:500}.test-cat-unit{background:#6366f126;color:#818cf8}.test-cat-integration{background:#34d39926;color:#34d399}.test-cat-e2e{background:#fbbf2426;color:#fbbf24}.test-cat-other{background:#94a3b826;color:#94a3b8}.test-failure-card{background:#f871710a;border:1px solid rgba(248,113,113,.15);border-radius:8px;padding:14px;margin-bottom:10px}.test-failure-name{font-weight:600;font-size:13px;margin-bottom:4px}.test-failure-file{font-size:11px;color:var(--text-2);margin-bottom:6px}.test-failure-class{font-size:10px;padding:2px 6px;border-radius:3px;background:#f871711f;color:#f87171;font-weight:500}.test-failure-error{font-size:11px;background:#0000004d;border-radius:6px;padding:10px;margin-top:8px;overflow-x:auto;white-space:pre-wrap;word-break:break-word;color:var(--text-2);max-height:120px;overflow-y:auto}.test-failure-rerun{margin-top:8px}.test-failure-rerun code{font-size:10px;background:#ffffff0d;padding:4px 8px;border-radius:4px;display:inline-block;word-break:break-all}.test-progress-live{background:#60a5fa0f;border:1px solid rgba(96,165,250,.2);border-radius:10px;padding:14px 18px;margin-bottom:16px;animation:test-progress-pulse 2s ease-in-out infinite}.test-progress-done{animation:none;background:#34d3990f;border-color:#34d39933}@keyframes test-progress-pulse{0%,to{border-color:#60a5fa33}50%{border-color:#60a5fa80}}.test-progress-live-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.test-progress-live-status{font-weight:700;font-size:14px;color:var(--accent)}.test-progress-live-stats{display:flex;gap:16px;font-size:13px;font-weight:500;margin-bottom:4px}.test-progress-live-stats span{color:var(--text-2)}.test-progress-live-file{font-size:11px;color:var(--text-2);font-family:monospace;margin-top:4px}.test-skips-section{margin:12px 0}.test-skips-section[open] summary{margin-bottom:10px}.test-history-chart{display:flex;align-items:flex-end;gap:4px;padding:12px 0;min-height:90px}.test-history-bar{flex:1;display:flex;flex-direction:column;align-items:center;cursor:default;min-width:20px}.test-history-bar-inner{width:100%;max-width:28px;border-radius:3px;overflow:hidden;display:flex;flex-direction:column}.test-history-pass{background:#34d399}.test-history-fail{background:#f87171}.test-history-label{font-size:9px;color:var(--text-2);margin-top:4px;white-space:nowrap}.test-history-table{width:100%;border-collapse:collapse;font-size:12px;margin-top:12px}.test-history-table th{text-align:left;font-size:11px;font-weight:600;color:var(--text-2);text-transform:uppercase;letter-spacing:.3px;padding:6px 10px;border-bottom:1px solid var(--border)}.test-history-table th.num,.test-history-table td.num{text-align:right;font-variant-numeric:tabular-nums}.test-history-table td{padding:5px 10px;border-bottom:1px solid rgba(255,255,255,.03)}.test-history-table tbody tr:hover{background:#ffffff05}.test-file-list{margin-top:8px;border-top:1px solid var(--border);padding-top:6px;max-height:180px;overflow-y:auto}.test-file-row{display:flex;align-items:center;gap:6px;padding:3px 0;font-size:11px}.test-file-dot{font-size:8px;flex-shrink:0}.test-file-name{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text-2)}.test-file-counts{color:var(--text-3);font-size:10px;white-space:nowrap}.test-file-run-btn{background:#6366f126;color:#818cf8;border:1px solid rgba(99,102,241,.3);border-radius:4px;padding:1px 6px;font-size:9px;cursor:pointer;flex-shrink:0;transition:background .15s}.test-file-run-btn:hover{background:#6366f14d}.test-stale-badge{background:#fbbf2426;color:#fbbf24;border:1px solid rgba(251,191,36,.3);border-radius:3px;font-size:9px;padding:1px 5px;white-space:nowrap;flex-shrink:0}.test-stream-panel{margin:12px 0;background:#0a0f1a;border:1px solid var(--border);border-radius:8px;overflow:hidden}.test-stream-header{display:flex;align-items:center;justify-content:space-between;padding:6px 12px;background:#0d1420;border-bottom:1px solid var(--border);font-size:11px;font-weight:600;color:var(--text-2);text-transform:uppercase;letter-spacing:.5px}.test-stream-close{background:none;border:none;color:var(--text-3);cursor:pointer;font-size:13px;padding:0 4px}.test-stream-close:hover{color:var(--text-1)}.test-stream-pre{margin:0;padding:12px;font-size:11px;font-family:SF Mono,Fira Code,Fira Mono,monospace;color:#a8d8a8;max-height:300px;overflow-y:auto;white-space:pre-wrap;word-break:break-all;line-height:1.5}.test-failure-expandable{cursor:default}.test-failure-header{display:flex;align-items:flex-start;gap:8px;cursor:pointer;padding:8px 12px;margin:-8px -12px;border-radius:4px;transition:background .1s}.test-failure-header:hover{background:#ffffff0a}.test-failure-toggle{color:var(--text-3);font-size:10px;flex-shrink:0;margin-top:2px}.test-failure-file-inline{color:var(--text-3);font-size:10px;margin-left:auto;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:200px}.test-failure-detail{margin-top:10px;padding-top:10px;border-top:1px solid var(--border)}.test-failure-stack{background:#0a0f1a;border:1px solid var(--border);border-radius:4px;padding:8px 12px;font-size:10px;color:#fca5a5;overflow-x:auto;white-space:pre-wrap;word-break:break-all;max-height:200px;overflow-y:auto;margin-top:6px}.test-failure-actions{display:flex;flex-direction:column;gap:6px;margin-top:8px}.test-failure-link{color:var(--accent);font-size:11px;text-decoration:none}.test-failure-link:hover{text-decoration:underline}.test-copy-btn{background:#6366f126;color:#818cf8;border:1px solid rgba(99,102,241,.3);border-radius:4px;padding:2px 8px;font-size:10px;cursor:pointer;margin-left:8px;transition:background .15s}.test-copy-btn:hover{background:#6366f14d}.test-failure-screenshot{margin-top:8px}.test-screenshot-thumb{max-width:200px;max-height:140px;border:1px solid var(--border);border-radius:4px;cursor:zoom-in;display:block;transition:max-width .2s,max-height .2s;object-fit:contain}.test-screenshot-thumb.test-screenshot-expanded{max-width:100%;max-height:600px;cursor:zoom-out}.test-coverage-grid{display:flex;flex-wrap:wrap;gap:3px;margin:10px 0}.test-coverage-block{width:14px;height:14px;border-radius:2px;cursor:pointer;transition:transform .1s,opacity .1s}.test-coverage-block:hover{transform:scale(1.3);opacity:.9}.test-coverage-covered{background:#22c55e}.test-coverage-uncovered{background:#ef4444;opacity:.7}.test-coverage-legend{display:flex;gap:16px;font-size:11px;color:var(--text-2);margin-top:4px}.test-coverage-dot{display:inline-block;width:10px;height:10px;border-radius:2px;margin-right:4px;vertical-align:middle}.test-coverage-dot-green{background:#22c55e}.test-coverage-dot-red{background:#ef4444}.test-chart-wrap{background:#ffffff05;border:1px solid var(--border);border-radius:8px;padding:12px;overflow-x:auto}.test-chart-legend{font-size:11px;font-weight:400;color:var(--text-2);margin-left:12px;text-transform:none;letter-spacing:0}.test-chart-legend span{margin-right:10px}
@@ -0,0 +1,2 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/tab-benchmarks-tab-BHjKCPm3.js","assets/core-utils-CmOkXgzi.js"])))=>i.map(i=>d[i]);
2
+ var e,t,n;import{a,g as o,b as s,s as i,p as r,d as l,c,k as d,r as p,h as m,l as u,m as g,e as h}from"./core-utils-CmOkXgzi.js";import{c as v}from"./setup-wizard-CA0Or47w.js";import{i as f}from"./components-BS9fQjE_.js";import{s as y}from"./orchestration-Ca2DLWN-.js";import"./cli-process-CNZ_UBCt.js";import{i as w}from"./chat-core-uXb_C0GM.js";import{i as b,s as x,h as C}from"./tab-swarm-chat-tab-BNrd88-r.js";import{i as k}from"./tab-waves-tab-SaJDkb4x.js";import{i as E,s as I}from"./tab-workflows-tab-B-soSy1k.js";import{c as T,m as B,s as S,l as j,a as A}from"./tab-memory-tab-Cu6u13EQ.js";import{i as P,s as L,l as M,a as _,r as N}from"./tab-services-tab-DU_LH3uG.js";import{i as O,s as R,l as F,a as H,t as D,b as z,c as G,d as $,e as V,f as q,g as K,h as U,j as W,k as J,m as Q,n as Y,o as X,p as Z,r as ee,q as te,u as ne,v as ae,w as oe,x as se,y as ie,z as re,A as le}from"./tab-agents-tab-BgpIsjkw.js";import{i as ce,a as de}from"./tab-prompts-tab-DVkUNaJd.js";import{i as pe,s as me,c as ue,t as ge,r as he,l as ve,a as fe,b as ye}from"./tab-testing-tab-Ea5K-rsb.js";import{s as we,a as be,l as xe,c as Ce,b as ke,i as Ee,t as Ie,d as Te,f as Be,r as Se,e as je,g as Ae,u as Pe}from"./tab-skills-tab-DR7PJ7NB.js";import{s as Le,i as Me,a as _e,l as Ne}from"./tab-contacts-tab-DiOyMYth.js";import{i as Oe,t as Re,l as Fe,d as He}from"./tab-engines-tab-BsdZVvU0.js";import{s as De,a as ze,b as Ge,c as $e,t as Ve,d as qe,r as Ke,i as Ue}from"./tab-swarm-tab-B1AcjL1W.js";import{i as We,s as Je,t as Qe,a as Ye,b as Xe,c as Ze,d as et,e as tt,f as nt,g as at,h as ot,j as st,k as it,l as rt,m as lt}from"./tab-models-tab-dNRgsTOO.js";import{s as ct,a as dt,b as pt,t as mt,c as ut,d as gt,e as ht,f as vt,g as ft,h as yt,i as wt,j as bt,k as xt,l as Ct,m as kt,u as Et,n as It,o as Tt,p as Bt,q as St,r as jt,v as At,w as Pt,x as Lt,y as Mt,z as _t,A as Nt,B as Ot,C as Rt,D as Ft,E as Ht,F as Dt,G as zt,H as Gt,I as $t,J as Vt}from"./tab-settings-tab-CuvH_Fj_.js";import{i as qt,s as Kt,l as Ut,a as Wt,b as Jt,c as Qt,d as Yt,e as Xt,f as Zt,g as en,h as tn,r as nn,j as an}from"./tab-comms-tab-kguqTIzD.js";import{i as on,p as sn,r as rn,c as ln,a as cn,b as dn,e as pn,d as mn,l as un,o as gn,f as hn,h as vn,j as fn,k as yn,m as wn,n as bn,q as xn,t as Cn,v as kn,w as En}from"./tab-projects-tab-SFH4E--a.js";import{a as In,r as Tn,c as Bn,b as Sn,l as jn,d as An}from"./tab-usage-tab-BIOOnB-Y.js";import{s as Pn,r as Ln,l as Mn,a as _n,b as Nn,c as On}from"./tab-spending-tab-DcXD5TQY.js";import{i as Rn}from"./tab-pm-loop-tab-DiAPTJXu.js";!function(){const e=document.createElement("link").relList;if(!(e&&e.supports&&e.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))t(e);new MutationObserver(e=>{for(const n of e)if("childList"===n.type)for(const e of n.addedNodes)"LINK"===e.tagName&&"modulepreload"===e.rel&&t(e)}).observe(document,{childList:!0,subtree:!0})}function t(e){if(e.ep)return;e.ep=!0;const t=function(e){const t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),"use-credentials"===e.crossOrigin?t.credentials="include":"anonymous"===e.crossOrigin?t.credentials="omit":t.credentials="same-origin",t}(e);fetch(e.href,t)}}();const Fn={};let Hn=null;async function Dn(){return Hn||(Hn=await function(e,t){let n=Promise.resolve();if(t&&t.length>0){let e=function(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:"fulfilled",value:e}),e=>({status:"rejected",reason:e}))))};document.getElementsByTagName("link");const a=document.querySelector("meta[property=csp-nonce]"),o=(null==a?void 0:a.nonce)||(null==a?void 0:a.getAttribute("nonce"));n=e(t.map(e=>{if((e=function(e){return"/"+e}(e))in Fn)return;Fn[e]=!0;const t=e.endsWith(".css"),n=t?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${e}"]${n}`))return;const a=document.createElement("link");return a.rel=t?"stylesheet":"modulepreload",t||(a.as="script"),a.crossOrigin="",a.href=e,o&&a.setAttribute("nonce",o),document.head.appendChild(a),t?new Promise((t,n)=>{a.addEventListener("load",t),a.addEventListener("error",()=>n(new Error(`Unable to preload CSS for ${e}`)))}):void 0}))}function a(e){const t=new Event("vite:preloadError",{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return n.then(t=>{for(const e of t||[])"rejected"===e.status&&a(e.reason);return e().catch(a)})}(()=>import("./tab-benchmarks-tab-BHjKCPm3.js"),__vite__mapDeps([0,1]))),Hn}async function zn(){try{const e=document.getElementById("statusDot");document.getElementById("status").textContent="online",e.className="status-dot online",await Bn();const t=await o("/api/dlq"),n=document.getElementById("dlqBadge");t.length?(n.textContent=t.length,n.classList.remove("hidden")):n.classList.add("hidden")}catch(e){document.getElementById("status").textContent="error",document.getElementById("statusDot").className="status-dot error"}}async function Gn(){await zn()}function $n(e){document.querySelectorAll(".nav-item").forEach(e=>e.classList.remove("active"));const t=document.getElementById(e);t&&t.classList.add("active")}function Vn(){u(a.activeTab),document.querySelectorAll(".view, .view-sessions").forEach(e=>{e.classList.remove("active"),e.style.display&&(e.style.display="")});const e=document.querySelector(".msg-bar");e&&(e.style.display="")}async function qn(e){const t=document.getElementById(e),n=encodeURIComponent((null==t?void 0:t.value)||window._crewHome||""),a=await o("/api/pick-folder?default="+n).catch(()=>null);(null==a?void 0:a.path)&&t&&(t.value=a.path)}function Kn(){const e=(location.hash||"#chat").slice(1),t=(e.split("?")[0]||"chat").split("/");return{view:t[0]||"chat",subtab:t[1],raw:e}}function Un(){return Kn().view}function Wn(e){const t=e&&String(e).trim()&&"undefined"!==e?e:"general",n=`#chat?project=${encodeURIComponent(t)}`;location.hash!==n&&history.replaceState(null,"",n)}async function Jn(){try{const e=await o("/api/ui/active-project");return String((null==e?void 0:e.projectId)||"").trim()||"general"}catch{return"general"}}async function Qn(e){const t=e&&String(e).trim()&&"undefined"!==e?String(e).trim():"general";try{await r("/api/ui/active-project",{projectId:t})}catch{}}async function Yn(){Vn(),document.getElementById("chatView").classList.add("active"),$n("navChat"),a.activeTab="chat",s();const e=document.querySelector(".msg-bar");e&&(e.style.display="none"),y();const t=document.getElementById("chatMessages");"true"===(null==t?void 0:t.dataset.historyLoading)&&await pa();const n=t&&"true"===t.dataset.historyLoaded&&t.children.length>0;try{const e=(await o("/api/projects")).projects||[];a.projectsData={},e.forEach(e=>{a.projectsData[e.id]=e}),s(),sn(e)}catch(c){console.warn("Failed to refresh projects dropdown:",c)}const i=new URLSearchParams(window.location.hash.replace(/^#chat\?/,"")).get("project");if(i)a.chatActiveProjectId=i;else{const e=await Jn();try{a.chatActiveProjectId=e||localStorage.getItem("crewswarm_chat_active_project_id")||"general"}catch{a.chatActiveProjectId=e||"general"}}window.location.hash.includes("?project=")||Wn(a.chatActiveProjectId),console.log("🔵 [INIT] Active project from URL:",a.chatActiveProjectId);const r=document.getElementById("chatProjectTabs");r&&Array.from(r.children).forEach(e=>{e.dataset.projectId===a.chatActiveProjectId?e.classList.add("active"):e.classList.remove("active")});const l=document.getElementById("chatProjectSelect");l&&a.chatActiveProjectId&&l.querySelector('option[value="'+a.chatActiveProjectId+'"]')&&(l.value=a.chatActiveProjectId),Qn(a.chatActiveProjectId),Bn(),ta(),async function(){try{const e=((await o("/api/agents-config")).agents||[]).find(e=>"crew-lead"===e.id);if(!e)return;window._crewLeadInfo={emoji:e.emoji||"🧠",name:e.name||"crew-lead",theme:e.theme||""};const t=document.getElementById("chatAgentTitle"),n=document.getElementById("chatAgentSub");t&&(t.textContent=(e.emoji||"🧠")+" "+(e.name||"Crew Lead")),n&&e.theme&&(n.textContent=e.theme+" — chat naturally, dispatch tasks to the crew")}catch(c){}}(),window.loadChatAgentSelector&&window.loadChatAgentSelector(),n?m("chat"):await da()}function Xn(){Vn(),document.getElementById("filesView").classList.add("active"),$n("navFiles"),a.activeTab="files",s(),Ea()}function Zn(){return"owner"}P({hideAllViews:Vn,setNavActive:$n}),O({hideAllViews:Vn,setNavActive:$n,refreshAgents:F}),ce({hideAllViews:Vn,setNavActive:$n}),Ue({hideAllViews:Vn,setNavActive:$n}),k(),E({hideAllViews:Vn,setNavActive:$n}),pe({hideAllViews:Vn,setNavActive:$n});let ea=null;function ta(){if(ea)return;const e=`http://${window.location.hostname||"127.0.0.1"}:5010/events`;console.log("[crewswarm] Starting EventSource listener for",e),ea=new EventSource(e);const t="undefined"!=typeof localStorage&&"1"===localStorage.getItem("crewswarm_debug_sse");ea.onmessage=e=>{if(e.data)try{const o=JSON.parse(e.data),s=e=>e&&"general"!==e?e:"general",r="owner";t&&console.log("[crewswarm] SSE:",o.type,e.data.slice(0,120));const l=document.getElementById("chatMessages");if(C(o))return;if("chat_stream"===o.type&&o.sessionId===r){const e=s(o.projectId);if(s(a.chatActiveProjectId)!==e)return;let t=document.getElementById("streaming-bubble");if(!t){const e=document.createElement("div");e.id="streaming-wrapper",e.style.cssText="display:flex;flex-direction:column;align-items:flex-start;gap:4px;";const n=document.createElement("div");n.style.cssText="font-size:11px;color:var(--text-3);padding:0 6px;";const a=window._crewLeadInfo||{emoji:"🧠",name:"crew-lead"};n.textContent=a.emoji+" "+a.name+" (streaming...)",t=document.createElement("div"),t.id="streaming-bubble",t.className="chat-bubble assistant",t.style.cssText="max-width:80%;padding:10px 14px;border-radius:14px 14px 14px 4px;background:var(--surface-2);color:var(--text-2);font-size:14px;line-height:1.5;white-space:pre-wrap;word-break:break-word;border:1px solid var(--border);",t._textNode=document.createTextNode(""),t.appendChild(t._textNode),e.appendChild(n),e.appendChild(t),l&&l.appendChild(e)}const n=(t.dataset.streamChunk||"")+o.token;return t.dataset.streamChunk=n,void(t._rafId||(t._rafId=requestAnimationFrame(()=>{const e=t.dataset.streamChunk||"";e&&(t._textNode||(t._textNode=document.createTextNode(""),t.appendChild(t._textNode)),t._textNode.textContent+=e,t.dataset.streamChunk=""),l&&(l.scrollTop=l.scrollHeight),t._rafId=null})))}if("draft_discarded"===o.type&&o.draftId){const e=document.querySelector('[data-draft-id="'+o.draftId+'"]');return void(e&&e.remove())}if("context_warning"===o.type&&"owner"===o.sessionId){const e=document.getElementById("contextWarningBanner");e&&e.remove();const t=document.createElement("div");t.id="contextWarningBanner";const n="critical"===o.level;t.style.cssText=`display:flex;align-items:center;gap:10px;padding:8px 14px;border-radius:8px;margin:6px 0;font-size:12px;background:${n?"rgba(239,68,68,0.1)":"rgba(245,158,11,0.1)"};border:1px solid ${n?"rgba(239,68,68,0.3)":"rgba(245,158,11,0.3)"};color:${n?"#f87171":"#f59e0b"};`,t.innerHTML=`<span style="flex:1;">${o.message}</span><button onclick="clearChatHistory()" style="padding:2px 8px;font-size:11px;border-radius:4px;border:1px solid currentColor;background:transparent;color:inherit;cursor:pointer;">Clear now</button><button onclick="this.parentElement.remove()" style="background:none;border:none;cursor:pointer;color:inherit;font-size:14px;padding:0 2px;">✕</button>`;const a=document.getElementById("chatMessages");return void(a&&(a.appendChild(t),a.scrollTop=a.scrollHeight))}if("chat_message"===o.type&&"owner"===o.sessionId){const e=s(a.chatActiveProjectId),t=s(o.projectId);if(e!==t)return void console.log("[crewswarm] ❌ SKIP - projectId mismatch:",{current:e||"(General)",message:t||"(General)"});if(console.log("[crewswarm] ✅ Displaying message for current session"),"user"===o.role){if(o.content===ca)return console.log("[crewswarm] Skipping SSE echo of locally-sent message"),void(ca=null);o.content!==la?(console.log("[crewswarm] Appending user bubble:",o.content.slice(0,50)),g("user",o.content),la=o.content):console.log("[crewswarm] Skipping duplicate user message")}else if("assistant"===o.role){document.querySelectorAll('[id^="typing-"]').forEach(e=>e.remove());const e=String(o.content||"").trim();if(e&&function(e){if(!e)return"";for(let t=e.children.length-1;t>=0;t--){const n=e.children[t];if("streaming-wrapper"!==n.id&&!(n.children.length<2)&&String(n.style.alignItems||"").includes("flex-start"))return(n.children[1].textContent||"").trim()}return""}(l)===e)return ra=o.content,void(l&&(l.scrollTop=l.scrollHeight));const t=document.getElementById("streaming-wrapper"),n=document.getElementById("streaming-bubble");if(n){n._rafId&&cancelAnimationFrame(n._rafId),n._rafId=null;const e=n.dataset.streamChunk||"";e&&(n._textNode||(n._textNode=document.createTextNode(""),n.appendChild(n._textNode)),n._textNode.textContent+=e,n.dataset.streamChunk="")}if(t&&n){const e=window._crewLeadInfo||{emoji:"🧠",name:"crew-lead"},a=t.firstElementChild;a&&a!==n&&(a.textContent=e.emoji+" "+e.name);const s=o.content??"";n._textNode?n._textNode.textContent=s:n.textContent=s,t.removeAttribute("id"),n.removeAttribute("id"),delete n.dataset.streamChunk,ra=o.content}else{t&&t.remove();const e=o.content===ra&&function(e,t){if(!e||null==t)return!1;const n=String(t).trim();if(!n)return!1;for(let a=e.children.length-1;a>=0;a--){const t=e.children[a];if("streaming-wrapper"!==t.id&&(!(t.children.length<2)&&String(t.style.alignItems||"").includes("flex-start")&&(t.children[1].textContent||"").trim()===n))return!0}return!1}(l,o.content);e?console.log("[crewswarm] Skipping duplicate assistant message"):(console.log("[crewswarm] Appending assistant bubble (final)"),g("assistant",o.content,o.fallbackModel,o.fallbackReason,o.model,o.engineUsed),ra=o.content)}}return void(l&&(l.scrollTop=l.scrollHeight))}if("pending_project"===o.type&&"owner"===o.sessionId&&o.pendingProject&&l)return ia(l,o.pendingProject),void(l.scrollTop=l.scrollHeight);if("agent_working"===o.type&&o.agent){const e=document.getElementById("coding-dot-"+o.agent);e&&(e.style.display="inline-flex")}if("agent_idle"===o.type&&o.agent){const e=document.getElementById("coding-dot-"+o.agent);e&&(e.style.display="none")}if("opencode_event"===o.type){const e=document.getElementById("ocFeed"),t=document.getElementById("ocFeedDot");if(!e)return;t&&(t.style.display="inline-block");const a=document.createElement("div");a.style.cssText="display:flex;align-items:center;gap:8px;padding:5px 10px;border-radius:8px;background:var(--bg-2);font-size:12px;font-family:var(--font-mono,monospace);animation:fadeIn .25s ease;";const s=new Date(o.ts||Date.now()).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"});let i="⚙️",r="";if("session_start"===o.kind){i="▶",a.style.borderLeft="3px solid var(--green-hi)";var n=o.dir||"";r="session started"+(n?" — "+n.split("/").pop():"")}else if("session_end"===o.kind)i="■",a.style.borderLeft="3px solid var(--text-3)",r="session ended",t&&(t.style.display="none");else if("file_edit"===o.kind)i="✏️",a.style.borderLeft="3px solid var(--amber)",r=(o.file||o.path||"")+(o.extra?' <span style="opacity:.5;">'+o.extra+"</span>":"");else if("error"===o.kind)i="✗",a.style.borderLeft="3px solid var(--red-hi)",a.style.color="var(--red-hi)",r=o.message||"error";else if("tool"===o.kind){const e={read_file:"var(--accent)",write_file:"var(--amber)",bash:"var(--purple)",list_directory:"var(--green)",grep:"var(--green)"}[o.tool]||"var(--text-2)";i="done"===o.phase?"✓":"→",a.style.borderLeft="3px solid "+e,a.style.color="done"===o.phase?"var(--text-2)":"var(--text-1)",r='<span style="color:'+e+';font-weight:600;">'+(o.tool||"")+"</span>"+(o.label?' <span style="opacity:.6;">'+o.label+"</span>":"")}for(a.innerHTML='<span style="opacity:.4;flex-shrink:0;">'+s+'</span><span style="flex-shrink:0;">'+i+'</span><span style="flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">'+r+"</span>",e.appendChild(a);e.children.length>80;)e.removeChild(e.firstChild);return void(e.scrollTop=e.scrollHeight)}if("agent_working"===o.type&&o.agent){const e="agent-spinner-"+(o.taskId||o.agent);if(l&&!document.getElementById(e)){const t=document.createElement("div");t.id=e,t.className="msg a",t.style.cssText="opacity:.7; font-style:italic;",t.innerHTML='<div class="meta"><strong>'+o.agent+'</strong> · working…</div><div class="t" style="display:flex;align-items:center;gap:8px;"><span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--accent);animation:pulse 1s ease-in-out infinite;"></span>Processing task…</div>',l.appendChild(t),l.scrollTop=l.scrollHeight}return}if("agent_reply"===o.type||o.from&&o.content){if(!o.from||!o.content)return;if(o._passthroughSummary)return;const e="agent-spinner-"+(o.taskId||o.from),t=document.getElementById(e);t&&t.remove();const n=document.getElementById("agent-spinner-"+o.from);return n&&n.remove(),g("🤖 "+o.from,o.content,!1,null,null,o.engineUsed),l&&(l.scrollTop=l.scrollHeight),void i(o.from+" finished a task")}if("task.timeout"===o.type&&o.agent){const e="agent-spinner-"+(o.taskId||o.agent),t=document.getElementById(e);t&&t.remove();const n=document.getElementById("agent-spinner-"+o.agent);n&&n.remove();const a="[crew-lead] Task to "+o.agent+" timed out (no reply in 90s). Consider @@SERVICE restart "+o.agent+" or re-dispatch to another agent.";if(l){const e=document.createElement("div");e.className="msg a",e.style.cssText="opacity:.85; font-style:italic; color:var(--text-3);",e.innerHTML='<div class="meta"><strong>'+o.agent+'</strong> · no reply</div><div class="t">'+h(a)+"</div>",l.appendChild(e),l.scrollTop=l.scrollHeight}return void i("Task to "+o.agent+" timed out")}if("pipeline_progress"===o.type){let e;e=o.agents?"Wave "+(o.waveIndex+1)+"/"+o.totalWaves+" → "+o.agents.join(" + "):"Step "+(o.stepIndex+1)+"/"+o.total+" → "+o.agent;const t=document.createElement("div");return t.style.cssText="font-size:11px;color:var(--text-3);padding:2px 8px;margin:2px 0;",t.textContent="↳ "+e,void(l&&(l.appendChild(t),l.scrollTop=l.scrollHeight))}if("pipeline_quality_gate"===o.type){const e=document.createElement("div"),t=o.willRetry?" — retrying wave":" — advancing anyway";return e.style.cssText="font-size:11px;color:var(--warning, #e8a030);padding:2px 8px;margin:2px 0;",e.textContent="⚠️ Wave "+(o.waveIndex+1)+" quality gate: "+(o.issues||[]).join("; ")+t,void(l&&(l.appendChild(e),l.scrollTop=l.scrollHeight))}if("project_launched"===o.type&&o.project){const e=o.project.projectId||o.project.id;return void setTimeout(async()=>{await mn(),e&&En(e);const t=document.getElementById("chatMessages");if(t){const n=document.createElement("div");n.style.cssText="font-size:11px;color:var(--green);padding:2px 8px;margin:2px 0;",n.textContent='📁 Project "'+(o.project.name||e)+'" registered — selected in chat',t.appendChild(n),t.scrollTop=t.scrollHeight}},800)}if("pipeline_done"===o.type){const e=document.createElement("div");return e.style.cssText="font-size:11px;color:var(--green);padding:2px 8px;margin:2px 0;",e.textContent="✅ Pipeline complete",void(l&&(l.appendChild(e),l.scrollTop=l.scrollHeight))}if("confirm_run_cmd"===o.type&&o.approvalId)return void function(e,t,n){if(document.getElementById("cmd-approval-"+e))return;const a=document.createElement("div");a.id="cmd-approval-"+e,a.style.cssText=["position:fixed;bottom:80px;right:24px;z-index:9999;","background:var(--bg-card);border:1px solid var(--border);border-radius:12px;","padding:16px 20px;max-width:440px;box-shadow:0 8px 32px rgba(0,0,0,.4);","display:flex;flex-direction:column;gap:10px;"].join("");const o=document.createElement("div");o.style.cssText="font-size:13px;font-weight:600;color:var(--text-1);",o.textContent="🔐 "+t+" wants to run a command";const s=document.createElement("code");s.style.cssText="display:block;font-size:12px;color:var(--accent);background:var(--bg-1);padding:6px 10px;border-radius:6px;word-break:break-all;",s.textContent=n;const r=document.createElement("label");r.style.cssText="display:flex;align-items:center;gap:8px;font-size:12px;color:var(--text-2);cursor:pointer;";const l=document.createElement("input");l.type="checkbox",l.style.cssText="width:14px;height:14px;cursor:pointer;accent-color:var(--green);";const c=n.trim().split(/\s+/)[0]+" *";r.appendChild(l),r.appendChild(document.createTextNode("Always allow "));const d=document.createElement("code");d.style.cssText="font-size:11px;background:var(--bg-1);padding:2px 6px;border-radius:4px;color:var(--accent);",d.textContent=c,r.appendChild(d);const p=document.createElement("div");p.style.cssText="font-size:11px;color:var(--text-3);";let m=60;p.textContent="Auto-reject in "+m+"s";const u=setInterval(()=>{m--,p.textContent="Auto-reject in "+m+"s",m<=0&&(clearInterval(u),a.remove())},1e3),g=document.createElement("div");g.style.cssText="display:flex;gap:8px;";const h=document.createElement("button");h.textContent="✅ Allow",h.style.cssText="flex:1;padding:8px;border-radius:8px;border:none;background:var(--green);color:#fff;cursor:pointer;font-weight:600;font-size:13px;",h.onclick=async()=>{clearInterval(u),a.remove(),l.checked&&(await fetch("/api/cmd-allowlist",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({pattern:c})}),i("Allowlisted: "+c)),await fetch("/api/cmd-approve",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({approvalId:e})}).catch(e=>i("Approve failed: "+e.message,!0)),l.checked||i(t+": command approved")};const v=document.createElement("button");v.textContent="⛔ Deny",v.style.cssText="flex:1;padding:8px;border-radius:8px;border:none;background:var(--red-hi);color:#fff;cursor:pointer;font-weight:600;font-size:13px;",v.onclick=async()=>{clearInterval(u),a.remove(),await fetch("/api/cmd-reject",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({approvalId:e})}).catch(e=>i("Reject failed: "+e.message,!0)),i(t+": command denied")},g.appendChild(h),g.appendChild(v),a.appendChild(o),a.appendChild(s),a.appendChild(r),a.appendChild(p),a.appendChild(g),document.body.appendChild(a)}(o.approvalId,o.agent,o.cmd);if("telemetry"===o.type&&o.payload){window._telemetryEvents=window._telemetryEvents||[],window._telemetryEvents.push(o.payload),window._telemetryEvents.length>100&&window._telemetryEvents.shift();const e=document.getElementById("toolMatrixView");e&&e.classList.contains("active")&&An(window._telemetryEvents)}}catch{}else console.warn("[crewswarm] SSE message with null/empty data")},ea.onopen=()=>{console.log("[crewswarm] SSE connection opened"),window._sseReconnectDelay=2e3},ea.onerror=e=>{console.error("[crewswarm] SSE error:",e),ea.close(),ea=null,window._sseReconnectTimer&&clearTimeout(window._sseReconnectTimer),window._sseReconnectTimer=setTimeout(()=>{window._sseReconnectTimer=null,window._sseReconnectDelay=Math.min(2*(window._sseReconnectDelay||2e3),3e4),ta()},window._sseReconnectDelay||2e3)}}const na=[{label:"npm",pattern:"npm *",desc:"install, run, build, test…"},{label:"node",pattern:"node *",desc:"run any node script"},{label:"python",pattern:"python *",desc:"python / python3 scripts"},{label:"pip",pattern:"pip *",desc:"pip install packages"},{label:"git",pattern:"git *",desc:"all git operations"},{label:"cursor",pattern:"cursor *",desc:"open files in Cursor"},{label:"make",pattern:"make *",desc:"Makefile targets"},{label:"yarn",pattern:"yarn *",desc:"yarn install / build / run"},{label:"pnpm",pattern:"pnpm *",desc:"pnpm package manager"},{label:"ls / cat / echo",pattern:"ls *",desc:"read-only shell utilities"}];async function aa(){const e=document.getElementById("cmdAllowlistItems"),t=document.getElementById("cmdPresets");if(!e)return;const n=(await o("/api/cmd-allowlist").catch(()=>({list:[]}))).list||[];t&&(t.innerHTML="",na.forEach(function(e){const a=n.includes(e.pattern),o=document.createElement("label");o.style.cssText="display:flex;align-items:center;gap:8px;cursor:pointer;padding:4px 6px;border-radius:6px;transition:background 0.1s;",o.onmouseover=function(){o.style.background="var(--bg-hover)"},o.onmouseout=function(){o.style.background=""};const s=document.createElement("input");s.type="checkbox",s.checked=a,s.style.cssText="width:14px;height:14px;cursor:pointer;accent-color:var(--green);flex-shrink:0;",s.onchange=async function(){s.checked?await fetch("/api/cmd-allowlist",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({pattern:e.pattern})}).catch(e=>i("Failed to add pattern: "+e.message,!0)):await fetch("/api/cmd-allowlist",{method:"DELETE",headers:{"content-type":"application/json"},body:JSON.stringify({pattern:e.pattern})}).catch(e=>i("Failed to remove pattern: "+e.message,!0)),aa()};const r=document.createElement("code");r.style.cssText="font-size:12px;color:var(--accent);min-width:90px;",r.textContent=e.pattern;const l=document.createElement("span");l.style.cssText="font-size:11px;color:var(--text-3);",l.textContent=e.desc,o.appendChild(s),o.appendChild(r),o.appendChild(l),t.appendChild(o)}));const a=new Set(na.map(function(e){return e.pattern})),s=t?n.filter(function(e){return!a.has(e)}):n;if(e.innerHTML="",s.length)for(const o of s){const t=document.createElement("div");t.style.cssText="display:flex;align-items:center;gap:8px;padding:5px 0;border-bottom:1px solid var(--border);";const n=document.createElement("code");n.style.cssText="flex:1;font-size:12px;color:var(--accent);",n.textContent=o;const a=document.createElement("button");a.textContent="✕",a.style.cssText="border:none;background:transparent;color:var(--text-3);cursor:pointer;font-size:14px;padding:0 4px;",a.title="Remove",a.onclick=async function(){await fetch("/api/cmd-allowlist",{method:"DELETE",headers:{"content-type":"application/json"},body:JSON.stringify({pattern:o})}).catch(e=>i("Failed to delete pattern: "+e.message,!0)),aa()},t.appendChild(n),t.appendChild(a),e.appendChild(t)}else e.innerHTML='<div style="color:var(--text-3);font-size:12px;padding:4px 0;">'+(t?"No custom patterns yet.":"No patterns yet.")+"</div>"}async function oa(){const e=document.getElementById("cmdAllowlistInput"),t=e?e.value.trim():"";t&&(await fetch("/api/cmd-allowlist",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({pattern:t})}).catch(e=>i("Failed to add pattern: "+e.message,!0)),e.value="",aa())}window._telemetryEvents=window._telemetryEvents||[];const sa=()=>jn(On);function ia(e,{draftId:t,name:n,outputDir:a,roadmapMd:o}){function s(e){return(e.match(/^- \[ \]/gm)||[]).length}const i=document.createElement("div");i.setAttribute("data-draft-id",t),i.style.cssText="width:100%;display:flex;flex-direction:column;gap:4px;";const l=document.createElement("div");l.style.cssText="font-size:11px;color:var(--text-3);padding:0 6px;",l.textContent="🗺️ Roadmap draft — review before building";const c=document.createElement("div");c.style.cssText="width:100%;border:1px solid var(--border);border-radius:12px;overflow:hidden;background:var(--bg-card);";const d=document.createElement("div");d.style.cssText="background:var(--bg-card2);padding:10px 14px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid var(--border);",d.innerHTML='<div><div style="font-size:13px;font-weight:600;color:var(--accent);">🚀 '+n+'</div><div style="font-size:11px;color:var(--blue);margin-top:2px;">'+a+'</div></div><span style="font-size:10px;color:var(--text-3);padding:2px 7px;background:var(--bg-card2);border-radius:10px;" class="task-count">'+s(o)+" tasks</span>";const p=document.createElement("textarea");p.value=o,p.spellcheck=!1,p.style.cssText="width:100%;background:var(--bg-card);border:none;outline:none;color:var(--text-1);font-size:11.5px;font-family:SF Mono,Monaco,Menlo,monospace;line-height:1.6;padding:12px 14px;resize:none;min-height:160px;max-height:320px;display:block;",setTimeout(()=>{p.style.height="",p.style.height=Math.min(p.scrollHeight,320)+"px"},50),p.addEventListener("input",()=>{p.style.height="",p.style.height=Math.min(p.scrollHeight,320)+"px",d.querySelector(".task-count").textContent=s(p.value)+" tasks"});const m=document.createElement("div");m.style.cssText="display:flex;gap:8px;align-items:center;padding:10px 14px 12px;border-top:1px solid var(--border);background:var(--bg-card2);";const u=document.createElement("button");u.textContent="▶ Start Building",u.style.cssText="background:var(--green-hi);color:#000;border:none;border-radius:8px;padding:8px 16px;font-size:12px;font-weight:700;cursor:pointer;",u.onclick=async()=>{u.disabled=!0,u.textContent="⏳ Launching…";try{const e=await r("/api/crew-lead/confirm-project",{draftId:t,roadmapMd:p.value});e.ok?(c.innerHTML='<div style="padding:14px;color:var(--green-hi);font-size:13px;font-weight:600;">✅ '+n+' — project created, PM loop running!<br><span style="color:var(--blue);font-size:11px;font-weight:400">'+(e.outputDir||a)+"</span></div>",g("assistant","🚀 "+n+" is building. Check the Projects tab to watch progress.")):(u.disabled=!1,u.textContent="▶ Start Building",v.textContent="⚠️ "+(e.error||"Launch failed"))}catch(e){u.disabled=!1,u.textContent="▶ Start Building",v.textContent="⚠️ "+e.message}};const h=document.createElement("button");h.textContent="Discard",h.style.cssText="background:none;border:1px solid var(--border);color:var(--text-3);border-radius:8px;padding:8px 14px;font-size:12px;cursor:pointer;",h.onclick=async()=>{await r("/api/crew-lead/discard-project",{draftId:t}).catch(()=>{}),i.remove()};const v=document.createElement("span");v.style.cssText="font-size:11px;color:var(--blue);margin-left:auto;",v.textContent="Edit above, then confirm",m.appendChild(u),m.appendChild(h),m.appendChild(v),c.appendChild(d),c.appendChild(p),c.appendChild(m),i.appendChild(l),i.appendChild(c),e.appendChild(i),e.scrollTop=e.scrollHeight}let ra="",la="",ca=null;const{loadChatHistory:da,waitForChatHistoryIdle:pa,chatAtAtInput:ma,chatKeydown:ua,sendChat:ga,clearChatHistory:ha,stopAll:va,killAll:fa,killPassthrough:ya,refreshSessionIndicator:wa,clearPassthroughSession:ba,resetSendButton:xa,handleImageUpload:Ca,toggleVoiceRecording:ka}=w({postJSON:r,getJSON:o,appendChatBubble:g,showNotification:i,state:a,getChatSessionId:()=>"owner",getChatActiveProjectId:()=>a.chatActiveProjectId,getCrewLeadInfo:()=>window._crewLeadInfo,appendRoadmapCard:ia,getLastAppendedAssistantContent:()=>ra,setLastAppendedAssistantContent:e=>{ra=e},setLastAppendedUserContent:e=>{la=e},setLastSentContent:e=>{ca=e}});async function Ea(e){const t=document.getElementById("filesContent"),n=document.getElementById("filesDir").value.trim()||window._crewCwd||(window._crewHome?window._crewHome+"/CrewSwarm":"");d(t,"Scanning "+n+"...");try{const e=await o("/api/files?dir="+encodeURIComponent(n));if(!e.files||!e.files.length)return void c(t,"No files found in "+n);const a={};e.files.forEach(e=>{const t=e.path.split(".").pop().toLowerCase()||"other";a[t]||(a[t]=[]),a[t].push(e)});const s=["html","css","js","mjs","ts","json","md","sh","txt","other"],i={html:"🌐",css:"🎨",js:"⚡",mjs:"⚡",ts:"🔷",json:"📋",md:"📝",sh:"🖥️",txt:"📄",other:"📁"};let r='<div style="display:grid;gap:1rem;padding:4px 0;">';for(const t of s)a[t]&&(r+="<div>",r+='<div style="font-size:11px;font-weight:600;color:var(--text-2);text-transform:uppercase;letter-spacing:0.08em;margin-bottom:8px;padding-left:2px;">'+(i[t]||"📁")+" ."+t+" — "+a[t].length+" file"+(a[t].length>1?"s":"")+"</div>",r+='<div style="display:grid;gap:6px;">',a[t].sort((e,t)=>t.mtime-e.mtime).forEach(e=>{const t=e.path.replace(n+"/",""),a=Ba(e.mtime),o=Sa(e.size);r+='<div class="file-row">',r+='<div class="file-info"><span class="file-name">'+t+'</span><span class="file-meta">'+o+" · "+a+"</span></div>",r+='<div class="file-actions">',r+='<a href="cursor://file/'+e.path+'" class="file-btn file-btn-cursor" title="Open in Cursor">Cursor</a>',r+='<a href="opencode://open?path='+encodeURIComponent(e.path)+'" class="file-btn file-btn-opencode" title="Open in OpenCode">OpenCode</a>',r+='<button data-action="previewFile" data-arg=\''+e.path.replace(/'/g,"&#39;")+'\' data-self="1" class="file-btn" title="Preview">👁</button>',r+="</div></div>"}),r+="</div></div>");r+="</div>",r+='<div id="file-preview-pane" style="display:none;margin-top:1rem;background:#0d1117;border:1px solid var(--border);border-radius:8px;overflow:hidden;"><div id="file-preview-bar" style="display:flex;align-items:center;gap:8px;padding:8px 12px;background:#0d1420;border-bottom:1px solid var(--border);font-size:12px;color:var(--text-2);"><span id="file-preview-name"></span><button data-action="closePreviewPane" style="margin-left:auto;background:none;border:none;color:var(--text-2);cursor:pointer;">✕</button></div><pre id="file-preview-content" style="margin:0;padding:1rem;font-size:0.75rem;overflow:auto;max-height:400px;"></pre></div>',t.innerHTML=r}catch(a){l(t,"Error: "+a.message)}}async function Ia(e,t){const n=document.getElementById("file-preview-pane"),a=document.getElementById("file-preview-content"),s=document.getElementById("file-preview-name");if(n){s.textContent=e.split("/").pop(),a.textContent="Loading...",n.style.display="block",n.scrollIntoView({behavior:"smooth",block:"nearest"});try{const t=await o("/api/file-content?path="+encodeURIComponent(e));a.textContent=t.content||"(empty)"}catch(i){a.textContent="Error: "+i.message}}}function Ta(){const e=document.getElementById("file-preview-pane");e&&(e.style.display="none")}function Ba(e){const t=Date.now()-e,n=Math.floor(t/6e4);if(n<1)return"just now";if(n<60)return n+"m ago";const a=Math.floor(n/60);return a<24?a+"h ago":Math.floor(a/24)+"d ago"}function Sa(e){return e<1024?e+"B":e<1048576?(e/1024).toFixed(1)+"KB":(e/1024/1024).toFixed(1)+"MB"}function ja(){Vn(),document.getElementById("settingsView").classList.add("active"),$n("navSettings"),a.activeTab="settings",s();const e=(location.hash||"").replace("#settings/",""),t={system:"engines",telegram:"comms",whatsapp:"comms"}[e]||e;Aa(["usage","engines","comms","security","webhooks"].includes(t)?t:"usage")}function Aa(e){var t;["usage","engines","comms","security","webhooks"].forEach(t=>{const n=document.getElementById("stab-panel-"+t),a=document.getElementById("stab-"+t);n&&a&&(n.style.display=t===e?"usage"===t?"grid":"block":"none",a.classList.toggle("active",t===e))}),"usage"===e&&(Sn(),Nn()),"engines"===e&&(St(),jt(),At(),Pt(),Lt(),Mt(),_t(),Nt(),Ot(),Rt(),Ft(),Ht(),Dt(),zt(),Gt()),"comms"===e&&an(),"security"===e&&(aa(),$t()),(null==(t=document.getElementById("settingsView"))?void 0:t.classList.contains("active"))&&history.replaceState(null,"","#settings/"+e)}function Pa(){Vn(),document.getElementById("enginesView").classList.add("active"),$n("navEngines"),Fe()}null==(e=document.getElementById("attachImageBtn"))||e.addEventListener("click",()=>{document.getElementById("imageUpload").click()}),null==(t=document.getElementById("imageUpload"))||t.addEventListener("change",Ca),null==(n=document.getElementById("recordVoiceBtn"))||n.addEventListener("click",ka),window.loadChatHistory=da,window.getChatSessionId=Zn,window.selectProjectTab=e=>{const t=e&&String(e).trim()&&"undefined"!==e?e:"general",n=a.chatActiveProjectId;console.log("🔵 [TAB CLICK] START",t,"- from:",n);const o=document.getElementById("chatProjectTabs");if(!o)return void console.error("🔵 [TAB CLICK] ERROR: chatProjectTabs container not found!");if(n===t)return void console.log("🔵 [TAB CLICK] Already on this tab, skipping reload");Wn(t),Array.from(o.children).forEach(e=>{e.classList.remove("active")});const s=Array.from(o.children).find(e=>e.dataset.projectId===t);s&&s.classList.add("active"),a.chatActiveProjectId=t;try{localStorage.setItem("crewswarm_chat_active_project_id",t)}catch{}Qn(t),console.log("🔵 [TAB CLICK] Updated state:",{projectId:a.chatActiveProjectId,sessionId:"owner",url:window.location.hash}),console.log("🔵 [TAB CLICK] Calling loadChatHistory()..."),da().then(()=>{console.log("🔵 [TAB CLICK] loadChatHistory() completed");const e=document.getElementById("chatMessages");console.log("🔵 [TAB CLICK] Messages in DOM:",(null==e?void 0:e.children.length)||0)}).catch(e=>{console.error("🔵 [TAB CLICK] loadChatHistory() ERROR:",e)})},window.addEventListener("focus",()=>{(async function(){if("chat"!==Kn().view)return;const e=await Jn(),t=e&&"undefined"!==e?e:"general";t!==(a.chatActiveProjectId&&"undefined"!==a.chatActiveProjectId?a.chatActiveProjectId:"general")&&window.selectProjectTab&&window.selectProjectTab(t)})().catch(()=>{})}),qt({showSettings:ja,showSettingsTab:Aa}),Vt({getModels:F,populateModelDropdown:le}),lt({hideAllViews:Vn,setNavActive:$n,loadAgents:F}),We(),b({hideAllViews:Vn,setNavActive:$n});const La=async()=>{Vn(),$n("navBenchmarks");const e=document.getElementById("benchmarksView");e&&e.classList.add("active");const{showBenchmarks:t}=await Dn();t({hideAllViews:Vn,setNavActive:$n})};function Ma(){Vn(),document.getElementById("memoryView").classList.add("active"),$n("navMemory"),A()}function _a(){Vn(),document.getElementById("cliProcessView").classList.add("active"),$n("navCLI"),window.initCLIProcess&&window.initCLIProcess()}function Na(){Vn(),document.getElementById("toolMatrixView").classList.add("active"),$n("navToolMatrix"),In()}async function Oa(){const e=document.getElementById("webhookChannel").value.trim()||"test";let t={};try{const e=document.getElementById("webhookPayload").value.trim();e&&(t=JSON.parse(e))}catch{t={raw:document.getElementById("webhookPayload").value}}const n=document.getElementById("webhookTestResult");try{const a=await fetch("/proxy-webhook/"+e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),o=await a.json();n.textContent=o.ok?"✅ Sent to RT bus":"❌ "+(o.error||"failed"),n.style.color=o.ok?"var(--green)":"var(--red)"}catch(a){n.textContent="❌ "+a.message,n.style.color="var(--red)"}}async function Ra(){document.getElementById("pendingApprovals").innerHTML='<div style="color:var(--text-3);font-size:12px;">Pending skill approvals appear here when an agent triggers a skill marked requiresApproval. You will also receive a Telegram notification with inline Approve/Reject buttons if Telegram is configured.</div>'}function Fa(){fn({hideAllViews:Vn,setNavActive:$n})}function Ha(){vn({hideAllViews:Vn,setNavActive:$n})}on({showChat:Yn,showBuild:Fa}),zn(),setInterval(zn,3e4),(async()=>{try{const e=(await o("/api/projects")).projects||[];a.projectsData={},e.forEach(e=>{a.projectsData[e.id]=e}),sn(e),s(),"#projects"===location.hash&&Ha()}catch{}})(),document.getElementById("refreshBtn").onclick=Gn,document.getElementById("runBuildBtn").onclick=rn,document.getElementById("continuousBuildBtn").onclick=ln,document.getElementById("stopBuildBtn").onclick=cn,document.getElementById("stopContinuousBtn").onclick=dn,document.getElementById("enhancePromptBtn").onclick=pn,Rn(),document.getElementById("newProjectBtn").onclick=()=>{const e=document.getElementById("newProjectForm");e.style.display="none"===e.style.display?"block":"none"},document.getElementById("npCancelBtn").onclick=()=>{document.getElementById("newProjectForm").style.display="none"},document.getElementById("npCreateBtn").onclick=async()=>{const e=document.getElementById("npName").value.trim(),t=document.getElementById("npDesc").value.trim(),n=document.getElementById("npOutputDir").value.trim(),a=document.getElementById("npFeaturesDoc").value.trim();if(e&&n)try{const o=await r("/api/projects",{name:e,description:t,outputDir:n,featuresDoc:a});i(`Project "${o.project.name}" created!`),document.getElementById("newProjectForm").style.display="none",document.getElementById("npName").value="",document.getElementById("npDesc").value="",document.getElementById("npOutputDir").value="",document.getElementById("npFeaturesDoc").value="",mn()}catch(o){i("Failed: "+o.message,!0)}else i("Name and output directory required",!0)};const Da={chat:Yn,"swarm-chat":x,swarm:Ge,rt:ze,dlq:De,files:Xn,services:L,agents:R,models:Je,settings:ja,engines:Pa,skills:be,"run-skills":we,benchmarks:La,"tool-matrix":Na,build:Fa,messaging:Kt,projects:Ha,contacts:Le,memory:Ma,workflows:I,"cli-process":_a,prompts:de,testing:me};for(const[qa,Ka]of Object.entries(Da)){const e=Ka,t=function(...t){const n=location.hash||"";return"chat"===qa?n.startsWith("#chat")||history.replaceState(null,"","#chat"):history.replaceState(null,"","#"+qa),e(...t)};Da[qa]=t,window[e.name]=t}function za(e){const t=String(e||"chat").split("?")[0].split("/")[0];(Da[t]||Da.chat)()}(async()=>{if(await v())return;const{view:e,subtab:t}=Kn();"1"===new URLSearchParams(window.location.search).get("focus")?setTimeout(()=>{const e=document.getElementById("chatInput");e&&(za("chat"),e.focus())},500):(za(e||"chat"),"settings"===e&&t&&Aa(t))})(),window.addEventListener("hashchange",()=>{const{view:e,subtab:t}=Kn(),n=Va[e];n?(n(),"settings"===e&&t&&Aa(t)):Yn()}),fetch("/api/env").then(e=>e.json()).then(e=>{window._crewHome=e.HOME||"",window._crewCwd=e.cwd||"";const t=document.getElementById("filesDir");t&&!t.value&&(t.value=e.cwd||"")}).catch(()=>{}),F().catch(e=>console.error("Initial agents-config load failed:",e)),Gn(),function(){function e(e){if(e.closest("form"))return;const t=document.createElement("form");t.autocomplete="off",t.onsubmit=()=>!1,t.style.cssText="margin:0;padding:0;display:contents;";const n=document.createElement("input");n.type="text",n.autocomplete="username",n.setAttribute("aria-hidden","true"),n.style.cssText="display:none;position:absolute;width:0;height:0;opacity:0;",t.appendChild(n),e.parentNode.insertBefore(t,e),t.appendChild(e)}function t(t){(t||document).querySelectorAll('input[type="password"]').forEach(e)}t();new MutationObserver(n=>{for(const a of n)for(const n of a.addedNodes)1===n.nodeType&&(n.matches&&n.matches('input[type="password"]')?e(n):t(n))}).observe(document.body,{childList:!0,subtree:!0})}();const Ga={showChat:Yn,showSwarm:Ge,showRT:ze,showBuild:Fa,showFiles:Xn,showDLQ:De,showProjects:Ha,showAgents:R,showModels:Je,showEngines:Pa,showSkills:be,showRunSkills:we,showBenchmarks:La,showToolMatrix:Na,showServices:L,showTesting:me,refreshTesting:()=>me(),runTests:e=>ye(e),stopTests:()=>fe(),loadRunDetail:e=>ve(e),runSingleFile:(e,t)=>he(e,t),toggleFailure:e=>ge(e),copyText:e=>ue(e),showSettings:ja,pickFolder:e=>qn(e),loadFiles:e=>Ea(),clearChatHistory:ha,clearAgentChat:()=>{const e=document.getElementById("agentChatSelector"),t=document.getElementById("agentChatMessages"),n=document.getElementById("agentChatInput");t&&(t.innerHTML='<div class="empty-state">No messages yet. Start chatting!</div>'),n&&(n.value=""),(null==e?void 0:e.value)&&i("Chat history cleared","success")},sendChat:ga,stopAll:va,killAll:fa,stopPassthrough:ya,clearPassthroughSession:ba,loadServices:M,saveRTToken:Tt,lockConfig:It,unlockConfig:Et,startCrew:H,toggleEmojiPicker:e=>ae(e),bulkSetRoute:(e,t)=>oe(e,t),loadSpending:_n,loadCrewCliStats:Mn,resetSpending:Ln,saveGlobalCaps:Pn,loadOcStats:sa,addAllowlistPattern:oa,sendTestWebhook:Oa,startTgBridge:tn,stopTgBridge:en,saveTgConfig:Zt,loadTelegramSessions:Xt,loadTgMessages:Yt,startWaBridge:Qt,stopWaBridge:Jt,saveWaConfig:Wt,loadWaMessages:Ut,saveOpencodeSettings:kt,saveOpencodeModel:Ct,saveGlobalFallback:xt,toggleBgConsciousness:bt,toggleCursorWaves:wt,toggleTmuxBridge:yt,toggleAutonomousMentions:ft,toggleClaudeCode:vt,toggleCodexExecutor:ht,toggleGeminiCliExecutor:gt,toggleCrewCliExecutor:ut,toggleOpencodeExecutor:mt,saveGlobalOcLoop:pt,saveGlobalOcLoopRounds:dt,savePassthroughNotify:ct,toggleAddSkill:Te,toggleImportSkill:Ie,importSkillFromUrl:Ee,showSkills:be,saveSkill:ke,cancelSkillForm:Ce,loadRunSkills:xe,loadBenchmarks:async()=>(await Dn()).loadBenchmarks(),loadBenchmarkLeaderboard:async()=>(await Dn()).loadBenchmarkLeaderboard(),loadBenchmarkTasks:async()=>(await Dn()).loadBenchmarkTasks(),onBenchmarkTaskSelect:async e=>(await Dn()).onBenchmarkTaskSelect(e),runBenchmarkTask:async()=>(await Dn()).runBenchmarkTask(),stopBenchmarkRun:async()=>(await Dn()).stopBenchmarkRun(),loadMemoryStats:j,searchMemory:S,migrateMemory:B,compactMemory:T,loadEngines:Fe,toggleImportEngine:Re,importEngineFromUrl:Oe,deleteEngine:e=>He(e),loadToolMatrix:In,loadBuildProjectPicker:un,scrollRTToBottom:()=>{const e=document.getElementById("rtView");e&&(e.scrollTop=e.scrollHeight)},toggleRTPause:Ve,clearRTMessages:$e,togglePmAdvanced:()=>{const e=document.getElementById("pmAdvanced");e&&(e.style.display="none"===e.style.display?"block":"none")},toggleRTTokenVis:()=>{const e=document.getElementById("rtTokenInput");e&&(e.type="password"===e.type?"text":"password")},restartService:e=>N(e),stopService:e=>_(e),closePreviewPane:Ta,previewFile:(e,t)=>Ia(e),replayDLQ:e=>Ke(e),deleteDLQ:e=>qe(e),runSkillFromUI:e=>Se(e),editSkill:e=>je(e),deleteSkill:e=>Ae(e),restartAgentFromUI:e=>Tn(e),saveSearchTool:e=>et(e),testSearchTool:e=>Ye(e),saveBuiltinKey:e=>nt(e),testBuiltinProvider:e=>Ze(e),fetchBuiltinModels:(e,t)=>ot(e,t),saveOauthModel:e=>rt(e),testOauthProvider:e=>it(e),showOauthModels:e=>st(e),saveKey:e=>tt(e),testKey:e=>Xe(e),fetchModels:(e,t)=>at(e,t),toggleKeyVis:(e,t)=>Qe(e,t),toggleAgentBody:e=>D(e),deleteAgent:e=>te(e),saveAgentModel:e=>Q(e),saveAgentFallback:e=>Z(e),saveAgentVoice:e=>X(e),toggleEmojiPicker:e=>ae(e),saveAgentIdentity:e=>Y(e),saveAgentPrompt:e=>J(e),resetAgentSession:e=>ee(e),saveAgentTools:e=>W(e),applyToolPreset:e=>ne(e),setRoute:(e,t)=>z(e,t),saveOpenCodeConfig:e=>V(e),saveOpenCodeFallback:e=>$(e),saveCursorCliConfig:e=>U(e),saveClaudeCodeConfig:e=>K(e),saveCodexConfig:e=>G(e),saveGeminiCliConfig:e=>q(e),saveCrewCLIConfig:e=>re(e),"pm-toggle":e=>{var t;const n=null==(t=a.projects)?void 0:t.find(t=>t.id===e);n&&n.running?Cn(e):kn(e)},"edit-roadmap":e=>{var t;const n=null==(t=a.projects)?void 0:t.find(t=>t.id===e);n&&xn(e,n.roadmapFile)},"retry-failed":e=>{var t;const n=null==(t=a.projects)?void 0:t.find(t=>t.id===e);n&&bn(n.roadmapFile)},"save-roadmap":e=>wn(e),"reset-failed":e=>yn(e),showSettingsTab:e=>Aa(e)};let $a=!1;document.addEventListener("touchstart",e=>{if(!(e.target instanceof Element))return;e.target.closest("[data-action]")&&($a=!0,setTimeout(()=>{$a=!1},500))},{passive:!0}),document.addEventListener("click",e=>{if(!(e.target instanceof Element))return;const t=e.target.closest("[data-action]");if(!t)return;if($a)return void e.preventDefault();e.stopPropagation();const n=t.dataset.action,a=Ga[n];if(!a)return void console.warn("[crewswarm] unknown data-action:",n);const o=t.dataset.arg??null,s=t.dataset.arg2??null,i="1"===t.dataset.self;null!==o&&null!==s?a(o,s):null!==o&&i?a(o,t):null!==o?a(o):i?a(t):a()}),document.addEventListener("change",e=>{const t=e.target.closest("[data-onchange]");if(!t)return;const n=Ga[t.dataset.onchange];if(!n)return;const a="this.value"===t.dataset.onchangeArg?t.value:null;null!==a?n(a):n()}),document.addEventListener("DOMContentLoaded",()=>{f("activeTasksPanel"),Me();const e=document.getElementById("dashSelfLink");e&&(e.href=window.location.origin,e.textContent=window.location.host),document.querySelectorAll(".nav-item").forEach(e=>{e.addEventListener("click",t=>{t.preventDefault(),t.stopPropagation();const n=e.dataset.view;if(!n)return;if(Un()!==n)return void(window.location.hash=n);const a=Va[n];a&&a()})});const t=document.getElementById("chatInput");t&&!t.dataset.boundChatComposer&&(t.dataset.boundChatComposer="1",t.addEventListener("keydown",ua),t.addEventListener("input",ma));const n=document.getElementById("chatSendBtn")||document.querySelector('[data-action="sendChat"]');n&&!n.dataset.boundChatComposer&&(n.dataset.boundChatComposer="1",n.addEventListener("click",e=>{e.preventDefault(),e.stopPropagation(),ga()}));const a=document.getElementById("cmdAllowlistInput");a&&a.addEventListener("keydown",e=>{"Enter"===e.key&&oa()});const o=document.getElementById("waAllowedNumbers");o&&o.addEventListener("input",nn);const s=document.getElementById("skillSearch");s&&s.addEventListener("input",e=>Be(e.target.value));const i=document.getElementById("passthroughEngine");i&&i.addEventListener("change",()=>{wa(),function(){const e=document.getElementById("passthroughEngine"),t=document.getElementById("passthroughModel");if(!e||!t)return;const n=e.value,a={cursor:[{value:"",label:"— default (composer-2-fast) —"},{optgroup:"Cursor Defaults"},{value:"composer-2-fast",label:"🟢 Composer 2 Fast (default)"},{value:"composer-2-thinking",label:"Composer 2 Thinking"},{optgroup:"Recommended (No Rate Limits)"},{value:"gpt-5.4",label:"🟢 GPT-5.4"},{value:"gemini-3-flash",label:"🟢 Gemini 3 Flash (fastest)"},{value:"gemini-3-pro",label:"🟢 Gemini 3 Pro"},{value:"gemini-3.1-pro",label:"🟢 Gemini 3.1 Pro"},{value:"gpt-5.2-codex",label:"🟢 GPT-5.2 Codex"},{value:"gpt-5.3-codex",label:"GPT-5.3 Codex"},{optgroup:"Claude Models (May Hit Rate Limits)"},{value:"sonnet-4.6",label:"🟡 Claude 4.6 Sonnet (current)"},{value:"opus-4.6",label:"🟡 Claude 4.6 Opus"},{optgroup:"Thinking Models (Slower)"},{value:"sonnet-4.6-thinking",label:"Claude 4.6 Sonnet Thinking"},{value:"opus-4.6-thinking",label:"Claude 4.6 Opus Thinking"},{optgroup:"Compatible Claude Models"},{value:"sonnet-4.5",label:"Claude 4.5 Sonnet"},{value:"opus-4.5",label:"Claude 4.5 Opus"},{value:"sonnet-4.5-thinking",label:"Claude 4.5 Sonnet Thinking"},{optgroup:"Other"},{value:"grok",label:"xAI Grok"},{value:"kimi-k2.5",label:"Moonshot Kimi K2.5"}],claude:[{value:"",label:"— default (Sonnet 4.6) —"},{optgroup:"Recommended"},{value:"sonnet",label:"🟢 Sonnet (alias for latest)"},{value:"Default",label:"🟢 Default (Sonnet 4.6)"},{optgroup:"Specific Versions"},{value:"claude-sonnet-4-6",label:"Sonnet 4.6 · Best for everyday tasks"},{value:"Opus",label:"Opus (Opus 4.6) · Most capable for complex work"},{value:"claude-opus-4-6",label:"Opus 4.6 · Most capable"},{value:"Haiku",label:"Haiku (Haiku 4.5) · Fastest for quick answers"},{value:"claude-haiku-4-5",label:"Haiku 4.5 · Fastest"},{optgroup:"Legacy"},{value:"claude-sonnet-4-5",label:"Sonnet 4.5 (legacy)"}],codex:[{value:"",label:"— default (gpt-5.4) —"},{optgroup:"Recommended"},{value:"gpt-5.4",label:"🟢 GPT-5.4 (current)"},{value:"gpt-5.3-codex",label:"GPT-5.3 Codex"},{value:"gpt-5.2-codex",label:"🟢 GPT-5.2 Codex"},{optgroup:"Specialized"},{value:"gpt-5.1-codex-max",label:"GPT-5.1 Codex Max (deep reasoning)"},{value:"gpt-5.2",label:"GPT-5.2 (general purpose)"},{value:"gpt-5.1-codex-mini",label:"GPT-5.1 Codex Mini (fast & cheap)"}],opencode:[{value:"",label:"— default —"},{optgroup:"Free Models 🎁"},{value:"opencode/big-pickle",label:"🆓 Big Pickle (Free)"},{value:"opencode/minimax-m2.5-free",label:"🆓 MiniMax M2.5 Free"},{value:"openai/gpt-5-nano",label:"🆓 GPT 5 Nano (Free)"},{optgroup:"Budget Models 💰"},{value:"openai/gpt-5.1-codex-mini",label:"💰 GPT 5.1 Codex Mini ($0.25/$2)"},{value:"google/gemini-3-flash",label:"💰 Gemini 3 Flash ($0.50/$3)"},{value:"anthropic/claude-haiku-4-5",label:"💰 Claude Haiku 4.5 ($1/$5)"},{optgroup:"Interesting Models 🎯"},{value:"moonshot/kimi-k2.5",label:"Kimi K2.5 ($0.60/$3)"},{value:"moonshot/kimi-k2-thinking",label:"Kimi K2 Thinking ($0.40/$2.50)"},{value:"alibaba/qwen3-coder-480b",label:"Qwen3 Coder 480B ($0.45/$1.50)"},{value:"zhipu/glm-5",label:"GLM 5 ($1/$3.20)"},{optgroup:"Premium Claude"},{value:"anthropic/claude-sonnet-4-6",label:"Claude Sonnet 4.6 ($3/$15)"},{value:"anthropic/claude-opus-4-6",label:"Claude Opus 4.6 ($5/$25)"},{optgroup:"Premium OpenAI"},{value:"openai/gpt-5.4",label:"GPT 5.4 ($3/$15)"},{value:"openai/gpt-5.3-codex",label:"GPT 5.3 Codex ($1.75/$14)"},{value:"openai/gpt-5.2-codex",label:"GPT 5.2 Codex ($1.75/$14)"},{value:"openai/gpt-5.1-codex-max",label:"GPT 5.1 Codex Max ($1.25/$10)"},{optgroup:"Premium Google"},{value:"google/gemini-3.1-pro",label:"Gemini 3.1 Pro ($2/$12)"},{value:"google/gemini-3-pro",label:"Gemini 3 Pro ($2/$12)"}],gemini:[{value:"",label:"— default (gemini-3-flash-preview) —"},{optgroup:"Recommended (Latest)"},{value:"gemini-3-flash-preview",label:"🟢 Gemini 3 Flash Preview (current)"},{value:"gemini-3.1-pro-preview",label:"🟢 Gemini 3.1 Pro Preview"},{optgroup:"Gemini 2.5 Series"},{value:"gemini-2.5-pro",label:"Gemini 2.5 Pro"},{value:"gemini-2.5-flash",label:"Gemini 2.5 Flash"},{value:"gemini-2.5-flash-lite",label:"Gemini 2.5 Flash Lite (fastest)"}]};if(!n||!a[n])return void(t.style.display="none");t.style.display="inline-block",t.innerHTML="";let o=null;for(const s of a[n])if(s.optgroup)o=document.createElement("optgroup"),o.label=s.optgroup,t.appendChild(o);else{const e=document.createElement("option");e.value=s.value,e.textContent=s.label,o?o.appendChild(e):t.appendChild(e)}}(),xa()});const r=document.getElementById("chatProjectSelect");r&&r.addEventListener("change",wa);const l=document.getElementById("passthroughModel");l&&l.addEventListener("change",()=>{xa()})},{once:!0});const Va={chat:Yn,"swarm-chat":x,swarm:Ge,rt:ze,build:Fa,files:Xn,dlq:De,projects:Ha,contacts:Le,agents:R,models:Je,engines:Pa,skills:be,"run-skills":we,waves:()=>{Vn(),document.getElementById("wavesView").style.display="block",$n("navWaves")},workflows:I,benchmarks:La,"tool-matrix":Na,memory:Ma,"cli-process":_a,services:L,prompts:de,testing:me,settings:ja};document.addEventListener("click",e=>{const t=e.target.closest("[data-view]");if(t){const e=t.dataset.view,n=Va[e];return void(n&&(Un()!==e?window.location.hash=e:n()))}const n=e.target.closest("[data-stab]");if(n){const e=n.dataset.stab;window.location.hash=`settings/${e}`,Aa(e)}const a=e.target.closest("[data-toggle-child]");if(a){const e=a.dataset.toggleChild,t=a.parentElement&&a.parentElement.querySelector(e);t&&(t.style.display="none"===t.style.display?"block":"none")}const o=e.target.closest("[data-toggle-sibling]");o&&o.nextElementSibling&&o.nextElementSibling.classList.toggle(o.dataset.toggleSibling)}),Object.assign(window,{addAllowlistPattern:oa,applyNewAgentToolPreset:ie,applyPromptPreset:se,bulkSetRoute:oe,cancelSkillForm:Ce,chatAtAtInput:ma,chatKeydown:ua,clearChatHistory:ha,filterSkills:Be,loadAllUsage:Nn,loadBenchmarkLeaderboard:async()=>(await Dn()).loadBenchmarkLeaderboard(),loadBenchmarks:async()=>(await Dn()).loadBenchmarks(),loadBenchmarkTasks:async()=>(await Dn()).loadBenchmarkTasks(),onBenchmarkTaskSelect:async e=>(await Dn()).onBenchmarkTaskSelect(e),runBenchmarkTask:async()=>(await Dn()).runBenchmarkTask(),stopBenchmarkRun:async()=>(await Dn()).stopBenchmarkRun(),loadMemoryStats:j,searchMemory:S,migrateMemory:B,compactMemory:T,loadBuildProjectPicker:un,loadFiles:Ea,loadCrewCliStats:Mn,loadOcStats:sa,loadRunSkills:xe,loadServices:M,loadSpending:_n,loadTelegramSessions:Xt,loadTgMessages:Yt,loadToolMatrix:In,loadWaMessages:Ut,onBuildProjectChange:hn,onChatProjectChange:gn,pickFolder:qn,renderWaContactRows:nn,resetSpending:Ln,approveSkill:async function(e){try{await fetch("/api/skills/approve",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({approvalId:e})}),i("Approved"),Ra()}catch(t){i("Failed: "+t.message,"error")}},loadPendingApprovals:Ra,rejectSkill:async function(e){try{await fetch("/api/skills/reject",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({approvalId:e})}),i("Rejected"),Ra()}catch(t){i("Failed: "+t.message,"error")}},saveGlobalCaps:Pn,saveGlobalFallback:xt,saveBgConsciousnessModel:Bt,saveOpencodeSettings:kt,saveRTToken:Tt,saveSkill:ke,saveTgConfig:Zt,saveWaConfig:Wt,sendChat:ga,sendTestWebhook:Oa,showAgents:R,showBenchmarks:La,showBuild:Fa,showChat:Yn,showContacts:Le,showDLQ:De,showFiles:Xn,showModels:Je,showProjects:Ha,showRT:ze,showRunSkills:we,showServices:L,showSettings:ja,showSettingsTab:Aa,showSkills:be,showSwarm:Ge,showToolMatrix:Na,showMemoryView:Ma,startCrew:H,startTgBridge:tn,startWaBridge:Qt,stopTgBridge:en,stopWaBridge:Jt,toggleAddSkill:Te,toggleBgConsciousness:bt,toggleCursorWaves:wt,toggleTmuxBridge:yt,toggleClaudeCode:vt,toggleEmojiPicker:ae,updateSkillAuthFields:Pe,navigateTo:za,renderStatusBadge:p,showLoading:d,showEmpty:c,showError:l,loadContacts:Ne,applyContactFilters:_e,applyToolPreset:ne,closePreviewPane:Ta,deleteAgent:te,deleteSkill:Ae,editSkill:je,fetchBuiltinModels:ot,fetchModels:at,previewFile:Ia,resetAgentSession:ee,restartAgentFromUI:Tn,restartService:N,runSkillFromUI:Se,saveAgentFallback:Z,saveAgentVoice:X,saveAgentIdentity:Y,saveAgentModel:Q,saveAgentPrompt:J,saveAgentTools:W,saveBuiltinKey:nt,saveCursorCliConfig:U,saveClaudeCodeConfig:K,saveGeminiCliConfig:q,saveKey:tt,saveOpenCodeConfig:V,saveOpenCodeFallback:$,saveSearchTool:et,saveCodexConfig:G,setRoute:z,stopService:_,testBuiltinProvider:Ze,testKey:Xe,testSearchTool:Ye,toggleAgentBody:D,toggleKeyVis:Qe});
@@ -0,0 +1 @@
1
+ import{s as t,g as e,d as o}from"./core-utils-CmOkXgzi.js";import{e as n,l as i}from"./tab-usage-tab-BIOOnB-Y.js";var l=null,a=null,s=null;function r(){var t=l,e=a,o=s,n=document.getElementById("gtAgentCost"),i=document.getElementById("gtOcCost"),r=document.getElementById("gtCrewCliCost"),d=document.getElementById("gtTotal");n&&(null!==t&&(n.textContent="$"+t.toFixed(4)),null!==e&&(i.textContent="$"+e.toFixed(4)),null!==o&&r&&(r.textContent="$"+o.toFixed(4)),null!==t&&null!==e&&null!==o&&(d.textContent="$"+(t+e+o).toFixed(4)))}function d(t){a=t,r()}function c(t){var e=document.getElementById("grandTotalDays"),o=document.getElementById("spendingDays"),n=document.getElementById("ocStatsDays"),i=document.getElementById("crewCliDays");e&&(e.value=String(t)),o&&(o.value=String(t)),n&&(n.value=String(t)),i&&(i.value=String(t))}async function p(){var t;c(parseInt((null==(t=document.getElementById("grandTotalDays"))?void 0:t.value)||"14")),l=null,a=null,s=null,document.getElementById("gtAgentCost").textContent="—",document.getElementById("gtOcCost").textContent="—";var e=document.getElementById("gtCrewCliCost");e&&(e.textContent="—"),document.getElementById("gtTotal").textContent="—",v(),i(d),y()}async function v(){var t;const i=document.getElementById("spendingWidget"),a=parseInt((null==(t=document.getElementById("spendingDays"))?void 0:t.value)||"1");c(a);try{{const t=(await e("/api/token-usage").catch(function(){return{}})).byDay||{},o=a<=1?(new Date).toISOString().slice(0,10):new Date(Date.now()-864e5*a).toISOString().slice(0,10),d=Object.keys(t).filter(function(t){return t>=o}).sort().reverse();if(!d.length)return i.innerHTML='<div style="color:var(--text-3);">No data for this period.</div>',l=0,void r();const c={};var s=0;d.forEach(function(e){const o=t[e].byModel||{};Object.entries(o).forEach(function(t){var e=t[0],o=t[1];c[e]||(c[e]={prompt:0,completion:0}),c[e].prompt+=o.prompt||0,c[e].completion+=o.completion||0,(o.prompt||0)+(o.completion||0)})}),s=n(c);let p='<div style="margin-bottom:10px;display:flex;justify-content:space-between;align-items:center;"><span style="font-size:12px;color:var(--text-3);">'+(a<=1?"Today":"Last "+a+" days &middot; "+d.length+" days of data")+'</span><span style="font-size:16px;font-weight:700;color:var(--yellow);">$'+s.toFixed(4)+"</span></div>";const v=Math.max(...d.map(function(e){return n(t[e].byModel||{})}),1e-4),y=(new Date).toISOString().slice(0,10);p+='<div style="display:flex;flex-direction:column;gap:3px;margin-bottom:12px;">',d.forEach(function(e){const o=n(t[e].byModel||{}),i=Math.max(o/v*100,o>0?2:0),l=e===y,a=((t[e].prompt||0)+(t[e].completion||0))/1e3;p+='<div style="display:flex;align-items:center;gap:8px;font-size:11px;"><span style="width:64px;color:var(--text-3);flex-shrink:0;">'+(l?"today":e.slice(5))+'</span><div style="flex:1;background:var(--bg-1);border-radius:3px;height:12px;overflow:hidden;"><div style="width:'+i.toFixed(1)+"%;height:100%;background:"+(l?"var(--accent)":"var(--green)")+';border-radius:3px;opacity:.8;"></div></div><span style="width:58px;text-align:right;color:var(--yellow);font-weight:600;">$'+o.toFixed(4)+'</span><span style="width:40px;text-align:right;color:var(--text-3);">'+a.toFixed(0)+"k</span></div>"}),p+="</div>";const x=Object.entries(c).sort(function(t,e){return n({b:e[1]})-n({a:t[1]})});x.length&&(p+='<div style="font-size:11px;color:var(--text-3);margin-bottom:4px;">By model</div>',x.slice(0,8).forEach(function(t){var e=t[0],o=t[1];const i=n({x:o}),l=((o.prompt||0)+(o.completion||0))/1e3;p+='<div style="display:flex;justify-content:space-between;font-size:11px;padding:2px 0;border-bottom:1px solid var(--border);"><code style="color:var(--accent);">'+e+'</code><span style="color:var(--text-2);">'+l.toFixed(1)+'k tok &middot; <span style="color:var(--yellow);">$'+i.toFixed(4)+"</span></span></div>"})),l=s,r(),i.innerHTML=p}}catch(d){o(i,"Error: "+d.message)}}async function y(){var t;const o=document.getElementById("crewCliStatsWidget");if(!o)return;const n=parseInt((null==(t=document.getElementById("crewCliDays"))?void 0:t.value)||"14");c(n),o.innerHTML='<div style="color:var(--text-3);font-size:12px;">Loading…</div>';try{const t=await e("/api/crew-cli-stats?days="+n);if(!t.ok||!Object.keys(t.byDay||{}).length)return o.innerHTML='<div style="color:var(--text-3);font-size:12px;">'+(t.error||"No crew-cli data found for this period.")+"</div>",s=0,void r();const i=t.byDay,l=Object.keys(i).sort().reverse(),a=t.totalCost||0,d=t.totalCalls||0,c=t.totalPromptTokens||0,p=t.totalCompletionTokens||0,v=Math.max(...l.map(function(t){return i[t].cost||0}),1e-4);let y='<div style="display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:16px;"><div style="text-align:center;"><div style="font-size:18px;font-weight:700;color:var(--yellow);">$'+a.toFixed(4)+'</div><div style="font-size:11px;color:var(--text-3);">total cost</div></div><div style="text-align:center;"><div style="font-size:18px;font-weight:700;color:var(--accent);">'+d.toLocaleString()+'</div><div style="font-size:11px;color:var(--text-3);">LLM calls</div></div><div style="text-align:center;"><div style="font-size:18px;font-weight:700;color:var(--green);">'+(c/1e6).toFixed(2)+'M</div><div style="font-size:11px;color:var(--text-3);">input tokens</div></div><div style="text-align:center;"><div style="font-size:18px;font-weight:700;color:var(--green);">'+(p/1e6).toFixed(2)+'M</div><div style="font-size:11px;color:var(--text-3);">output tokens</div></div></div>';const x=(new Date).toISOString().slice(0,10);y+='<div style="display:flex;flex-direction:column;gap:4px;margin-bottom:16px;">',l.forEach(function(t){const e=i[t],o=Math.max(e.cost/v*100,e.cost>0?2:0),n=t===x,l=((e.prompt_tokens||0)+(e.completion_tokens||0))/1e6;y+='<div style="display:flex;align-items:center;gap:8px;font-size:11px;"><span style="width:70px;color:var(--text-3);flex-shrink:0;">'+(n?"today":t.slice(5))+'</span><div style="flex:1;background:var(--bg-1);border-radius:3px;height:16px;overflow:hidden;"><div style="width:'+o.toFixed(1)+"%;height:100%;background:"+(n?"var(--accent)":"var(--purple, #a78bfa)")+';border-radius:3px;opacity:0.85;"></div></div><span style="width:60px;text-align:right;color:var(--yellow);font-weight:600;">$'+e.cost.toFixed(4)+'</span><span style="width:50px;text-align:right;color:var(--text-3);">'+l.toFixed(2)+'M</span><span style="width:36px;text-align:right;color:var(--text-3);">'+(e.calls||0)+"</span></div>"}),y+="</div>";const g={};l.forEach(function(t){Object.entries(i[t].byModel||{}).forEach(function(t){var e=t[0],o=t[1];g[e]||(g[e]={cost:0,calls:0}),g[e].cost+=o.cost||0,g[e].calls+=o.calls||0})});const u=Object.entries(g).sort(function(t,e){return e[1].cost-t[1].cost});u.length&&(y+='<div style="font-size:11px;color:var(--text-3);margin-bottom:4px;">By model</div>',u.slice(0,8).forEach(function(t){var e=t[0],o=t[1];y+='<div style="display:flex;justify-content:space-between;font-size:11px;padding:2px 0;border-bottom:1px solid var(--border);"><code style="color:var(--accent);">'+e+'</code><span style="color:var(--text-2);">'+o.calls+' calls &middot; <span style="color:var(--yellow);">$'+o.cost.toFixed(4)+"</span></span></div>"})),s=a,r(),o.innerHTML=y}catch(i){o.innerHTML='<div style="color:var(--text-3);font-size:12px;">Error: '+i.message+"</div>",s=0,r()}}async function x(){if(confirm("Reset today's spending counters?"))try{await fetch("/api/spending/reset",{method:"POST",headers:{"content-type":"application/json"},body:"{}"}),v(),t("Spending reset")}catch(e){t("Reset failed",!0)}}async function g(){const e=parseInt(document.getElementById("gcapTokens").value)||null,o=parseFloat(document.getElementById("gcapCost").value)||null;t('Add to ~/.crewswarm/crewswarm.json: "globalSpendingCaps": {"dailyTokenLimit":'+(e||"null")+',"dailyCostLimitUSD":'+(o||"null")+"}","warning")}export{v as a,p as b,d as c,y as l,x as r,g as s};
@@ -0,0 +1 @@
1
+ import{a as t,b as s,g as e,e as a,s as n,p as i}from"./core-utils-CmOkXgzi.js";let l=()=>{},r=()=>{};function o(t={}){l=t.hideAllViews||l,r=t.setNavActive||r}let c=null,d=null,p="";function u(){l(),document.getElementById("testingView").classList.add("active"),r("navTesting"),t.activeTab="testing",s(),y(),b(),E(),async function(){try{const t=await e("/api/tests/stale");$=new Set((t.stale||[]).map(t=>t.file))}catch{}}(),e("/api/tests/progress").then(t=>{t.running&&!k&&(x(),k=setInterval(x,2e3),L())}).catch(()=>{}),c&&clearInterval(c),c=setInterval(()=>{document.getElementById("testingView").classList.contains("active")?(y(),b()):(clearInterval(c),c=null)},3e4)}function f(t){return!t||t<=0?"-":t>=6e4?(t/6e4).toFixed(1)+"m":t>=1e3?(t/1e3).toFixed(1)+"s":Math.round(t)+"ms"}function h(t){if(!t)return"-";const s=new Date(t);return s.toLocaleDateString(void 0,{month:"short",day:"numeric"})+" "+s.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit"})}function v(t,s){const e=t+s;return 0===e?"-":(t/e*100).toFixed(0)+"%"}const g={unit:"Unit",integration:"Integration",e2e:"E2E",playwright:"Playwright","crew-cli":"crew-cli",all:"All",unknown:"Other"},m={unit:"#818cf8",integration:"#34d399",e2e:"#fbbf24",playwright:"#f472b6","crew-cli":"#10b981",all:"#60a5fa",unknown:"#94a3b8"};let $=new Set;async function y(){var t;const s=document.getElementById("testingContent");if(s)try{const n=await e("/api/tests/summary");if(!n.latest&&!n.fileCounts)return void(s.innerHTML='<div class="empty-state">No test results found. Run tests to see results here.</div>');let i="";const l=n.fileCounts||{},r=n.testCounts||{};i+='<div class="test-launch-grid">';const o=[{key:"unit",label:"Unit",files:l.unit,tests:r.unit,cmd:"test:unit",color:m.unit},{key:"integration",label:"Integration",files:l.integration,tests:r.integration,cmd:"test:integration",color:m.integration},{key:"e2e",label:"E2E",files:l.e2e,tests:r.e2e,cmd:"test:e2e",color:m.e2e},{key:"playwright",label:"Playwright",files:l.playwright,tests:r.playwright,cmd:"test:playwright",color:"#f472b6"},{key:"crew-cli",label:"crew-cli",files:l["crew-cli"],tests:r["crew-cli"],cmd:"test",color:"#10b981"}];for(const t of o){const s=t.tests?`<span class="test-launch-tests">${t.tests} tests</span>`:"",e=t.cmd?`<button class="test-launch-btn" data-action="runTests" data-arg="${t.cmd}">▶ Run</button>`:'<span class="meta" style="font-size:10px">npx playwright test</span>';i+=`\n <div class="test-launch-card" style="border-color:${t.color}30">\n <div class="test-launch-header">\n <span class="test-launch-name" style="color:${t.color}">${t.label}</span>\n ${e}\n </div>\n <div class="test-launch-counts">\n <span class="test-launch-files">${t.files||0} files</span>\n ${s}\n </div>\n </div>`}const c=Object.values(r).reduce((t,s)=>t+(s||0),0);i+=`\n <div class="test-launch-card test-launch-total" style="border-color:var(--accent)">\n <div class="test-launch-header">\n <span class="test-launch-name" style="color:var(--accent)">All</span>\n <button class="test-launch-btn" data-action="runTests" data-arg="test:all" style="background:var(--accent);color:#fff">▶ Run All</button>\n </div>\n <div class="test-launch-counts">\n <span class="test-launch-files">${l.total||0} files</span>\n ${c?`<span class="test-launch-tests">${c}+ tests</span>`:""}\n </div>\n </div>`,i+="</div>",i+='<div class="test-section-title">Latest Results by Suite</div>',i+='<div class="test-suite-grid">';for(const s of["unit","integration","e2e","playwright","crew-cli","all"]){const e=null==(t=n.suites)?void 0:t[s];if(!e||!e.total&&!e.passed&&!e.failed)continue;const l=(e.passed||0)+(e.failed||0),r=e.failed>0?"test-status-fail":"test-status-pass",o=e.failed>0?"FAIL":"PASS",c=m[s];let d="";if(e.tests&&e.tests.length>0){const t=new Map;for(const s of e.tests){const e=s.file||"unknown";t.has(e)||t.set(e,{pass:0,fail:0,skip:0});const a=t.get(e);"pass"===s.status?a.pass++:"fail"===s.status?a.fail++:"skip"===s.status&&a.skip++}d='<div class="test-file-list">';for(const[e,n]of t){const t=e.split("/").pop(),i=e.replace(/^\/.*?CrewSwarm\//,""),l=$.has(i)||$.has(e)?'<span class="test-stale-badge" title="Source changed since last run">⚠️ stale</span>':"";d+=`\n <div class="test-file-row">\n <span class="test-file-dot">${n.fail>0?"🔴":"🟢"}</span>\n <span class="test-file-name" title="${a(e)}">${a(t)}</span>\n ${l}\n <span class="test-file-counts"><span class="test-color-pass">${n.pass}p</span> <span class="${n.fail>0?"test-color-fail":""}">${n.fail}f</span></span>\n <button class="test-file-run-btn" data-action="runSingleFile" data-arg="${a(s)}" data-arg2="${a(i)}" title="Run this file only">▶</button>\n </div>`}d+="</div>"}i+=`\n <div class="test-suite-card">\n <div class="test-suite-header">\n <span class="test-suite-name" style="color:${c}">${g[s]}</span>\n <span class="test-summary-status ${r}">${o}</span>\n </div>\n <div class="test-suite-stats">\n <div><span class="test-color-pass">${e.passed||0}</span> pass</div>\n <div><span class="${e.failed>0?"test-color-fail":""}">${e.failed||0}</span> fail</div>\n <div><span class="${e.skipped>0?"test-color-skip":""}">${e.skipped||0}</span> skip</div>\n <div><strong>${e.total||0}</strong> total</div>\n </div>\n <div class="test-suite-meta">\n ${v(e.passed||0,e.failed||0)} pass rate · ${f(e.duration_ms)} · ${h(e.timestamp)}\n </div>\n <div class="test-progress-bar">\n <div class="test-progress-pass" style="width:${l>0?(e.passed||0)/l*100:0}%"></div>\n <div class="test-progress-fail" style="width:${l>0?(e.failed||0)/l*100:0}%"></div>\n </div>\n ${d}\n </div>`}i+="</div>";const d=[];for(const t of Object.values(n.suites||{}))t.failures&&d.push(...t.failures);if(d.length>0){i+=`<div class="test-section-title">Failures (${d.length})</div>`;for(const t of d){const s="fail-"+Math.random().toString(36).slice(2),e=(t.file||"").replace(/^\/.*?CrewSwarm\//,""),n=t.rerun_command||"",l=(t.error||"").split("\n").slice(0,10).join("\n"),r=`${(t.name||"").toLowerCase().replace(/[^a-z0-9]+/g,"-").slice(0,80)}/test-failed-1.png`,o=(t.file||"").includes(".spec.")||(t.file||"").includes("playwright")?`\n <div class="test-failure-screenshot" id="ss-${a(s)}">\n <img src="/api/tests/screenshot?path=${encodeURIComponent(r)}"\n class="test-screenshot-thumb"\n alt="Failure screenshot"\n onerror="this.parentElement.style.display='none'"\n onclick="this.classList.toggle('test-screenshot-expanded')"\n title="Click to expand" />\n </div>`:"";i+=`\n <div class="test-failure-card test-failure-expandable" id="${a(s)}">\n <div class="test-failure-header" data-action="toggleFailure" data-arg="${a(s)}">\n <span class="test-failure-toggle">▶</span>\n <span class="test-failure-name">${a(t.name)}</span>\n <span class="test-failure-file-inline">${a(t.file||"")}</span>\n ${t.classification&&"unknown"!==t.classification?`<span class="test-failure-class">${a(t.classification)}</span>`:""}\n </div>\n <div class="test-failure-detail" style="display:none">\n ${t.error?`<pre class="test-failure-error">${a(String(t.error).slice(0,500))}</pre>`:""}\n ${l?`<pre class="test-failure-stack">${a(l)}</pre>`:""}\n ${o}\n <div class="test-failure-actions">\n ${e?`<a class="test-failure-link" href="#" onclick="return false" title="${a(e)}">${a(e.split("/").pop())}</a>`:""}\n ${n?`<div class="test-failure-rerun">\n <code>${a(n)}</code>\n <button class="test-copy-btn" data-action="copyText" data-arg="${a(n)}" title="Copy rerun command">Copy</button>\n </div>`:""}\n </div>\n </div>\n </div>`}}const p=[];for(const[t,s]of Object.entries(n.suites||{}))s.skips&&p.push(...s.skips.map(s=>({...s,suite:t})));if(p.length>0){i+='<details class="test-skips-section">',i+=`<summary class="test-section-title" style="cursor:pointer">Skipped (${p.length}) — click to expand</summary>`,i+='<table class="test-groups-table"><thead><tr><th>Test</th><th>File</th><th>Suite</th></tr></thead><tbody>';for(const t of p.slice(0,50))i+=`<tr><td>${a(t.name)}</td><td class="meta">${a(t.file)}</td><td><span class="test-cat-badge test-cat-${a(t.suite)}">${a(t.suite)}</span></td></tr>`;p.length>50&&(i+=`<tr><td colspan="3" class="meta">...and ${p.length-50} more</td></tr>`),i+="</tbody></table></details>"}s.innerHTML=i}catch(n){s.innerHTML=`<div class="empty-state">Failed to load test results: ${a(n.message)}</div>`}}async function b(){const t=document.getElementById("testingHistory");if(t)try{const s=await e("/api/tests/history");if(!s.history||0===s.history.length)return void(t.innerHTML='<div class="meta">No run history yet.</div>');let n='<div class="test-section-title">Run History</div>';n+='\n <table class="test-history-table">\n <thead>\n <tr>\n <th>When</th>\n <th>Suite</th>\n <th>Status</th>\n <th class="num">Pass</th>\n <th class="num">Fail</th>\n <th class="num">Skip</th>\n <th class="num">Total</th>\n <th class="num">Duration</th>\n <th class="num">Rate</th>\n </tr>\n </thead>\n <tbody>';for(const t of s.history.slice(0,25)){const s=t.failed>0?"test-color-fail":"test-color-pass",e=g[t.suite]||t.suite||"?",i=m[t.suite]||m.unknown;n+=`\n <tr data-action="loadRunDetail" data-arg="${a(t.runId)}" style="cursor:pointer" class="${t.failed>0?"test-row-fail":""}">\n <td class="meta" style="white-space:nowrap">${h(t.timestamp)}</td>\n <td><span class="test-cat-badge" style="background:${i}20;color:${i}">${e}</span></td>\n <td class="${s}" style="font-weight:600">${t.failed>0?"FAIL":"PASS"} ▸</td>\n <td class="num">${t.passed}</td>\n <td class="num ${t.failed>0?"test-color-fail":""}">${t.failed}</td>\n <td class="num ${t.skipped>0?"test-color-skip":""}">${t.skipped}</td>\n <td class="num"><strong>${t.total}</strong></td>\n <td class="num">${f(t.duration_ms)}</td>\n <td class="num">${v(t.passed,t.failed)}</td>\n </tr>`}n+="</tbody></table>",n+='<div id="testingRunDetail"></div>',t.innerHTML=n}catch(s){t.innerHTML=`<div class="meta">Failed to load history: ${a(s.message)}</div>`}}async function w(t){var s,n,i;const l=document.getElementById("testingRunDetail");if(l){l.innerHTML='<div class="meta" style="padding:12px">Loading run detail...</div>';try{const r=await e("/api/tests/run-detail?runId="+encodeURIComponent(t));if(r.error)return void(l.innerHTML=`<div class="meta">${a(r.error)}</div>`);let o=`<div class="test-section-title">Run Detail: ${a(t)} <span class="meta" style="font-weight:400;font-size:11px;text-transform:none">${h(r.timestamp)}</span></div>`;o+=`<div class="test-suite-meta" style="margin-bottom:12px">${r.passed} pass, ${r.failed} fail, ${r.skipped} skip, ${r.total} total · ${f(r.duration_ms)} · ${v(r.passed,r.failed)} pass rate</div>`;if(!((null==(s=r.failures)?void 0:s.length)>0||(null==(n=r.skips)?void 0:n.length)>0)&&r.total>0&&(o+='<div class="meta" style="padding:8px 0;color:var(--text-2)">No detailed failure/skip data saved for this run. Run with <code>npm run test:all</code> to generate full reports.</div>'),r.failures&&r.failures.length>0){o+=`<div class="test-section-title">Failures (${r.failures.length})</div>`;for(const t of r.failures){const s="rd-fail-"+Math.random().toString(36).slice(2),e=t.rerun_command||(null==(i=t.selector)?void 0:i.command)||"";o+=`\n <div class="test-failure-card test-failure-expandable" id="${a(s)}">\n <div class="test-failure-header" data-action="toggleFailure" data-arg="${a(s)}">\n <span class="test-failure-toggle">▶</span>\n <span class="test-failure-name">${a(t.name)}</span>\n </div>\n <div class="test-failure-detail" style="display:none">\n <div class="test-failure-file">${a(t.file)}</div>\n ${t.error?`<pre class="test-failure-error">${a(String(t.error).slice(0,500))}</pre>`:""}\n ${t.error_stack?`<pre class="test-failure-stack">${a(String(t.error_stack).split("\n").slice(0,10).join("\n"))}</pre>`:""}\n <div class="test-failure-actions">\n ${e?`<div class="test-failure-rerun">\n <code>${a(e)}</code>\n <button class="test-copy-btn" data-action="copyText" data-arg="${a(e)}" title="Copy rerun command">Copy</button>\n </div>`:""}\n </div>\n </div>\n </div>`}}if(r.skips&&r.skips.length>0){o+=`<details><summary class="test-section-title" style="cursor:pointer">Skipped (${r.skips.length})</summary>`,o+='<table class="test-groups-table"><thead><tr><th>Test</th><th>File</th></tr></thead><tbody>';for(const t of r.skips.slice(0,50))o+=`<tr><td>${a(t.name)}</td><td class="meta">${a(t.file)}</td></tr>`;r.skips.length>50&&(o+=`<tr><td colspan="2" class="meta">...and ${r.skips.length-50} more</td></tr>`),o+="</tbody></table></details>"}l.innerHTML=o,l.scrollIntoView({behavior:"smooth",block:"nearest"})}catch(r){l.innerHTML=`<div class="meta">Failed: ${a(r.message)}</div>`}}}let k=null;function x(){const t=document.getElementById("testProgressBar");t&&e("/api/tests/progress").then(s=>{var e;if(!s.running&&!s.finished)return void(t.innerHTML="");const n=((s.finished||Date.now())-s.started)/1e3,i=n>=60?(n/60).toFixed(1)+"m":Math.round(n)+"s",l=s.passed+s.failed+s.skipped,r=g[null==(e=s.suite)?void 0:e.replace("test:","")]||s.suite||"Tests";if(s.running){const e=s.current_file?s.current_file.split("/").pop():"";t.innerHTML=`\n <div class="test-progress-live">\n <div class="test-progress-live-header">\n <span class="test-progress-live-status">⏳ Running ${a(r)}...</span>\n <span class="meta">${i}</span>\n <button class="test-stop-btn" data-action="stopTests" title="Stop running tests">■ Stop</button>\n </div>\n <div class="test-progress-live-stats">\n <span class="test-color-pass">${s.passed} pass</span>\n <span class="test-color-fail">${s.failed} fail</span>\n <span class="test-color-skip">${s.skipped} skip</span>\n <span>${s.files_done}${s.files_total?"/"+s.files_total:""} files</span>\n <span>${l} tests</span>\n </div>\n ${e?`<div class="test-progress-live-file">${a(e)}</div>`:""}\n <div class="test-progress-bar" style="margin-top:6px">\n <div class="test-progress-pass" style="width:${s.files_total>0?s.files_done/s.files_total*100:l>0?s.passed/l*100:0}%;transition:width 0.3s;background:#22c55e"></div>\n <div class="test-progress-fail" style="width:${s.files_total>0?0:l>0?s.failed/l*100:0}%;transition:width 0.3s"></div>\n </div>\n </div>`}else{const e=s.failed>0?"test-color-fail":"test-color-pass",n=s.failed>0?"FAILED":"PASSED";t.innerHTML=`\n <div class="test-progress-live test-progress-done">\n <div class="test-progress-live-header">\n <span class="${e}" style="font-weight:700">✓ ${a(r)} ${n}</span>\n <span class="meta">${i}</span>\n </div>\n <div class="test-progress-live-stats">\n <span class="test-color-pass">${s.passed} pass</span>\n <span class="test-color-fail">${s.failed} fail</span>\n <span class="test-color-skip">${s.skipped} skip</span>\n <span>${s.files_done} files</span>\n </div>\n </div>`,k&&(clearInterval(k),k=null),M(),y(),b(),E(),setTimeout(()=>{t&&(t.innerHTML="")},1e4)}}).catch(()=>{})}async function S(t){try{n(`Starting ${t}...`),await i("/api/tests/run",{suite:t}),k&&clearInterval(k),x(),k=setInterval(x,2e3),L()}catch(s){n("Failed to start tests: "+s.message,!0)}}async function T(){try{(await i("/api/tests/stop",{})).stopped?(n("Tests stopped."),k&&(clearInterval(k),k=null),M(),x(),setTimeout(()=>refreshTestData(),1e3)):n("No running tests to stop.")}catch(t){n("Failed to stop tests: "+t.message,!0)}}async function I(t,s){const e={unit:"test:unit",integration:"test:integration",e2e:"test:e2e",all:"test:all",unknown:"test:unit"}[t]||"test:unit";try{n(`Running ${s.split("/").pop()}...`),await i("/api/tests/run",{suite:e,file:s}),k&&clearInterval(k),x(),k=setInterval(x,2e3),L()}catch(a){n("Failed to start test: "+a.message,!0)}}function L(){M(),p="";const t=function(){var t;let s=document.getElementById("testStreamPanel");if(!s){const e=document.getElementById("testProgressBar");if(!e)return null;s=document.createElement("div"),s.id="testStreamPanel",s.className="test-stream-panel",s.style.display="none",s.innerHTML='\n <div class="test-stream-header">\n <span>Live Output</span>\n <button class="test-stream-close" onclick="document.getElementById(\'testStreamPanel\').style.display=\'none\'">✕</button>\n </div>\n <pre id="testStreamPre" class="test-stream-pre"></pre>',null==(t=e.parentNode)||t.insertBefore(s,e.nextSibling)}return s}();t&&(t.style.display="block",t.querySelector("pre").textContent=""),d=new EventSource("/api/tests/stream"),d.onmessage=t=>{try{const s=JSON.parse(t.data);s.reset?p=s.text||"":s.text&&(p+=s.text),s.done&&M();const e=document.getElementById("testStreamPre");e&&(e.textContent=p,e.scrollTop=e.scrollHeight)}catch{}},d.onerror=()=>{M()}}function M(){d&&(d.close(),d=null)}function F(t){const s=document.getElementById(t);if(!s)return;const e=s.querySelector(".test-failure-detail"),a=s.querySelector(".test-failure-toggle");if(!e)return;const n="none"!==e.style.display;e.style.display=n?"none":"block",a&&(a.textContent=n?"▶":"▼")}async function E(){const t=document.getElementById("testingChart");if(t)try{const s=((await e("/api/tests/history")).history||[]).slice(0,20).reverse();if(0===s.length)return void(t.innerHTML="");const a=600,n=120,i=30,l=2,r=Math.max(...s.map(t=>(t.passed||0)+(t.failed||0)),1),o=Math.floor((a-2*i-l*(s.length-1))/s.length);let c="",d="";s.forEach((t,e)=>{const a=i+e*(o+l),p=(t.passed||0)+(t.failed||0),u=p>0?Math.round((t.passed||0)/r*(n-i)):0,f=p>0?Math.round((t.failed||0)/r*(n-i)):0,v=n-i-u-f;if(f>0&&(c+=`<rect x="${a}" y="${n-i-f}" width="${o}" height="${f}" fill="#ef4444" rx="1" opacity="0.85"><title>${h(t.timestamp)} — ${t.failed} fail</title></rect>`),u>0&&(c+=`<rect x="${a}" y="${v}" width="${o}" height="${u}" fill="#22c55e" rx="1" opacity="0.85"><title>${h(t.timestamp)} — ${t.passed} pass</title></rect>`),e%5==0||e===s.length-1){const s=t.timestamp?new Date(t.timestamp).toLocaleDateString(void 0,{month:"short",day:"numeric"}):"";d+=`<text x="${a+o/2}" y="${n-2}" text-anchor="middle" font-size="9" fill="var(--text-3, #888)">${s}</text>`}});const p=`<svg viewBox="0 0 ${a} ${n}" xmlns="http://www.w3.org/2000/svg" style="width:100%;max-width:${a}px;height:${n}px;display:block">\n <line x1="${i}" y1="${n-i}" x2="${a-i}" y2="${n-i}" stroke="var(--border,#333)" stroke-width="1"/>\n ${c}\n ${d}\n </svg>`;t.innerHTML=`\n <div class="test-section-title">Run History (last ${s.length})\n <span class="test-chart-legend">\n <span style="color:#22c55e">■</span> Pass\n <span style="color:#ef4444">■</span> Fail\n </span>\n </div>\n <div class="test-chart-wrap">${p}</div>`}catch{}}function H(t){var s;null==(s=navigator.clipboard)||s.writeText(t).then(()=>{n("Copied to clipboard")}).catch(()=>{n("Copy failed",!0)})}export{T as a,S as b,H as c,o as i,w as l,I as r,u as s,F as t};