[bug][ai-chat] Хрупкая передача «текущей страницы» агенту: openPage всегда null + контекст только в system-промпте #43
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Контекст
Агент не понимает «эта/текущая страница». Через CLIProxyAPI отвечает «я не вижу текущую страницу» и просит уточнить id/название. По словам пользователя, без прокси (прямой эндпоинт) работает. Механика передачи страницы хрупкая по двум независимым причинам.
Полный разбор:
docs/backlog/ai-chat-current-page-fragile.md.Как сейчас инжектится текущая страница
Только текстом в system-промпт: клиент вычисляет
openPageиз роута → кладёт в телоPOST /api/ai-chat/stream→ сервис прокидывает вopenedPage→buildSystemPromptдописывает строкуThe user is currently viewing the page "<title>" (pageId: <id>). Ни инструмента «get current page», ни поля в user-сообщении нет.Хрупкость №1 (клиент) — НЕ исправлена
apps/client/src/features/ai-chat/components/ai-chat-window.tsx:openPageберётся черезconst { pageSlug } = useParams(). НоAiChatWindowсмонтирован в pathless-родительском layout-роуте, где сегмент:pageSlugне заматчен →useParams()возвращает{}→pageSlug === undefined→usePageQueryотключён →openPageвсегдаnull. (Тот же антипаттерн рядом:Layoutтак же получаетspaceSlug === undefined→SearchSpotlightбез привязки к спейсу.)Варианты фикса:
useParams()наuseMatch("/s/:spaceSlug/p/:pageSlug")/matchPathпоuseLocation().pathname— матчится по полному URL независимо от позиции в дереве. Минимально и точечно.<Page/>(он внутри дочернего роута, видит params); читать в окне чата. Заодно чинитLayout/SearchSpotlight.Хрупкость №2 (прокси-устойчивость) — НЕ исправлена
pageId передаётся ТОЛЬКО строкой в роли
system(apps/server/src/core/ai-chat/ai-chat.prompt.ts). CLIProxyAPI оборачивает CLI-бэкенды (Gemini CLI / Claude Code / Codex / Qwen) с их объёмными системными промптами — нашsystemможет быть склеен с их преамбулой, перенесён вsystemInstruction, обрезан или недооценён моделью → контекст теряется.Вариант фикса:
get_current_page(берёт pageId из серверной сессии запроса) — идентичность страницы перестаёт зависеть от сохранности system-промпта прокси. C — единственное, что реально лечит исходный симптом.ПРОТИВОРЕЧИЕ — разрешить ДО фикса
По исходнику
openPageдолжен бытьnullв обоих режимах, а пользователь говорит, что напрямую работает. Сначала залогировать (дёшево) и сравнить direct vs proxy:systemпередstreamText(ai-chat.service.ts) — строка должна быть байт-в-байт одинаковой;body.openPageнепустым до сервера в обоих режимах;pageId: ...в системной инструкции модели.Отладочного логирования (предложенного в «открытых вопросах») сейчас тоже НЕ добавлено.
Рекомендация
Сначала разрешить противоречие логами, затем A или B (клиент) + C (устойчивость к прокси).
Файлы
apps/client/src/features/ai-chat/components/ai-chat-window.tsxapps/server/src/core/ai-chat/ai-chat.prompt.tsapps/server/src/core/ai-chat/ai-chat.service.tsapps/server/src/core/ai-chat/ai-chat.controller.tsapps/server/src/core/ai-chat/tools/ai-chat-tools.service.ts(новый инструментget_current_page, если выбираем вариант C)Источник: бэклог
docs/backlog/ai-chat-current-page-fragile.md(статус 🔴 не сделано).инструмент get_current_page принимается