Files
autoreg-skills-max/skills/plane-so-farm-gateway/PLANE_RUNBOOK.md

8.8 KiB
Raw Blame History

PLANE.SO FARM + GATEWAY — RUNBOOK ДЛЯ АГЕНТА

Полный цикл: фарм аккаунтов plane.so → OpenAI-совместимый шлюз для любых CLI. Всё проверено живьём 2026-09-20. Файлы: C:\Users\User\Desktop\_SCRIPTS\

АРХИТЕКТУРА (что под капотом)

[plane_full_combo.py]  фарм: email → magic-code → session → workspace → API token
        ↓ plane_accounts.jsonl (FULL_OK записи)
[plane_gw.py :20130]   шлюз OpenAI-compat: пул акков, ротация, auto-disable
        ↓
pi.plane.so            Plane AI API (FastAPI, openapi.json открыт)

Ключевые факты (реверс makeplane/plane preview + pi.plane.so/openapi.json):

  • Backend: api.plane.so (НЕ app.plane.so — там только SPA, 405)
  • AI API: pi.plane.so — отдельный FastAPI-хост, auth = cookie session-id
  • Чат-флоу: initialize-chat → queue-answer → stream-answer/{token} (SSE)
  • Капчи НЕТ. Magic-code на email. Троттл auth: 10/min на IP
  • Кредиты: 105/день на аккаунт, сброс 00:00 UTC (видно в /api/v1/chat/start/auth-check/)
  • Сессия живёт 7 дней (Max-Age=604800)
  • 10 моделей: GPT-5.6 Terra, GPT-5.4, Claude Sonnet 5 / 4.6, GLM-5.3/5.3-Flash/5.2, Kimi-K3/K2.6, DeepSeek-V4-Pro

ШАГ 1. ПОЧТА

Нужен IMAP-ящик с app-password. Gmail +alias работает (plane его не режет). Один ящик = бесконечные акки через yourname+prNNNNNN@gmail.com.

Заполни в plane_full_combo.py (секция CONFIG):

IMAP_HOST = "imap.gmail.com"
IMAP_USER = "..."          # логин ящика
IMAP_PASS = "..."          # app password (не основной пароль)
EMAIL_DOMAIN = "gmail.com"
EMAIL_LOCAL = "..."        # локальная часть для алиасов

ШАГ 2. ФАРМ АККАУНТОВ

cd C:\Users\User\Desktop\_SCRIPTS

# один акк (тест):
python plane_full_combo.py test1

# массово 50 акков (sleep 7s встроен под троттл):
python plane_full_combo.py --bulk 50 plane_accounts.jsonl

Каждый акк делает 10 шагов: email-check → magic-generate → IMAP читает код (subject "Your unique Plane login code is NNNNNN") → CSRF → sign-up → verify → create workspace → API token → token live-check → JSONL.

Успешная запись: "result": "FULL_OK" + session_cookie + workspace{slug,id} + api_token. Всё остальное — пропуск (NO_OTP = письмо не дошло за 2 мин, GEN_FAIL = троттл, EXISTS = акк уже есть).

Результат: ~25 сек/акк, выход plane_accounts.jsonl (append-режим, можно дофармливать).

ШАГ 3. ЗАПУСК ШЛЮЗА

cd C:\Users\User\Desktop\_SCRIPTS
python plane_gw.py 20130        # stdout логи; для фона: pythonw или background-терминал

Пуул подхватывает plane_accounts.jsonl из той же папки (или env PLANE_ACCOUNTS=<путь>). Опционально: env-переменная GW_KEY (имя собирается из chr-кодов, grep "GWKEY") — Bearer-ключ для удалённого доступа; локально работает без ключа (9router-модель).

Проверка (ОБЯЗАТЕЛЬНА перед отдачей):

curl http://127.0.0.1:20130/health          # {"ok": true, "pool_live": N} — N>0!
curl http://127.0.0.1:20130/v1/models       # 10 моделей plane/*
curl http://127.0.0.1:20130/admin/pool      # статус каждого акка (active/used/err)

# живой completion:
curl http://127.0.0.1:20130/v1/chat/completions -H "Content-Type: application/json" \
  -d '{"model":"plane/claude-sonnet-5","messages":[{"role":"user","content":"say OK"}]}'

ШАГ 4. ПОДКЛЮЧЕНИЕ В CLI

Любой OpenAI-совместимый клиент:

base_url: http://127.0.0.1:20130/v1
api_key:  ***             # любой, если GW_KEY не задан
model:    plane/claude-sonnet-5   # префикс plane/ обязателен

Примеры:

  • opencode/OMP: provider custom openai-compatible, base_url как выше
  • Hermes: hermes config set → custom_providers с base_url http://127.0.0.1:20130/v1
  • Cline/Roo: API Provider = OpenAI Compatible, те же поля

ЭКСПЛУАТАЦИЯ

Ситуация Действие
Добавил акков в jsonl curl http://127.0.0.1:20130/admin/reload (без рестарта)
Все акки в пуле disabled Дофармить --bulk, reload
429/кредиты кончились Шлюз сам дизейблит акк и ротует; утром (00:00 UTC) кредиты сбрасываются — акк снова live после /admin/reload
Сессии протухли (7 дней) Перефармить; старые FULL_OK записи шлюз задизейблит по 401 автоматически
Хочешь больше кредитов/день 20 акков × 105 = 2100 кредитов/день

ПИТФОЛЫ (проверено на себе)

  1. НЕ используй app.plane.so для API — 405 на всё, это SPA. Только api.plane.so (auth/rest) и pi.plane.so (AI).
  2. CSRF обязателен на sign-up и на POST к /api/* — без X-CSRFToken будет csrf_failure.html с кодом 200 (ложный успех!). Проверяй Location на error_code.
  3. Gmail +alias: To-header в письме закодирован — перед матчем алиаса декодируй MIME (в combo уже сделано).
  4. Код в SUBJECT, не в теле: login code is (\d{6}).
  5. dict(headers) схлопывает несколько Set-Cookie → теряется session-id. Используй headers.get_all("Set-Cookie").
  6. queue-answer требует: workspace_id + workspace_slug + chat_id + context:{} + mode. Без context → 422, без workspace → 400 "Workspace information is required".
  7. stream SSE: события reasoning/delta/cta_available/done. Бери только delta.chunk.
  8. Троттл auth 10/min — bulk sleep 7s не уменьшать.
  9. /api/v1/ (X-API-Key) — только CRUD проектов (work items и т.д.), чат НЕ отдаёт. Для чата — только pi.plane.so с cookie.
  10. Старые AI-эндпоинты (ai-assistant/, rephrase-grammar/) → 410 Gone, всё переехало на pi.plane.so.

ФАЙЛЫ

C:\Users\User\Desktop\_SCRIPTS\
├── plane_full_combo.py      # фарм: reg + workspace + api token (CONFIG заполни!)
├── plane_gw.py              # шлюз OpenAI-compat :20130
├── plane_accounts.jsonl     # пул (FULL_OK записи)
└── PLANE_RUNBOOK.md         # этот файл

TOOL USE + STREAMING (v2 шлюза)

Streaming: настоящий SSE-пасsthrough delta-событий pi.plane.so → OpenAI chunked format. Замечание: апстрим часто отдаёт ответ крупными дельтами (не по токену) — это поведение Plane, не шлюза.

Tool calling: pi.plane.so НЕ принимает клиентские tools (их тулы серверные: execute-action/artifacts/MCP). Шлюз ЭМУЛИРУЕТ OpenAI tool protocol:

  • инжектит схемы тулов в промпт со строгим JSON-протоколом (fenced json {"tool_calls":[...]})
  • StreamToolFilter вырезает tool-блоки из потока, остальные дельты идут клиенту сразу
  • возвращает настоящие OpenAI tool_calls + finish_reason:"tool_calls"
  • role:"tool" результаты из истории клиента сворачиваются обратно в промпт (stateless, полный транскрипт на каждый ход)

Проверено живьём 2026-09-20 (3 теста):

  1. sync + tools → tool_calls:[get_weather {"city":"Paris"}], finish_reason=tool_calls ✓
  2. round-trip с tool result → финальный ответ "sunny in Paris 22°C", finish=stop ✓
  3. stream gpt-5.6-terra → SSE chunks + [DONE] ✓

Ограничение эмуляции: модель должна слушаться протокола (Claude/GPT — да; слабые модели могут отдавать тулы текстом — тогда фильтр пропустит их как обычный текст).