diff options
Diffstat (limited to 'internal/cli')
| -rw-r--r-- | internal/cli/command.go | 1 | ||||
| -rw-r--r-- | internal/cli/command_test.go | 12 | ||||
| -rw-r--r-- | internal/cli/flags.go | 2 | ||||
| -rw-r--r-- | internal/cli/flags_test.go | 3 |
4 files changed, 17 insertions, 1 deletions
diff --git a/internal/cli/command.go b/internal/cli/command.go index 43a03bc..526dffe 100644 --- a/internal/cli/command.go +++ b/internal/cli/command.go @@ -22,6 +22,7 @@ Examples: totalrecall # Launch interactive GUI (default) totalrecall ябълка # Generate materials for "apple" via CLI totalrecall --batch words.txt # Process multiple words from file + totalrecall --retry-failed-assets # Resume incomplete cards in the output directory totalrecall --archive # Archive existing cards directory Batch file formats: diff --git a/internal/cli/command_test.go b/internal/cli/command_test.go index 80626eb..4c95c3b 100644 --- a/internal/cli/command_test.go +++ b/internal/cli/command_test.go @@ -32,6 +32,9 @@ func TestCreateRootCommand(t *testing.T) { if !strings.Contains(cmd.Long, "Explicit CLI and batch runs also use Nano Banana by default") { t.Errorf("Expected Long description to describe the CLI and batch Nano Banana default") } + if !strings.Contains(cmd.Long, "--retry-failed-assets") { + t.Errorf("Expected Long description to mention retry-failed-assets mode") + } // Test that flags are set up flagTests := []struct { @@ -45,6 +48,7 @@ func TestCreateRootCommand(t *testing.T) { {"batch", true}, {"skip-audio", true}, {"skip-images", true}, + {"retry-failed-assets", true}, {"anki", true}, {"anki-csv", true}, {"deck-name", true}, @@ -119,6 +123,14 @@ func TestSetupFlags(t *testing.T) { t.Errorf("Expected image-api help to describe the CLI Nano Banana default and config fallback, got %q", imageAPIFlag.Usage) } + retryFailedAssetsFlag := cmd.Flags().Lookup("retry-failed-assets") + if retryFailedAssetsFlag == nil { + t.Fatal("retry-failed-assets flag not found") + } + if !strings.Contains(retryFailedAssetsFlag.Usage, "stopping on the first error") { + t.Errorf("Expected retry-failed-assets help to describe stop-on-first-error behavior, got %q", retryFailedAssetsFlag.Usage) + } + openAIVoiceFlag := cmd.Flags().Lookup("openai-voice") if openAIVoiceFlag == nil { t.Fatal("openai-voice flag not found") diff --git a/internal/cli/flags.go b/internal/cli/flags.go index 43e3b23..bdcc88b 100644 --- a/internal/cli/flags.go +++ b/internal/cli/flags.go @@ -38,6 +38,7 @@ type Flags struct { VideoEnabled bool // --video: whether to prompt for Veo video generation after --story completes SkipAudio bool SkipImages bool + RetryFailedAssets bool GenerateAnki bool AnkiCSV bool DeckName string @@ -131,6 +132,7 @@ func setupFlags(cmd *cobra.Command, flags *Flags) { "Prompt to generate Veo videos after comic generation (default true; use --video=false to skip)") cmd.Flags().BoolVar(&flags.SkipAudio, "skip-audio", false, "Skip audio generation") cmd.Flags().BoolVar(&flags.SkipImages, "skip-images", false, "Skip image download") + cmd.Flags().BoolVar(&flags.RetryFailedAssets, "retry-failed-assets", false, "Scan existing cards and regenerate missing or failed audio/image assets, stopping on the first error") cmd.Flags().BoolVar(&flags.GenerateAnki, "anki", false, "Generate Anki import file (APKG format by default, use --anki-csv for legacy CSV)") cmd.Flags().BoolVar(&flags.AnkiCSV, "anki-csv", false, "Generate legacy CSV format instead of APKG when using --anki") cmd.Flags().StringVar(&flags.DeckName, "deck-name", flags.DeckName, "Deck name for APKG export") diff --git a/internal/cli/flags_test.go b/internal/cli/flags_test.go index 4b59bee..5c56770 100644 --- a/internal/cli/flags_test.go +++ b/internal/cli/flags_test.go @@ -51,6 +51,7 @@ func TestNewFlags(t *testing.T) { }{ {"SkipAudio", flags.SkipAudio}, {"SkipImages", flags.SkipImages}, + {"RetryFailedAssets", flags.RetryFailedAssets}, {"GenerateAnki", flags.GenerateAnki}, {"AnkiCSV", flags.AnkiCSV}, {"ListModels", flags.ListModels}, @@ -94,7 +95,7 @@ func TestFlagsStructure(t *testing.T) { expectedFields := []string{ "CfgFile", "OutputDir", "AudioFormat", "AudioFormatSpecified", "AudioProvider", "ImageAPI", "ImageAPISpecified", "BatchFile", - "SkipAudio", "SkipImages", "GenerateAnki", "AnkiCSV", "DeckName", + "SkipAudio", "SkipImages", "RetryFailedAssets", "GenerateAnki", "AnkiCSV", "DeckName", "ListModels", "AllVoices", "NoAutoPlay", "OpenAIModel", "OpenAIVoice", "OpenAISpeed", "OpenAIInstruction", "OpenAIImageModel", "OpenAIImageSize", "OpenAIImageQuality", "OpenAIImageStyle", |
