chore: scaffold tauri transcription app

This commit is contained in:
Evandro committed 2026-06-10 20:48:49 -03:00
commit 3b05cb22a0
18 files changed
+8054

No files matched your search

@@ -0,0 +1,207 @@
# Aplicativo de Transcrição Desktop MVP Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Criar o esqueleto funcional de um app desktop Windows/Linux de transcrição offline-first com Tauri, Rust, TypeScript, modal editável, catálogo de modelo Parakeet GGUF Q8, sidecar CrispASR preparado e CI/CD.
**Architecture:** O frontend TypeScript renderiza a tela/modal e chama comandos Tauri. O backend Rust mantém módulos pequenos para settings, modelos, transcrição, injeção, áudio e tray. Integrações nativas arriscadas ficam atrás de contratos e stubs explícitos para evoluir sem quebrar a arquitetura.
**Tech Stack:** Tauri 2, Rust 1.95, TypeScript, Vite, Vitest, GitHub Actions.
---
## File Structure
```text
.github/workflows/ci.yml CI de lint/typecheck/test/build
.github/workflows/build.yml Builds desktop Windows/Linux manuais
.github/workflows/release.yml Release por tag v*.*.*
.gitignore Ignora builds, deps, modelos e segredos
README.md Visão geral, comandos e limitações
package.json Scripts frontend/Tauri
index.html Entrada Vite
src/main.ts Estado e eventos da UI
src/styles.css Modal/responsividade/acessibilidade
src/vite-env.d.ts Tipos Vite/Tauri
src-tauri/Cargo.toml Crates Rust/Tauri
src-tauri/build.rs Build script Tauri
src-tauri/tauri.conf.json Configuração Tauri e bundle
src-tauri/capabilities/default.json Permissões Tauri
src-tauri/icons/icon.png Ícone mínimo temporário
src-tauri/src/main.rs Entrada nativa
src-tauri/src/lib.rs Bootstrap Tauri
src-tauri/src/app_state.rs Estado compartilhado
src-tauri/src/ui_commands.rs Comandos Tauri
src-tauri/src/tray.rs Tray/menu
src-tauri/src/settings/mod.rs Settings e defaults
src-tauri/src/models/mod.rs Catálogo/status de modelos
src-tauri/src/transcription/mod.rs Contratos de transcrição
src-tauri/src/transcription/crispasr.rs Sidecar CrispASR preparado
src-tauri/src/transcription/openai.rs Adaptador OpenAI-compatible preparado
src-tauri/src/injection/mod.rs Contratos/fallback de inserção
src-tauri/src/audio/mod.rs Estado de gravação MVP
src-tauri/src/error.rs Erros serializáveis
```
## Task 1: Scaffolding do projeto
**Files:**
- Create: `.gitignore`
- Create: `package.json`
- Create: `index.html`
- Create: `src/vite-env.d.ts`
- Create: `src-tauri/Cargo.toml`
- Create: `src-tauri/build.rs`
- Create: `src-tauri/tauri.conf.json`
- Create: `src-tauri/capabilities/default.json`
- Create: `src-tauri/src/main.rs`
- Create: `src-tauri/src/lib.rs`
- [ ] **Step 1: Criar configuração base do frontend e Tauri**
Criar arquivos com scripts `dev`, `build`, `test`, `typecheck`, `tauri:dev` e `tauri:build`. Usar Tauri 2 e Vite.
- [ ] **Step 2: Instalar dependências npm**
Run: `npm install`
Expected: `package-lock.json` criado e dependências instaladas.
- [ ] **Step 3: Verificar build frontend vazio**
Run: `npm run typecheck && npm run build`
Expected: TypeScript e Vite passam.
## Task 2: Contratos backend e testes Rust
**Files:**
- Create: `src-tauri/src/error.rs`
- Create: `src-tauri/src/settings/mod.rs`
- Create: `src-tauri/src/models/mod.rs`
- Create: `src-tauri/src/transcription/mod.rs`
- Create: `src-tauri/src/transcription/crispasr.rs`
- Create: `src-tauri/src/transcription/openai.rs`
- Create: `src-tauri/src/injection/mod.rs`
- Create: `src-tauri/src/audio/mod.rs`
- Modify: `src-tauri/src/lib.rs`
- [ ] **Step 1: Escrever tipos e testes unitários primeiro**
Testes devem cobrir:
- modelo Parakeet Q8 existe no catálogo;
- idioma manual é opcional por padrão;
- Wayland retorna inserção parcial/manual;
- CrispASR sem modelo configurado retorna erro claro.
- [ ] **Step 2: Rodar testes para validar contratos**
Run: `cargo test --manifest-path src-tauri/Cargo.toml`
Expected: todos os testes passam após implementação mínima.
## Task 3: Comandos Tauri e estado do app
**Files:**
- Create: `src-tauri/src/app_state.rs`
- Create: `src-tauri/src/ui_commands.rs`
- Modify: `src-tauri/src/lib.rs`
- [ ] **Step 1: Expor comandos pequenos para frontend**
Comandos:
- `get_app_snapshot`
- `start_recording`
- `stop_recording_and_transcribe`
- `copy_ready_text`
- `request_insert_text`
- `list_models`
- `get_settings`
- `save_settings`
- [ ] **Step 2: Testar build Rust**
Run: `cargo test --manifest-path src-tauri/Cargo.toml`
Expected: comandos compilam e testes continuam passando.
## Task 4: UI do modal flutuante
**Files:**
- Create: `src/main.ts`
- Create: `src/styles.css`
- Modify: `index.html`
- [ ] **Step 1: Construir UI sem framework pesado**
Criar interface com:
- status;
- textarea editável;
- botões gravar/parar, continuar, copiar, inserir e salvar;
- painel de modelo/configuração resumida;
- mensagens de fallback.
- [ ] **Step 2: Testar frontend**
Run: `npm run typecheck && npm run test -- --run && npm run build`
Expected: typecheck, Vitest e build passam.
## Task 5: Tray, assets e empacotamento
**Files:**
- Create: `src-tauri/src/tray.rs`
- Create: `src-tauri/icons/icon.png`
- Modify: `src-tauri/src/lib.rs`
- Modify: `src-tauri/tauri.conf.json`
- [ ] **Step 1: Adicionar tray básico**
Menu:
- Mostrar app;
- Iniciar gravação;
- Sair.
- [ ] **Step 2: Verificar build Tauri até onde o ambiente permitir**
Run: `npm run tauri:build`
Expected: se dependências do sistema estiverem instaladas, build gera bundle; se faltar WebView/NSIS/AppImage tooling, documentar o bloqueio e manter `cargo test` + `npm run build` verdes.
## Task 6: CI/CD e documentação
**Files:**
- Create: `.github/workflows/ci.yml`
- Create: `.github/workflows/build.yml`
- Create: `.github/workflows/release.yml`
- Create: `README.md`
- [ ] **Step 1: Criar workflows**
CI roda em PR/push para `main`. Build é manual. Release roda em tags `v*.*.*` e publica artefatos.
- [ ] **Step 2: Documentar arquitetura e limitações**
README deve explicar:
- offline-first;
- modelo Parakeet GGUF Q8;
- CrispASR sidecar;
- suporte Windows/Linux;
- Wayland parcial;
- comandos locais.
- [ ] **Step 3: Verificação final**
Run:
- `npm run typecheck`
- `npm run test -- --run`
- `npm run build`
- `cargo test --manifest-path src-tauri/Cargo.toml`
Expected: todos passam.
## Self-review
- Spec coverage: cobre organização, modal, inserção, modelo offline, CrispASR sidecar e CI/CD.
- Placeholder scan: não há etapas com TBD/TODO; integrações fora do MVP estão explicitamente isoladas.
- Type consistency: comandos e módulos nomeados de forma consistente com a estrutura proposta.
@@ -0,0 +1,130 @@
# Design do Aplicativo de Transcrição Desktop
## Objetivo
Construir um aplicativo desktop de transcrição para Windows e Linux, com foco inicial em operação offline. O usuário inicia e encerra gravações por hotkey global, revisa a transcrição em um modal flutuante editável e confirma a inserção no aplicativo de destino. O app deve permanecer residente na bandeja/barra do sistema e ser organizado para manutenção simples, builds automatizados e evolução incremental.
## Requisitos aprovados
- Plataforma: Windows e Linux.
- Base técnica: Tauri + Rust com frontend web mínimo em TypeScript.
- Linux: suporte completo no X11 quando possível; suporte parcial e honesto no Wayland.
- Transcrição: offline-first.
- Modelo principal: `cstr/parakeet-tdt-0.6b-v3-GGUF`, arquivo `parakeet-tdt-0.6b-v3-q8_0.gguf`.
- Runtime local: CrispASR como sidecar.
- UX de revisão: sempre exibir modal editável antes de inserir texto.
- Inserção: padrão por clipboard + colar, com modo manual/fallback.
- App residente: tray/system tray com ações principais.
- CI/CD: preparado para GitHub Actions, com comandos portáveis para adaptação futura ao GitLab CI.
## Arquitetura
O projeto usa uma arquitetura modular simples. O frontend Tauri renderiza o modal, configurações e estado visível. O backend Rust expõe comandos Tauri pequenos e delega cada responsabilidade a módulos focados.
```text
src/ Frontend TypeScript/CSS
src-tauri/src/
audio/ Estado e gravação simulada/MVP
transcription/ Contrato comum, CrispASR sidecar e API OpenAI-compatible
injection/ Estratégias de inserção/cópia de texto
models/ Catálogo, status e metadados de modelos offline
settings/ Configuração local serializável
tray.rs Ícone da bandeja e menu
ui_commands.rs Comandos Tauri expostos ao frontend
app_state.rs Estado compartilhado mínimo
lib.rs Bootstrap Tauri
main.rs Entrada nativa
```
A implementação inicial entrega um esqueleto funcional e testável. Integrações que dependem de APIs nativas frágeis, como hotkey global e injeção real em Wayland, ficam isoladas por contratos para serem implementadas em fatias futuras sem reestruturar o app.
## Modal flutuante
O modal é a interface principal após cada gravação. Ele sempre abre antes de qualquer inserção no aplicativo de destino.
Componentes:
- Cabeçalho com estado atual: pronto, gravando, transcrevendo ou revisando.
- Metadados: backend, modelo e idioma.
- Área editável para texto transcrito.
- Ações: iniciar/parar gravação, continuar, copiar, inserir, salvar.
- Mensagens de erro e fallback.
Fluxo principal:
```text
Pronto -> Gravando -> Transcrevendo -> Revisando -> Inserido/Copiado/Salvo
```
## Inserção de texto
A inserção padrão será `ClipboardPaste`: salvar clipboard atual, copiar transcrição, enviar colar quando o sistema suportar e restaurar clipboard depois de um atraso seguro. No MVP, a implementação real de colar é representada por contrato e fallback manual; o texto é copiado para o clipboard pelo frontend quando o usuário pressiona copiar.
Política por sistema:
- Windows: usar Win32 APIs em implementação futura (`GetForegroundWindow`, `SetForegroundWindow`, `SendInput`).
- Linux X11: usar X11 ou fallback com ferramenta opcional detectada.
- Linux Wayland: tratar como parcial; se automação for bloqueada, copiar texto e orientar Ctrl+V.
## Modelos offline
O gerenciador de modelos começa com catálogo estático e validação por metadados.
Modelo principal:
- ID: `parakeet-tdt-0.6b-v3-q8_0`
- Repositório: `cstr/parakeet-tdt-0.6b-v3-GGUF`
- Arquivo: `parakeet-tdt-0.6b-v3-q8_0.gguf`
- Tamanho aproximado: 711 MiB / 745,121,600 bytes conforme metadados do repositório.
- Idiomas: modelo base Parakeet v3 com detecção automática e suporte a 25 idiomas europeus, incluindo português.
O app não embute o modelo no instalador principal. O instalador fica leve; o modelo é baixado pelo app ou instalado manualmente em diretório local configurado.
## Transcrição local com CrispASR
CrispASR será executado como sidecar empacotado por Tauri. O contrato de transcrição aceita caminho de áudio e opções, e retorna texto, idioma detectado opcional, backend, modelo e duração.
No MVP, se o sidecar ou o modelo ainda não estiver configurado, o backend retorna mensagem clara de erro/pendência para o modal. Isso permite validar UI, settings e pipeline sem depender imediatamente do binário externo.
## API OpenAI-compatible
A integração com API externa fica em adaptador separado. Campos previstos:
- endpoint base;
- API key;
- modelo;
- idioma opcional;
- timeout.
Esse adaptador não é o padrão inicial. Ele existe para manter a arquitetura pronta para fallback online sem contaminar o fluxo offline.
## CI/CD
Workflows previstos:
- `ci.yml`: lint, typecheck, testes Rust, testes frontend e build web.
- `build.yml`: build desktop por matriz Windows/Linux.
- `release.yml`: publicação automática em GitHub Releases por tag `v*.*.*`.
A lógica principal fica em scripts npm/cargo para facilitar migração para GitLab CI.
## Escopo do MVP implementado nesta primeira fatia
- Estrutura de projeto Tauri + Rust + TypeScript.
- Módulos backend com contratos e testes unitários.
- Catálogo do modelo Parakeet GGUF Q8.
- Configuração local padrão.
- Modal funcional no frontend com revisão, cópia e simulação de fluxo.
- Tray com menu básico.
- Workflows de CI/build/release.
- Documentação de desenvolvimento e arquitetura.
## Fora do escopo imediato
- Captura real de áudio por dispositivo.
- Hotkey global real.
- Execução real do CrispASR em todos os SOs.
- Injeção real em aplicativos externos.
- Download real com barra de progresso.
Essas partes ficam isoladas em módulos para serem implementadas sem alterar a arquitetura principal.