[2026-09-28] eagle: personal/plans/runtime-pr4-openai-toolcalls-fixes.md personal/tech/adk-hostedagent-openai-mcp.md personal/tech/flaresolverr-taiga.md
This commit is contained in:
1 parent
c5d21f962a
commit
87f719f46b
3 files changed
+319
-4
No files matched your search
@@ -173,8 +173,67 @@ if _, ok := toolset.(requestProcessor); ok {
|
||||
|
||||
---
|
||||
|
||||
## 8. Wire-контракт OpenAI tool_calls: 4 дефекта (2026-09-28)
|
||||
|
||||
`hostedagent/openai.go` — наш патч tool_calls поверх runtime v2. Ревью PR
|
||||
**normahq/runtime#4** дало вердикт «Request changes» с 4 воспроизводимыми дефектами.
|
||||
Все подтверждены фактами и закрыты коммитом **`0937011`**. Разбор —
|
||||
[[personal/plans/runtime-pr4-openai-toolcalls-fixes]].
|
||||
|
||||
| # | Дефект | Суть |
|
||||
|---|---|---|
|
||||
| P1-a | `genai.Schema` маршалится напрямую | типы уходят как `"type":"OBJECT"`/`"STRING"` — **genai использует uppercase-константы**, а OpenAI требует JSON Schema lowercase → 400 |
|
||||
| P1-b | `content,omitempty` у tool-message | пустой результат → `{"role":"tool","tool_call_id":"..."}` без `content`, а он **обязателен** по схеме OpenAI → 400 |
|
||||
| P2-a | Ветка `toolResponses` | `Content{FunctionResponse + Text}` терял текст (ADK такой Content разрешает) |
|
||||
| P2-b | Декод аргументов | не-объект (массив/скаляр) падал в мусорный `{"raw":...}` → исполнитель не получал аргументов |
|
||||
|
||||
📌 **Как проверить фактом, а не глазами** (использовать при любой правке схем):
|
||||
```go
|
||||
// пробник: как реально сериализуется genai.Schema
|
||||
out, _ := json.Marshal(&genai.Schema{Type: genai.TypeObject, Properties: ...})
|
||||
t.Logf("%s", out) // → "type":"OBJECT" ← вот дефект
|
||||
```
|
||||
📌 **`genai.Schema.Nullable` — это `*bool`**, не `bool`. Компилятор ловит:
|
||||
`non-boolean condition in if statement`.
|
||||
|
||||
🔴 **Урок про маскирующие тесты.** Существовавший
|
||||
`TestOpenAIToolsFromConfig_WithParameters` проверял
|
||||
`params["type"] != "OBJECT" && params["type"] != "object"` — **принимал обе формы**, поэтому
|
||||
uppercase-баг жил незамеченным через все гейты. **Терпимый ассерт = отсутствующая проверка.**
|
||||
Ассерт должен пинить ровно одно ожидаемое значение.
|
||||
|
||||
📌 **Формы аргументов, которые надо переживать** (все встречаются у провайдеров):
|
||||
`{"query":"x"}` · `"{\"query\":\"x\"}"` · `"\"{\\\"query\\\":\\\"x\\\"}\""` (двойное) ·
|
||||
`"[...]"` (массив) · `"scalar"`. Корень бага: `json.Unmarshal` в `map[string]any` **падает**,
|
||||
если после unwrap получился не объект.
|
||||
|
||||
📌 **`FunctionCall.Args` по контракту — объект.** Поэтому не-объектный результат оборачивается
|
||||
под стабильный ключ, а не отбрасывается.
|
||||
|
||||
### ⛔ CI PR из форка: `action_required`, 0s
|
||||
|
||||
Все PR-раны для веток из форка (`isCrossRepository: true`) висят в статусе **`action_required`
|
||||
с длительностью `0s`** — GitHub не запускает workflow до одобрения мейнтейнером.
|
||||
Диагностика:
|
||||
```bash
|
||||
gh run list --repo normahq/runtime --limit 10 # → completed | action_required | 0s
|
||||
gh pr view 4 --json isCrossRepository,headRepository
|
||||
```
|
||||
Контроль: PR из ветки **в самом upstream** проходит нормально (`1m5s`). Это **внешний блокер**,
|
||||
не дефект кода. Обход — ветка в upstream при наличии write-доступа.
|
||||
|
||||
### ⚠️ Копия рантайма в balda — отдельная!
|
||||
|
||||
`~/Developer/balda/runtime-local` — **отдельная копия** (не симлинк), подключена через
|
||||
`replace github.com/normahq/runtime/v2 => ./runtime-local`. Её HEAD — коммит **balda**, а не
|
||||
runtime. Правки в `~/Developer/runtime-local` **не доезжают** до боевого стенда автоматически.
|
||||
Проверять: `git -C ~/Developer/balda/runtime-local rev-parse --short HEAD`.
|
||||
|
||||
---
|
||||
|
||||
## Связанные заметки
|
||||
|
||||
- [[personal/plans/runtime-pr4-openai-toolcalls-fixes]] — PR #4: 4 дефекта, фиксы, тесты
|
||||
- [[personal/plans/balda-mm-phase4-agents]] — §19 (корень, фикс, тесты, приёмка), §16.2 и §18 опровергнуты
|
||||
- [[personal/projects/balda/balda-kraken-mm-deploy]] — Фаза 3, образ `balda-mm:0.1.13`
|
||||
- [[personal/tech/balda-go-fx-pitfalls]] — fx-питфоллы Балды
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
# FlareSolverr на Тайге + обход блокировок индексеров
|
||||
|
||||
> ✅ **СОСТОЯНИЕ 2026-09-28 (поздний вечер): ГОТОВО на всех четырёх arr-сервисах.**
|
||||
> **Prowlarr** — 6/6 индексеров, `health` → `[]`, `indexerstatus` → `[]`.
|
||||
> ✅ **СОСТОЯНИЕ 2026-09-28 (финал): инфраструктура готова, 2 дефекта на стороне трекеров.**
|
||||
> **Prowlarr** — `health` → `[]`, 6/6 индексеров настроены; RuTracker в карантине (капча, см. ниже).
|
||||
> **Radarr** — `health` → `[]`. **Sonarr** — `health` → `[]`.
|
||||
> **Lidarr** — работает (SkyHook + 23 релиза); 1 warning `Kinozal (M)` лечится
|
||||
> `docker restart lidarr` после правки `proxyBypassFilter` (см. питфолл в конце).
|
||||
> **Lidarr** — SkyHook работает, 1 артист, поиск релизов отдаёт результаты.
|
||||
> ⚠️ Открыто: **RuTracker — капча на логин** (нужен ручной вход Alex), **RuTor — категории**
|
||||
> (не отдаёт фильмы/сериалы). Оба — на стороне трекеров, не инфраструктура.
|
||||
> Контейнер `flaresolverr` (v3.5.2), порт `8191`, сеть `media_net`, `shm_size: 1gb`,
|
||||
> `LOG_LEVEL=warning`, **`PROXY_URL=socks5://vless-proxy:1080`**.
|
||||
> Compose — `/mnt/RED_2TB/docker/arr/docker-compose.yml` (6-й сервис).
|
||||
@@ -242,6 +243,43 @@ CPU 0.68%); канал прокси нормальный (kinozal через soc
|
||||
прокси-конфига. Остаток: RuTor — несовпадение категорий (не блок), и 1 warning в Lidarr
|
||||
до перезапуска с новым bypass.
|
||||
|
||||
## 🔴 ОТКРЫТО 2026-09-28 (финал сессии): RuTracker отдаёт КАПЧУ на логин
|
||||
|
||||
Хронология одного вечера — пароль один и тот же, результат разный:
|
||||
|
||||
| Время | Проверка | `len` HTML | Итог |
|
||||
|---|---|---|---|
|
||||
| ~15:20 | `request.post /forum/login.php` | **251 792** | ✅ залогинен |
|
||||
| ~16:40 | `request.post /forum/login.php` | **13 335** | ❌ форма вернулась |
|
||||
|
||||
Пароль в Prowlarr при этом **не менялся** (сверено: `username`/`password` из
|
||||
`/api/v1/indexer/1` совпадают с локальной копией). Причина смены результата —
|
||||
**трекер выдаёт капчу**: в HTML найден блок `cap_code` + метка `Код:`.
|
||||
Пишется это в лог Prowlarr как `NzbDrone.Core.Indexers.Exceptions.IndexerAuthException:
|
||||
RuTracker Auth Failed` и `Invalid Credentials for RuTracker [https://rutracker.org/forum/tracker.php?nm=...&f=...]`.
|
||||
|
||||
🔴 **Правильный признак «залогинен/нет» — РАЗМЕР страницы, а не подстрока.**
|
||||
- **~250 KB** = залогиненный форум.
|
||||
- **~13 KB** = форма логина (вернулась).
|
||||
|
||||
Подстрока `login_username` присутствует **в обоих** случаях (HTML-шаблон + скрытая форма
|
||||
быстрого входа) — по ней диагноз ставить НЕЛЬЗЯ, это дало ложное «Auth Failed» двумя
|
||||
диагнозами подряд.
|
||||
|
||||
**Обходного пути в Prowlarr нет:** форма индексера RuTracker принимает только
|
||||
`username`/`password` — поля для cookie-сессии (`bb_data`) не существует, вписать
|
||||
живую сессию из браузера нельзя.
|
||||
|
||||
**Что делать (нужен Alex):** зайти на `rutracker.org` браузером с **этого же**
|
||||
исходящего IP (через тот же `vless-proxy`), ввести логин+пароль и **пройти капчу один раз**.
|
||||
После успешного входа капча обычно снимается. Если не поможет — сменить пароль на
|
||||
трекере и вписать новый в Prowlarr (`Indexers → RuTracker`), либо поискать у RuTracker
|
||||
обход капчи (в Cardigann-определении поддержки нет).
|
||||
|
||||
⚠️ Следствие: **RuTracker в карантине** в Prowlarr, поэтому его `caps` отдаёт **429** →
|
||||
каскад `429:TooManyRequests` в Radarr/Sonarr/Lidarr. Это нормальное поведение, лечится
|
||||
только восстановлением логина. См. питфолл про `429` ниже.
|
||||
|
||||
## ✅ ЗАКРЫТО: пароль RuTracker — рабочий (первый диагноз был НЕВЕРЕН)
|
||||
|
||||
**Итог 2026-09-28 (позже в тот же вечер):** сохранённая в Prowlarr пара
|
||||
|
||||
Reference in new issue
Block a user