feat: add mobile shell and unified search
Some checks failed
ci / 정본·보안·린트·타입·테스트 (push) Failing after 50s
ci / 워크스페이스 빌드 검증 (push) Has been skipped
ci / Supabase Edge Functions + Cloudflare Worker (push) Successful in 20s
ci / .NET API 서버 테스트 (push) Successful in 12s
deploy-site / deploy (push) Successful in 39s
ci / 모바일 린트·타입·Jest (push) Failing after 3h10m31s
Some checks failed
ci / 정본·보안·린트·타입·테스트 (push) Failing after 50s
ci / 워크스페이스 빌드 검증 (push) Has been skipped
ci / Supabase Edge Functions + Cloudflare Worker (push) Successful in 20s
ci / .NET API 서버 테스트 (push) Successful in 12s
deploy-site / deploy (push) Successful in 39s
ci / 모바일 린트·타입·Jest (push) Failing after 3h10m31s
This commit is contained in:
parent
f505a03d34
commit
5ca3709b32
98 changed files with 5168 additions and 2093 deletions
|
|
@ -54,6 +54,7 @@ Singleton + `EventEmitter` pattern (`getXService()` accessors).
|
|||
| Service | Purpose |
|
||||
|---|---|
|
||||
| `HistoryService` | SQLite history CRUD/search/stats |
|
||||
| `UnifiedSearchService` | Read-only SQLite search across history title/content and meeting title/transcript; merges newest-first results without changing either schema |
|
||||
| `DictionaryService` | Custom vocabulary CRUD/search + cloud sync hooks + JSON/CSV import/export (`dictionary:import`/`export`, save/open dialogs) |
|
||||
| `MemoService` | Memo tags over history (`memo_tags`) |
|
||||
| `RAGService` | Local RAG: `nomic-embed-text` embeddings, cosine search over `rag_chunks` |
|
||||
|
|
@ -131,6 +132,7 @@ Registry: `src/main/ipc/index.ts` calls 31 `registerXHandlers()` in fixed order.
|
|||
| `dictionary-handlers` | DICTIONARY |
|
||||
| `file-transcription-handlers` | FILE_TRANSCRIPTION |
|
||||
| `history-handlers` | HISTORY (incl. `history:setFavorite`, `history:getAudio` → local bytes or signed URL) + `stats:getSummary` |
|
||||
| `unified-search-handlers` | UNIFIED_SEARCH (`unifiedSearch:query`), returning `IPCResult<UnifiedSearchResponse>` |
|
||||
| `input-telemetry-handlers` | INPUT_TELEMETRY |
|
||||
| `instruction-handlers` | INSTRUCTION |
|
||||
| `keybinding-handlers` | KEYBINDING |
|
||||
|
|
@ -156,7 +158,7 @@ The **`KEYBINDING`** group replaced the old per-action `HOTKEY` group. `HOTKEY`
|
|||
|
||||
**`LLM.PROCESS` normalizes at the IPC boundary.** The handler runs `buildInstructionInvocation` itself when `action === 'custom'` with a `customPrompt` (`llm-handlers.ts:94-108`), so the renderer passes the **raw instruction text** and never duplicates the substitution or argument-placement rules. This is what makes `VoiceModeService`, `ChainService`, and `LLM.PROCESS` literally share one implementation. No channel or type changed for this; `LLMProcessParams` is unchanged.
|
||||
|
||||
Preload exposes **`window.electronAPI`** with 35 namespaces: `platform, audio, config, voice, stt, keybinding, llm (incl. premium), history, dictionary, stats, window, system, instruction, app, memo, voiceCommand, context, chain, caption, license, fileTranscription, meetingSummary, dictationTemplate, rag, voiceAction, voiceConversation, meetingMode, meetingChat, meetingDocTemplate, cloudSync, onlineAuth, ads, support, inputTelemetry, suggestion`. The `keybinding` bridge is 9 methods mirroring the channels above (`src/preload/index.ts:323`), replacing the 11-method `hotkey` bridge. Envelope: `IPCResult<T>` (success/error); `app.onDataChanged` is the global refresh channel.
|
||||
Preload exposes **`window.electronAPI`** with 37 namespaces: `platform, audio, config, voice, stt, runtime, keybinding, llm (incl. premium), history, unifiedSearch, dictionary, stats, window, system, instruction, app, memo, voiceCommand, context, chain, caption, license, fileTranscription, meetingSummary, dictationTemplate, rag, voiceAction, voiceConversation, meetingMode, meetingChat, meetingDocTemplate, cloudSync, onlineAuth, ads, support, inputTelemetry, suggestion`. The `keybinding` bridge is 9 methods mirroring the channels above (`src/preload/index.ts:323`), replacing the 11-method `hotkey` bridge. Envelope: `IPCResult<T>` (success/error); `app.onDataChanged` is the global refresh channel.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -185,17 +187,18 @@ Vanilla popups (`src/renderer/popups/`):
|
|||
|
||||
## 5. Renderer IA
|
||||
|
||||
Routing is state-based in `AppLayout.tsx` (`Route` union + `NAV_ITEMS`), no react-router.
|
||||
Routing is state-based in `renderer/navigation/app-navigation.tsx` (`AppRoute`, params, history/back), no react-router. `Ctrl+K` opens the search route and `Ctrl+1..3` opens Home/Records/Meetings.
|
||||
|
||||
| Page | Route | Feature |
|
||||
|---|---|---|
|
||||
| `DashboardPage` | dashboard | Voice cockpit: hero, bento tiles, multi-engine hub (STT/LLM), telemetry, recent history, file drop |
|
||||
| `HistoryPage` | history | History & memory timeline; search, tag filter, pagination, export/delete |
|
||||
| `HomePage` | home | Today summary, recording/meeting/caption starts, current blockers, recent records/meetings, file transcription, bounded free usage |
|
||||
| `UnifiedSearchPage` | search | Record+meeting search, newest-first merged results, source-aware detail navigation; source/tests complete, Electron manual proof pending |
|
||||
| `HistoryPage` | records | History & memory timeline; search, tag/mode/favorite filters, pagination, export/delete |
|
||||
| `DictionaryPage` | dictionary | Custom vocabulary editor |
|
||||
| `CommandsPage` | commands | Custom instructions + voice keyword rules + LLM chains + dictation templates |
|
||||
| `VoiceConversationPage` | conversation | Duplex voice assistant (local pipeline vs OpenAI Realtime) |
|
||||
| `KnowledgeBasePage` | knowledge | Local RAG: add/index docs, semantic query, reindex/remove |
|
||||
| `MeetingModePage` | meeting | Meeting studio: live transcript, memos, doc generation/export, diarization |
|
||||
| `MeetingModePage` | meetings | Meeting studio: live transcript, memos, doc generation/export, diarization |
|
||||
|
||||
Modals/components: `SettingsModal` (tabs General/Audio/STT/LLM/Input/License/Cloud/About), `LicenseModal`, `LicenseTab`, `CloudSyncSection`, `InputInsightsPanel` (consent + suggestion policy + weekly insights + learned phrases), `InputConsentPanel` (receipt + current-app exclusion recommendation), `InputInsightsView` (flow, friction and app-quality summaries), `OnboardingModal`, `UpgradePromptModal`, `ProBadge`, `TemplateSection`, `FileDropZone`, `OllamaGuideModal`, `CodexOAuthGuideModal`, `TitleBar`, `StatusBar`, meeting components (9), voice-conversation, payment (`CheckoutModal`, `checkout-flow.ts`), support (`SupportModal`), ads (`AdBanner`, `RewardedQuotaModal`), shared cards.
|
||||
|
||||
|
|
@ -220,6 +223,7 @@ DB schema (`src/main/db/schema.ts`, drizzle SQLite): `history`, `dictionary`, `s
|
|||
- **Local STT is packaged** (`1.3.0`): `electron-builder.yml` `extraResources` copies `sidecar-dist/sidecar` → `resources/sidecar` and `resources/ffmpeg` → `resources/ffmpeg`; `scripts/ci/verify-sidecar-bundle.mjs` gates packaging. Build locally with `npm --prefix apps/desktop run sidecar:setup && npm --prefix apps/desktop run sidecar:build`. The sidecar stays in console mode so `stdout`/`stderr` reach the app log (UTF-8, line-buffered); a packaged sidecar **must** exist or startup fails loudly instead of silently falling back to a system Python.
|
||||
- All local engine URLs (`LocalSTTService`, `LocalLLMService`, `RAGService`, `OnlineLLMService`, `STTManager`) pass through `src/main/utils/loopback.ts`, which rewrites `localhost` to `127.0.0.1`, because some Windows hosts resolve `localhost` to IPv6 only and local engines bind IPv4.
|
||||
- Meeting intelligence, RAG, voice conversation (local + Realtime), captions, file transcription: implemented.
|
||||
- **Unified search (2026-09-28): source and automated tests only.** `UnifiedSearchService` + `unifiedSearch:query` IPC + preload bridge + `UnifiedSearchPage` search records and meetings and route to their detail views. The focused service and IPC tests pass; the renderer is source/type-gated, not headful-tested. No external-terminal Electron run has yet proven `Ctrl+K`, result rendering, or both detail transitions; treat the desktop capability as `[~]` until that run is retained.
|
||||
- **LLM instruction prompts: fixed 2026-09-21 (`9c2b4d4`), not yet verified in a running app.** Running a custom instruction inserted the instruction's own wording instead of the processed result. Two faults stacked: the instruction was passed in the `text` argument with the system-prompt argument left empty, and `BASE_SYSTEM_PROMPTS` has no `custom` key so resolution fell back to `refine` **silently** — the model polished the instruction and the transcript never reached it; separately, only `{{text}}` was substituted and none of the five built-in presets use it (`{{targetLanguage}}`, `{{userPrompt}}`, or no placeholder), so the substitution was a no-op from the day it was written. Introduced in `fea923d` (2026-04-05) and present in every release `v0.1.0-alpha`..`v1.4.0` — **the path never worked; this is not a regression.** Plain actions (`refine`/`summarize`/`grammar`/`expand`) were unaffected and are now pinned by regression cases. The fix routes all three entry paths through `llm-prompts.ts` (see §2) and additionally corrects two things found alongside it: a voice shortcut naming an instruction was nullified by the `defaultLLMAction === 'none'` gate (`VoiceModeService.ts:779`), and the commands-page pipeline bench called `llm.generate`, which preload does not expose, so every run threw and the `catch` displayed the **input** as if it had succeeded — a fail-closed violation that is the reason the bug went unnoticed for five months (`CommandsPage.tsx:180-205`, now on `llm.process` with failures rendered as failures).
|
||||
- **Verification limits — do not read this as verified.** Unit tests pass (`llm-prompts.test.ts` 21, `llm-handlers.test.ts` 7, `VoiceModeService.test.ts` 22, `ChainService.test.ts` 5), and each of the four fixes was reverted individually to confirm the tests actually fail without it. `npm run lint` (apps/desktop scope) passes; `tsconfig.check.json` errors went 36 → 35 (the `llm.generate` error is gone) with no errors in the touched files. But there is **no running-app run**, and `tests/red/{instruction,chain,voice,config}.usecase.test.ts` — precisely the related paths — never executed because of the `better-sqlite3` ABI mismatch. That range is neither passing nor failing; it is untested (`11` GAP-LLM-02, GAP-INFRA-06).
|
||||
- **Key bindings: implemented and verified on Windows.** Every global shortcut now comes from one contract (`@d3ro/core/keybinding`) with multiple bindings per action, mouse-button support, and no hardcoded accelerators left in `bootstrap.ts`. A manual run on 2026-09-21 confirmed legacy migration (custom values preserved), 6 actions loaded, the uiohook keyboard **and** mouse hook active with zero boot errors, and multi-binding working; contract side is `packages/core` 117 tests GREEN with no type errors in the key-binding files (`11` GAP-KEY-01 `[x]`). Two things remain open: `KeyBindingService` has no unit test of its own, and macOS/Linux mouse behavior is unconfirmed (`11` GAP-KEY-02). The rewrite also fixed a dead hands-free double-press path, an order-dependent reserved-combo check, a `globalShortcut.unregisterAll()` that wiped the popup accelerators, and a `setEnabled(true)` that re-enabled hooking with an empty binding set.
|
||||
|
|
@ -252,6 +256,7 @@ DB schema (`src/main/db/schema.ts`, drizzle SQLite): `history`, `dictionary`, `s
|
|||
| LLM prompt / placeholder SSOT | `src/main/services/llm-prompts.ts` (shared by `VoiceModeService`, `ChainService`, `ipc/llm-handlers.ts`) |
|
||||
| DB schema | `src/main/db/schema.ts` |
|
||||
| Renderer shell / routes | `src/renderer/components/AppLayout.tsx` |
|
||||
| Unified search | `src/main/services/UnifiedSearchService.ts`, `src/main/ipc/unified-search-handlers.ts`, `src/renderer/pages/UnifiedSearchPage.tsx` |
|
||||
| Update feed SSOT | `src/main/update-feed.ts` |
|
||||
| Update policy SSOT | `release/update-policy.json` + `src/main/update-policy.ts` |
|
||||
| Path/loopback resolution | `src/main/utils/paths.ts`, `src/main/utils/loopback.ts` |
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue