y83 code / инструмент

Интеграции

«Интеграции» — экран учётных данных внешних сервисов, которыми пользуются MCP-тулы агента. Четыре независимых блока с токенами и карточка-переход на экран GitLab:

раздел реестра
Приложение
код
1 274 строк в 4 файлах
документ
36-tools.md
Раздел: App
Идентификатор: tools · Экран: ui/tools/ToolsScreen.kt
Снимок: 2026-10-11

1. Зачем и что это

БлокЗачем агентуПлейсхолдер
GitHubпоиск кода (webget_github_search)ghp_…
AgentSearchосновной веб-поиск (backend + MCP)—
Генерация изображенийimage_generate / image_edit (Krea 2 Turbo и Flux Klein 4B через y83.media)`1…`
Context7живая документация библиотек по MCPctx7sk…
GitLabпубликация репозиториев (адрес и токен — на своём экране)—

Это единственный экран хаба, который пишет в backend и перезапускает сервисы: после сохранения нового GitHub-токена backend сам перезапускает прокси и codex app-server, чтобы MCP подхватил конфигурацию. Пользователю не нужно ничего перезапускать руками.

2. Как попасть

Хаб инструментов → секция App → карточка «Интеграции» (hub_tools_title, подпись «Интеграции GitHub и AgentSearch», тайл на главной — «Интегр.»).

Откуда ещёПуть
Параметр embeddedОтключает терминальную шапку, если экран куда-то встраивают. Сейчас его никто не передаёт: вход всегда из хаба
Мостapp_navigate с screen: "tools_settings"

Маршрут: Screen.kt:154 ("tools" -> Screen.ToolsSettings) → MainRouter.kt:295 (ToolsScreen). Обратите внимание: id инструмента tools, а ключ экрана в мосте — tools_settings (BridgeScreenCatalog.kt:211, MainScreen.kt:192).

3. Экран: элементы и действия

ЭлементЧто делаетГде в коде
Шапка y83@toolsТерминальная: промпт :~$, мета «интеграций 5 · токенов N», loading…/saving…; при embedded = true не рисуетсяTerminalHeader
Строка статусаЗакреплена под шапкой и не уезжает со списком: итог сохранения и ошибки (вместо Snackbar)ToggleStatusStrip
СпиннерПока идёт загрузка настроекif (loading)
Карточка ошибкиТекст ошибки + кнопка «Повторить»loadError?.let
Секции«поиск и код», «медиа», «документация», «git»SectionHeader
Блок GitHubПоле токена, «глаз», Test, Remove, кнопка «i»ToolTokenCard
Блок AgentSearchURL сервера + bearer-токен, Test, Remove, «i»ToolTokenCard c showUrl = true
Блок Image generationURL эндпоинта + токен, Test, Remove, «i»ToolTokenCard c showUrl = true
Блок Context7Ключ, Test, Remove, «i» (инлайн-инструкция стала окном)ToolTokenCard
Карточка GitLabСостояние подключения (адрес, токен) и переход на экран GitLab, «i»GitLabShortcutCard
Подвал SaveЗакреплён внизу, активен только при несохранённых правкахToolsSaveBar

Строка состояния токена (TokenStatusRow → StatusDot) показывает три состояния: «Токена нет» (приглушённый маркер), «Токен сохранён» (primary, рядом маска с сервера) и «новый, не сохранён» (primary, пока черновик не записан). Маска приходит с сервера — сам токен приложение никогда не читает.

Черновик считает toolsHasDraft (ui/tools/ToolsHelp.kt): изменённые адреса, непустые поля токенов и флаги удаления. Пока черновик не пуст, подвал показывает «есть несохранённые правки», а выход (стрелка «назад» или системная кнопка) спрашивает «сохранить или выйти» — введённый токен не теряется молча.

Кнопка Test у каждого блока отправляет POST /api/v1/tools/test с несохранёнными значениями полей, поэтому токен можно проверить до сохранения.

4. Возможности подробно

Семантика пустых значений

Ключевая тонкость запроса — image_url, image_token, context7_token приходят указателями (*string), а остальные поля — строками:

ПолеСемантика
github_token, agentsearch_url, agentsearch_tokenобычная строка: пустая строка = записать пустое
image_url, image_token, context7_tokennull = не трогать; "" = очистить; значение = записать

На экране это выражено флагом imageTokenClear / context7TokenClear: пока поле не меняли и флаг не выставлен, в запрос уходит null, и сохранённый токен на сервере остаётся целым. Remove выставляет флаг и сразу сохраняет, то есть удаление — это сохранение пустой строки, а не отдельный вызов.

Валидация на клиенте

Перед сохранением URL AgentSearch обрезается пробелами и проверяется на ://: непустой URL без схемы блокирует сохранение, и в строке статуса появляется «Адрес должен быть полным — со схемой https://» — типичная ошибка ввода «localhost:8080» без префикса. Ключ Context7 проверяется на сервере (ctx7sk): ответ с ошибкой приходит из PUT /api/v1/tools/settings.

Проверка токенов

POST /api/v1/tools/test делает реальный сетевой запрос с таймаутом 20 секунд (context.WithTimeout) и клиентом на 15 секунд:

toolЗапросУспех
githubGET https://api.github.com/user200 → «token works»
agentsearchGET <url>/search?q=test&max_results=1200 → «server responds»
imageGET <url>/tokens200 → «token works»
context7context7.Probeсообщение + `mode: tokenanonymous`

Пустые значения в запросе не мешают проверке: код берёт сохранённые настройки как fallback (githubTokenFull(), toolscfg.Get(), toolscfg.ImageConfig()), так что кнопка Test работает и для давно сохранённого токена. 401/403 превращаются в «token rejected (Unauthorized)» через 502 — чтобы отличать от сетевой ошибки. Что-то кроме четырёх известных значений → 400 «tool must be github, agentsearch, image, or context7».

Сохранение и перезапуск

SaveToolsSettings на сервере делает по шагам:

  1. applyGitHubToken — пишет токен и перезапускает сервисы (в restarted попадает имя перезапущенного компонента);
  2. toolscfg.Set(agentsearch_url, agentsearch_token) — пишет tools.json;
  3. toolscfg.SetImage(image_url, image_token) — только если указатели не null;
  4. Context7: проверка префикса ctx7sk, toolscfg.SetContext7Token, затем context7.ApplyToConfig(codexConfigPath()) — секция конфига переписывается сразу, потому что ключ читает прокси, а в файл он не попадает;
  5. если менялся Context7 — h.restartCodex() добавляет «codex» в restarted.

Приложение показывает строкой статуса «Настройки сохранены» и, если что-то перезапускалось, дописывает « перезапущено: <компоненты>». Ошибка рестарта codex не проваливает сохранение — она пишется в лог как Warn.

Инструкции по токенам (кнопка «i»)

У каждого блока есть кнопка «i» — она открывает окно HelpWindow (ui/components/HelpWindow.kt) с терминальной шапкой y83@tools/help: нумерованные шаги, блок «Важно» и кнопка перехода на страницу выдачи токена (через onOpenUrl — встроенный браузер, не внешний). Спецификации инструкций — GitHubHelp/AgentSearchHelp/ImageHelp/Context7Help в ui/tools/ToolsHelp.kt; тексты — в strings_tools.xml. Инструкция по токену GitLab общая (ui/gitlab/GitLabHelp.kt): её открывают и экран GitLab, и карточка GitLab на этом экране, ссылка собирается из адреса сервера.

Локализация

Все подписи экрана живут в res/values/strings_tools.xml (RU — дефолт, values-en — английский), в коде — stringResource/ResText.get. До 0.8.136 подписи были английским текстом прямо в коде, поэтому экран оставался английским и в русской локали.

GitHub: миграция из легаси

GitHub-токен живёт в tools.json, но есть legacyProxyConfigPath() (~/y83-proxy/config.json, переопределяется Y83_PROXY_CONFIG) — источник одноразовой миграции, потому что сам y83-proxy выведен из эксплуатации. Клиенту наружу отдаётся только github_has и маска.

5. Данные: БД, файлы, настройки

ЧтоГде лежитКак меняетсяКто читает
GitHub-токен~/.y83-ws/tools.jsonPUT /api/v1/tools/settingsпрокси, MCP webget
AgentSearch URL + bearerтот же tools.jsonтам жеwebget, MCP web_search/web_fetch
Image URL + токентот же tools.jsonтам жеMCP image_generate / image_edit / image_status / image_jobs / image_cancel / image_quota и окно правки в приложении (POST /api/v1/image-jobs)
Context7 ключтот же tools.json + секция в ~/.codex/config.tomlтам же + context7.ApplyToConfigMCP mcp__context7__*

Файл: backend/internal/toolscfg (const fileName = "tools.json", функция Path()). Значения из файла имеют приоритет над переменными окружения — это отражено в KDoc модуля. Маскирование — maskToken.

6. Backend: REST/роуты

Метод и путьНазначениеОбработчик
GET /api/v1/tools/settingsтекущее состояние (флаги has, маски, URL)webget.ToolsSettings, backend/internal/handlers/webget/settings.go:85
PUT /api/v1/tools/settingsсохранить токены/URL, перезапустить сервисыwebget.SaveToolsSettings, там же:107
POST /api/v1/tools/testпроверить токен реальным запросомwebget.ToolsTest, там же:183
GET /api/v1/webget/settingslegacy: только GitHub-токен и путь к конфигуwebget.Settings, там же:37
PUT /api/v1/webget/settingslegacy: сохранить только GitHub-токенwebget.SaveSettings, там же:48

Роуты объявлены в backend/internal/api/v1/routes.go:102–104.

7. Мост и MCP

ЧтоКакПримечание
Открыть экранapp_navigate с screen: "tools_settings"BridgeScreenCatalog.kt:211
Проверить GitHub-поискMCP web_search (движок agentsearch)требует AgentSearch
КартинкиMCP image_generate / image_edit (маска mask_path/mask_url, прямоугольники, outpaint, style_refs, LoRA) + image_status/image_jobs/image_cancel/image_quotaтребует image-токен; тот же токен использует окно правки в просмотрщике
Документация библиотекMCP mcp__context7__resolve_library_id, mcp__context7__query_docsработает и анонимно

Отдельной bridge-команды для чтения/записи токенов нет — только открытие экрана.

8. Настройки, конфиг, квоты и лимиты

ПараметрЗначениеГде задаётся
Файл конфигурации~/.y83-ws/tools.jsontoolscfg.Path()
Легаси-источник GitHub-токена~/y83-proxy/config.json или $Y83_PROXY_CONFIGlegacyProxyConfigPath()
Таймаут проверки20 с контекст, 15 с HTTP-клиентToolsTest
Ограничение ответа1 МиБ (1<<20)bearerGet
Формат Context7-ключапрефикс ctx7skcontext7.IsKey
Дашборд Context7https://context7.com/dashboardCONTEXT7_KEYS_URL

9. Ловушки и ограничения

  • Сохраняются все четыре блока сразу. Кнопка одна на весь экран, поэтому несохранённый текст в поле другого блока уедет вместе с остальным — сбой в одной строке (например, битый URL AgentSearch) отменяет сохранение целиком.
  • Токен не читается обратно. После сохранения поле пустое, видно только маску; чтобы «проверить, что сохранено», нужно нажать Test.
  • Пустая строка в AgentSearch-токене означает «стереть», в отличие от image_token/context7_token, где пустая строка значит то же, но null — «не трогать». Смешение этих двух семантик легко приводит к потере ключа Context7 при невинном сохранении.
  • Контекст7 без ключа работает анонимно — с ограничением частоты. То есть пустой результат Test с mode: "anonymous" это не ошибка конфигурации.
  • Экран полностью на английском, строки захардкожены — локализации нет.
  • URL AgentSearch обязан быть абсолютным; относительный путь отклоняется ещё до сети.
  • Рестарт codex после смены Context7 логируется как Warn, а не падает: можно получить «Tools saved.» и при этом неработающую MCP-секцию Context7 до ручного рестарта app-server.

10. Источники правды

  • app/src/main/java/com/y83/ws/ui/tools/ToolsScreen.kt — экран.
  • app/src/main/java/com/y83/ws/data/repo/ToolsRepository.kt, data/api/BackendApiSettings.kt — клиент REST.
  • backend/internal/handlers/webget/settings.go — все три обработчика и легаси-миграция.
  • backend/internal/toolscfg/ — чтение и запись tools.json.
  • backend/internal/context7/ — IsKey, Probe, ApplyToConfig.
  • backend/internal/api/v1/routes.go:102–104 — роуты.

Источник: docs/project/hub/36-tools.md · Приложение · 1 274 строк в 4 файлах. Страница собирается из документации проекта при сборке сайта.