| Age | Commit message (Collapse) | Author |
|
Introduce internal/apicircuit with sony/gobreaker: trip after five
consecutive failures, 45s open state, 2m count reset, half-open trial cap.
context.Canceled is not counted as a failure for breaker stats.
Wrap OpenAI TTS, Gemini TTS, OpenAI DALL-E/chat (image path), and Nano Banana
Gemini GenerateContent calls. HTTP timeouts remain unchanged in httpctx.
Made-with: Cursor
|
|
Add internal/config/defaults.go with shared model IDs, output format, OpenAI/Gemini
audio literals, and speed defaults. Wire audio.DefaultProviderConfig, CLI flags,
GUI defaulting paths, and image package re-exports to these constants. Update
command_test to use the public config identifiers.
Made-with: Cursor
|
|
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
|
|
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
|
|
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>
|
|
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>
|
|
TTS chunks
- Increase story pages from 3 to 5 (10 total with cover/gallery/back)
- Add 3 text-free gallery pages with close-up heroine poses before back cover
- Add retry logic to cover and back cover generation (same as story pages)
- Enforce adult (18+) characters in generator prompt to avoid content policy blocks
- Reduce TTS chunk size from 200 to 100 words to stay under 1-minute quality threshold
- Increase TTS timeout from 2 to 3 minutes to avoid spurious deadline exceeded errors
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
subfolder, 16:9
- Iterative image chaining: each page receives cover + prev page as pixel-level
reference (multimodal) so the model copies appearance directly, not from text alone
- --story-theme flag overrides random genre pick per run
- Gemini now generates a short comic title (---COMIC TITLE--- separator) used as
the output slug; all files named <slug>_cover.png, <slug>_page_1.png, etc.
- All comic output stored under comics/<slug>/ subdirectory
- Aspect ratio changed to 16:9 (ThinkPad X1 Gen 9 screen fit; 16:10 not supported)
- Bulgarian language rule moved to top of every prompt for stronger compliance
- Dynamic story-specific cover masthead + publisher logo badge matching story genre
- --story-theme "a thrilling space..." forces genre without touching random pool
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
narration
- Replace 3 separate comic pages with one 9:16 tall comic_strip.png
- Prompt explicitly requests 3 vertically stacked panels with consistent characters
- Add AspectRatio field to SearchOptions; NanoBanana uses it when set
- Make cinematic narration instruction more dramatic (movie trailer narrator style)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Introduce AttributionProvider interface with GetAttribution() separate from
ImageSearcher so callers only needing search/download don't carry attribution.
ImageClient composes both. Downloader.searcher and NewDownloader now take
ImageClient since attribution is needed when saving downloaded files.
Compile-time assertions updated to ImageClient.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
provider normalization
- task 009: remove translateBulgarianToEnglish from OpenAIClient and
NanoBananaClient. Image clients no longer make internal translation API calls;
callers must supply SearchOptions.Translation (processor and GUI already do).
When translation is absent, opts.Query (the Bulgarian word) is used as
fallback subject so image generation still proceeds. Update tests to pass
translation via SearchOptions rather than relying on the removed fallback.
- task 00i: consolidate duplicate ProviderGemini/ProviderOpenAI constants and
normalizeProvider() functions from internal/translation and internal/phonetic
into a shared config.NormalizeProvider(string) string in
internal/config/provider.go. Both packages now delegate to the shared
function so the normalization rule (lowercase, trim, default "gemini") has
one authoritative home.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Enable -race flag on the default 'task test' command so race conditions
are caught by default, not only when running 'task test-race'
- Add t.Parallel() to all tests in internal/image/prompt_test.go (pure
function tests with no shared state)
- Add t.Parallel() to TestReadBatchFile and its subtests in batch package
(file I/O with t.TempDir(), no global state)
- Add t.Parallel() to TestValidateBulgarianText and its subtests in audio
package (pure string validation, no shared state)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
shared prompt
- task 00g: fix gofmt violations (trailing whitespace, missing newlines,
indentation) in 8 files; all pass gofmt -l now
- task 00k: remove unused ProviderWithFallback and its tests (YAGNI — no
production caller existed; voice-level fallback via RunWithVoiceFallbacks
already covers the real use case)
- task 00h: replace private splitLines/trimSpace/isSpace helpers in
internal/batch/processor.go with strings.Split+ReplaceAll and
strings.TrimSpace from the stdlib; remove the now-redundant tests
- task 008: extract buildEducationalPrompt into internal/image/prompt.go so
the prompt-assembly policy (scene truncation cascade, char limit) lives in
one place; both OpenAIClient and NanoBananaClient delegate to it
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- Remove dead DownloadImage stub from image/search.go (always returned nil,
real implementation lives in Downloader.DownloadImage in download.go)
- Add compile-time interface assertions for OpenAIProvider, ProviderWithFallback,
and OpenAIClient to catch interface drift at compile time
- Replace http.DefaultClient (no timeout) with a shared imageHTTPClient
(60s timeout) in both OpenAIClient and NanoBananaClient Download methods;
prevents goroutine hangs on slow/unresponsive image servers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- Add file.Sync() after image download to ensure data is flushed to disk
- Add double-checking in UI updates to prevent wrong card updates
- Fix background job completion to reload files when user navigates back
- Add file size validation in image display widget
- Improve error messages for image loading failures
This fixes two issues:
1. 'png: invalid format: not enough pixel data' error when navigating during generation
2. Images not updating when navigating back to a card after background generation completes
|
|
|
|
- Add tests for audio package (62.8% coverage)
- OpenAI provider tests with mocking
- Provider interface and fallback mechanism tests
- Bulgarian text validation tests
- Audio caching functionality tests
- Add tests for anki package (84.8% coverage)
- CSV generation tests
- APKG package generation tests
- Card management and formatting tests
- Directory scanning and media handling tests
- Add test utilities and mocks
- Mock implementations for external dependencies
- Test helpers for common operations
- Utilities for creating test directories and files
- Update Taskfile.yaml with comprehensive test targets
- test: Run all tests
- test-verbose: Run with verbose output
- test-coverage: Run with coverage report
- test-coverage-html: Generate HTML coverage report
- test-race: Run with race detector
- test-short: Run only short tests
- test-all: Comprehensive suite with coverage and race detection
- clean: Remove build artifacts and test files
- Fix existing image package tests
- Remove tests for non-existent methods
- Update tests to match actual implementation
- Skip tests requiring live OpenAI API
This provides a solid foundation for ensuring code quality and catching regressions.
🤖 Generated with [opencode](https://opencode.ai)
Co-Authored-By: opencode <noreply@opencode.ai>
|
|
- Add random voice speed between 0.90-1.00 for more natural audio
- Display voice and speed info in GUI audio player
- Implement automatic retry loading for missing files (checks every 2 seconds)
- Fix voice/speed info persistence during audio playback
- Remove image caching functionality for cleaner codebase
- Rename prompt.txt to image_prompt.txt for clarity
- Fix GUI to recognize newly added cards during runtime (rescan on navigation)
- Update README to reflect removed image cache
These changes improve the user experience by making the audio more natural,
providing better feedback about audio generation parameters, and ensuring
the GUI stays synchronized with externally added cards.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
- Added automatic prompt truncation when exceeding 1000 chars
- Progressively removes less important parts: IMPORTANT notice first, then truncates scene
- Also applies 1000 char limit to custom prompts
- Added character count to prompt logging for visibility
- Ensures compatibility with API limits while maintaining prompt effectiveness
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
- Remove 42 hard-coded image generation styles
- Load styles from cache file (artistic_styles.txt)
- Generate styles via OpenAI API if file doesn't exist
- Regenerate styles automatically if older than one week
- Shuffle styles on each use to prevent LLM bias
- Fix bug where generated images appeared in wrong dialog
- Handle empty custom prompts properly
- Remove Bulgarian word references from image prompts
- Improve subject focus and visibility in prompts
- Add error handling when styles cannot be loaded
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
|
|
- Generate meaningful scenes for each Bulgarian word using OpenAI
- Scene descriptions use English words for DALL-E compatibility
- Creates more engaging and memorable flashcards with context
- Bump version to v0.2.0
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
- Delete Pixabay and Unsplash implementation files
- Remove API key configuration for both services
- Update CLI and GUI to only support OpenAI DALL-E
- Update documentation to reflect OpenAI as sole image provider
- Fix tests to handle nil client in OpenAI implementation
- Simplify configuration examples
The application now exclusively uses OpenAI DALL-E for image generation,
providing AI-generated educational images with creative art styles.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
|
|
- Change all button labels to show lowercase letters (g, n, i, a, r, d, p)
- Update delete confirmation dialog to show lowercase y/n
- Set default export location to anki_cards directory
- Add note about CSV needing to be in same directory as media files
- Fix prompt generation to remove Bulgarian word reference
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
- Add text area next to image display for custom image generation prompts
- Users can specify their own prompts or leave empty for auto-generation
- Display the used prompt in the text area after generation
- Load prompts from attribution files when navigating to existing cards
- Add keyboard shortcuts for all GUI buttons:
- G: Generate, N: New Word, I: Regenerate Image, A: Regenerate Audio
- R: Regenerate All, D: Delete, P: Play audio
- Left/Right arrows: Navigate between words
- Y/N: Confirm/cancel delete dialog
- Update UI layout with equal 50/50 split between image and prompt
- Enable text wrapping in prompt text area
- Add 25% chance to ask OpenAI for creative photo style suggestions
- Fix concurrent processing to properly use custom prompts
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
- Automatic Bulgarian to English translation for all words
- Save translations to separate _translation.txt files
- Include translations in Anki CSV export
- Add detailed attribution files for audio and images:
- Audio: model, voice, speed, instructions, processed text
- Image: model, size, quality, style, full prompt used
- Expand image styles to 42 different options (including superhero comic, yoga, etc.)
- Improve image prompts to strongly avoid text generation
- Fix image overwrite issue - now overwrites existing files instead of failing
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
- Removed espeak audio provider completely, now only uses OpenAI TTS
- Audio now uses random voice selection by default (can override with --openai-voice)
- Added --all-voices flag to generate audio in all 11 OpenAI voices
- Images now use random art styles (13 different styles including superhero, yoga, cat-themed)
- Fixed TTS to remove punctuation marks before speaking
- Updated Bulgarian pronunciation instructions to explicitly avoid Russian accent
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
- Add support for OpenAI's new gpt-4o-mini-tts model with customizable voice instructions
- Add OpenAIInstruction field to audio configuration for natural language voice control
- Update CLI with --openai-instruction flag for runtime voice customization
- Enhanced cache key generation to include voice instructions
- Update default model to gpt-4o-mini-tts with Bulgarian-optimized instructions
- Add support for new voices: ash, ballad, coral, sage, verse
- Improve error handling for models requiring special API access
- Update documentation with examples and model information
- Create .totalrecall.yaml.example with comprehensive configuration options
Note: The gpt-4o-mini-tts model requires special API access and may not be available to all accounts yet.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
- Implement OpenAI DALL-E provider for generating educational flashcard images
- Add support for DALL-E 2 and DALL-E 3 with configurable size, quality, and style
- Implement intelligent caching to minimize API costs
- Make OpenAI the default provider for both audio (TTS) and images (DALL-E)
- Add automatic fallback to free alternatives (espeak/pixabay) when OpenAI unavailable
- Fix bug where cached images couldn't be copied to output directory
- Update documentation with OpenAI setup instructions and examples
- Add comprehensive unit tests for OpenAI image provider
- Bump version to 0.1.0
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
|