<div align="center">

# viktor-valency

**OpenAI-совместимый мост к ИИ-агенту Viktor для OpenCode.**
**Управление через TUI на Bubble Tea + Lip Gloss. Никаких браузерных дашбордов.**

`by Valency Labs`

[![npm](https://img.shields.io/npm/v/valency-viktor.svg?label=npm&color=7B5BFF)](https://www.npmjs.com/package/valency-viktor)
[![License: MIT](https://img.shields.io/badge/license-MIT-7B5BFF.svg)](LICENSE)

</div>

---

## Что это

`viktor-valency` — это локальный мост между **OpenCode** (или любым клиентом, говорящим OpenAI API) и AI-агентом **Viktor**, который живёт в Slack как бот. Мост сам:

- общается с Viktor через хайджек браузерной сессии (xoxc-токен + cookie `d`, без Slack-приложения),
- выглядит для OpenCode как обычный OpenAI-провайдер `viktor`,
- держит **несколько аккаунтов Viktor** с авто-failover по балансу кредитов,
- синхронизирует **открытую папку OpenCode ↔ приватный GitHub-репозиторий** (Viktor пушит — мост подтягивает),
- скачивает локально картинки/видео, которые Viktor генерирует в Slack,
- даёт нативный TUI для управления — без HTTP-дашбордов, без браузера, без зависимостей в браузере.

```
[OpenCode] ──┐                              ┌──► Slack DM с Viktor ──► GitHub
             ├──► viktor-valency proxy ─────┤
[Telegram*]──┘     (FastAPI :8799)          └──► api.viktor.com (статус, кредиты, модель)

           ↑
           └── valencyviktor (TUI на Bubble Tea + Lip Gloss)
```

\* Telegram-бот пока не входит в v0.1.0 — вернётся в одной из следующих версий.

## Установка

### Через npm (рекомендуется)

```bash
npm install -g valency-viktor
```

`postinstall` сам подтянет:
- предсобранный TUI-бинарь под твою платформу (Windows / macOS / Linux, x64 + arm64),
- проверит наличие Python 3.10+,
- создаст `.venv` и поставит зависимости прокси.

После установки — одна команда:

```bash
valencyviktor
```

Она поднимет прокси фоном, дождётся `/health` и откроет TUI.

### Из исходников

```bash
git clone https://github.com/svlktv/viktor-valency.git
cd viktor-valency
make venv     # python venv + requirements
make tui      # собрать TUI (нужен Go 1.22+)
make tui-run  # запустить (TUI сам поднимет прокси)
```

## Что нужно от тебя

| Что | Где взять |
|---|---|
| **Slack xoxc-токен** | DevTools на `app.slack.com` → Network → любой запрос к `app.slack.com/api/...` → Payload → поле `token` (начинается с `xoxc-`) |
| **Slack cookie `d`** | DevTools → Application → Cookies → `slack.com` → значение `d` (начинается с `xoxd-`) |
| **`SLACK_TEAM_ID`** | часть `T...` из URL Slack: `app.slack.com/client/T.../...` |
| **JWT к `api.viktor.com`** | DevTools → Network → любой запрос к `api.viktor.com` → Headers → `Authorization: Bearer <JWT>` |
| **GitHub CLI (`gh`)** | установлен и авторизован: `gh auth login` |

DM с Viktor (`D...`) и user_id бота (`U...`) **искать вручную не надо** — кнопка «Детект» в TUI сама их найдёт по Slack-токену.

## TUI: как он выглядит

```
◆ viktor-valency  ·  by Valency Labs

  ██╗   ██╗██╗██╗  ██╗████████╗ ██████╗ ██████╗
  ██║   ██║██║██║ ██╔╝╚══██╔══╝██╔═══██╗██╔══██╗
  ██║   ██║██║█████╔╝    ██║   ██║   ██║██████╔╝
  ╚██╗ ██╔╝██║██╔═██╗    ██║   ██║   ██║██╔══██╗
   ╚████╔╝ ██║██║  ██╗   ██║   ╚██████╔╝██║  ██║
    ╚═══╝  ╚═╝╚═╝  ╚═╝   ╚═╝    ╚═════╝ ╚═╝  ╚═╝
                  by Valency Labs · OpenCode bridge

  ╭─────────────────────────────────────────────────╮
  │ ✓ Прокси на связи                               │
  │   Аккаунтов: 3 (включено: 3, исчерпано: 0)      │
  │   Режим: auto (failover по кредитам)            │
  │   Активный: work-main                           │
  │   Сумма кредитов (по 3 с JWT): 12 480           │
  ╰─────────────────────────────────────────────────╯

  ▶ Аккаунты Viktor       просмотр / редактирование / удаление
    Добавить аккаунт      ввести Slack-креды + JWT, авто-детект
    Справка               хоткеи и где брать креды
    Выход                 закрыть TUI (прокси останется в фоне)

 proxy: http://127.0.0.1:8799 · режим: auto      ?: помощь · esc: назад · q: выход
```

### Хоткеи

| Клавиша | Действие |
|---|---|
| `r` | обновить состояние из прокси |
| `a` | добавить аккаунт |
| `e` | редактировать выбранный |
| `d` | удалить выбранный |
| `space` | сделать активным (manual mode) |
| `m` | переключить auto / manual |
| `M` | выбор модели и reasoning |
| `?` | справка |
| `esc` | назад / закрыть форму |
| `q` | выход |

Закрытие TUI **не останавливает прокси** — он живёт в фоне, OpenCode продолжает работать.

## Подключение в OpenCode

В `~/.config/opencode/opencode.json` (Windows: `%USERPROFILE%\.config\opencode\opencode.json`):

```json
{
  "provider": {
    "viktor": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Viktor (через viktor-valency)",
      "options": {
        "baseURL": "http://127.0.0.1:8799/v1",
        "apiKey": "viktor"
      },
      "models": { "viktor": { "name": "Viktor" } }
    }
  }
}
```

Затем в OpenCode выбери модель **`viktor/viktor`** — мост сам определит открытую папку и заведёт под неё приватный репозиторий.

## Что прокси делает на каждый запрос

1. **Определяет папку проекта** — из заголовка `X-Project-Path`, или парсит из системного промпта OpenCode, или берёт `LOCAL_REPO_PATH` из `.env`.
2. **Выбирает аккаунт Viktor** — `auto` режим крутит список по кругу до первого с балансом > `ACCOUNT_MIN_CREDITS`; `manual` — строго выбранный.
3. **Sync вверх** — `gh repo create --private`, добавляет remote `viktor`, коммитит локальные изменения, делает `pull --ff-only` → fallback на merge `-X ours` → `--allow-unrelated-histories`. Создаёт ветку `viktor/{session_id}` для изоляции.
4. **Шлёт задачу Viktor'у** — top-level в Slack DM, с обёрткой «Работай в репо X, ветка Y, только пушь».
5. **Ждёт ответ** — главный сигнал из `api.viktor.com/api/flow/tasks` (`running` → `idle`); фолбэк на текстовые эвристики если JWT недоступен. Стримит каждое сообщение Viktor'а в OpenCode как SSE-чанк, плюс `:ping` каждые 10с.
6. **Reasoning** — для Claude нативно (через Viktor API), для GPT/Kimi/Gemini инжектит `<thinking_mode>` теги.
7. **Скачивает медиа** — картинки/видео Viktor'а локально в `viktor_media/`, конвертирует webp → png. Папка добавляется в `.git/info/exclude` — не пушится.
8. **Sync вниз** — `git pull` в локальную папку через нативный tool-вопрос OpenCode (Да / Нет / Всегда / Никогда). Управление в чате: `/nopull` `/pullask` `/pullauto`.
9. **Возвращается на main** с подсказкой `git merge viktor/{session_id}`.

Если ходов в сессии больше `SESSION_MAX_TURNS` — авто-компакт: мост берёт у Viktor'а handoff-summary и стартует новый тред.

## Авто-обновление токена

Slack `xoxc` и cookie `d` тухнут со временем. Мост держит постоянный профиль Playwright (`.slack_profile`), при ошибке `invalid_auth` запускает рефрешер, снимает свежие creds в `creds.json` и повторяет запрос. Плюс профилактический рефреш раз в `SLACK_REFRESH_HOURS` (по умолчанию 6 ч).

Первый запуск засевает профиль кукой `d` из `.env`, ручной вход обычно не нужен. Если профиль разлогинится:

```bash
.venv/Scripts/python.exe -m viktor_valency.refresh_creds --login
```

## Несколько аккаунтов и failover

Все аккаунты заводятся в TUI. Каждый = свой Slack-DM с Viktor + свой JWT + свой выбор модели/reasoning.

**Режимы:**
- **Auto** — берётся первый с балансом > `ACCOUNT_MIN_CREDITS` (500), при исчерпании — на следующий.
- **Manual** — строго выбранный аккаунт, без авто-переключения. Удобно держать отдельный аккаунт под конкретный репозиторий.

Смена аккаунта = другой Viktor без памяти прежнего диалога → стартует чистая сессия с пометкой `🔁 переключился на X` в чате.

## Состав

```
viktor_valency/
  openai_proxy.py      OpenAI-совместимый прокси (FastAPI :8799)
  accounts.py          мульти-аккаунт + failover по кредитам
  slack_connector.py   xoxc + cookie d → пост/чтение Slack DM
  refresh_creds.py     авто-обновление токена через Playwright
  viktor_api.py        клиент к api.viktor.com (статус, кредиты, модели)
  git_sync.py          синхронизация папка ↔ GitHub
  sessions.py          сессии и авто-компакт
  config.py            настройки из .env
  creds.py             хранилище актуальных Slack-creds

tui/                   TUI на Bubble Tea + Lip Gloss (Go)
  cmd/viktor-tui/      бинарник
  internal/ui/         экраны: меню, аккаунты, редактор, модели, справка
  internal/api/        REST-клиент к прокси

scripts/
  install.js           postinstall: бинарь TUI + venv + requirements
  launch.js            bin valencyviktor → запуск TUI

bin/release/           прекомпилированные бинарники под все платформы
```

## API прокси (для интеграций)

Прокси отдаёт REST на `http://127.0.0.1:8799`:

| Метод | Путь | Что |
|---|---|---|
| POST | `/v1/chat/completions` | OpenAI-совместимый endpoint для OpenCode |
| GET | `/v1/models` | список моделей (`viktor` + модель активного аккаунта) |
| GET | `/health` | проверка живости |
| GET | `/api/accounts` | список аккаунтов + балансы |
| POST | `/api/accounts` | upsert/rename |
| POST | `/api/accounts/mode` | переключение auto/manual |
| POST | `/api/accounts/detect` | авто-детект DM/user/email/баланса |
| POST | `/api/accounts/remove` | удалить |
| POST | `/api/accounts/activate` | сделать активным |
| GET | `/api/models/list?name=` | модели + текущие настройки |
| POST | `/api/models/set` | модель + reasoning level |

TUI использует только эти endpoints — никакого скрытого протокола.

## Конфигурация

Все ключи в `.env.example`. Минимум для работы — пустой `.env` и заведение первого аккаунта в TUI. Подробности — в комментариях `.env.example`.

## Лицензия

[MIT](LICENSE) © 2026 Valency Labs.

---

<div align="center">

`by Valency Labs`

</div>
