- Reduce ActionInput.svelte from 1521 to 689 lines (55% reduction)
- Create ActionInputOrchestrator.ts for reusable helpers (suggestions, translation)
- Remove unused imports and consolidate builder functions
- All extracted services properly export types from index.ts
- Typecheck passes (only pre-existing errors remain)
- ActionInput is now pure UI code with business logic in services
Extract export data gathering logic from Header.svelte into a dedicated
coordination service. The service gathers all story data in parallel:
entries, characters, locations, items, story beats, lorebook entries,
embedded images, checkpoints, branches, and chapters.
ExportCoordinationService is 81 lines. Header.svelte now delegates to
gatherStoryData() instead of inline Promise.all calls.
Extract image embedding/processing logic from StoryEntry.svelte into
a dedicated service. Provides four functions for processing narrative
content with embedded images:
- processContentWithImages: Standard regex-based marker system
- processVisualProseWithImages: HTML sanitization with image injection
- processContentWithInlineImages: <pic> tag replacement
- processVisualProseWithInlineImages: Combined Visual Prose + inline
- Created RetryService.ts (236 lines) for retry/stop/restore operations
- Service handles full state restore (in-memory backup with snapshots)
- Service handles persistent restore (ID-based cleanup for cross-session retry)
- Uses callback pattern to avoid direct store imports
- ActionInput.svelte delegates to retryService.handleStopGeneration()
and retryService.handleRetryLastMessage()
- ActionInput.svelte reduced from 1765 to 1702 lines (63 lines less)
- Refactored ActionInput.svelte to delegate generation orchestration to GenerationPipeline
- Replaced inline retrieval/narrative/classification/translation/image/post phases with pipeline
- Added buildPipelineDependencies() helper to wire AIService methods to pipeline
- Added handlePipelineEvent() for processing pipeline events and updating UI state
- Extracted translateWorldStateElements() as a helper function
- Fixed PostGenerationPhase to use activeThreads: StoryBeat[] instead of pendingQuests: string[]
- Fixed WorldState.currentLocation type to be Location | undefined
- Made lorebookEntries optional in restoreFromRetryBackup parameter
Note: ActionInput.svelte is now 1765 lines (down from ~2288). Further reduction requires
extracting RetryService (US-013) and potentially other services.
Thin orchestrator that coordinates all generation phases in order:
pre → retrieval → narrative → classification → translation → image → post
- Aggregates all phase dependencies into PipelineDependencies interface
- Runs phases sequentially, yielding all events for UI updates
- Handles abort signals and fatal errors
- Returns comprehensive PipelineResult with all phase results
Add ImagePhase service for coordinating image generation in the pipeline:
- Check if image generation is enabled and auto-generate is on
- Call aiService.generateImagesForNarrative() for both inline and analyzed modes
- Support skip reasons: disabled, auto_generate_off, not_configured, aborted
- Handle errors gracefully (non-fatal)
Adds TranslationPhase service for handling narration translation.
- Checks if translation is enabled via TranslationService.shouldTranslateNarration()
- Gracefully handles translation stub errors (non-fatal)
- Yields phase_start and phase_complete events
- Returns TranslationResult2 with translated content or null on skip/error
Extract world state classification logic into a dedicated phase service
that coordinates entity updates (characters, locations, items, story
beats) via dependency injection.
Extract memory and lorebook retrieval logic into dedicated phase service.
Coordinates timeline fill or agentic retrieval based on settings, and
runs lorebook entry retrieval (tiered injection) in parallel.
Add PreGenerationPhase service to handle pre-generation setup:
- Prepare retry state backup data for restore capability
- Capture time tracking context in backup
- Yield phase_start and phase_complete events
Files added:
- src/lib/services/generation/phases/PreGenerationPhase.ts (113 lines)
- src/lib/services/generation/phases/index.ts
The phase prepares RetryBackupData that the caller applies via
ui.createRetryBackup(), maintaining separation from UI store.
Remove OpenRouter-specific provider routing code. Users can now use
the manual body JSON feature for any provider-specific options like
{ "provider": { "order": ["openai"] } }.
Changes:
- Delete providers.ts (DEFAULT_PROVIDERS list)
- Delete ProviderOnlySelector.svelte component
- Remove providerOnly from GenerationPreset and related types
- Remove providerOnly from apiSettings and all service settings
- Remove provider routing code from generate.ts
- Remove providerOnly handling from requestOverrides.ts
- Update all components to remove providerOptions prop chain
- Update prompt export/import to exclude providerOnly