# Proposal: openai-transcriber Issue: #5 — Провайдер распознавания: OpenAI-совместимый `/v1/audio/transcriptions` (AITUNNEL, gpt-4o-transcribe). ## Why Core умеет сохранять запись и доводить её до текста через очередь с повторами, но реализации порта `Transcriber` нет: распознавать нечем. Нужен провайдер, который отправляет аудио файлом во внешний сервис и раскладывает любой исход в контракт `TranscribeResult` (`ok` / `temporary` / `permanent`) так, чтобы правила повторов из `recording-lifecycle` работали, а API-ключ не утекал ни в репозиторий, ни в заметки. ## What Changes - Новый порт `HttpClient` в `src/core/ports.ts`: POST с телом `ArrayBuffer` и отдельным полем `contentType`; любой HTTP-статус — ответ, исключение — только сетевой сбой. - `src/core/multipart.ts`: побайтная сборка `multipart/form-data` (у `requestUrl` нет `FormData`). - `src/core/openai.ts`: `OpenAiTranscriber` — запрос к `/audio/transcriptions`, предпроверки без сети, таймаут и отмена через гонку промисов, классификация ответа, очистка секретов в причине ошибки. Настройки и умолчания (AITUNNEL, `gpt-4o-transcribe`). - `src/obsidian/http.ts`: адаптер `HttpClient` на `requestUrl`. - `src/obsidian/settings.ts` и `src/main.ts`: загрузка и сохранение настроек провайдера в `data.json`, вкладка настроек, команда «Проверить провайдер распознавания». - Интеграционный тест против живого AITUNNEL, пропускаемый без `AITUNNEL_API_KEY`. - Вне объёма: запуск очереди в плагине, команды записи, `MediaRecorder`, UI записи (issue обёртки); цепочка провайдеров с переключением по 403/таймауту; провайдер `yandex`. ## Capabilities ### New Capabilities - `transcription-provider`: запрос к OpenAI-совместимому сервису распознавания, предпроверки, таймаут и отмена, классификация ответов, причина ошибки без секретов, настройки провайдера и их хранение, команда проверки провайдера. ### Modified Capabilities Нет. Провайдер реализует контракт `Transcriber`, уже описанный в `recording-lifecycle`. ## Impact - Новые файлы: `src/core/multipart.ts`, `src/core/openai.ts`, `src/obsidian/http.ts`, `src/obsidian/settings.ts`, `tests/multipart.test.ts`, `tests/openai-*.test.ts`, `tests/integration/aitunnel.test.ts`. - Изменяемые: `src/core/ports.ts` (порт `HttpClient`), `src/core/naming.ts` (mime по расширению для команды проверки), `src/main.ts`. - Зависимостей не добавляется: интеграционный тест использует встроенный `fetch` Node. - `data.json` уже в `.gitignore`; ключ синхронизируется через iCloud вместе с vault — это ожидаемое поведение. - Сетевые запросы появляются впервые: к `baseUrl` из настроек, только при отправке записи и по команде проверки.