76 lines
4.4 KiB
Markdown
76 lines
4.4 KiB
Markdown
# opencode-fixes
|
||
|
||
Плагин-«ремонт» для [OpenCode](https://opencode.ai) **v2** против типичных проблем self-hosted inference
|
||
(llama.cpp / llama-swap / vLLM и т.п.):
|
||
|
||
| Фикс | Симптом | Что делает |
|
||
|---|---|---|
|
||
| **bool-args** | `Invalid input: expected boolean, received "True"` — модель отдаёт `"True"`/`"FALSE"` строками вместо булевых аргументов инструментов | Приводит строки к `true`/`false`, но только в позициях схемы, доказуемо булевых (Effect-схемы нативных инструментов и JSON-схемы плагинов/MCP). Обычные строковые поля не трогает |
|
||
| **toolcall-leak** | Сессия «зависает»: модель сгенерировала вызов инструмента, сервер не распарсил его и вернул как обычный текст с `finish_reason=stop`; OpenCode считает ход финальным ответом | Распознаёт протёкший tool call и автоматически просит модель повторить действие настоящим вызовом инструмента |
|
||
|
||
## Установка
|
||
|
||
**Вариант 1 — файл** (самый простой): скопируйте `index.ts` в
|
||
|
||
```
|
||
~/.config/opencode/plugins/opencode-fixes.ts # глобально
|
||
<проект>/.opencode/plugin/opencode-fixes.ts # для одного проекта
|
||
```
|
||
|
||
OpenCode v2 подхватывает файлы из этих папок автоматически, без рестарта.
|
||
|
||
**Вариант 2 — путь в конфиге**: склонируйте репозиторий и пропишите в `~/.config/opencode/opencode.json`:
|
||
|
||
```json
|
||
{ "plugin": ["/абсолютный/путь/до/opencode-fixes/index.ts"] }
|
||
```
|
||
|
||
Зависимостей нет: только `node:fs/os/path` и рантайм-модуль `@opencode/plugin`, который предоставляет OpenCode.
|
||
|
||
## Как работает toolcall-leak
|
||
|
||
Ход считается «протёкшим», если он:
|
||
|
||
- завершился с `finish=stop` (не ошибка и не настоящий tool call);
|
||
- не содержит ни одного tool-вызова;
|
||
- его текст ≤ 1200 символов, без markdown-код-блоков;
|
||
- начинается с `<tool_call>` **или** заканчивается на `</tool_call>`.
|
||
|
||
Действие: в сессию отправляется короткое системное уведомление с просьбой повторить действие
|
||
настоящим вызовом инструмента.
|
||
|
||
Защита от петель: максимум 3 ретрая подряд, счётчик сбрасывается первым же успешным ходом.
|
||
Кумулятивных лимитов нет — в длинной сессии каждая новая утечка чинится штатно.
|
||
Есть дедупликация между инстансами плагина (хот-релоад может оставить старые копии) —
|
||
ретрай всегда ровно один на утечку.
|
||
|
||
## Настройка (переменные окружения)
|
||
|
||
| Переменная | По умолчанию | Значение |
|
||
|---|---|---|
|
||
| `OPENCODE_FIXES_LOG` | `~/.local/state/opencode/opencode-fixes.log` | путь к логу |
|
||
| `OPENCODE_FIXES_LEAK_MAX_LEN` | `1200` | максимальная длина «утёкшего» текста |
|
||
| `OPENCODE_FIXES_LEAK_MAX_CONSECUTIVE` | `3` | ретраев подряд до сдачи |
|
||
| `OPENCODE_FIXES_DEBUG` | — | подробные логи bool-фикса |
|
||
|
||
## Диагностика
|
||
|
||
При старте плагин прогоняет self-test обоих фиксаторов (4 + 8 кейсов). Полезные строки лога:
|
||
|
||
```
|
||
bool self-test True: PASS
|
||
bool: repaired shell: {"command":"ls","background":true}
|
||
leak self-test prefix-leak: PASS
|
||
leak: tool call leaked as text (pid ... ses_... msg_...), retry 1/3
|
||
leak: clean turn, consecutive reset (ses_...)
|
||
```
|
||
|
||
## Требования
|
||
|
||
OpenCode v2 (API `Plugin.define`). Проверено с серверами на базе llama.cpp (llama-swap),
|
||
vLLM и совместимыми OpenAI API.
|
||
|
||
## Лицензия
|
||
|
||
MIT
|