fix: рецепт assembler не влиял на LLM + логи вход→выход по всему тракту#13
Merged
Conversation
Два слоя одного бага: 1. Дропдаун рецепта в ConfigPanel обновлял только config.recipe, а config.system (который реально идёт в LLM) оставался дефолтным — блок подстановки был пустой заглушкой. Теперь при выборе пресета пишем recipe+system одним обновлением (для 'custom' system не трогаем). 2. Корень: demo.json/Import грузят ассемблер без ключа system (loadWorld не заполняет дефолты схемы) → handler слал пустой system, модель эхом отдавала текст. Теперь assemblerHandler резолвит system из recipe, если он не задан явно. +AC1b регресс-тест. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Сервер (main.py): единый log() формата [tag] k=v с усечением длинных значений — /llm (in/out/ERR, mock и реальный), /proxy (in/out/ERR), /webhook (in). url в /proxy усекается (может нести секрет в пути). Клиент (runtime.ts): I/O каждого станка → панель Логи + консоль (node-io: IN «..» → OUT «..»), ошибки узлов и падения пакетов тоже. Cap панели логов 50 → 200 (store.ts), чтобы история не вымывалась. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
PR исправляет сценарий с assembler-пресетами, чтобы выбранный рецепт реально влиял на system-промпт, и добавляет сквозные логи вход→выход по узлам и серверным эндпоинтам, облегчая отладку всего тракта (UI → engine → server → LLM/proxy/webhook).
Changes:
- Обновление UI/handler для assembler:
systemтеперь корректно подставляется из recipe (включая fallback при загрузке мира безconfig.system) + регресс-чек AC1b. - Логи I/O узлов на клиенте (панель логов + консоль), расширение cap логов/тостов.
- Единый формат серверных логов для
/llm,/proxy,/webhookс усечением значений.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| web/src/ui/ConfigPanel.tsx | При выборе recipe для assembler выставляет system пресета вместе с recipe. |
| web/src/state/store.ts | Увеличивает лимит хранимых логов/тостов с 50 до 200. |
| web/src/state/runtime.ts | Добавляет форматирование и вывод I/O/ошибок узлов в логи/консоль. |
| web/src/core/nodes/assembler.ts | Делает fallback: если config.system отсутствует, берёт system из recipe. |
| web/src/core/checks/nodes.ts | Добавляет регресс-чек AC1b на fallback system из recipe. |
| server/main.py | Добавляет единый helper логирования и логирует in/out/ERR для /llm, /proxy, /webhook. |
Comments suppressed due to low confidence (1)
server/main.py:222
- В обработке ошибок
/proxyтакже логируетсяurlцеликом, что может утечь в логи вместе с секретами в пути/параметрах. Стоит редактировать/убрать URL и тут.
log("proxy←ERR", url=url, error=str(e))
return err(502, f"Proxy error: {str(e)}")
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
160
to
+165
| if (field.key === 'recipe' && entity.kind === 'assembler') { | ||
| const selectedOption = field.options?.find((opt) => opt.value === value); | ||
| if (selectedOption?.label) { | ||
| // Извлекаем system из опции (это лучше сделать в NODE_DEFS если поддерживается) | ||
| // Пока просто обновляем рецепт | ||
| const recipe = RECIPES.find((r) => r.value === value); | ||
| if (recipe && recipe.value !== 'custom') { | ||
| setConfig(entity.id, { ...entity.config, recipe: value, system: recipe.system }); | ||
| } else { | ||
| handleConfigChange('recipe', value); |
Comment on lines
+113
to
+118
| function logPreview(value: unknown, max = 160): string { | ||
| if (value === undefined) return '∅'; | ||
| const s = typeof value === 'string' ? value : JSON.stringify(value); | ||
| const oneLine = s.replace(/\s+/g, ' ').trim(); | ||
| return oneLine.length > max ? oneLine.slice(0, max) + '…' : oneLine; | ||
| } |
Comment on lines
+163
to
+166
| if (parts.length > 0) { | ||
| store.toast(`${label}: ${parts.join(' → ')}`); | ||
| console.log('[io]', label, { in: event.lastIn, out: event.lastOut }); | ||
| } |
Comment on lines
+41
to
+44
| def log(tag: str, **fields) -> None: | ||
| """Единый формат логов эндпоинтов: [tag] k=v k=v ... (flush — сразу в /tmp/server.log).""" | ||
| parts = " ".join(f"{k}={_short(v)}" for k, v in fields.items()) | ||
| print(f"[{tag}] {parts}", flush=True) |
Comment on lines
+193
to
+195
| # url может содержать секрет (напр. bot-token telegram в пути) — усекается _short'ом. | ||
| log("proxy→in", method=method, url=url, body=req_body) | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Что
Два независимых изменения:
1. Баг: рецепт ассемблера не влиял на перевод/суммаризацию
Выбор «Переводчик на английский» в дропдауне ничего не менял — станок отдавал тот же текст. Причина двойная:
onChangeрецепта обновлял толькоconfig.recipe, аconfig.system(реально идёт в LLM) оставался дефолтным — блок подстановки был пустой заглушкой с комментарием.demo.json/ Import грузят ассемблер сconfig:{recipe:...}без ключаsystem, аloadWorldне заполняет дефолты схемы (в отличие от постановки мышью) → handler слал пустой system → модель просто эхом отдавала текст.Фикс: ConfigPanel пишет
recipe+systemодним обновлением при выборе пресета;assemblerHandlerрезолвитsystemизrecipe, если он не задан явно. Регресс-тестAC1b.Подтверждено сквозняком:
system='Переведи текст на английский…'реально доезжает до LLM, модель переводит ("Hi, I'm Anton, I'm a student.").2. Логи вход→выход по всему тракту
main.py): единыйlog()формата[tag] k=vс усечением./llm(in/out/ERR, mock+реальный),/proxy(in/out/ERR),/webhook(in).urlв/proxyусекается (может нести секрет в пути).runtime.ts): I/O каждого станка → панель «Логи» + консоль (IN «..» → OUT «..»), ошибки узлов и падения пакетов. Cap панели 50→200.Проверка
pnpm typecheck✓,pnpm check✓ (13 AC движка + stress + AC1b)🤖 Generated with Claude Code