diff --git a/story/writer.py b/story/writer.py index 5b6b1c5..07d1160 100644 --- a/story/writer.py +++ b/story/writer.py @@ -6,6 +6,38 @@ from story.style_persona import get_style_guidelines from story.editor import evaluate_chapter_quality +def expand_beats_to_treatment(beats, pov_char, genre, folder): + """Expand sparse scene beats into a Director's Treatment using a fast model. + This pre-flight step gives the writer detailed staging and emotional direction, + reducing rewrites by preventing skipped beats and flat pacing.""" + if not beats: + return None + prompt = f""" + ROLE: Story Director + TASK: Expand the following sparse scene beats into a concise "Director's Treatment". + + GENRE: {genre} + POV_CHARACTER: {pov_char or 'Protagonist'} + SCENE_BEATS: {json.dumps(beats)} + + For EACH beat, provide 3-4 sentences covering: + 1. STAGING: Where are characters physically? How do they enter/exit the scene? + 2. SENSORY ANCHOR: One specific sensory detail (sound, smell, texture) to ground the beat. + 3. EMOTIONAL SHIFT: What is the POV character's internal state at the START vs END of this beat? + 4. SUBTEXT: What does the POV character want vs. what they actually do or say? + + OUTPUT: Prose treatment only. Do NOT write the chapter prose itself. + """ + try: + response = ai_models.model_logic.generate_content(prompt) + utils.log_usage(folder, ai_models.model_logic.name, response.usage_metadata) + utils.log("WRITER", " -> Beat expansion complete.") + return response.text + except Exception as e: + utils.log("WRITER", f" -> Beat expansion failed: {e}. Using raw beats.") + return None + + def write_chapter(chap, bp, folder, prev_sum, tracking=None, prev_content=None, next_chapter_hint=""): pacing = chap.get('pacing', 'Standard') est_words = chap.get('estimated_words', 'Flexible') @@ -101,6 +133,10 @@ def write_chapter(chap, bp, folder, prev_sum, tracking=None, prev_content=None, trunc_content = utils.truncate_to_tokens(prev_content, 1000) prev_context_block = f"\nPREVIOUS CHAPTER TEXT (Last ~1000 Tokens — For Immediate Continuity):\n{trunc_content}\n" + utils.log("WRITER", f" -> Expanding beats to Director's Treatment...") + treatment = expand_beats_to_treatment(chap.get('beats', []), pov_char, genre, folder) + treatment_block = f"\n DIRECTORS_TREATMENT (Staged expansion of the beats — use this as your scene blueprint; DRAMATIZE every moment, do NOT summarize):\n{treatment}\n" if treatment else "" + total_chapters = ls.get('chapters', '?') prompt = f""" ROLE: Fiction Writer @@ -168,6 +204,7 @@ def write_chapter(chap, bp, folder, prev_sum, tracking=None, prev_content=None, - CHARACTERS: {json.dumps(chars_for_writer)} {char_visuals} - SCENE_BEATS: {json.dumps(chap['beats'])} + {treatment_block} OUTPUT: Markdown text. """