docs: update proxy to 194.87.245.138:8889, add sync-creds note

This commit is contained in:
aedes
2026-04-23 06:52:13 +03:00
parent 18c758e52d
commit 50fe5f4621

125
CLAUDE.md
View File

@@ -1,42 +1,121 @@
# sechenov — Claude Chat
# sechenov — Claude Chat + Stealth Portal + OpenAI-compat Endpoint
Express-сервер, совмещающий три роли:
1. **Stealth чат** для студента на клоне портала Сеченовки (`https://s.akyra.ru/`, `https://student.sechen0v.ru/`, `https://dl.sechen0v.ru/`)
2. **OpenAI-совместимый endpoint** `/v1/chat/completions` для Chrome-расширения `ext/` (Moodle AI Solver)
3. **Мост Anthropic** через Claude Max OAuth с авто-рефрешем токена, HTTP-прокси на VPS и fallback Opus→Sonnet→Haiku
## Stack
- Node.js + Express (server.js)
- Claude CLI (`@anthropic-ai/claude-code`) spawned via `claude -p`
- Proxy: HTTP прокси на VPS (194.87.245.138:8888) для обхода блокировок
- Node.js + Express
- Anthropic API напрямую (`https://api.anthropic.com/v1/messages`) через Claude Max OAuth (`.credentials.json`)
- undici `ProxyAgent` (Anthropic-only routing через VPS HTTP-прокси; остальной трафик — direct)
- Playwright (`mcr.microsoft.com/playwright:v1.59.1-noble`) для снапшотов quiz-страниц в `/q`
- Caddy reverse proxy на Debian В
## Structure
```
sechenov/
├── server.js — Express API + SSE стриминг
├── server.js — всё: /api/chat, /api/notify, /v1/chat/completions, /q, /auth.php, OAuth refresh
├── public/
── index.html — Chat UI (две панели: запрос / ответ)
── index.html — stealth portal + скрытый чат
│ ├── q/index.html — Playwright-снятый клон quiz-страницы со слотами чата
│ └── assets/... — зеркало статики с оригинала
├── scripts/
│ └── mirror.js — Playwright fullPage screenshot + инжект чат-слотов
└── package.json
```
## Models
- Sonnet 4.6 (`claude-sonnet-4-6`)
- Haiku 4.5 (`claude-haiku-4-5-20251001`)
```js
MODELS = {
opus: 'claude-opus-4-7',
sonnet: 'claude-sonnet-4-6',
haiku: 'claude-haiku-4-5-20251001'
}
THINKING_MODELS = new Set(['claude-opus-4-7'])
THINKING_BUDGET_TOKENS = 16000
```
- `/api/chat` — default `opus`, fallback на Haiku при 429
- `/v1/chat/completions` — принимает OpenAI-совместимый payload, mapping модели по substring, конвертирует `image_url` → Anthropic `image/base64`
## Auth
- `.credentials.json` скопирован с машины Б в `/opt/stack/autoclaude-config/acc1/`
- Монтируется в контейнер как `/root/.claude`
- При смене аккаунта: `scp ~/.claude/.credentials.json aedes@192.168.1.20:/opt/stack/autoclaude-config/acc1/`
## Endpoints
| Путь | Назначение |
|---|---|
| `/` | `public/index.html` (stealth portal) |
| `/q`, `/q.html`, `/mod/quiz/attempt.php` | `public/q/index.html` (клон quiz) |
| `/auth.php` | `public/index.html` |
| `/api/chat` | SSE-стрим ответа Claude (используется скрытым чатом) |
| `/api/notify` | POST → Telegram (через fresh ProxyAgent) |
| `/v1/chat/completions` | OpenAI-compat endpoint для расширения `ext/` |
## Stealth UI (`public/index.html`)
- Live clock: синяя дата `<span>` + время `<em>`
- `#quiz-redirect-btn` «Получить пароль» → `window.location.href = 'https://dl.sechen0v.ru/mod/quiz/attempt.php?attempt=6060166&cmid=192893'`
- `#tg-notify-btn` «Авторизация» → POST `/api/notify`
- Скрытый чат: `#chat-input` (прозрачная textarea, `color:#f2f2f2`), `#chat-output-tiny` под синей полосой
- Paste handler: собирает все картинки + текст из одного clipboard-события в один запрос
## /q Playwright mirror (`scripts/mirror.js`)
- Запуск в docker: `mcr.microsoft.com/playwright:v1.59.1-noble` + `npm install playwright@1.59.1 --no-save`
- Viewport 1600×900, deviceScaleFactor 2, `fullPage: true`
- Инжект `.que + .que { margin-top: 180px !important }` для гэпа под чат
- `N-1` слотов чата между вопросами как абсолютные `top: X%` (percentage — стабильно при zoom)
- Wrapper: `zoom: 1.12`, `<title>Экзаменационный билет (ЦТ)</title>`, favicon `/assets/images/favicon.png`
- 5-секундный debounce на paste с countdown «через Xс (N img)»
- `urlToSafePath(url, contentType)`: md5 на query >80 символов, добавляет `.css/.js/.png` по Content-Type
## OAuth (Claude Max)
- Credentials: `/opt/stack/sechenov-config/.credentials.json` (изолированы от mps/autoclaude — раньше шаринг с mps acc3 вызывал `invalid_grant`)
- Монтируются в контейнер как `/root/.claude`
- `ensureFreshToken()`: `REFRESH_SKEW_MS = 5*60*1000`, atomic `writeCreds()`, сериализация через `refreshInFlight` promise
- Смена аккаунта: `scp ~/.claude/.credentials.json aedes@192.168.1.20:/opt/stack/sechenov-config/`
## VPS Proxy (IPv4-only HTTP)
- VPS: **194.87.245.138:8889** (актуальный), скрипт `/opt/claude-proxy-8889.py`, systemd `claude-proxy.service`
- Патч: `ipv4_connect()` через `getaddrinfo(..., AF_INET)` — без него Telegram/Anthropic резолвились в IPv6 и падали
- Env контейнера: `HTTPS_PROXY=http://194.87.245.138:8889``/opt/stack/docker-compose.yml`)
- В коде: `anthropicAgent = new ProxyAgent(proxyUrl)` применяется только к запросам на Anthropic. Глобально — `directAgent`.
- **TG notify:** создаётся свежий `ProxyAgent` per-call (переиспользование вело к stale TLS / `fetch failed`)
- ⚠️ `89.125.243.153` — другой сервер (без SSH-доступа), не использовать
## Telegram notify
```js
TG_BOT_TOKEN = '8489078585:AAH3PrYNBiX-YMZA9XgHT2rE6yaK8BqwCOI'
TG_CHAT_ID = '833411630'
TG_MESSAGE = 'начинай решать через 5 мин'
```
Fresh ProxyAgent per call → `api.telegram.org/bot<token>/sendMessage`.
## Chrome Extension integration (`../ext/`)
- `OR_URL = 'https://s.akyra.ru/v1/chat/completions'`
- `DEFAULT_MODEL = 'opus'`, `FALLBACK_MODELS = ['sonnet', 'haiku']`
- `DEFAULT_KEY = 'sechenov-local'` (сервер принимает любой bearer)
- Расширение маскируется под uBlock Origin, активация Alt+w на quiz-странице
## Local (machine B)
- Path: C:\Users\aedes\REUNION\sync\scriptsAedes\sechenov
- Path: `C:\Users\aedes\REUNION\sync\scriptsAedes\sechenov`
## Remote (Debian V)
- Path: /opt/stack/sechenov/
- URL: https://s.akyra.ru
## Remote (Debian В)
- Path: `/opt/stack/sechenov/`
- URL: `https://s.akyra.ru` + алиасы `student.sechen0v.ru`, `dl.sechen0v.ru`
- Port: 8108
- Deploy: git push -> ssh aedes@192.168.1.20 "cd /opt/stack/sechenov && git pull && docker compose restart sechenov"
- Caddy: блоки для всех трёх доменов → `127.0.0.1:8108`, Let's Encrypt автоматически
- DNS (Beget, `login=fezarms2`): A-записи `student.sechen0v.ru`, `dl.sechen0v.ru``94.141.253.12`
- Deploy:
```bash
git push
ssh aedes@192.168.1.20 "cd /opt/stack/sechenov && git pull && docker compose restart sechenov"
```
## VPS Proxy (claude-proxy.service)
- Сервис: `/etc/systemd/system/claude-proxy.service` на VPS 194.87.245.138
- Скрипт: `/opt/claude-proxy.py`
- Порт: 8888
- Env в контейнере: `HTTPS_PROXY=http://194.87.245.138:8888`
## Известные грабли
- **invalid_grant** если шарить `.credentials.json` с mps/autoclaude — держать изолированно в `sechenov-config/`. Авторефреш через `scripts/sync-creds.ps1` (Windows Task Scheduler, смотрит `~/.claude/.credentials.json`)
- **TG 502** → IPv6 в proxy; фикс — `AF_INET` в `/opt/claude-proxy.py`
- **TG fetch failed** на reused ProxyAgent → fresh per-call
- **ENAMETOOLONG** при сохранении snapshot → md5 query в `urlToSafePath`
- **CSS/JS без расширения игнорятся браузером** → append extension по Content-Type
- **Playwright image mismatch** → строго `v1.59.1-noble` + `playwright@1.59.1`
- **Sechenov banned IP** при полном reverse-proxy — отказались, только локальный клон + /q snapshot
- **docker-compose.yml sed** легко задевает mps/autoclaude mounts — править вручную
## Update this file
After any changes to structure, stack or configs - update this CLAUDE.md.
После изменений в структуре, стеке, конфигах или инфре — обновить этот CLAUDE.md.