@oeronteros-1/opencode-orchestra 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +207 -0
- package/dashboard-dist/assets/index-89Gs8jun.css +2 -0
- package/dashboard-dist/assets/index-Bhe8OPZD.js +124 -0
- package/dashboard-dist/index.html +14 -0
- package/dist/agents/build.d.ts +7 -0
- package/dist/agents/build.js +16 -0
- package/dist/agents/build.js.map +1 -0
- package/dist/agents/judge.d.ts +3 -0
- package/dist/agents/judge.js +29 -0
- package/dist/agents/judge.js.map +1 -0
- package/dist/agents/lead.d.ts +3 -0
- package/dist/agents/lead.js +54 -0
- package/dist/agents/lead.js.map +1 -0
- package/dist/agents/types.d.ts +14 -0
- package/dist/agents/types.js +2 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/agents/workers.d.ts +3 -0
- package/dist/agents/workers.js +114 -0
- package/dist/agents/workers.js.map +1 -0
- package/dist/cli.d.ts +24 -0
- package/dist/cli.js +418 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/defaults.d.ts +4 -0
- package/dist/config/defaults.js +26 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/load.d.ts +6 -0
- package/dist/config/load.js +58 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/paths.d.ts +2 -0
- package/dist/config/paths.js +13 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/config/schema.d.ts +341 -0
- package/dist/config/schema.js +103 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/dashboard/server.d.ts +12 -0
- package/dist/dashboard/server.js +297 -0
- package/dist/dashboard/server.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +85 -0
- package/dist/index.js.map +1 -0
- package/dist/profiles/architecture.d.ts +2 -0
- package/dist/profiles/architecture.js +13 -0
- package/dist/profiles/architecture.js.map +1 -0
- package/dist/profiles/catalog.d.ts +2 -0
- package/dist/profiles/catalog.js +39 -0
- package/dist/profiles/catalog.js.map +1 -0
- package/dist/profiles/debug.d.ts +2 -0
- package/dist/profiles/debug.js +14 -0
- package/dist/profiles/debug.js.map +1 -0
- package/dist/profiles/performance.d.ts +2 -0
- package/dist/profiles/performance.js +13 -0
- package/dist/profiles/performance.js.map +1 -0
- package/dist/profiles/research.d.ts +2 -0
- package/dist/profiles/research.js +13 -0
- package/dist/profiles/research.js.map +1 -0
- package/dist/profiles/security.d.ts +2 -0
- package/dist/profiles/security.js +13 -0
- package/dist/profiles/security.js.map +1 -0
- package/dist/profiles/types.d.ts +9 -0
- package/dist/profiles/types.js +2 -0
- package/dist/profiles/types.js.map +1 -0
- package/dist/profiles/ui.d.ts +2 -0
- package/dist/profiles/ui.js +13 -0
- package/dist/profiles/ui.js.map +1 -0
- package/dist/prompts/load.d.ts +4 -0
- package/dist/prompts/load.js +26 -0
- package/dist/prompts/load.js.map +1 -0
- package/dist/routing/budget.d.ts +11 -0
- package/dist/routing/budget.js +45 -0
- package/dist/routing/budget.js.map +1 -0
- package/dist/routing/classifier.d.ts +10 -0
- package/dist/routing/classifier.js +160 -0
- package/dist/routing/classifier.js.map +1 -0
- package/dist/routing/escalation.d.ts +12 -0
- package/dist/routing/escalation.js +30 -0
- package/dist/routing/escalation.js.map +1 -0
- package/dist/routing/model-discovery.d.ts +3 -0
- package/dist/routing/model-discovery.js +96 -0
- package/dist/routing/model-discovery.js.map +1 -0
- package/dist/routing/model-resolver.d.ts +26 -0
- package/dist/routing/model-resolver.js +66 -0
- package/dist/routing/model-resolver.js.map +1 -0
- package/dist/superpowers/compatibility.d.ts +2 -0
- package/dist/superpowers/compatibility.js +9 -0
- package/dist/superpowers/compatibility.js.map +1 -0
- package/dist/telemetry/ledger.d.ts +68 -0
- package/dist/telemetry/ledger.js +179 -0
- package/dist/telemetry/ledger.js.map +1 -0
- package/dist/tools.d.ts +4 -0
- package/dist/tools.js +57 -0
- package/dist/tools.js.map +1 -0
- package/package.json +79 -0
- package/prompts/judge.md +13 -0
- package/prompts/lead.md +24 -0
- package/schema/opencode-orchestra.schema.json +112 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OpenCode Orchestra contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# OpenCode Orchestra
|
|
2
|
+
|
|
3
|
+
`@oeronteros-1/opencode-orchestra` — плагин-оркестратор для OpenCode. Он добавляет ведущего агента, небольшую команду скрытых специалистов, арбитра для сложных случаев, автоматический выбор подключённых моделей и готовую интеграцию Context7 + Codebase Memory + MemoryGraph.
|
|
4
|
+
|
|
5
|
+
## Установка одной командой
|
|
6
|
+
|
|
7
|
+
Одинаково для Linux, macOS и Windows (PowerShell/Terminal с установленным Bun):
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
bunx @oeronteros-1/opencode-orchestra@latest install
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
CLI использует Bun напрямую, поэтому отдельный Node.js для этой команды не требуется.
|
|
14
|
+
|
|
15
|
+
Команда:
|
|
16
|
+
|
|
17
|
+
- добавит `@oeronteros-1/opencode-orchestra` в `~/.config/opencode/opencode.json`;
|
|
18
|
+
- подключит удалённый Context7 MCP (`https://mcp.context7.com/mcp`);
|
|
19
|
+
- установит статический `codebase-memory-mcp`, включит автоматическую индексацию и подключит его к OpenCode;
|
|
20
|
+
- установит MemoryGraph (`memorygraphMCP`) в изолированное окружение через `uv` и подключит локальную SQLite-память;
|
|
21
|
+
- сохранит все пользовательские MCP и плагины без удаления или переименования;
|
|
22
|
+
- создаст `~/.config/opencode/orchestra.jsonc` с автоматическим выбором моделей;
|
|
23
|
+
- сделает резервную копию существующего конфига перед изменением;
|
|
24
|
+
- не потребует API-ключей, Docker или административных прав для стандартной локальной конфигурации.
|
|
25
|
+
|
|
26
|
+
Установщик идемпотентен. Существующие настройки MCP он сохраняет; заменить их стандартными значениями можно только через `--force`.
|
|
27
|
+
|
|
28
|
+
На Linux и macOS используются официальные shell-инсталляторы Codebase Memory и uv. На Windows загружаются официальные PowerShell-инсталляторы, исполняемые с временным `ExecutionPolicy Bypass`; Codebase Memory устанавливается в `%LOCALAPPDATA%`, а пути к `uv` и MemoryGraph определяются автоматически. Сам установщик Orchestra не изменяет системные каталоги.
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
bunx @oeronteros-1/opencode-orchestra@latest install --help
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Полезные флаги: `--no-context7`, `--no-codebase-memory`, `--no-memorygraph`, `--no-deps`, `--force`, `--dry-run`, `--config-dir DIR`.
|
|
35
|
+
|
|
36
|
+
## Модели без ручной настройки
|
|
37
|
+
|
|
38
|
+
По умолчанию используется `models.strategy: "auto"`. При запуске плагин получает через OpenCode список реально подключённых провайдеров и моделей, определяет доступные возможности (reasoning, tools, vision, image output, размер контекста) и заполняет только пустые пулы.
|
|
39
|
+
|
|
40
|
+
Если каталог моделей временно недоступен, поле `model` у агента не задаётся и OpenCode использует текущую пользовательскую модель. Плагин не меняет primary-модель сессии.
|
|
41
|
+
|
|
42
|
+
Минимальный глобальный конфиг создаётся автоматически:
|
|
43
|
+
|
|
44
|
+
```jsonc
|
|
45
|
+
{
|
|
46
|
+
"$schema": "https://unpkg.com/@oeronteros-1/opencode-orchestra@latest/schema/opencode-orchestra.schema.json",
|
|
47
|
+
"budget": "balanced",
|
|
48
|
+
"models": {
|
|
49
|
+
"strategy": "auto",
|
|
50
|
+
"agents": {}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Точная модель для отдельного агента
|
|
56
|
+
|
|
57
|
+
Переопределение в `models.agents` имеет наивысший приоритет:
|
|
58
|
+
|
|
59
|
+
```jsonc
|
|
60
|
+
{
|
|
61
|
+
"models": {
|
|
62
|
+
"strategy": "auto",
|
|
63
|
+
"agents": {
|
|
64
|
+
"orch-lead": "anthropic/claude-sonnet-4-5",
|
|
65
|
+
"orch-repo": "openai/gpt-5-mini",
|
|
66
|
+
"orch-judge": "openai/gpt-5"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Доступные имена: `orch-lead`, `orch-repo`, `orch-docs`, `orch-tests`, `orch-research`, `orch-critic`, `orch-security`, `orch-visual-reference`, `orch-visual-generate`, `orch-visual-review`, `orch-judge`.
|
|
73
|
+
|
|
74
|
+
### Ручные пулы
|
|
75
|
+
|
|
76
|
+
Непустой ручной пул не заменяется автоподбором. Можно настроить только нужную категорию, сохранив auto для остальных:
|
|
77
|
+
|
|
78
|
+
```jsonc
|
|
79
|
+
{
|
|
80
|
+
"budget": "balanced",
|
|
81
|
+
"models": {
|
|
82
|
+
"strategy": "auto",
|
|
83
|
+
"worker": {
|
|
84
|
+
"code": [
|
|
85
|
+
{
|
|
86
|
+
"id": "provider/model-id",
|
|
87
|
+
"cost": "subscription",
|
|
88
|
+
"tier": "worker",
|
|
89
|
+
"priority": 90,
|
|
90
|
+
"capabilities": ["code", "large-context"],
|
|
91
|
+
"scores": { "code": 9 }
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Для полностью ручного режима задайте `models.strategy: "manual"`. Полный пример находится в [`examples/.opencode/orchestra.jsonc`](examples/.opencode/orchestra.jsonc).
|
|
100
|
+
|
|
101
|
+
## Приоритет выбора модели
|
|
102
|
+
|
|
103
|
+
Порядок разрешения:
|
|
104
|
+
|
|
105
|
+
1. точное значение `models.agents[agent-name]`;
|
|
106
|
+
2. непустой пользовательский пул;
|
|
107
|
+
3. автоматически собранный пул подключённых моделей;
|
|
108
|
+
4. текущая модель OpenCode, если подходящего кандидата нет.
|
|
109
|
+
|
|
110
|
+
Режимы бюджета:
|
|
111
|
+
|
|
112
|
+
- `eco` — сильный приоритет бесплатных workers; judge вызывается только при критическом несогласии;
|
|
113
|
+
- `balanced` — бесплатные workers, subscription-first lead, frontier judge при низкой уверенности или споре;
|
|
114
|
+
- `quality` — разрешает передовые платные модели для lead и workers, предпочитает сильные `lead/frontier` модели и вызывает frontier judge для критических, неуверенных или спорных решений;
|
|
115
|
+
- `ebobo` — максимальный режим: до 8 параллельных и 12 суммарных workers, весь доступный состав специалистов, frontier-first выбор моделей и обязательный `orch-judge`. Платные модели не штрафуются.
|
|
116
|
+
|
|
117
|
+
В `ebobo` «топовая» модель определяется без жёсткой привязки к бренду: приоритет получают подключённые модели класса `frontier`, затем `lead`, а внутри класса учитываются capabilities, контекст и пользовательский priority. Точное назначение через `models.agents` всё равно имеет высший приоритет.
|
|
118
|
+
|
|
119
|
+
Это взаимоисключающие runtime-режимы одного поля, а не варианты установки:
|
|
120
|
+
|
|
121
|
+
```jsonc
|
|
122
|
+
{
|
|
123
|
+
"budget": "ebobo"
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Цена из каталога — сигнал ранжирования, а не гарантия фактического тарифа. Для подписочных моделей можно явно указать `cost: "subscription"` в ручном пуле.
|
|
128
|
+
|
|
129
|
+
## Агенты и команды
|
|
130
|
+
|
|
131
|
+
Плагин добавляет один публичный `orch-lead`, скрытых workers и скрытый `orch-judge`. Workers не могут делегировать работу дальше; lead может вызывать только агентов Orchestra.
|
|
132
|
+
|
|
133
|
+
Команды OpenCode:
|
|
134
|
+
|
|
135
|
+
```text
|
|
136
|
+
/orchestra <задача>
|
|
137
|
+
/orchestra-status
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Профили: `architecture`, `debug`, `ui`, `research`, `review`, `security`, `performance`, `migration`, `ops`.
|
|
141
|
+
|
|
142
|
+
## Context7, Codebase Memory и MemoryGraph
|
|
143
|
+
|
|
144
|
+
Context7 остаётся удалённым MCP для актуальной документации библиотек. OAuth отключён; при наличии ключа можно самостоятельно добавить заголовок `CONTEXT7_API_KEY`.
|
|
145
|
+
|
|
146
|
+
Codebase Memory отвечает за знания, которые можно восстановить из исходников: символы, вызовы, зависимости, маршруты и impact analysis. Установщик использует официальный Linux-инсталлятор с `--skip-config`, чтобы тот не создавал конкурирующие агенты и инструкции, после чего включает `auto_index`. Индекс хранится локально в `~/.cache/codebase-memory-mcp/`.
|
|
147
|
+
|
|
148
|
+
MemoryGraph отвечает за знания, которых нет непосредственно в коде: принятые архитектурные решения, проверенные исправления и повторно используемые паттерны. Используется core-профиль с локальным SQLite в `~/.local/share/memorygraph/`. Lead вызывает `recall_memories` не более одного раза в начале релевантной задачи и сохраняет только проверенные устойчивые знания.
|
|
149
|
+
|
|
150
|
+
Разделение намеренное:
|
|
151
|
+
|
|
152
|
+
- Codebase Memory — актуальная структура репозитория;
|
|
153
|
+
- MemoryGraph — история решений и связей между ними;
|
|
154
|
+
- Context7 — актуальные внешние API и документация.
|
|
155
|
+
|
|
156
|
+
Если зависимости уже установлены, повторный запуск использует существующие исполняемые файлы. `--no-deps` только записывает MCP-конфигурацию и ожидает, что команды `codebase-memory-mcp` и `memorygraph` уже доступны.
|
|
157
|
+
|
|
158
|
+
## Локальный и проектный конфиг
|
|
159
|
+
|
|
160
|
+
Глобальный конфиг: `~/.config/opencode/orchestra.jsonc` (или `$XDG_CONFIG_HOME/opencode/orchestra.jsonc`). Проектный `.opencode/orchestra.jsonc` накладывается поверх глобального. Переменная `OPENCODE_CONFIG_DIR` также поддерживается.
|
|
161
|
+
|
|
162
|
+
## Разработка
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
npm install
|
|
166
|
+
npm run check
|
|
167
|
+
npm run build
|
|
168
|
+
npm pack --dry-run
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Перед публикацией пакет автоматически собирается через `prepack`.
|
|
172
|
+
|
|
173
|
+
## Документация
|
|
174
|
+
|
|
175
|
+
- [OpenCode plugins](https://opencode.ai/docs/plugins/)
|
|
176
|
+
- [OpenCode MCP servers](https://opencode.ai/docs/mcp-servers/)
|
|
177
|
+
- [OpenCode agents](https://opencode.ai/docs/agents/)
|
|
178
|
+
- [Context7](https://github.com/upstash/context7)
|
|
179
|
+
- [Codebase Memory MCP](https://github.com/DeusData/codebase-memory-mcp)
|
|
180
|
+
- [MemoryGraph](https://github.com/memory-graph/memory-graph)
|
|
181
|
+
- [uv](https://docs.astral.sh/uv/)
|
|
182
|
+
|
|
183
|
+
## Локальный dashboard
|
|
184
|
+
|
|
185
|
+
Dashboard входит в тот же npm-пакет и запускается из корня нужного проекта:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
bunx @oeronteros-1/opencode-orchestra@latest dashboard
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Команда поднимает защищённый случайным токеном сервер на `127.0.0.1`, открывает локальный сайт и показывает:
|
|
192
|
+
|
|
193
|
+
- число сессий и вызовов;
|
|
194
|
+
- input, output, reasoning и cache-токены;
|
|
195
|
+
- фактическую стоимость, которую возвращает провайдер;
|
|
196
|
+
- расходы и нагрузку по моделям и агентам;
|
|
197
|
+
- виртуализированный журнал activity без текстов промптов и ответов;
|
|
198
|
+
- статус Context7, Codebase Memory, MemoryGraph и сохранённого пользователем Supermemory;
|
|
199
|
+
- настройку режимов `eco`, `balanced`, `quality`, `ebobo` и моделей отдельных агентов.
|
|
200
|
+
|
|
201
|
+
Настройки сохраняются в `orchestra.jsonc` с резервной копией. Существующие MCP-записи dashboard не удаляет и не перезаписывает.
|
|
202
|
+
|
|
203
|
+
Полезные параметры: `--directory DIR`, `--config-dir DIR`, `--host HOST`, `--port PORT`, `--no-open`.
|
|
204
|
+
|
|
205
|
+
## License
|
|
206
|
+
|
|
207
|
+
MIT
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-violet-400:oklch(70.2% .183 293.541);--color-violet-500:oklch(60.6% .25 292.717);--color-zinc-200:oklch(92% .004 286.32);--color-zinc-400:oklch(70.5% .015 286.067);--color-zinc-700:oklch(37% .013 285.805);--color-white:#fff;--spacing:.25rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-semibold:600;--radius-xl:.75rem;--radius-2xl:1rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.relative{position:relative}.block{display:block}.inline-flex{display:inline-flex}.table{display:table}.table-row{display:table-row}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-10{height:calc(var(--spacing) * 10)}.w-11{width:calc(var(--spacing) * 11)}.translate-x-0\.5{--tw-translate-x:calc(var(--spacing) * .5);translate:var(--tw-translate-x) var(--tw-translate-y)}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.items-center{align-items:center}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing) * 2)}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:2147483647px}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-white\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.border-white\/10{border-color:color-mix(in oklab, var(--color-white) 10%, transparent)}}.border-white\/\[0\.08\]{border-color:#ffffff14}@supports (color:color-mix(in lab, red, red)){.border-white\/\[0\.08\]{border-color:color-mix(in oklab, var(--color-white) 8%, transparent)}}.bg-\[\#10131a\]\/85{background-color:oklab(18.6905% -.000851832 -.0150777/.85)}.bg-violet-500{background-color:var(--color-violet-500)}.bg-white{background-color:var(--color-white)}.bg-white\/\[0\.03\]{background-color:#ffffff08}@supports (color:color-mix(in lab, red, red)){.bg-white\/\[0\.03\]{background-color:color-mix(in oklab, var(--color-white) 3%, transparent)}}.bg-zinc-700{background-color:var(--color-zinc-700)}.px-4{padding-inline:calc(var(--spacing) * 4)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-white{color:var(--color-white)}.text-zinc-200{color:var(--color-zinc-200)}.text-zinc-400{color:var(--color-zinc-400)}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\[0_24px_80px_-48px_rgba\(0\,0\,0\,\.9\)\]{--tw-shadow:0 24px 80px -48px var(--tw-shadow-color,#000000e6);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media (hover:hover){.hover\:bg-violet-400:hover{background-color:var(--color-violet-400)}.hover\:bg-white\/\[0\.05\]:hover{background-color:#ffffff0d}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/\[0\.05\]:hover{background-color:color-mix(in oklab, var(--color-white) 5%, transparent)}}.hover\:bg-white\/\[0\.07\]:hover{background-color:#ffffff12}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/\[0\.07\]:hover{background-color:color-mix(in oklab, var(--color-white) 7.0%, transparent)}}.hover\:text-white:hover{color:var(--color-white)}}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-violet-400:focus-visible{--tw-ring-color:var(--color-violet-400)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}.data-\[checked\]\:translate-x-5[data-checked]{--tw-translate-x:calc(var(--spacing) * 5);translate:var(--tw-translate-x) var(--tw-translate-y)}.data-\[checked\]\:bg-violet-500[data-checked]{background-color:var(--color-violet-500)}}:root{color:#f4f4f5;font-synthesis:none;text-rendering:optimizelegibility;background:#090b10;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}*{box-sizing:border-box}body{background:radial-gradient(circle at 75% -10%,#7c3aed1f,#0000 32rem),#090b10;min-width:320px;min-height:100vh;margin:0}button,input,select{font:inherit}button{cursor:pointer}.app-shell{grid-template-columns:230px minmax(0,1fr);min-height:100vh;display:grid}.sidebar{-webkit-backdrop-filter:blur(24px);backdrop-filter:blur(24px);z-index:10;background:#080a0fd1;border-right:1px solid #ffffff12;flex-direction:column;height:100vh;padding:26px 16px 20px;display:flex;position:sticky;top:0}.brand{align-items:center;gap:12px;padding:0 9px 28px;display:flex}.brand strong,.brand small{letter-spacing:.16em;display:block}.brand strong{font-size:13px}.brand small{color:#71717a;margin-top:3px;font-size:8px}.brand-mark{color:#fff;background:linear-gradient(145deg,#8b5cf6,#5b21b6);border-radius:10px;justify-content:center;align-items:end;gap:3px;width:32px;height:32px;padding:7px;display:flex;box-shadow:0 8px 28px #7c3aed47}.brand-mark span{background:currentColor;border-radius:2px;width:3px;display:block}.brand-mark span:first-child{opacity:.65;height:8px}.brand-mark span:nth-child(2){height:17px}.brand-mark span:nth-child(3){opacity:.8;height:12px}nav{gap:5px;display:grid}.nav-link{color:#8b8b95;border-radius:11px;align-items:center;gap:12px;height:43px;padding:0 12px;font-size:13px;font-weight:550;text-decoration:none;transition:all .18s;display:flex;position:relative}.nav-link:hover{color:#e4e4e7;background:#ffffff09}.nav-link.active{color:#fff;background:#8b5cf61f}.nav-link.active:before{content:"";background:#8b5cf6;border-radius:1px;width:2px;height:20px;position:absolute;left:-16px;box-shadow:0 0 14px #8b5cf6}.sidebar-foot{border-top:1px solid #ffffff12;margin-top:auto;padding:16px 11px 0}.local-chip{color:#a1a1aa;letter-spacing:.14em;text-transform:uppercase;align-items:center;gap:7px;font-size:10px;font-weight:700;display:flex}.project-name{color:#71717a;white-space:nowrap;text-overflow:ellipsis;margin-top:7px;font-size:11px;overflow:hidden}.status-dot{background:#34d399;border-radius:50%;flex:none;width:7px;height:7px;box-shadow:0 0 10px #34d399bf}.status-dot.off{box-shadow:none;background:#52525b}.main-panel{min-width:0}.topbar{border-bottom:1px solid #ffffff0f;justify-content:space-between;align-items:center;height:70px;padding:0 4vw;display:flex}.top-actions{align-items:center;gap:4px;display:flex}.eyebrow{color:#777783;letter-spacing:.17em;text-transform:uppercase;font-size:9px;font-weight:700;line-height:1.4}.topbar .eyebrow{white-space:nowrap;text-overflow:ellipsis;max-width:60vw;display:block;overflow:hidden}.content{max-width:1480px;margin:0 auto;padding:46px 4vw 80px}.page-intro{margin-bottom:32px}.page-intro h1{letter-spacing:-.04em;margin:8px 0;font-size:clamp(28px,3vw,44px);font-weight:650;line-height:1.08}.page-intro p{color:#8b8b95;max-width:640px;margin:0;font-size:14px;line-height:1.6}h2{letter-spacing:-.015em;margin:5px 0 0;font-size:16px}.metrics-grid{grid-template-columns:repeat(4,minmax(0,1fr));gap:13px;margin-bottom:14px;display:grid}.metric-card{grid-template-columns:1fr auto;align-items:center;min-height:158px;padding:20px;display:grid}.metric-card>span{color:#85858f;letter-spacing:.06em;text-transform:uppercase;font-size:11px;font-weight:650}.metric-card strong{letter-spacing:-.045em;grid-column:1/-1;font-size:clamp(25px,2.4vw,36px)}.metric-card small{color:#656570;grid-column:1/-1;font-size:10px}.metric-icon{color:#a78bfa;background:#8b5cf61a;border-radius:10px;place-items:center;width:34px;height:34px;display:grid}.dashboard-grid{grid-template-columns:minmax(0,2fr) minmax(260px,1fr);gap:14px;margin-bottom:14px;display:grid}.chart-card,.mcp-card,.list-card,.ranking-card,.settings-card{padding:22px}.card-heading{justify-content:space-between;align-items:start;margin-bottom:20px;display:flex}.updated{color:#5f5f69;font-size:10px}.chart-wrap{height:260px;margin:4px -4px -8px -16px;font-size:10px}.mcp-list{margin-top:20px;display:grid}.mcp-list>div{border-top:1px solid #ffffff0f;grid-template-columns:auto 1fr auto;align-items:center;gap:10px;min-height:50px;font-size:12px;display:grid}.mcp-list small{color:#656570;font-size:9px}.text-link{color:#a78bfa;font-size:11px;text-decoration:none}.recent-list>div{color:#a1a1aa;border-top:1px solid #ffffff0e;grid-template-columns:90px minmax(0,1fr) 100px 80px;align-items:center;gap:14px;min-height:56px;font-size:11px;display:grid}.recent-list strong,.recent-list small{display:block}.recent-list strong{color:#d4d4d8;font-size:11px;font-weight:550}.recent-list small{color:#5f5f69;margin-top:3px;font-size:9px}.agent-badge{color:#a78bfa;background:#8b5cf612;border:1px solid #8b5cf62e;border-radius:6px;justify-self:start;padding:4px 8px;font-size:9px}.empty-state{color:#666671;justify-content:center;align-items:center;gap:10px;min-height:180px;font-size:11px;display:flex}.table-card{overflow:hidden}.virtual-table{min-width:0}.table-head,.table-row{align-items:center;min-width:940px;display:flex}.table-head{color:#666671;letter-spacing:.11em;text-transform:uppercase;border-bottom:1px solid #ffffff14;height:46px;font-size:9px;font-weight:700}.table-head>div,.table-row>div{text-overflow:ellipsis;white-space:nowrap;flex:none;padding:0 14px;overflow:hidden}.table-scroll{height:min(65vh,650px);overflow:auto}.table-row{color:#b1b1ba;border-bottom:1px solid #ffffff0b;min-height:46px;font-size:10px;position:absolute;inset-inline:0}.table-row:hover{background:#ffffff06}.ranking-list>div{color:#898994;border-top:1px solid #ffffff0e;grid-template-columns:42px minmax(230px,1fr) 90px 100px 90px;align-items:center;gap:16px;min-height:65px;font-size:10px;display:grid}.ranking-list>div:first-child{border-top:0}.rank{color:#52525b;font-variant-numeric:tabular-nums}.rank-main strong{color:#d4d4d8;font-size:11px;font-weight:550}.usage-bar{background:#ffffff0d;border-radius:2px;width:100%;max-width:420px;height:2px;margin-top:10px;overflow:hidden}.usage-bar span{background:linear-gradient(90deg,#7c3aed,#22d3ee);height:100%;display:block}.settings-stack{gap:14px;display:grid}.setting-title{justify-content:space-between;align-items:start;gap:22px;margin-bottom:22px;display:flex}.setting-title h2,.inline-setting h2{margin:0 0 5px}.setting-title p,.inline-setting p{color:#73737e;margin:0;font-size:11px;line-height:1.5}.setting-title select{color:#d4d4d8;background:#151820;border:1px solid #ffffff1a;border-radius:9px;outline:none;min-width:120px;height:36px;padding:0 32px 0 12px}.budget-grid{grid-template-columns:repeat(4,1fr);gap:10px;display:grid}.budget-option{color:#9b9ba5;text-align:left;background:#ffffff05;border:1px solid #ffffff14;border-radius:12px;min-height:92px;padding:14px;transition:all .18s}.budget-option strong,.budget-option span{display:block}.budget-option strong{color:#d4d4d8;text-transform:uppercase;font-size:12px}.budget-option span{margin-top:7px;font-size:9px;line-height:1.4}.budget-option:hover,.budget-option.selected{background:#8b5cf614;border-color:#8b5cf673}.budget-option.selected strong{color:#c4b5fd}.agent-form-grid{grid-template-columns:repeat(2,1fr);gap:10px 14px;display:grid}.agent-form-grid label span{color:#767680;margin:0 0 5px 2px;font-size:9px;display:block}.agent-form-grid input{color:#e4e4e7;background:#ffffff06;border:1px solid #ffffff14;border-radius:10px;outline:none;width:100%;height:40px;padding:0 12px}.agent-form-grid input:focus{border-color:#8b5cf6a6;box-shadow:0 0 0 3px #8b5cf614}.inline-setting{justify-content:space-between;align-items:center;gap:24px;display:flex}.form-actions{color:#666671;justify-content:space-between;align-items:center;gap:16px;font-size:9px;display:flex}.form-actions>span{white-space:nowrap;text-overflow:ellipsis;max-width:65%;overflow:hidden}.loading,.error-state{color:#71717a;justify-content:center;align-items:center;gap:10px;min-height:55vh;font-size:11px;display:flex}.error-state{color:#f87171}.spin{animation:1s linear infinite spin}@keyframes spin{to{transform:rotate(360deg)}}html.light{color:#18181b;background:#f5f5f7}html.light body{background:radial-gradient(circle at 75% -10%,#7c3aed1a,#0000 32rem),#f5f5f7}html.light .sidebar{background:#f8f8fae0;border-color:#00000014}html.light .nav-link{color:#71717a}html.light .nav-link.active{color:#5b21b6}html.light section{background:#ffffffdb;border-color:#00000014}html.light .topbar{border-color:#00000012}html.light .page-intro p,html.light .setting-title p,html.light .inline-setting p{color:#71717a}html.light h1,html.light h2,html.light .metric-card strong,html.light .recent-list strong,html.light .rank-main strong{color:#18181b}html.light .table-row,html.light .recent-list>div,html.light .ranking-list>div,html.light .mcp-list>div{border-color:#0000000f}@media (width<=1000px){.metrics-grid{grid-template-columns:repeat(2,1fr)}.dashboard-grid{grid-template-columns:1fr}.budget-grid{grid-template-columns:repeat(2,1fr)}}@media (width<=720px){.app-shell{display:block}.sidebar{border:0;border-top:1px solid #ffffff14;width:100%;height:66px;padding:7px 10px;position:fixed;inset:auto 0 0}.brand,.sidebar-foot{display:none}.sidebar nav{justify-content:space-around;display:flex}.nav-link{flex-direction:column;justify-content:center;gap:2px;width:58px;height:50px;padding:0;font-size:8px}.nav-link.active:before{display:none}.topbar{height:58px;padding:0 18px}.content{padding:30px 16px 100px}.metrics-grid{grid-template-columns:1fr 1fr}.metric-card{min-height:135px;padding:16px}.recent-list>div{grid-template-columns:72px minmax(0,1fr) 70px}.recent-list>div>span:last-child{display:none}.agent-form-grid{grid-template-columns:1fr}.ranking-list>div{grid-template-columns:30px minmax(150px,1fr) 80px}.ranking-list>div>span:nth-last-child(-n+2){display:none}.form-actions{flex-direction:column;align-items:stretch}.form-actions>span{max-width:100%}.form-actions button{width:100%}}@media (width<=470px){.metrics-grid{grid-template-columns:1fr}.budget-grid{grid-template-columns:1fr 1fr}.page-intro h1{font-size:30px}.mcp-list small{display:none}.mcp-list>div{grid-template-columns:auto 1fr}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}
|