---
title: "proxym — naprawa voice.jsx: DSL→API zamiast LLM tłumaczący instrukcje"
date: 2026-03-22
status: draft
tags: [proxym, voice, dsl, action-schema, vscode-api, fix]
project: proxym
---

# Dlaczego "uruchom vscode" dawało instrukcję zamiast uruchamiać

## Problem

```
Użytkownik mówi: "uruchom vscode"
                      ↓
           DSL nie rozpoznaje frazy
                      ↓
    LLM dostaje pytanie BEZ narzędzi
                      ↓
  LLM odpowiada: "Aby uruchomić VSCode, wykonaj następujące kroki: 1. Otwórz terminal..."
```

Dwa błędy naraz:
1. **DSL nie miał reguły** dla "uruchom vscode"
2. **LLM był wywoływany bez `tools`** — nie mógł wykonać akcji nawet gdyby chciał

## Rozwiązanie — ACTION_SCHEMA + tool_calling

```
Użytkownik mówi: "uruchom vscode"
                      ↓
         ACTION_SCHEMA: /uruchom\s+vscode/i ✓
                      ↓
    POST /api/v1/vscode/start  (bez LLM!)
                      ↓
    "VS Code uruchomiony. http://localhost:8080"
    + window.open('http://localhost:8080')
```

Jeśli DSL nie rozpoznaje → LLM z `tool_choice: 'auto'` i pełnym `TOOL_SCHEMA`:

```
Użytkownik: "mam dzisiaj za mało środków — otwórz coś tańszego"
                      ↓
    DSL: brak dopasowania
                      ↓
    LLM (z narzędziami) → wywołuje get_costs()
                      ↓
    "Dziś: $0.024. Polecam tryb 'free' (Gemini) dla tańszych zapytań."
```

---

## Nowa architektura voice.jsx

### 1. ACTION_SCHEMA — 15 reguł → API

Każda reguła: `{ patterns[], action, label, success, then? }`:

```javascript
{
  patterns: [/uruchom\s+vscode/i, /start\s+vscode/i, /włącz\s+vscode/i],
  action: { method: 'POST', path: '/api/v1/vscode/start' },
  label: 'Uruchamiam VS Code Web…',
  success: (d) => `VS Code uruchomiony. ${d.url}`,
  then: (d) => { if (d.url) window.open(d.url, '_blank'); },
}
```

Pełna lista reguł:

| Fraza | API call | Efekt |
|-------|----------|-------|
| `uruchom vscode` | POST /api/v1/vscode/start | otwiera w nowej karcie |
| `zatrzymaj vscode` | POST /api/v1/vscode/stop | — |
| `status vscode` | GET /api/v1/vscode/status | info o porcie |
| `pokaż VM-y` | GET /api/v1/vms | lista VM-ów |
| `uruchom vm windsurf-work` | POST /api/v1/vms/windsurf-work/start | start VM |
| `zatrzymaj vm windsurf-work` | POST /api/v1/vms/windsurf-work/stop | stop VM |
| `snapshot windsurf-work` | POST /api/v1/vms/windsurf-work/snapshot | backup |
| `ile wydałem` | GET /api/v1/dashboard/costs/summary | koszty |
| `status` | GET /health | health check |
| `logi` | GET /api/v1/logs?level=error | błędy |
| `jakie modele` | GET /v1/models | lista modeli |
| `test routing` | GET /api/v1/routing/test | test providerów |
| `pokaż konta` | GET /api/v1/accounts | lista kont |

### 2. TOOL_SCHEMA dla LLM

Gdy fraza nie pasuje do DSL, LLM dostaje narzędzia i może je wywołać:

```javascript
const TOOL_SCHEMA = [
  { type: 'function', function: { name: 'vscode_start', ... } },
  { type: 'function', function: { name: 'vm_action', ... } },
  { type: 'function', function: { name: 'get_costs', ... } },
  { type: 'function', function: { name: 'get_status', ... } },
  { type: 'function', function: { name: 'get_logs', ... } },
];
```

System prompt wymusza akcje zamiast opisów:

```javascript
'ZAWSZE używaj dostępnych narzędzi zamiast opisywać jak coś zrobić. ' +
'Gdy użytkownik pyta o status, koszty, VM-y lub VS Code — wywołaj odpowiednie narzędzie. ' +
'Odpowiadaj maksymalnie 1–2 zdaniami.'
```

### 3. Chipsy podpowiedzi

Klikalne przyciski z gotowymi komendami — ułatwia discovery:

```
[uruchom vscode] [status vscode] [pokaż VM-y] [ile wydałem] [logi] [test routing]
```

---

## Nowe endpointy — `vscode_api.py`

Brakujące endpoints wymagane przez voice.jsx:

```
GET  /api/v1/vscode/status  → { running, port, url }
POST /api/v1/vscode/start   → { running, url, message }
POST /api/v1/vscode/stop    → { stopped, message }
POST /api/v1/vscode/restart → { running, url }
GET  /api/v1/vscode/logs    → { lines: [...] }
POST /api/v1/vscode/build   → { building }
```

Rejestracja w `main.py`:

```python
from proxym.api.vscode_api import router as vscode_router
from proxym.api.console import router as console_router

app.include_router(vscode_router)
app.include_router(console_router)
```

---

## Jak wdrożyć

```bash
# 1. Zastąp stary voice.jsx
cp voice_fixed.jsx src/proxym/dashboard/components/voice.jsx

# 2. Dodaj nowe endpointy
cp vscode_api.py src/proxym/api/vscode_api.py

# 3. Zarejestruj w main.py
# Dodaj: from proxym.api.vscode_api import router as vscode_router
#        app.include_router(vscode_router)

# 4. Dodaj endpoint serwowania w frontend.py
# @router.get("/dashboard/voice.jsx")
# async def dashboard_voice_jsx():
#     return _serve_file([...voice.jsx...], media_type="application/javascript")

# 5. Dodaj tab Voice w panel.jsx
# tab === 'voice' && h(VoiceChat, { proxymBase: API, apiKey: KEY })

# 6. Restart
make restart
```

---

## Dalsze kroki refaktoryzacji kodu

### Faza A — Porządki (priorytet: KRYTYCZNY)

```bash
# 1. Przenieś testy z src/
mv src/proxym/api/tests.py tests/test_api_integration.py

# 2. Przenieś TODO/ do właściwych miejsc
mv TODO/test_vscode_gui.py tests/gui/test_gui_vscode_full.py
mv TODO/conftest.py tests/vscode/conftest.py  # lub usuń jeśli duplikat
rmdir TODO/

# 3. .toonignore
cat > .toonignore << 'EOF'
htmlcov/
services/vscode/
project/examples/
TODO/
*.min.js
EOF
```

### Faza B — Frontend CC (diagnostics.jsx, vms.jsx, logs.jsx)

```
diagnostics.jsx CC=29 → split na DiagRooConfig, DiagExtensions, DiagProxymStatus
vms.jsx         CC=19 → _compareByState/Name/Size + dispatch table
logs.jsx        CC=21 → useLogFilter hook + LogRow komponent
```

### Metryki po Fazie A

```
god-modules: 3 → 0  (api/tests.py + TODO/ zostaną usunięte)
CC̄: 3.4 → ~2.8
max-CC: 29 → ≤ 10
```
