arch/ai-chat: завершить унификацию (live+enabled резолв роли в одном месте; describeProviderError на анонимном пути) #95

Closed
opened 2026-06-21 02:33:16 +03:00 by Ghost · 0 comments

Найдено в multi-aspect code review (грань: architecture, forward-looking, не блокирует мерж).

Область: apps/server/src/core/ai-chat (резолв роли: ai-chat.service.ts, public-share-chat.service.ts, roles/; форматирование ошибок стрима)

Наблюдение
(1) Security-инвариант «резолвить roleId в живую enabled роль, scoped по воркспейсу, иначе null» реализован дважды побайтно (AiChatService.resolveRoleForRequest и PublicShareChatService.resolveShareRole). (2) Рефакторинг describeProviderError (коммит cedea407, breaking) унифицировал формат ошибок в ai-chat.service/контроллере/ai.service, но public-share-chat.service.ts всё ещё конструирует ошибки вручную (2 блока) — расхождение формата, заявленная цель рефактора не достигнута на анонимном пути.

Значимость
Низкий, forward-looking. Расхождение формата ошибок — небольшая регрессия консистентности на анонимном пути (читатель шары не увидит причину 402/429/503 в едином виде).

Опции

  • Option 1 (small): AiAgentRoleRepo.findLiveEnabled(id, workspaceId) (репозиторий уже владеет фильтром deleted_at IS NULL) + замена двух ручных блоков в public-share-chat.service.ts на describeProviderError; параметризовать prepareStep лимитом шагов, чтобы 5-шаговый анонимный бюджет переиспользовал ту же принудительную финализацию. Pros: завершает уже начатый рефактор + чинит формат ошибок анонимного пути. Cons: минимально.
  • Option 2 (medium): общий runAgentStream(model, system, messages, tools, {stopAt,onFinish,onError,onAbort}) для обоих сервисов. Pros: один владелец обвязки streamText. Cons: слияние сервисов, которые законно различаются.

Рекомендация
Option 1 — корректное завершение рефактора этой фичи и починка формата ошибок анонимного пути несколькими строками, без риска слияния законно различных сервисов.

Найдено в multi-aspect code review (грань: architecture, forward-looking, не блокирует мерж). **Область:** apps/server/src/core/ai-chat (резолв роли: ai-chat.service.ts, public-share-chat.service.ts, roles/; форматирование ошибок стрима) **Наблюдение** (1) Security-инвариант «резолвить roleId в живую enabled роль, scoped по воркспейсу, иначе null» реализован дважды побайтно (AiChatService.resolveRoleForRequest и PublicShareChatService.resolveShareRole). (2) Рефакторинг describeProviderError (коммит cedea407, breaking) унифицировал формат ошибок в ai-chat.service/контроллере/ai.service, но public-share-chat.service.ts всё ещё конструирует ошибки вручную (2 блока) — расхождение формата, заявленная цель рефактора не достигнута на анонимном пути. **Значимость** Низкий, forward-looking. Расхождение формата ошибок — небольшая регрессия консистентности на анонимном пути (читатель шары не увидит причину 402/429/503 в едином виде). **Опции** - *Option 1 (small)*: `AiAgentRoleRepo.findLiveEnabled(id, workspaceId)` (репозиторий уже владеет фильтром deleted_at IS NULL) + замена двух ручных блоков в public-share-chat.service.ts на describeProviderError; параметризовать prepareStep лимитом шагов, чтобы 5-шаговый анонимный бюджет переиспользовал ту же принудительную финализацию. Pros: завершает уже начатый рефактор + чинит формат ошибок анонимного пути. Cons: минимально. - *Option 2 (medium)*: общий `runAgentStream(model, system, messages, tools, {stopAt,onFinish,onError,onAbort})` для обоих сервисов. Pros: один владелец обвязки streamText. Cons: слияние сервисов, которые законно различаются. **Рекомендация** Option 1 — корректное завершение рефактора этой фичи и починка формата ошибок анонимного пути несколькими строками, без риска слияния законно различных сервисов.
Ghost closed this issue 2026-06-21 14:10:34 +03:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: vvzvlad/gitmost#95