summaryrefslogtreecommitdiff
path: root/internal/processor
AgeCommit message (Collapse)Author
2026-04-08refactor(processor): split BatchProcessor, AnkiExporter, CLIConfigResolverPaul Buetow
Extract CLIConfigResolver for flag/config precedence and GUI wiring; embed it on Processor so audio and image helpers use promoted accessors. Move batch file flow to BatchProcessor and Anki generation to AnkiExporter; Processor delegates while keeping per-word processing and translation cache. Made-with: Cursor
2026-04-08refactor: registry pattern for audio and image provider factoriesPaul Buetow
Add internal/registry generic Registry[K,T] for keyed factory registration. Wire audio.NewProvider via registered per-provider constructors; GUI and processor newImageSearcher use registries of *Orchestrator/*Processor methods. Export image.ImageProviderOpenAI and ImageProviderNanoBanana from search.go and use them across gui to avoid duplicate string constants. Made-with: Cursor
2026-04-08feat(httpctx): add timeouts for OpenAI, Gemini, and HTTP downloadsPaul Buetow
Introduce internal/httpctx with non-zero http.Client timeouts for go-openai and google.golang.org/genai, shared image download client, and WithTimeoutUnlessSet for operation-level deadlines when callers use Background. Wire NewOpenAIClient/NewGenAIClient everywhere clients are constructed. Apply Search timeouts for DALL-E and Nano Banana, provider audio timeouts, model-list timeouts, Veo operation timeouts, story page download context, and single-word CLI processing cap. Made-with: Cursor
2026-04-08fix(processor): propagate errors from attribution and sidecar writesPaul Buetow
Return errors from saveAudioAttribution (including audio_metadata.txt), image prompt persistence (callback + saveImagePrompt), and ProcessWordWithTranslationAndType (card type, translation, phonetic) instead of only logging warnings so callers see partial failures. Made-with: Cursor
2026-04-06refactor: extract shared CardStore into internal/store to eliminate duplicationPaul Buetow
FindCardDirectory, FindOrCreateCardDirectory, GenerateCardID and the ScanWords helper previously existed in both internal/utils.go (as standalone functions) and were partially duplicated in internal/gui/card_service.go (readWordFromDir, ScanExistingWords). Introduce internal/store.CardStore as the single source of truth for all on-disk card-directory operations. Both internal/processor and internal/gui now hold a *store.CardStore field and delegate to it, removing the last copy of the directory-scanning loop from card_service.go. internal/utils.go keeps thin forwarding wrappers for callers that import the root internal package. Also adds table-driven unit tests for the new package covering FindCardDirectory (including legacy _word.txt fallback), FindOrCreateCardDirectory, and CardStore.ScanWords. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06refactor: consolidate provider factory test seams into shared named typesPaul Buetow
Define audio.ProviderFactory, image.PromptAwareClient, image.OpenAIClientFactory, image.NanoBananaClientFactory, and image.ClientFactories as the single source of truth for the three injectable factory signatures that were previously duplicated across processor.Processor, gui.Application, and gui.GenerationOrchestrator. Replace all three separate function-type fields with imageFactories image.ClientFactories + newAudioProvider audio.ProviderFactory, eliminating the parallel field declarations and the local promptAwareImageClient interface in gui/generator.go. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06refactor: remove Viper coupling from processor package (DIP)Paul Buetow
Resolve all Viper config values once at startup in cmd/totalrecall/main.go via the new newProcessorConfig() helper. The exported processor.Config struct replaces the internal viperConfig type, and NewProcessor now accepts *Config instead of querying Viper internally. The processor package no longer imports Viper at all. Tests are updated to pass Config values directly, eliminating the viper.Set/Reset boilerplate that coupled tests to the global singleton. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06refactor: decompose Processor god object into focused files (SRP)Paul Buetow
Extract audio coordination (voice selection, config assembly, attribution writing) into audio_coordinator.go, card directory management into card_store.go, and image downloading/searcher construction into image_downloader.go. processor.go shrinks from ~1119 to ~575 lines, each file now has a single clear responsibility. Also apply go fmt to all touched files. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03fix: resolve all golangci-lint issuesPaul Buetow
- audio/fallbacks.go: lowercase error string per Go convention - gui/app.go: remove empty else branch in keyboard shortcut handler - audio/provider_test.go: remove unused mockProvider type - update test assertions in voices_test.go and processor_test.go to match the corrected lowercase error string Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03tasks 00d, 006, 007: move test seams to struct fields, centralize Viper ↵Paul Buetow
config, extract shared card-dir logic task 00d: remove package-level var test seams from processor and gui packages; factory functions (newAudioProvider, newOpenAIImageClient, newNanoBananaImageClient) are now struct fields on Processor and Application, initialized with production defaults in constructors and replaced in tests without global mutation. task 006: add viperConfig struct captured once in NewProcessor; no method body calls viper.GetString/IsSet/GetFloat64 directly any more — all config-file values are accessed via p.viperCfg fields. task 007: extract FindCardDirectory and FindOrCreateCardDirectory into internal/utils.go; both Processor.findCardDirectory and Application.findCardDirectory now delegate to the shared implementation, which also handles the legacy _word.txt backward-compat fallback. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02task zz: add Voices()/BuildAttribution() to Provider interface [OCP]Paul Buetow
Extend audio.Provider with Voices() []string and BuildAttribution() string so all provider-specific behaviour is encapsulated in the implementation rather than scattered as switch-cases across callers. Add package-level VoicesFor(name) and BuildAttributionFor(name, params) for callers (processor, GUI) that need these before constructing a Provider instance. Add AttributionParamsFrom(config, word, ...) so callers can build AttributionParams from the flat Config without a manual provider switch. Implement both new interface methods in OpenAIProvider and GeminiProvider. Update all Provider mock/fake types in tests. Migrate audioVoicesForProvider() and saveAudioAttribution() in both processor.go and gui/generator.go to use the new package-level helpers, replacing the 10+ duplicated switch blocks. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02task zy: move GUI application launch out of Processor into cmd/main.go [SoC]Paul Buetow
Replace Processor.RunGUIMode() with a standalone runGUIMode() function in the composition root (cmd/main.go) that calls proc.GUIConfig() to get the GUI settings and then owns the gui.New()/Run() lifecycle. The processor package still imports gui for the gui.Config return type; complete removal of that import is deferred to task 000 (god-object decomposition) where the Processor itself will be split up. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02task 00e: inject phonetic.Fetcher and translation.Translator into gui.New()Paul Buetow
Add PhoneticFetcher and Translator fields to gui.Config so callers can inject ready-to-use instances. gui.New() uses the injected values when non-nil and falls back to constructing from provider/key fields otherwise. The processor composition root now builds both dependencies and sets them on gui.Config, keeping construction logic out of gui.New(). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02task 00c/00f: thread context through processor audio/image calls; per-word ↵Paul Buetow
batch timeout - Thread ctx context.Context through generateAudio, generateAudioBgBg, generateAudioWithVoice, generateAudioWithVoiceAndFilename, generateAudioWithVoiceAndFilenameInDir, and downloadImagesWithTranslation. Also add ctx to ProcessWordWithTranslationAndType so callers can control the deadline for the full word-processing pipeline. - In ProcessBatch, create a context.WithTimeout(5 * time.Minute) per word so a single hung TTS or image API call cannot block the whole batch run. Previously both functions created context.Background() internally, making cancellation impossible. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02task 003: handle home-dir and APKG marshal errorsPaul Buetow
2026-04-02task 002: restore Gemini warning outputPaul Buetow
2026-04-02task 002: restore Gemini fallback output and add failure coveragePaul Buetow
2026-04-02task 002: centralize Gemini voice fallbacksPaul Buetow
2026-04-02task 001: remove committed debug printf tracesPaul Buetow
2026-04-02Release v0.9.0v0.9.0Paul Buetow
2026-04-02Fix verification gate lint and test issuesPaul Buetow
2026-04-02Fix processor audio metadata instruction gatingPaul Buetow
2026-04-02Align processor attribution with provider semanticsPaul Buetow
2026-04-02Fix processor Gemini/OpenAI voice wiringPaul Buetow
2026-04-02Fix Gemini voice selection in processorPaul Buetow
2026-04-02Centralize audio sidecar generationPaul Buetow
2026-04-02Fix processor GUI parity gapsPaul Buetow
2026-04-02Align GUI and CLI provider wiringPaul Buetow
2026-04-01Wire Gemini audio into GUIPaul Buetow
2026-04-01Fix multi-voice audio path resolutionPaul Buetow
2026-04-01Honor config audio format for OpenAIPaul Buetow
2026-04-01Fix Gemini audio format handlingPaul Buetow
2026-04-01Add Gemini audio CLI flagsPaul Buetow
2026-04-01zg: add bg-bg consumer coveragePaul Buetow
2026-04-01zg: add consumer coverage for shared voice listsPaul Buetow
2026-04-01zg: extract shared audio voice listsPaul Buetow
2026-04-01z8: preserve Nano Banana CLI precedencePaul Buetow
2026-04-01z8: finish Nano Banana CLI wiringPaul Buetow
2026-04-01z8: wire Nano Banana into processorPaul Buetow
2026-04-01z9: fix GUI launch provider propagationPaul Buetow
2026-04-01zt: route GUI translations through shared translatorPaul Buetow
2026-04-01zu: switch GUI phonetics to shared fetcherPaul Buetow
2026-04-01zs: preserve OpenAI default for phoneticsPaul Buetow
2026-04-01zs: add Gemini-backed phonetic fetchingPaul Buetow
2026-04-01zr: preserve Gemini init errors and docsPaul Buetow
2026-04-01zr: restore OpenAI default translation providerPaul Buetow
2026-04-01zr: add Gemini-backed translation providerPaul Buetow
2026-03-08refactor(task-376): share audio attribution builderPaul Buetow
2026-03-08test(task-374): fix errcheck issues in tests and support codePaul Buetow
2026-01-21fix: bg-bg cards generating audio in separate directoriesPaul Buetow
- Fix critical bug where generateAudioBgBg() was creating two separate card directories (one for front audio, one for back audio) - Root cause: generateAudioWithVoiceAndFilename() calls findOrCreateWordDirectory() with both the front word AND the back word, creating separate directories - Solution: Pass wordDir to both audio generation calls - Create new generateAudioWithVoiceAndFilenameInDir() function - Refactor generateAudioWithVoiceAndFilename() to use new function - generateAudioBgBg() now finds directory ONCE and passes it to both calls This fixes the issue where opening a bg-bg card showed 'no audio loaded' because audio_front.mp3 and audio_back.mp3 were in different directories.