From 7446e074e9796f70dea3de610cfdb4a85c3d00e6 Mon Sep 17 00:00:00 2001 From: claude code agent 227 Date: Sat, 20 Jun 2026 05:05:34 +0300 Subject: [PATCH] docs: remove implemented api-key-field-clear backlog plan Co-Authored-By: Claude Opus 4.8 --- .../api-key-field-clear-in-place-of-eye.md | 157 ------------------ 1 file changed, 157 deletions(-) delete mode 100644 docs/backlog/api-key-field-clear-in-place-of-eye.md diff --git a/docs/backlog/api-key-field-clear-in-place-of-eye.md b/docs/backlog/api-key-field-clear-in-place-of-eye.md deleted file mode 100644 index 3376a4e8..00000000 --- a/docs/backlog/api-key-field-clear-in-place-of-eye.md +++ /dev/null @@ -1,157 +0,0 @@ -# Поле «API key»: убрать бесполезный «глазок», поставить Clear на его место - -Статус: **план, код не менялся.** UI-задача на клиенте. Бэкенда не касается. - -## Суть - -В настройках AI-провайдера (Workspace settings → AI) у каждого из трёх -эндпоинтов есть поле `PasswordInput` для API-ключа. Когда ключ уже сохранён на -сервере, поле показывает плейсхолдер `•••• set`, а справа — встроенный в -Mantine `PasswordInput` тогл видимости («глазок»). Под полем отдельной строкой -висит ссылка **Clear**. - -Проблема: **«глазок» бессмысленен.** Поле ключа — write-only буфер: реальный -ключ в него никогда не загружается (сервер отдаёт только факт «ключ есть», -`hasApiKey`, см. `ai-provider-settings.tsx:120-130, 154-177`). Когда ключ -сохранён, буфер пустой → нажатие «глазка» показывает пустоту. Полезного смысла -нет. - -Хотим: **в состоянии «ключ сохранён» показывать кнопку Clear прямо на месте -«глазка» (в правой секции поля), а не отдельной ссылкой снизу.** Сделать это во -**всех трёх эндпоинтах** (Chat / LLM, Embeddings, Voice / STT). - -## Где править (точные места) - -Один файл: -[ai-provider-settings.tsx](apps/client/src/features/workspace/components/settings/components/ai-provider-settings.tsx) - -Три одинаковых по структуре блока — `` с `PasswordInput` + ссылкой -`Clear` снизу: - -1. **Chat / LLM** — строки ~433-445 (`apiKey`, `hasApiKey`, `handleClearKey`). -2. **Embeddings** — строки ~538-560 (`embeddingApiKey`, `hasEmbeddingApiKey`, - `handleClearEmbeddingKey`). -3. **Voice / STT** — строки ~657-679 (`sttApiKey`, `hasSttApiKey`, - `handleClearSttKey`). - -Обработчики очистки (`handleClearKey` / `handleClearEmbeddingKey` / -`handleClearSttKey`, строки 239-255) и вся логика буферов/payload -(`buildPayload`, строки 179-222) — **остаются без изменений.** Меняется только -разметка трёх полей. - -## Ключевой факт Mantine (подтверждён по докам) - -У `PasswordInput`: **если передать свой `rightSection`, встроенный тогл -видимости («глазок») не рендерится** (Mantine docs, PasswordInput → «Usage -without visibility toggle»: *“When the `rightSection` prop is used, the -visibility toggle button is not rendered.”*). - -То есть «поставить Clear на место глазка» = передать в `PasswordInput` -`rightSection` с кнопкой Clear. Отдельный костыль для скрытия глазка не нужен. - -## Рекомендуемое поведение - -Показывать Clear в правой секции **только когда ключ сохранён И буфер пуст** -(`hasApiKey && form.values.apiKey.length === 0`). Как только пользователь -начинает вводить НОВЫЙ ключ (буфер непустой) — возвращать дефолтный «глазок»: -вот тут он осмыслен (проверить, что набрал). После клика по Clear обработчик -ставит `hasApiKey=false` → `rightSection` снова `undefined` → поле становится -обычным пустым `PasswordInput` с глазком для ввода свежего ключа. Поведение -самосогласованное. - -Альтернатива (проще, но грубее): показывать Clear всегда, пока `hasApiKey` -(без проверки буфера). Тогда при вводе нового поверх старого глазка не будет. -Допустимо, но теряем удобную проверку набранного. Рекомендуется вариант с -проверкой буфера. - -## Эскиз правки (на примере Chat-поля; для двух других — аналогично) - -Было: -```tsx - - - {hasApiKey && ( - - {t("Clear")} - - )} - -``` - -Стало: -```tsx -{/* The key field is write-only: the stored key never loads back, so the - built-in visibility toggle reveals nothing. Replace it with a Clear action - in the right section. Passing rightSection suppresses the eye (Mantine). - While typing a new key (buffer non-empty) fall back to the default eye. */} - - - - - - ) : undefined - } - rightSectionPointerEvents="all" - {...form.getInputProps("apiKey")} -/> -``` - -Изменения по каждому из трёх блоков: -- Убрать обёртку `` и ссылку `Clear` - снизу (Clear переезжает внутрь поля). После удаления `Stack` второй ребёнок - `` — сам `PasswordInput`; раскладка «Model | API key» в две - колонки сохраняется. -- Подставить свои переменные/обработчики: эндпоинт 2 — `hasEmbeddingApiKey` / - `embeddingApiKey` / `handleClearEmbeddingKey`; эндпоинт 3 — `hasSttApiKey` / - `sttApiKey` / `handleClearSttKey`. - -## Тонкости / на что смотреть - -- **Импорты.** Добавить `ActionIcon`, `Tooltip` из `@mantine/core` и `IconX` - из `@tabler/icons-react` (рядом с уже импортируемым `IconPencil`). После - переезда Clear внутрь поля `Anchor` может стать неиспользуемым — проверить и - убрать из импорта, иначе словим lint-ошибку `no-unused-vars`. -- **Кликабельность правой секции.** У `Input`/`PasswordInput` правая секция по - умолчанию не всегда принимает клики — задать `rightSectionPointerEvents="all"`, - чтобы клик по Clear срабатывал. -- **Тип кнопки.** `ActionIcon` рендерит `