encx-cli

module
v0.18.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 16, 2026 License: Apache-2.0

README

encx-cli

GitHub stars Last commit License Ask DeepWiki Download binaries

encx-cli — это Go-клиент и CLI для API движка городских квестов Encounter (en.cx).

Если короче: здесь есть и библиотека для встраивания в свой код, и консольная утилита, которой можно быстро залогиниться, посмотреть игру, прочитать задания и отправить код без браузера.

  • Модуль: github.com/skrashevich/encx-cli
  • CLI: cmd/encli
  • Пакет-библиотека: encx
  • Тестовый домен для примеров и интеграционных тестов: tech.en.cx
Скриншоты

Общий вид: боковая панель с историей чатов, выбор домена и игры, авторизация, поле ввода и режим агента (только чтение / с согласованием / полный доступ). В левом верхнем углу — текущая LLM-модель.

Общий вид Web UI encli

Чат с агентом: запрос на естественном языке и пошаговые вызовы инструментов (admin API, чтение уровней и т.д.).

Чат с агентом и логом инструментов

Тёмная тема (переключатель ◐ в верхней панели).

Web UI encli в тёмной теме

Что внутри

Проект пригодится в двух сценариях:

  • хотите написать свой тулинг поверх Encounter API — берите пакет encx;
  • хотите просто работать из терминала — ставьте encli.

Инструменты движка для ИИ-агентов

Пакет agenttools превращает движок Encounter в каталог инструментов для LLM-агента, а agentmcp отдаёт этот каталог наружу по MCP:

encli mcp -domain tech.en.cx                     # только чтение (по умолчанию)
encli mcp -domain tech.en.cx -security approve   # мутации подтверждаются клиентом

Тот же каталог встроен в Encx.xcframework как агент PicoClaw (MIT) — см. EncClient.NewAgentSession в mobile/encxmobile. Каталог, политики доступа (readonly / approve / full) и конфигурация внешнего PicoClaw описаны в docs/agent-tools.md.

encli --llm и encli -web также работают на runtime и HTTP-провайдере PicoClaw. Их расширенный CLI-каталог (админские команды, локальные файлы и Wikipedia) подключён к tools.ToolRegistry через адаптер совместимости.

Установка

Готовые бинарники

Подписанные и нотаризованные бинарники для macOS, Linux и Windows доступны на странице Releases. macOS-бинарники подписаны сертификатом Developer ID и прошли нотаризацию Apple — Gatekeeper не покажет предупреждение о недоверенном разработчике.

CLI
go install github.com/skrashevich/encx-cli/cmd/encli@latest
go install github.com/skrashevich/encx-cli/cmd/encx-mock@latest
Mock-сервер

Для локальной разработки и ручной проверки CLI в репозитории есть encx-mock — небольшой HTTP-сервер, который имитирует домен Encounter без похода в реальный tech.en.cx.

Скрипты VHS: docs/vhs/. GIF генерируются в CI и публикуются на GitHub Pages.

# запустить mock-сервер на 0.0.0.0:18080
encx-mock

# или публичный demo (HTTPS, без локального сервера)
encli login -domain encounter.exe.xyz -login demo -password demo
encli game-list -domain encounter.exe.xyz

# или через Docker
docker run --rm -p 18080:18080 -e ENCX_MOCK_ADDR=0.0.0.0:18080 ghcr.io/skrashevich/encx-mock

# подключиться к нему через encli
encli login -domain 127.0.0.1:18080 -http -login demo -password demo
encli game-list -domain 127.0.0.1:18080 -http
encli status -domain 127.0.0.1:18080 -http -game-id 424242
encli send-code -domain 127.0.0.1:18080 -http -game-id 424242 "CODE-1"

Особенности mock-сервера:

  • слушает адрес из ENCX_MOCK_ADDR или 0.0.0.0:18080 по умолчанию;
  • принимает любой логин/пароль, кроме fail:fail;
  • поднимает тестовую игру 424242 с тремя уровнями и кодами секторов 112;
  • умеет загружать экспорт Game scenario.html через -scenario или ENCX_MOCK_SCENARIO;
  • умеет через ENCX_MOCK_HAR потоково извлекать из всего HAR только очищенные формы и варианты протокольных ответов; raw HAR, cookies, ответы, идентификаторы и игровой контент в репозиторий не добавляются;
  • код PZDC включает минутную "потерю сети" для текущей пары логин/пароль, чтобы проверять retry/timeout-логику клиента.

Подробное описание режимов, кодов и ограничений: cmd/encx-mock/README.md.

Docker
docker run --rm ghcr.io/skrashevich/encx-cli -v
docker run --rm ghcr.io/skrashevich/encx-cli games -domain tech.en.cx
docker run --rm -p 18080:18080 -e ENCX_MOCK_ADDR=0.0.0.0:18080 ghcr.io/skrashevich/encx-mock

# LLM-режим: передайте ключ и модель через -e
docker run --rm \
  -e ENCX_LOGIN=user -e ENCX_PASSWORD=secret -e ENCX_GAME_ID=12345 \
  -e LLM_API_KEY=sk-or-v1-... \
  -e LLM_MODEL=anthropic/claude-sonnet-4 \
  ghcr.io/skrashevich/encx-cli -game-id 12345 --llm "покажи уровни"
Библиотека
go get github.com/skrashevich/encx-cli/encx

Использование библиотеки

Ниже минимальный пример: логинимся, смотрим список игр, читаем состояние и пробуем отправить код.

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/skrashevich/encx-cli/encx"
)

func main() {
	client := encx.New("tech.en.cx", encx.WithInsecureTLS())
	ctx := context.Background()

	resp, err := client.Login(ctx, "user", "password")
	if err != nil {
		log.Fatal(err)
	}
	if resp.Error != 0 {
		log.Fatalf("Login error %d: %s", resp.Error, encx.LoginErrorText(resp.Error))
	}

	// Список игр
	list, _ := client.GetGameList(ctx)
	for _, g := range list.ActiveGames {
		fmt.Printf("%d: %s\n", g.GameID, g.Title)
	}

	// Состояние игры
	model, _ := client.GetGameModel(ctx, 12345)
	if model.Level != nil {
		fmt.Printf("Уровень %d: %s\n", model.Level.Number, model.Level.Name)
	}

	// Отправка кода
	result, _ := client.SendCode(ctx, 12345, model.Level.LevelId, model.Level.Number, "КОД123")
	if result.EngineAction != nil && result.EngineAction.LevelAction != nil &&
		result.EngineAction.LevelAction.IsCorrectAnswer != nil &&
		*result.EngineAction.LevelAction.IsCorrectAnswer {
		fmt.Println("Верный код!")
	}

	// Список игр с пагинацией
	page2, _ := client.GetGameList(ctx, 2)
	for _, g := range page2.ComingGames {
		fmt.Printf("%d: %s (levels: %d)\n", g.GameID, g.Title, g.LevelNumber)
	}

	// Статистика игры
	stats, _ := client.GetGameStatistics(ctx, 12345)
	if stats.Game != nil {
		fmt.Printf("Игра: %s, Уровней: %d\n", stats.Game.Title, len(stats.Levels))
		for _, l := range stats.Levels {
			fmt.Printf("  Уровень %d: %s\n", l.LevelNumber, l.LevelName)
		}
	}
}
Опции клиента

Можно подкрутить поведение клиента через опции:

Опция Описание
WithInsecureTLS() Пропустить проверку TLS-сертификата
WithHTTP() Использовать HTTP вместо HTTPS
WithTimeout(d) Установить таймаут HTTP-клиента
WithUserAgent(ua) Установить User-Agent
WithLang(lang) Язык запросов (по умолчанию: ru)
WithEngine(mode) Движок Encounter: EngineAuto (по умолчанию), EngineLegacy, EngineNew
WithAPIBaseURL(url) Хост нового движка (по умолчанию выводится из домена: tech.en.cxapi.en.cx)
Старый и новый движок

Encounter переезжает с ASP.NET на новый REST-бэкенд. encx реализует оба и переключается между ними прозрачно: сигнатуры методов и возвращаемые типы одинаковы, меняется только то, кто отвечает на запрос.

По умолчанию движок определяется автоматически: клиент один раз спрашивает GET {api}/sites/domain/{domain} — новый бэкенд отвечает описанием сайта для доменов, которые уже переехали, и 404 domain_unregistered для остальных. Вопрос именно про домен, а не про хост: один API-хост обслуживает всю зону и отвечает на любой запрос, поэтому проверка доступности хоста объявила бы переехавшими вообще все сайты.

c := encx.New("tech.en.cx")            // auto: определит сам
fmt.Println(c.Engine())                // legacy | new

c := encx.New("demo.en.cx", encx.WithEngine(encx.EngineNew))   // принудительно
c := encx.New("tech.en.cx", encx.WithEngine(encx.EngineLegacy))

То же самое даёт переменная окружения ENCX_ENGINE=legacy|new|auto и флаг encli -engine. Хост нового движка выводится из домена (demo.en.cxapi.en.cx); для локального mock-сервера или своей инсталляции его задают через encx.WithAPIBaseURL(...), флаг -api-base-url или ENCX_API_BASE_URL.

Выбор можно не повторять при каждом запуске: мастер первого запуска и Web UI сохраняют его в ~/.config/encli/engine/settings.json (путь переопределяется через ENCLI_ENGINE_SETTINGS_FILE). Файл — самый младший источник: флаг и переменная окружения по-прежнему старше него. Испорченный файл не роняет команды, а игнорируется с сообщением в -debug: умолчание auto всё равно опрашивает хост и исправляет себя само. Хост нового движка выводится только для зон Encounter (en.cx, encounter.cx, encounter.ru, en-world.org, quest.ua), и сайт в ответе обязан сам назвать запрошенный домен — иначе на неподтверждённый хост не уходят ни заголовок сайта, ни учётные данные. Для домена вне этих зон хост не выводится: в auto клиент останется на старом движке, а при явном new вернёт ошибку с просьбой указать -api-base-url.

Спецификация нового API, протокол WebSocket движка и матрица паритета методов — в docs/newengine.

iOS

Нативное приложение вынесено в отдельный репозиторий enkapp. Здесь остаётся только gomobile-библиотека и сборка Encx.xcframework.

Пакет mobile/encxmobile — gomobile-обёртка над encx. API возвращает JSON-строки, которые декодируются в Swift через JSONDecoder.

Сборка Encx.xcframework
# из корня репозитория
./mobile/bind-ios.sh

# результат: mobile/build/Encx.xcframework

Скрипт устанавливает gomobile, прогоняет тесты и собирает фреймворк для устройства и симулятора.

Подключение в Xcode

См. также enkapp — готовый Xcode-проект с этим фреймворком.

  1. Перетащите Encx.xcframework в проект (Embed & Sign).
  2. Добавьте в Info.plist разрешение на сеть (если ещё нет):
<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoads</key>
  <true/>
</dict>

Для production лучше настроить ATS exceptions только для нужных доменов (*.en.cx).

Пример (Swift)
import Encx

guard let client = EncxmobileNewClient("tech.en.cx", true) else { return }

// Авторизация
var loginErr: NSError?
let loginJSON = client.login("user", password: "secret", error: &loginErr)
if let err = loginErr { print(err); return }

struct LoginResponse: Decodable {
    let Error: Int
    let Message: String
}
let login = try JSONDecoder().decode(LoginResponse.self, from: loginJSON.data(using: .utf8)!)
guard login.Error == 0 else {
    print(EncxmobileLoginErrorText(login.Error))
    return
}

// Сохранение сессии (Keychain / UserDefaults)
if let cookies = client.exportCookies(&loginErr) {
    UserDefaults.standard.set(cookies, forKey: "encx_cookies")
}

// Состояние игры
let gameJSON = client.getGameModel(12345, error: &loginErr)
// decode GameModel from gameJSON...

// Отправка кода
let resultJSON = client.sendCode(12345, levelID: 67890, levelNumber: 1, code: "КОД123", error: &loginErr)
Доступные методы
Go (encxmobile) Описание
NewClient / NewClientWithOptions Создание клиента
Login / LoginWithCaptcha Авторизация
GetGameModel Состояние игры
SendCode Отправка кодов
GetPenaltyHint Штрафная подсказка
GetGameList / GetDomainGames Список игр
GetGameStatistics Статистика
EnterGame Вступление в игру
GetProfile Профиль пользователя
ExportCookies / ImportCookies Сохранение сессии
LoginErrorText / EventText Тексты ошибок

PHP

Тот же пакет mobile/encxmobile доступен из PHP: он собирается в разделяемую библиотеку (-buildmode=c-shared), которую PHP вызывает через FFI. Клиент живёт на стороне Go, поэтому сессия и куки сохраняются между вызовами.

require __DIR__ . '/bindings/php/autoload.php';

$client = Encx\Client::newClient('demo.en.cx', false);
$client->login('user', 'password');
$model = json_decode($client->getGameModel(82448), true);

Обёртки не пишутся руками: cgo-экспорты, C-заголовок и PHP-классы генерируются из Go-исходника командой go generate ./bindings/..., а отставание ловят drift-тест, CI и pre-commit hook. Сборка, установка и полный список связанных методов — в bindings/php/README.md.

CLI: encli

encli полезен, когда нужно быстро дернуть API руками и не городить под это отдельный код.

Демо использует публичный mock-сервер encounter.exe.xyz. GIF обновляются автоматически через GitHub Pages.

Типичный поток такой:

  1. залогиниться;
  2. выбрать игру;
  3. смотреть статус, задания и сообщения;
  4. отправлять коды и запрашивать подсказки.
# Авторизация (интерактивный ввод пароля)
encli login -domain tech.en.cx -insecure

# Список игр
encli games
encli game-list

# Статус игры
encli status -game-id 12345

# Задание текущего уровня
encli level -game-id 12345

# Все уровни с прогрессом
encli levels -game-id 12345

# Бонусы текущего уровня
encli bonuses -game-id 12345

# Подсказки (обычные и штрафные)
encli hints -game-id 12345

# Секторы текущего уровня
encli sectors -game-id 12345

# Лог пробитий кодов
encli log -game-id 12345

# Сообщения от организаторов
encli messages -game-id 12345

# Вступить в игру
encli enter -game-id 12345

# Отправка кода уровня/сектора
encli send-code -game-id 12345 "КОД123"

# Отправка бонусного кода
encli send-bonus -game-id 12345 "БОНУС123"

# Запрос штрафной подсказки
encli hint -game-id 12345 42

# Статистика игры
encli game-stats -game-id 12345

# Профиль
encli profile

# Версия
encli -v

# LLM-агент (кратко; подробнее — раздел «LLM-агент и OpenRouter» ниже)
export LLM_API_KEY=sk-or-v1-...          # ключ с https://openrouter.ai/keys
export LLM_MODEL=anthropic/claude-sonnet-4  # любая модель из каталога OpenRouter

encli -game-id 12345 --llm "создай 3 уровня с бонусами и подсказками"
encli -game-id 12345 --llm "пройдись по уровням, проверь ответы и предложи исправления"
encli -readonly -game-id 12345 --llm "покажи содержимое всех уровней"  # без записи в игру

# Web UI с тем же ключом и моделью
encli -web

# Выход
encli logout

# --- Admin-команды ---

# Список авторских игр
encli admin-games

# Список уровней с ID
encli admin-levels -game-id 12345

# Создать 3 уровня
encli admin-create-levels -game-id 12345 3

# Удалить уровень №5
encli admin-delete-level -game-id 12345 5

# Переименовать уровень (ID из admin-levels)
encli admin-rename-level -game-id 12345 67890 "Новое название"

# Установить автопереход 1ч 30мин с штрафом 15мин
encli admin-set-autopass -game-id 12345 1 1:30:00 0:15:00

# Блокировка: 3 попытки за 1 минуту, на игрока
encli admin-set-block -game-id 12345 1 3 0:01:00 player

# Создать бонус (уровень 1, level-id 67890, название, ответы)
encli admin-create-bonus -game-id 12345 1 67890 "Бонус 1" "ответ1" "ответ2"

# Удалить бонус
# bonus-id берите из admin-level-content
# там бонусы печатаются как [bonus <id>]
encli admin-delete-bonus -game-id 12345 1 <bonus-id>

# Создать сектор
encli admin-create-sector -game-id 12345 1 "Сектор А" "код1" "код2"

# Посмотреть содержимое уровня и найти sector-id
encli admin-level-content -game-id 12345 1

# Удалить сектор
# sector-id берите из admin-level-content
# там секторы печатаются как [sector <id>]
encli admin-delete-sector -game-id 12345 1 <sector-id>

# Обновить сектор
# sector-id берите из admin-level-content
# пример: переименовать сектор и заменить список ответов
encli admin-update-sector -game-id 12345 1 <sector-id> name="Сектор Б" answers="код3,код4"

# Создать подсказку (откроется через 30 минут)
encli admin-create-hint -game-id 12345 1 0:30:00 "Текст подсказки"

# Удалить подсказку
# hint-id берите из admin-level-content
# там подсказки печатаются как [hint <id>]
encli admin-delete-hint -game-id 12345 1 <hint-id>

# Создать задание
encli admin-create-task -game-id 12345 1 "Текст задания уровня"

# Обновить задание
# task-id берите из admin-level-content
# там задания печатаются как [task <id>]
encli admin-update-task -game-id 12345 1 <task-id> "Новый текст задания"

# Установить имя и комментарий уровня
encli admin-set-comment -game-id 12345 1 "Название" "Комментарий для орга"

# Список команд в игре
encli admin-teams -game-id 12345

# Начисления бонусного/штрафного времени
encli admin-corrections -game-id 12345
encli admin-add-correction -game-id 12345 "Team Name" bonus 0:10:00 0 "за красоту"
encli admin-delete-correction -game-id 12345 444

# Чтение содержимого уровня (задание, секторы, бонусы, подсказки, настройки)
encli admin-level-content -game-id 12345 1

# Сообщения уровня
# сначала посмотрите список сообщений и их message-id
encli admin-messages -game-id 12345 1

# создать сообщение
# здесь 67890 — это level-id, его берите из admin-levels
encli admin-create-message -game-id 12345 67890 "Текст сообщения"

# обновить сообщение
# message-id берите из admin-messages
encli admin-update-message -game-id 12345 1 <message-id> text="Новый текст" mode=chosen levels=67890

# удалить сообщение
# message-id берите из admin-messages
encli admin-delete-message -game-id 12345 1 <message-id>

# Создать новую игру (title, start, finish обязательны; даты в RFC3339)
encli admin-create-game title="Новая игра" start="2026-09-10T18:00:00+03:00" finish="2026-09-11T18:00:00+03:00"

# Информация об игре (название, авторы, описание, даты, модерация заявок)
encli admin-game-info -game-id 12345

# Обновить настройки игры
# Ключи: title, authors, description, prize, start, finish, request_last_date, moderated
# Не указанные ключи сохраняют текущее значение
encli admin-update-game -game-id 12345 title="Новое название" description="Описание"

# Перенести старт и включить автоприём заявок (moderated=false)
# Даты в RFC3339; старый движок понимает и DD.MM.YYYY HH:MM:SS
# Старт нельзя изменить после начала игры
encli admin-update-game -game-id 12345 start="2026-09-10T18:00:00+03:00" moderated=false

# Полная очистка игры (обнуление)
encli admin-wipe-game -game-id 67890

# Удаление игры целиком (безвозвратно; ID повторяется как подтверждение)
encli admin-delete-game -game-id 67890 67890

# Копирование игры целиком (из 12345 в 67890)
# Рекомендуется сначала admin-wipe-game на целевой
encli admin-copy-game -game-id 12345 67890

# Перестановка и клонирование уровней
encli admin-swap-levels -game-id 12345 2 5
encli admin-insert-level -game-id 12345 3 0
encli admin-clone-levels -game-id 12345 2 1

# Обновление бонуса и подсказки
encli admin-update-bonus -game-id 12345 1 <bonus-id> name="Новое имя" answers="код1,код2"
encli admin-update-hint -game-id 12345 1 <hint-id> text="Новый текст" delay=0:45:00

# Удаление задания
encli admin-delete-task -game-id 12345 1 <task-id>

# Жизненный цикл игры
encli admin-deliver -game-id 12345
encli admin-not-deliver -game-id 12345
encli admin-award-points -game-id 12345
encli admin-end-ratings -game-id 12345
encli admin-calc-ik -game-id 12345
encli admin-action-monitor -game-id 12345

LLM-агент и OpenRouter

encli встраивает PicoClaw с tool-calling: агент читает состояние игры, вызывает admin-команды, ищет факты в Википедии и читает локальные файлы со сценарием. Один runtime используется в CLI (--llm), локальном Web UI (-web) и Docker (через -e).

API-ключ и модель

По умолчанию используется OpenRouter (https://openrouter.ai/api/v1) и бесплатная модель openai/gpt-oss-120b:free. Чтобы использовать свой ключ и другую модель, задайте переменные окружения (или передайте их в docker run -e ...):

Переменная Алиас Назначение
LLM_API_KEY OPENROUTER_API_KEY API-ключ OpenRouter (получить)
LLM_MODEL OPENROUTER_MODEL Идентификатор модели в каталоге OpenRouter, например anthropic/claude-sonnet-4 или google/gemini-2.5-pro-preview
LLM_BASE_URL OPENROUTER_BASE_URL Base URL OpenAI-совместимого API (если не OpenRouter)

Приоритет: сначала LLM_*, затем OPENROUTER_*. Для localhost (127.0.0.1 / localhost в URL) ключ не обязателен — удобно для локального прокси.

Всё то же самое настраивается мышкой в Web UI — см. Настройка LLM в Web UI.

Подписка ChatGPT вместо API-ключа

Вместо ключа агент умеет работать на подписке ChatGPT — через тот же backend, что использует Codex CLI. Токенов по прайсу OpenRouter это не тратит: в отчёте о выполнении стоимость показывается как $0 (подписка ChatGPT).

encli codex-login              # откроет браузер и дождётся редиректа
encli codex-login -device      # headless-хост: код вводится на chatgpt.com
encli codex-login -no-browser  # напечатает ссылку, ждёт вставки redirect URL

encli codex-status             # аккаунт, срок действия токена, путь к файлу
encli codex-logout             # удалить сохранённую учётку

Учётка (access- и refresh-токен) лежит в ~/.config/encli/codex/auth.json с правами 0600; путь переопределяется через ENCLI_CODEX_AUTH_FILE. Отдельный подкаталог не случаен: -web считает каждый *.json в ~/.config/encli/ сессией домена Encounter, и учётка в общем каталоге показалась бы там фиктивным доменом с кнопкой Logout, которая её удаляет. Access-токен обновляется автоматически за 5 минут до истечения, обновлённое значение сразу пишется обратно в файл — повторный codex-login нужен, только если истёк refresh-токен.

Как выбирается транспорт:

Условие Транспорт
-llm-auth codex или LLM_AUTH=codex Подписка ChatGPT (ошибка, если codex-login не выполнен)
-llm-auth gigachat или LLM_AUTH=gigachat GigaChat (ошибка, если не задан GIGACHAT_CREDENTIALS)
-llm-auth apikey или LLM_AUTH=apikey Только API-ключ, сохранённая учётка игнорируется
Ничего не задано, LLM_API_KEY задан API-ключ (явный ключ всегда в приоритете)
Ничего не задано, задан LLM_BASE_URL / OPENROUTER_BASE_URL Указанный endpoint (в том числе локальный прокси без ключа)
Ничего не задано в окружении, есть настройки из Web UI То, что сохранено в ~/.config/encli/llm/settings.json
Ничего не задано, ключа и endpoint нет, учётка ChatGPT есть Подписка ChatGPT
Ничего не задано, ключа и endpoint нет, задан GIGACHAT_CREDENTIALS GigaChat

Автовыбор подписки или GigaChat срабатывает, только когда не задано вообще ничего: и ключ, и base URL — это явно выраженное намерение, поэтому оставшаяся с прошлого раза учётка не уводит локальный прокси на chatgpt.com. Чтобы использовать подписку при заданном ключе или endpoint, укажите -llm-auth codex явно. Учётка ChatGPT имеет приоритет над GIGACHAT_CREDENTIALS; выбрать GigaChat при обеих настройках можно через -llm-auth gigachat.

Модель по умолчанию для подписки — gpt-5.5; LLM_MODEL её переопределяет, но только именем, которое backend действительно обслуживает: префикс openai/ отбрасывается, принимаются семейства gpt-*, o3*, o4*. Любое другое имя (в том числе забытое в шелле openrouter/free или claude-sonnet-4) заменяется на дефолтную модель с предупреждением в stderr — иначе backend подменил бы её молча, а в отчёте стояла бы запрошенная модель, а не та, что отвечала. Флаг -llm-auth доступен в --llm, -chat и -web.

# Разовая настройка
encli codex-login

# Дальше ключ не нужен ни в одном из режимов
encli -game-id 12345 --llm "проверь ответы на уровне 3"
encli -game-id 12345 -chat
encli -web

# Явный выбор, когда в окружении есть и LLM_API_KEY
encli -llm-auth codex -game-id 12345 --llm "покажи статус игры"
GigaChat (Сбер)

Агент умеет работать на GigaChat API. Ключ авторизации (Authorization key — base64 от Client ID:Client Secret) берётся в личном кабинете Сбера, в проекте GigaChat API; по нему клиент сам получает access-токен, живущий 30 минут, и обновляет его за 2 минуты до истечения.

export GIGACHAT_CREDENTIALS=<Ключ авторизации из личного кабинета>
encli -game-id 12345 --llm "покажи уровни"

# Явный выбор, когда в окружении есть и LLM_API_KEY
encli -llm-auth gigachat -game-id 12345 --llm "покажи статус игры"
Переменная Назначение
GIGACHAT_CREDENTIALS Ключ авторизации (обязательна)
GIGACHAT_SCOPE Версия API: GIGACHAT_API_PERS (по умолчанию), GIGACHAT_API_B2B, GIGACHAT_API_CORP
GIGACHAT_MODEL Модель (по умолчанию: GigaChat-2-Max); при отсутствии берётся LLM_MODEL
GIGACHAT_BASE_URL Base URL API (по умолчанию: https://api.giga.chat/v1)
GIGACHAT_AUTH_URL Endpoint OAuth (по умолчанию: https://ngw.devices.sberbank.ru:9443/api/v2/oauth)
GIGACHAT_CA_BUNDLE PEM-файл с «Российским доверенным корневым УЦ» — включает проверку сертификата
GIGACHAT_INSECURE 0 — проверять сертификат; 1 — не проверять (по умолчанию не проверяется)

Две площадки и модели. По умолчанию используется https://api.giga.chat/v1 — там живут GigaChat-2, GigaChat-2-Pro, GigaChat-2-Max и третье поколение: GigaChat-3-Lightning, GigaChat-3-Pro, GigaChat-3-Ultra. Старые имена (GigaChat, GigaChat-Pro, GigaChat-Max, *-preview) обслуживает только legacy-хост — для них задайте GIGACHAT_BASE_URL=https://gigachat.devices.sberbank.ru/api/v1. Если модели на площадке нет, API отвечает 404 No such model; encli дополняет эту ошибку списком моделей, которые площадка реально отдаёт, и подсказкой про legacy-хост.

LLM_BASE_URL для GigaChat НЕ читается — это намеренно. Переменная означает «адрес OpenAI-совместимого endpoint», и если бы она действовала здесь, забытый в шелле LLM_BASE_URL=https://openrouter.ai/api/v1 отправил бы OAuth-токен GigaChat в заголовке Authorization постороннему хосту. Адрес переопределяется только через GIGACHAT_BASE_URL.

Сертификат. GigaChat отдаётся под сертификатом Минцифры, которого нет ни в одном системном хранилище по умолчанию. Проверка, которая падает всегда, — это не защита, а поломка, поэтому по умолчанию сертификат GigaChat не проверяется (один раз за запуск об этом печатается предупреждение в stderr). Чтобы включить проверку, скачайте корневой сертификат Минцифры и укажите путь в GIGACHAT_CA_BUNDLE — он добавляется к системному пулу, а не заменяет его. Если корень уже установлен в системе, достаточно GIGACHAT_INSECURE=0.

# Просто работает, без проверки сертификата
export GIGACHAT_CREDENTIALS=<ключ>
encli -game-id 12345 --llm "проверь ответы на уровне 3"

# Третье поколение
GIGACHAT_MODEL=GigaChat-3-Ultra encli -domain demo.en.cx --llm "покажи игры на домене"

# С проверкой сертификата
export GIGACHAT_CA_BUNDLE=~/.config/encli/russian_trusted_root_ca.pem
export GIGACHAT_MODEL=GigaChat-2-Pro
encli -game-id 12345 --llm "проверь ответы на уровне 3"

Инструменты передаются GigaChat в его собственном формате (functions / function_call), а не в OpenAI-совместимом tools / tool_calls: OpenAI-образный запрос GigaChat принимает без ошибки, но молча теряет все инструменты, и агент остаётся без единого действия. За один ход GigaChat вызывает не больше одной функции — цикл агента от этого просто становится длиннее. Стоимость в отчёте о выполнении не показывается: GigaChat тарифицируется в собственных единицах с предоплаченного баланса, а не в долларах.

Примеры:

# Разовый запуск с другой моделью
LLM_API_KEY=sk-or-v1-XXXX LLM_MODEL=anthropic/claude-sonnet-4 \
  encli -game-id 12345 --llm "создай уровень с бонусом"

# Постоянная настройка в shell
export LLM_API_KEY=sk-or-v1-XXXX
export LLM_MODEL=google/gemini-2.5-flash-preview
encli -game-id 12345 --llm "проверь ответы на уровне 3"

# Старые имена переменных (обратная совместимость)
export OPENROUTER_API_KEY=sk-or-v1-XXXX
export OPENROUTER_MODEL=openai/gpt-4o
encli -game-id 12345 --llm "покажи статус"

# Локальный OpenAI-совместимый сервер (Ollama, LiteLLM, Cursor proxy и т.п.)
export LLM_BASE_URL=http://127.0.0.1:8317/v1
export LLM_MODEL=my-local-model
encli -game-id 12345 --llm "покажи уровни"

Список моделей и цены: openrouter.ai/models. В конце сессии агент печатает отчёт: модель, число запросов к LLM, токены и ориентировочная стоимость (для OpenRouter — по прайсу из /models).

Режим --llm
encli -game-id 12345 --llm "скопируй игру 82033 в 82034"
encli -debug -game-id 12345 --llm "покажи статус игры"   # подробный лог в stderr
encli -readonly -game-id 12345 --llm "аудит всех уровней" # без изменений в игре

Для review-запросов (проверь ответы, найди ошибки) агент не применяет правки сразу: сначала предлагает исправления, затем CLI (или Web UI) спрашивает подтверждение по каждому пункту.

Поведение агента:

  • Вызовы инструментов выводятся в читаемом виде (например, [admin_level_content] Читаю содержимое уровня 3).
  • Большие ответы tool-call'ов сжимаются перед отправкой обратно в модель.
  • При 429 и 502–504 — до 3 повторов с нарастающей задержкой.
  • После создания или изменения уровней агент проверяет результат (коды, тайминги, подсказки, задания).
Web UI (-web)

Локальный чат с тем же агентом, историей диалогов и переключателем режима безопасности (только чтение / с подтверждением / полный доступ):

export LLM_API_KEY=sk-or-v1-...
export LLM_MODEL=anthropic/claude-sonnet-4
encli -web
# по умолчанию http://127.0.0.1:8787 — откроется в браузере

encli -web -web-addr 0.0.0.0:8787   # слушать на всех интерфейсах
# или: ENCLI_WEB_ADDR=0.0.0.0:8787 encli -web

В шапке UI отображается текущая модель. Сессии Encounter логинятся через UI; чаты сохраняются в ~/.config/encli/web/chats/.

Онбординг при первом запуске

Ничего не настроено — и первый же encli -web встречает мастером вместо пустого чата, который не может ответить. Четыре шага: приветствие → модель → движок → вход в en.cx.

  • Модель. Те же два способа, что и в панели «Настройки LLM»: вход по подписке ChatGPT или OpenAI-совместимый провайдер (Base URL, ключ, модель). Кнопка «Проверить подключение» показывает, что именно уйдёт агенту, до того как вы закроете мастер.
  • Движок. auto, legacy или new. Кнопка «Определить автоматически» спрашивает у API-хоста, на чём реально живёт домен, и предлагает найденное значение. Выбор сохраняется в ~/.config/encli/engine/settings.json (права 0600, атомарная запись), путь переопределяется через ENCLI_ENGINE_SETTINGS_FILE.
  • Вход в en.cx. Домен, логин, пароль. Шаг пропускаемый: без него агент уже настроен, просто ещё не авторизован, и войти можно позже в шапке.

Факт прохождения хранится в ~/.config/encli/onboarding/state.json (переопределяется через ENCLI_ONBOARDING_FILE), так что мастер не повторяется на каждом старте. Кнопка «Пропустить настройку» закрывает его тоже насовсем. Открыть мастер снова — кнопка «Мастер настройки» (◈) в шапке; чтобы он снова появился при следующем запуске, удалите файл состояния или вызовите POST /api/v1/onboarding/reset.

Файлы настроек и состояния лежат в подкаталогах, а не прямо в ~/.config/encli/, по той же причине, что и учётка ChatGPT: -web показывает каждый *.json из корня этого каталога как сессию домена Encounter, и кнопка «Выйти» рядом с такой «сессией» удалила бы файл.

Приоритет источников тот же, что и у настроек LLM: флаг CLI → переменная окружения → сохранённые настройки → дефолт. Если поле перекрыто переменной или флагом, мастер показывает это рядом с полем, а не делает вид, что сохранение подействовало.

Эндпоинты: GET /api/v1/onboarding, POST /api/v1/onboarding/complete, POST /api/v1/onboarding/reset, GET/PUT/DELETE /api/v1/engine/settings, GET /api/v1/engine/probe?domain=....

Настройка LLM в Web UI

Переменные окружения задавать не обязательно: кнопка «Настройки LLM» в шапке открывает панель, где настраивается подключение к модели.

  • Подписка ChatGPT. Кнопка «Войти через ChatGPT» запускает тот же OAuth-поток, что и encli codex-login, но целиком из браузера: encli открывает страницу авторизации, ждёт редирект на http://localhost:1455/auth/callback и сохраняет учётку в ~/.config/encli/codex/auth.json. Если браузер живёт на другой машине, в панели есть поле для ручной вставки redirect URL. Порт 1455 не выбирается произвольно: OpenAI сверяет redirect URI с зарегистрированным для клиента Codex, поэтому при занятом порте вход честно падает с ошибкой вместо молчаливого отказа на стороне провайдера.
  • OpenAI-совместимый провайдер. Поля Base URL, API-ключ и модель. Сохраняются в ~/.config/encli/llm/settings.json (права 0600, атомарная запись); путь переопределяется через ENCLI_LLM_SETTINGS_FILE. Файл лежит в подкаталоге по той же причине, что и учётка ChatGPT: -web показывает каждый *.json из ~/.config/encli/ как сессию домена Encounter. Через API ключ наружу не отдаётся — только маска вида ••••1234.

Приоритет источников: флаг CLI → переменная окружения → сохранённые настройки → дефолт. Окружение намеренно старше файла: ключ, выставленный в шелле или в контейнере, — это голос деплоя, и его не должно перебивать значение, введённое в UI когда-то давно. Чтобы это не выглядело как «сохранил, а ничего не изменилось», панель рядом с таким полем показывает плашку с именем переменной, которая его перекрывает, и внизу — что реально уйдёт агенту.

Настройки читаются на каждом запросе, так что менять их можно не перезапуская encli -web. Соответствие эндпоинтов: GET/PUT/DELETE /api/v1/llm/settings, POST /api/v1/llm/codex/login (+ GET .../login/{id} для статуса, POST .../login/{id}/code для ручной вставки), GET /api/v1/llm/codex/status, POST /api/v1/llm/codex/logout.

На Windows Web UI стартует и без флага: если encli.exe запущен без команды и без терминала (двойной клик в проводнике, ярлык), вместо мелькнувшей справки поднимается Web UI и открывается браузер. Запуск из cmd.exe или PowerShell не меняется — encli.exe без аргументов там по-прежнему печатает справку, а любая команда (encli.exe game-list) выполняется как обычно.

TUI-чат (-chat)

Консольный аналог Web UI: полноэкранный чат в терминале с тем же агентом, той же историей (~/.config/encli/web/chats/ — чаты видны и в -web), теми же сессиями Encounter и режимами безопасности per-chat.

export LLM_API_KEY=sk-or-v1-...
encli -chat -domain tech.en.cx
encli -chat -readonly            # по умолчанию режим approve

Слева — список чатов, справа — переписка с инлайновым логом вызовов инструментов; подтверждения изменений запрашиваются прямо в интерфейсе (y / n / q). Слэш-команды: /help, /new, /chats, /domain, /game, /games, /mode readonly|approve|full, /login, /logout, /auth, /delete, /export [md|json], /quit. Клавиши: Enter — отправить, Tab — фокус на список чатов, Ctrl+B — показать/скрыть список, Esc — отменить текущий запрос, PgUp/PgDn — прокрутка.

Импорт HTML-сценария в чате

Для файла экспорта Encounter GameScenario агент использует inspect_scenario_file (название и точные счётчики), затем admin_import_scenario с ID целевой игры. Импортёр переносит уровни и содержимое напрямую из файла и сверяет результат со свежим экспортом. admin_verify_scenario выполняет такую сверку без изменений. Повторный импорт выравнивает содержимое существующих уровней; лишние уровни не удаляются автоматически и попадают в отчёт о расхождениях.

Большие результаты старых инструментов сокращаются только в запросе к модели; полная история сохраняется. Пустые и незавершённые ответы модели выводятся как ошибки, а в Web UI ошибки остаются в переписке после обновления страницы.

Локальные файлы, Википедия и веб

Агент может читать сценарии с диска, открывать ссылки и сверять факты:

Инструмент Назначение
read_local_file Прочитать текстовый файл
list_local_dir Список файлов в каталоге
search_local_files Поиск по содержимому / glob
wikipedia_search Поиск статей
wikipedia_article Краткое содержание статьи
fetch_url Загрузить внешнюю страницу по ссылке как текст

fetch_url принимает только http/https, конвертирует HTML в читаемый текст (содержимое <script> и <style> отбрасывается) и отдаёт длинные страницы частями через offset. Адреса, которые резолвятся в loopback, приватные или link-local сети, отклоняются на этапе подключения — включая редиректы, — поэтому ссылкой из чата нельзя дотянуться до внутренних сервисов хоста.

Корень для локальных путей — LLM_FILES_ROOT (по умолчанию текущая рабочая директория); файлы вне этого каталога недоступны.

export LLM_FILES_ROOT=~/quests/my-scenario
encli -game-id 12345 --llm "прочитай levels.md и создай уровни по сценарию"

Команды CLI

Команда Что делает
login Логинится и сохраняет сессию
logout Чистит сохраненную сессию
codex-login Авторизует агента по подписке ChatGPT (OAuth, без API-ключа)
codex-logout Удаляет сохранённую учётку ChatGPT
codex-status Показывает сохранённую учётку ChatGPT (аккаунт, срок, путь)
games Показывает список игр через HTML-страницу домена
game-list Показывает список игр через JSON API
status Показывает текущее состояние игры
level Печатает текст текущего задания
levels Показывает все уровни с прогрессом
bonuses Показывает бонусы текущего уровня
hints Показывает подсказки (обычные и штрафные)
sectors Показывает секторы текущего уровня
log Показывает лог пробитий кодов
messages Показывает сообщения от организаторов
enter Подает заявку на вход в игру
send-code Отправляет код уровня/сектора через LevelAction.Answer
send-bonus Отправляет бонусный код через BonusAction.Answer
hint Запрашивает штрафную подсказку
game-stats Показывает статистику игры (уровни, команды, результаты)
profile Показывает профиль текущего пользователя (ранг, очки, домен)
import-scenario Импортирует Game scenario.html в игру (уровни, задания, подсказки, ответы)
--llm <prompt> Естественно-языковая команда через LLM-агента (OpenRouter или совместимый API)
-web Локальный Web UI для агента (чат, история, режимы безопасности)
-chat Полноэкранный TUI-чат с агентом в терминале (общая история с -web)
-readonly Запретить агенту инструменты, изменяющие игру (для --llm, -web и -chat)
-llm-auth Транспорт агента: apikey (по умолчанию) или codex — подписка ChatGPT
-v Показывает версию

Admin-команды (требуют прав редактора игры):

Команда Что делает
admin-games Показывает список авторских игр
admin-levels Показывает все уровни с их ID (админка)
admin-create-levels Создаёт указанное количество новых уровней
admin-delete-level Удаляет уровень по номеру
admin-rename-level Переименовывает уровень
admin-set-autopass Устанавливает таймер автоперехода
admin-set-block Настраивает блокировку ответов
admin-create-bonus Создаёт бонус на уровне
admin-delete-bonus Удаляет бонус по ID
admin-create-sector Создаёт сектор на уровне
admin-delete-sector Удаляет сектор по ID
admin-update-sector Обновляет сектор по ID
admin-create-hint Создаёт подсказку на уровне
admin-delete-hint Удаляет подсказку по ID
admin-update-hint Обновляет подсказку по ID
admin-create-task Создаёт задание на уровне
admin-update-task Обновляет задание по ID
admin-set-comment Устанавливает название и комментарий уровня
admin-teams Показывает команды в игре
admin-corrections Показывает начисления бонусного/штрафного времени
admin-add-correction Добавляет начисление времени
admin-delete-correction Удаляет начисление по ID
admin-level-content Читает содержимое уровня (задание, секторы, бонусы, подсказки, настройки)
admin-create-message Создаёт игровое сообщение
admin-messages Показывает сообщения уровня
admin-update-message Обновляет сообщение по ID
admin-delete-message Удаляет сообщение по ID
admin-create-game Создаёт новую игру (key=value: title, start, finish обязательны)
admin-game-info Показывает информацию об игре (название, авторы, описание, дата)
admin-update-game Обновляет настройки игры (key=value: title, authors, description, prize, start, finish, request_last_date, moderated)
admin-deliver Помечает игру как состоявшуюся
admin-award-points Начисляет очки участникам
admin-end-ratings Завершает приём оценок
admin-calc-ik Считает игровой коэффициент
admin-wipe-game Полностью обнуляет игру (удаляет всё содержимое)
admin-copy-game Копирует всю игру (уровни, настройки, бонусы, секторы, подсказки) в другую
admin-delete-game Удаляет игру целиком, без возврата (ID повторяется вторым аргументом как подтверждение)
admin-swap-levels Меняет местами два уровня по номеру
admin-insert-level Перемещает уровень на новую позицию
admin-clone-levels Клонирует N уровней с настроек существующего
admin-delete-task Удаляет задание по ID
admin-update-bonus Обновляет бонус по ID (key=value)
admin-update-hint Обновляет подсказку по ID (key=value)
admin-action-monitor Показывает монитор действий в игре
admin-not-deliver Помечает игру как несостоявшуюся
Импорт сценария из HTML

import-scenario загружает экспорт страницы Game scenario.html (Encounter), удаляет текущие уровни в целевой игре и создаёт новые:

Запросы нового REST API по умолчанию отправляются с интервалом не меньше 40 мс. Заголовки X-Ratelimit-Limit и X-Ratelimit-Remaining могут дополнительно замедлить запросы: клиент распределяет остаток бюджета с запасом 5% (минимум один запрос), а при малом остатке ждёт минуту. Без заголовка сброса минута — консервативное предположение клиента. Retry-After также учитывается. Бюджет общий для клиентов одного API-хоста внутри процесса; другие процессы и устройства за общим IP учитываются только косвенно через ответы сервера. Ожидание не расходует сетевой таймаут, но подчиняется контексту операции. Для изменения минимального интервала: -api-request-interval 200ms (5 запросов/с); серверный бюджет приоритетнее этого параметра. При --sync-missing -har журнал сохраняется и при ошибке импорта.

  • названия уровней
  • автопереходы
  • задания
  • подсказки с задержками
  • ответы (как секторы)

Для ссылок на локальные изображения (./..._files/...) команда встраивает файлы как data: URL прямо в HTML текста заданий/подсказок. Если Encounter включает anti-spam (NotHumanRequest.aspx) или запрос попадает в таймаут, import-scenario не падает: CLI возьмёт ссылку на Login.aspx со страницы проверки и попробует автоматически ввести -login/-password (или ENCX_*), затем JSON sign-in; если не выйдет — попросит завершить проверку в браузере и повторит шаг. Флаг --sync-missing приводит существующие уровни в соответствие со сценарием: при расхождении задания, подсказки и секторы на уровне пересоздаются по экспорту (источник истины — HTML), без полного wipe игры. Недостающие уровни создаются целиком.

encli import-scenario -game-id 82307 "/Users/svk/Downloads/moscow.en.cx __ Game scenario.html"

# Проверка без записи в игру
encli import-scenario -game-id 82307 --dry-run "/Users/svk/Downloads/moscow.en.cx __ Game scenario.html"

# Сверка и выравнивание уровней по сценарию (без полного wipe)
encli import-scenario -game-id 82307 --sync-missing "/Users/svk/Downloads/moscow.en.cx __ Game scenario.html"
Флаги и переменные окружения

Почти все можно передавать либо через флаги, либо через env. Удобно, если гоняете команды часто.

Флаг Env-переменная Описание
-domain ENCX_DOMAIN Домен Encounter (по умолчанию: tech.en.cx)
-login ENCX_LOGIN Логин
-password ENCX_PASSWORD Пароль
-game-id ENCX_GAME_ID ID игры
-insecure ENCX_INSECURE Пропустить проверку TLS-сертификата
-http Использовать HTTP вместо HTTPS
-engine ENCX_ENGINE Движок Encounter: auto (по умолчанию), legacy, new
-api-base-url ENCX_API_BASE_URL Хост нового движка (по умолчанию выводится из домена)
-json Выводить результат в формате JSON
-debug ENCX_DEBUG Включить отладочный вывод в stderr
-har ENCX_HAR Записывать HTTP-трафик в HAR 1.2
-har-out ENCX_HAR_OUT Путь экспорта HAR (файл или каталог)
-web-addr ENCLI_WEB_ADDR Адрес Web UI (по умолчанию: 127.0.0.1:8787)
-readonly Блокировать у агента инструменты записи (см. также режим в Web UI)
LLM_BASE_URL Base URL OpenAI-совместимого API (по умолчанию: https://openrouter.ai/api/v1)
OPENROUTER_BASE_URL Алиас для LLM_BASE_URL
LLM_API_KEY API-ключ для --llm и -web (не нужен для localhost)
LLM_MODEL Модель для агента (по умолчанию: openai/gpt-oss-120b:free)
-llm-auth LLM_AUTH Транспорт агента: apikey (по умолчанию), codex — подписка ChatGPT, gigachat — GigaChat API
ENCLI_CODEX_AUTH_FILE Путь к учётке ChatGPT (по умолчанию: ~/.config/encli/codex/auth.json)
ENCLI_LLM_SETTINGS_FILE Путь к настройкам LLM из Web UI (по умолчанию: ~/.config/encli/llm/settings.json)
ENCLI_ENGINE_SETTINGS_FILE Путь к настройкам движка из Web UI (по умолчанию: ~/.config/encli/engine/settings.json)
ENCLI_ONBOARDING_FILE Путь к состоянию мастера первого запуска (по умолчанию: ~/.config/encli/onboarding/state.json)
GIGACHAT_CREDENTIALS Ключ авторизации GigaChat (base64 от Client ID:Client Secret)
GIGACHAT_SCOPE Версия GigaChat API (по умолчанию: GIGACHAT_API_PERS)
GIGACHAT_MODEL Модель GigaChat (по умолчанию: GigaChat-2-Max)
GIGACHAT_BASE_URL Base URL GigaChat (по умолчанию: https://api.giga.chat/v1)
GIGACHAT_AUTH_URL Endpoint OAuth GigaChat (по умолчанию: https://ngw.devices.sberbank.ru:9443/api/v2/oauth)
GIGACHAT_CA_BUNDLE PEM с корневым сертификатом Минцифры — включает проверку TLS для GigaChat
GIGACHAT_INSECURE 0 — проверять TLS-сертификат GigaChat (по умолчанию не проверяется)
LLM_FILES_ROOT Корень каталога для read_local_file / search_local_files (по умолчанию: cwd)
OPENROUTER_API_KEY Алиас для LLM_API_KEY
OPENROUTER_MODEL Алиас для LLM_MODEL

Пример:

export ENCX_DOMAIN=tech.en.cx
export ENCX_LOGIN=my_login
export ENCX_PASSWORD=my_password
export ENCX_GAME_ID=12345
export ENCX_DEBUG=1

# LLM (OpenRouter)
export LLM_API_KEY=sk-or-v1-...
export LLM_MODEL=anthropic/claude-sonnet-4

encli login -insecure
encli status
encli -debug status
encli -game-id 12345 --llm "покажи уровни"

В -debug режиме encli пишет в stderr полный разбор аргументов, шаги LLM-агента, запуск и завершение tool-call'ов, а также HTTP-запросы encx с таймингами. Вывод не обрезается — данные показываются целиком для полноценной диагностики.

Подробнее про агента, смену модели и Web UI — в разделе LLM-агент и OpenRouter.

Сборка из исходников
go build -o encli ./cmd/encli/

API

Ниже краткая шпаргалка по основным методам, которые уже завернуты в клиент. Endpoint'ы в таблице — старого движка; чем каждый метод обслуживается на новом, перечислено в матрице паритета.

Метод Endpoint Описание
Login POST /login/signin Авторизация
GetGameModel POST /gameengines/encounter/play/{id} Состояние игры
SendCode POST /gameengines/encounter/play/{id} Отправка кода (LevelAction.Answer)
GetPenaltyHint GET /gameengines/encounter/play/{id} Запрос штрафной подсказки
GetGameList GET /home/?json=1 Список игр (JSON, с пагинацией)
GetDomainGames GET m.{domain}/ Список игр (HTML)
GetGameStatistics GET /gamestatistics/full/{id}?json=1 Полная статистика игры
GetTimeoutToGame GET m.{domain}/gameengines/encounter/play/{id} Таймер до начала
EnterGame GET /MakeGameFee.aspx?confirm=yes&gid={id} (fallback: POST …/makefee/Login.aspx) Подать заявку / вступить в игру
GetGameDetails GET /GameDetails.aspx?gid={id} Детали игры (HTML)
GetTeamDetails GET /Teams/TeamDetails.aspx?tid={id} Информация о команде
AcceptTeamInvitation GET /Teams/TeamDetails.aspx?action=accept_invitation&tid={id} Принять приглашение

Admin API (требует прав редактора):

Метод Endpoint Описание
AdminGetLevels GET /Administration/Games/LevelManager.aspx Список уровней (ID, названия)
AdminCreateLevels GET /Administration/Games/LevelManager.aspx?levels=create Создание уровней
AdminDeleteLevel GET /Administration/Games/LevelManager.aspx?levels=delete Удаление уровня
AdminRenameLevels POST /Administration/Games/LevelManager.aspx?level_names=update Переименование уровней
AdminUpdateAutopass POST /Administration/Games/LevelEditor.aspx Настройка автоперехода
AdminUpdateAnswerBlock POST /Administration/Games/LevelEditor.aspx Настройка блокировки ответов
AdminCreateBonus POST /Administration/Games/BonusEdit.aspx?action=save Создание бонуса
AdminDeleteBonus GET /Administration/Games/BonusEdit.aspx?action=delete Удаление бонуса
AdminCreateSector POST /Administration/Games/LevelEditor.aspx Создание сектора
AdminDeleteSector GET /Administration/Games/LevelEditor.aspx?delsector={id} Удаление сектора
AdminCreateHint POST /Administration/Games/PromptEdit.aspx Создание подсказки
AdminDeleteHint GET /Administration/Games/PromptEdit.aspx?action=PromptDelete Удаление подсказки
AdminCreateTask POST /Administration/Games/TaskEdit.aspx Создание задания
AdminUpdateComment POST /Administration/Games/NameCommentEdit.aspx Обновление названия/комментария
AdminGetTeams GET /Administration/Games/TaskEdit.aspx Список команд
AdminGetCorrections GET /GameBonusPenaltyTime.aspx Список начислений времени
AdminAddCorrection POST /GameBonusPenaltyTime.aspx?action=save Добавление начисления
AdminDeleteCorrection GET /GameBonusPenaltyTime.aspx?action=delete Удаление начисления
AdminGetLevelSettings GET /Administration/Games/LevelEditor.aspx Чтение настроек уровня (автопереход, блокировка)
AdminGetBonusIds GET /Administration/Games/LevelEditor.aspx Список ID бонусов на уровне
AdminGetBonus GET /Administration/Games/BonusEdit.aspx?action=edit Чтение деталей бонуса
AdminGetHintIds GET /Administration/Games/LevelEditor.aspx Список ID подсказок на уровне
AdminGetHint GET /Administration/Games/PromptEdit.aspx?action=PromptEdit Чтение деталей подсказки (обычной и штрафной)
AdminGetTaskIds GET /Administration/Games/LevelEditor.aspx Список ID заданий на уровне
AdminGetTask GET /Administration/Games/TaskEdit.aspx?action=TaskEdit Чтение деталей задания
AdminGetComment GET /Administration/Games/NameCommentEdit.aspx Чтение названия и комментария уровня
AdminGetSectorAnswers GET /ALoader/LevelInfo.aspx Чтение секторов и ответов уровня
AdminGetGameInfo GET /Administration/Games/GameEditor.aspx Чтение настроек игры (название, авторы, описание, приз, дата)
AdminUpdateGameInfo POST /Administration/Games/GameEditor.aspx Обновление настроек игры
AdminWipeGame (комбинированный) Полная очистка игры (удаление всего содержимого)
AdminCopyGame (комбинированный) Полное копирование игры (уровни, настройки, бонусы, секторы, подсказки)

Полная неофициальная (полученная методом реверс-инжиниринга) спецификация API в формате OpenAPI 3.1: openapi.yaml.

Поддерживаемые домены: *.en.cx, *.encounter.cx, *.encounter.ru. Домен quest.ua deprecated — мигрирован в {city}questua.en.cx (напр. kharkov.quest.ua -> kharkovquestua.en.cx).

Тестовый домен

Для тестирования собственных разработок предусмотрен специализированный домен tech.en.cx. Чтобы получить на нём права создания игр (исключительно в технологических целях) — напишите в техподдержку сети.

Тесты

Интеграционные тесты ходят в tech.en.cx:

ENCX_INTEGRATION=1 go test ./encx/ -v -count=1

Если переменную ENCX_INTEGRATION не задавать, запустятся только юнит-тесты.

E2E-тесты

Пакет e2e/ содержит сквозные тесты библиотеки encx и CLI encli против реального домена Encounter. Они исключены из обычной сборки билд-тегом e2e:

go test -tags e2e ./e2e -v -timeout 15m

Конфигурация через переменные окружения:

Переменная Назначение По умолчанию
ENCX_E2E_DOMAIN Домен Encounter svk.en.cx
ENCX_E2E_LOGIN Логин аккаунта skrashevich
ENCX_E2E_PASSWORD Пароль аккаунта
ENCX_E2E_GAME_ID ID игры-песочницы 82448

Аккаунт должен быть автором игры-песочницы. Тесты создают собственные уровни в конце игры, проверяют контент и удаляют всё созданное; существующие уровни не изменяются. Если игра-песочница завершилась, тесты сами продлевают дату её окончания. CLI-тесты собирают encli во временный каталог и работают с изолированным HOME, не трогая сессии в ~/.config/encli.

Directories

Path Synopsis
Package agentmcp serves the Encounter engine toolset over the Model Context Protocol so a standalone PicoClaw instance (or any MCP client) can play through the same tools the in-app agent uses.
Package agentmcp serves the Encounter engine toolset over the Model Context Protocol so a standalone PicoClaw instance (or any MCP client) can play through the same tools the in-app agent uses.
Package agenttools exposes the Encounter engine to LLM agents as a catalog of callable tools.
Package agenttools exposes the Encounter engine to LLM agents as a catalog of callable tools.
bindings
php
Package php holds the PHP bindings for encx: a C-shared library built from mobile/encxmobile and the PHP classes that call it through FFI.
Package php holds the PHP bindings for encx: a C-shared library built from mobile/encxmobile and the PHP classes that call it through FFI.
php/cmd/encxphpgen command
Command encxphpgen generates the PHP bindings for encx from the Go source of mobile/encxmobile.
Command encxphpgen generates the PHP bindings for encx from the Go source of mobile/encxmobile.
php/cshared command
Command cshared is the c-shared library the PHP bindings load through FFI.
Command cshared is the c-shared library the PHP bindings load through FFI.
php/internal/gen
Package gen emits the C side of the PHP bindings from a surface.Model: the cgo wrapper file compiled into the c-shared library, the FFI-parsable C header, and a JSON manifest describing what was bound and what was not.
Package gen emits the C side of the PHP bindings from a surface.Model: the cgo wrapper file compiled into the c-shared library, the FFI-parsable C header, and a JSON manifest describing what was bound and what was not.
php/internal/genphp
Package genphp emits the PHP side of the encx bindings: the Client class wrapping the opaque Go handle, and the Helpers class holding the package-level functions that need no client.
Package genphp emits the PHP side of the encx bindings: the Client class wrapping the opaque Go handle, and the Helpers class holding the package-level functions that need no client.
php/internal/rt
Package rt provides the hand-written runtime shared by the generated PHP cgo bindings: a handle registry for live *encxmobile.EncClient values and a JSON response envelope.
Package rt provides the hand-written runtime shared by the generated PHP cgo bindings: a handle registry for live *encxmobile.EncClient values and a JSON response envelope.
php/internal/surface
Package surface models the exported surface of the encxmobile Go package as it can be projected onto a C ABI.
Package surface models the exported surface of the encxmobile Go package as it can be projected onto a C ABI.
cmd
encli command
Command encli is a CLI tool for interacting with the Encounter (en.cx) game engine.
Command encli is a CLI tool for interacting with the Encounter (en.cx) game engine.
encx-mock command
Package encx provides a Go client for the Encounter (en.cx) game engine JSON API.
Package encx provides a Go client for the Encounter (en.cx) game engine JSON API.
enapi
Package enapi is a low-level HTTP client for the Encounter Go Backend API — the REST engine that replaces the ASP.NET one.
Package enapi is a low-level HTTP client for the Encounter Go Backend API — the REST engine that replaces the ASP.NET one.
mobile
encxmobile
Package encxmobile provides gomobile-compatible bindings for the encx Encounter API client.
Package encxmobile provides gomobile-compatible bindings for the encx Encounter API client.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL