diff --git a/templates/project_setup.html b/templates/project_setup.html index 092b991..9b7c07b 100644 --- a/templates/project_setup.html +++ b/templates/project_setup.html @@ -121,12 +121,12 @@
- +
- +
- +
diff --git a/web/routes/project.py b/web/routes/project.py index 9e20d57..c8a073d 100644 --- a/web/routes/project.py +++ b/web/routes/project.py @@ -30,10 +30,6 @@ def project_setup_wizard(): try: ai_setup.init_models() except: pass - if not ai_models.model_logic: - flash("AI models not initialized.") - return redirect(url_for('project.index')) - prompt = f""" ROLE: Publishing Analyst TASK: Suggest metadata for a story concept. @@ -67,13 +63,46 @@ def project_setup_wizard(): }} """ + _default_suggestions = { + "title": concept[:60] if concept else "New Project", + "genre": "Fiction", + "target_audience": "", + "tone": "", + "length_category": "4", + "estimated_chapters": 20, + "estimated_word_count": "75,000", + "include_prologue": False, + "include_epilogue": False, + "tropes": [], + "pov_style": "", + "time_period": "Modern", + "spice": "", + "violence": "", + "is_series": False, + "series_title": "", + "narrative_tense": "", + "language_style": "", + "dialogue_style": "", + "page_orientation": "Portrait", + "formatting_rules": [], + "author_bio": "" + } + suggestions = {} - try: - response = ai_models.model_logic.generate_content(prompt) - suggestions = json.loads(utils.clean_json(response.text)) - except Exception as e: - flash(f"AI Analysis failed: {e}") - suggestions = {"title": "New Project", "genre": "Fiction"} + if not ai_models.model_logic: + flash("AI models not initialized — fill in the details manually.", "warning") + suggestions = _default_suggestions + else: + try: + response = ai_models.model_logic.generate_content(prompt) + suggestions = json.loads(utils.clean_json(response.text)) + # Ensure list fields are always lists + for list_field in ("tropes", "formatting_rules"): + if not isinstance(suggestions.get(list_field), list): + suggestions[list_field] = [] + except Exception as e: + flash(f"AI Analysis failed — fill in the details manually. ({e})", "warning") + suggestions = _default_suggestions personas = {} if os.path.exists(config.PERSONAS_FILE): @@ -201,8 +230,33 @@ def create_project_final(): try: ai_setup.init_models() - bible = planner.enrich(bible, proj_path) - except: pass + # Build a per-book blueprint matching what enrich() expects + first_book = bible['books'][0] if bible.get('books') else {} + bp = { + 'manual_instruction': first_book.get('manual_instruction', concept), + 'book_metadata': { + 'title': bible['project_metadata']['title'], + 'genre': bible['project_metadata']['genre'], + 'style': dict(bible['project_metadata'].get('style', {})), + }, + 'length_settings': dict(bible['project_metadata'].get('length_settings', {})), + 'characters': [], + 'plot_beats': [], + } + bp = planner.enrich(bp, proj_path) + # Merge enriched characters and plot_beats back into the bible + if bp.get('characters'): + bible['characters'] = bp['characters'] + if bp.get('plot_beats') and bible.get('books'): + bible['books'][0]['plot_beats'] = bp['plot_beats'] + # Merge enriched style fields back (structure_prompt, content_warnings) + bm = bp.get('book_metadata', {}) + if bm.get('structure_prompt') and bible.get('books'): + bible['books'][0]['structure_prompt'] = bm['structure_prompt'] + if bm.get('content_warnings'): + bible['project_metadata']['content_warnings'] = bm['content_warnings'] + except Exception: + pass with open(os.path.join(proj_path, "bible.json"), 'w') as f: json.dump(bible, f, indent=2)