diff --git a/IMPLEMENTATION_LOG.md b/IMPLEMENTATION_LOG.md index 3d90f27..64bd1ce 100644 --- a/IMPLEMENTATION_LOG.md +++ b/IMPLEMENTATION_LOG.md @@ -368,3 +368,13 @@ - Что изменено: `client/src/pages/TaskDetail.tsx` → 14 файлов в `client/src/components/task-detail/`: types.ts, systemTabs.ts, TabFieldsContent, TaskAccessTab (мёртвый код, сохранён для паритета — кандидат на удаление), InlineSystemFields (ответственные, «На себя», срок, замещение), SubtasksTabContent, TaskContent (роутер вкладок + слоты пресетов), TaskTitleInline (хуки в исходном порядке, фикс условного useRef сохранён), useTaskFieldConditions, ReminderDialog, DeleteTaskDialog, TaskDetailHeader, TaskTabsBar, TaskMobileAccordion. В TaskDetail — композиция + хуки верхнего уровня (SSE, переходы, просмотры). - Как проверялось: посимвольная сверка — 32 несовпавшие строки, все объяснены (22 — префикс export, 4 — разбитые импорты, 5 — адаптации пропсов, 1 — комментарий). Чеклист: per-field editing, «На себя», просмотры, geo/contact в потоке, пресеты, порядок хуков 1:1. check/lint/build чисто; vitest 104/104. - Влияние на поиск/UX: нет. + +--- + +## [2.2c] Разбиение Bots.tsx (3928 → 163 строки) + +- Статус: ✅ done +- Зачем: см. 2.2a. БЕЗ смены поведения. +- Что изменено: `client/src/pages/Bots.tsx` → 16 файлов в `client/src/components/bots/`: bots-types.ts (+zod-схемы), bots-utils.ts, CollapsibleSection, CreateBotUsersPicker, useBotsController.tsx (вся логика дословно, хуки 1:1), CreateBotDialog, BotListCard, BotSettingsTab (apiAccess/регенерация ключей), BotAiTab, BotWebhookTab, BotSubscriptionsTab, BotApiDocsCard, ServicesSection, JsPagesSection, TabModulesSection. В Bots.tsx — каркас композиции (публичный экспорт BotsContent сохранён — используется в Settings.tsx). +- Как проверялось: программная сверка — 28/28 сегментов дословно; пропсы типизированы через Pick>. Чеклист: выдача/регенерация API-ключей, zod-валидации, вкладки — дословно. check/lint/build чисто; vitest 104/104. +- Влияние на поиск/UX: нет. diff --git a/client/src/components/bots/BotAiTab.tsx b/client/src/components/bots/BotAiTab.tsx new file mode 100644 index 0000000..86e3bc4 --- /dev/null +++ b/client/src/components/bots/BotAiTab.tsx @@ -0,0 +1,386 @@ +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Switch } from '@/components/ui/switch'; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; +import { TabsContent } from '@/components/ui/tabs'; +import { CheckCircle2, Plus, RefreshCw, Trash2, XCircle } from 'lucide-react'; +import { CollapsibleSection } from './CollapsibleSection'; +import type { BotWithSubscriptions } from './bots-types'; +import type { useBotsController } from './useBotsController'; + +type C = ReturnType; + +type BotAiTabProps = Pick & { selectedBot: BotWithSubscriptions }; + +export function BotAiTab({ + botLoading, + selectedBot, + editAiLlmProviderId, + setEditAiLlmProviderId, + editAiLlmModel, + setEditAiLlmModel, + editProviderObj, + llmProviders, + editOllamaQuery, + editAiSendSystemPrompt, + setEditAiSendSystemPrompt, + editAiSystemPrompt, + setEditAiSystemPrompt, + editAiSendCardInfo, + setEditAiSendCardInfo, + editAiSendChatHistory, + setEditAiSendChatHistory, + editAiMcpEnabled, + setEditAiMcpEnabled, + editAiMcpServers, + setEditAiMcpServers, + editMcpTestResults, + testMcpMutation, + editAiAccessPolicy, + setEditAiAccessPolicy, + orgUsersData, + saveAiSettingsMutation, +}: BotAiTabProps) { + return ( + + {botLoading ? ( +
Загрузка AI-настроек...
+ ) : ( + <> + {/* LLM Provider */} + { + if (!editAiLlmProviderId) return 'Глобальный'; + const prov = editProviderObj; + if (!prov) return ''; + const modelName = editAiLlmModel || 'По умолчанию'; + return `${prov.name} · ${modelName}`; + })()}> +
+ + +
+ {editAiLlmProviderId && (() => { + const prov = editProviderObj; + if (!prov) return null; + return ( +
+ + {prov.providerType === 'ollama' ? (() => { + if (editOllamaQuery.isLoading) { + return ; + } + if (editOllamaQuery.isError || editOllamaQuery.data?.success === false) { + return ( +
+ setEditAiLlmModel(e.target.value)} + placeholder="llama3" className="h-8 text-sm" /> +

Не удалось подключиться к Ollama — введите название модели вручную

+
+ ); + } + const ollamaModels = (editOllamaQuery.data?.models ?? []).map(m => m.name); + return ( + + ); + })() : (() => { + const modelOptions = prov.enabledModels ?? []; + return modelOptions.length > 0 ? ( + + ) : ( + setEditAiLlmModel(e.target.value)} + placeholder="gpt-4o-mini" + className="h-8 text-sm" + /> + ); + })()} +
+ ); + })()} + {llmProviders.length === 0 && ( +

+ Провайдеры не настроены. Добавьте их в Настройки → LLM Провайдеры. +

+ )} +
+ + {/* System prompt */} + { + setEditAiSendSystemPrompt(v); + }} + /> + } + > +
+
+ +
+