docs: update proxy to 194.87.245.138:8889, add sync-creds note
This commit is contained in:
125
CLAUDE.md
125
CLAUDE.md
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user