diff --git a/examples/scientific_paper_writer.yaml b/examples/scientific_paper_writer.yaml index 1c17ef55..9115bf1d 100644 --- a/examples/scientific_paper_writer.yaml +++ b/examples/scientific_paper_writer.yaml @@ -31,11 +31,9 @@ context: - brainstorming - vetting - structure - - deep_research - - core_content - - framing_content - - proofreading - - formatting + - section_writing + - paper_review + - latex_generation writing_stage: null initial_message: "" paper_details: @@ -48,20 +46,29 @@ context: brainstorming_summary: null vetting_sources: [] table_of_contents: null - deep_research_sources: null - core_content_progress: - current_section_index: 0 - accept_current_section: false - paper_content: {} - final_paper_text: null - proofread_paper: null + # Section writing stage + section_paths: null + current_section_index: 0 + current_section_path: null + section_content: {} + # Paper review stage + assembled_paper: null + reviewed_paper: null + # LaTeX generation stage + latex_structure: null + latex_sections: {} + current_latex_index: 0 + current_latex_section: null + latex_sections_complete: false latex_source: null + latex_compiled: false + latex_errors: null + latex_fix_attempts: 0 pdf_path: null # For vetting stage complex workflow vetting_expanded_plan: null vetting_plan_index: 0 current_vetting_action: null - current_section_to_write: null # Agent definitions - ALL original agents with exact prompts from V1 agents: @@ -180,14 +187,13 @@ agents: elif command == '!stage': stage_descriptions = { 'intro': 'Introduction to the writing system.', - 'brainstorming': 'Refines the high-level idea for the paper.', - 'vetting': 'Interactive research stage where you work with the assistant to compile high-quality sources. You can specify criteria and refine the citation list through discussion.', + 'discovery': 'Interactive setup where we collect all paper requirements.', + 'brainstorming': 'Refines the high-level idea for the paper.', + 'vetting': 'Interactive research stage where you work with the assistant to compile high-quality sources.', 'structure': 'Defines the complete table of contents for the paper.', - 'deep_research': 'Performs detailed research for each section of the paper.', - 'core_content': 'Writes the core content for each section, one by one.', - 'framing_content': 'Writes the Abstract and Conclusion sections.', - 'proofreading': 'Proofreads the entire paper for errors and inconsistencies.', - 'formatting': 'Formats the paper in LaTeX, compiles it, and saves the output.' + 'section_writing': 'Writes each section of the paper individually. Selects relevant sources, finds additional sources if needed, then writes the content.', + 'paper_review': 'Reviews the complete assembled paper for consistency, grammar, style, citations, and logical flow.', + 'latex_generation': 'Generates LaTeX structure, converts sections to LaTeX, assembles the document, compiles with pdflatex, and fixes any compilation errors.' } current_stage = context.get('writing_stage', 'unknown') description = stage_descriptions.get(current_stage, 'No description available.') @@ -583,292 +589,517 @@ agents: context['table_of_contents'] = input_data result = input_data + # ============================================ - # Deep Research Agent + # SECTION WRITING STAGE # ============================================ - deep_research_agent: - type: llm - config: - provider: openai - model: gpt-4-turbo - system_prompt: | - You are a deep research specialist. The paper's topic is: {{ context.paper_details.topic }}. - Start by introducing yourself and explaining: "I'll perform detailed research for each section of your paper. For each section, I'll find relevant sources and explain how they relate specifically to that section's content. This will provide the foundation for writing comprehensive section content. Please let me know if you'd like me to begin, or if you have specific research directions." - - Once the user confirms or provides input, research each section of the paper in detail. Find detailed, relevant - sources for each section. For each source, provide a full citation, link, a general summary, and a paragraph on - how the source's content specifically relates to the section being researched. - - deep_research_saver: + section_writing_controller: type: tool config: tools: - - name: save_deep_research + - name: section_controller code: | - # Save deep research sources to context - context['deep_research_sources'] = input_data - result = input_data + import sys + import json + print(f"DEBUG section_writing_controller", file=sys.stderr) - # ============================================ - # Core Content Stage Agents - # ============================================ - core_content_manager: - type: tool - config: - tools: - - name: section_manager - code: | - toc = context.get('table_of_contents', '') - # Parse TOC to get list of sections (simplified for now) - sections = ['Introduction', 'Methods', 'Results', 'Discussion'] # This would be parsed from TOC - - progress = context.get('core_content_progress', {}) - current_index = progress.get('current_section_index', 0) - - if progress.get('accept_current_section'): - # Save previous section's content and advance - if current_index > 0 and current_index <= len(sections): - last_section_title = sections[current_index - 1] - # Get the last message from history - if 'history' in context and len(context['history']) > 0: - last_content = context['history'][-1].get('message', '') - else: - last_content = input_data - context.setdefault('paper_content', {})[last_section_title] = last_content - - progress['accept_current_section'] = False - - if current_index < len(sections): - section_to_write = sections[current_index] - context['current_section_to_write'] = section_to_write - progress['current_section_index'] = current_index + 1 - result = f"WRITE_SECTION:{section_to_write}" + # Parse table of contents JSON to get section hierarchy + if not context.get('section_paths'): + toc_text = context.get('table_of_contents', '') + if not toc_text: + result = "ERROR: No table of contents found. Please complete structure stage first." + else: + # Try to parse as JSON, fallback to simple parsing + try: + if toc_text.strip().startswith('{') or toc_text.strip().startswith('['): + toc_data = json.loads(toc_text) + + # Extract all section paths from nested structure + paths = [] + def extract_paths(obj, prefix=""): + if isinstance(obj, dict): + for key, val in obj.items(): + if key not in ['description', 'purpose']: + new_prefix = f"{prefix}/{key}" if prefix else key + paths.append(new_prefix) + if isinstance(val, dict): + extract_paths(val, new_prefix) + elif isinstance(obj, list): + for item in obj: + extract_paths(item, prefix) + + extract_paths(toc_data) + else: + # Simple line-based parsing for non-JSON TOC + paths = [] + for line in toc_text.split('\n'): + line = line.strip() + if line and not line.startswith('-') and not line.lower().startswith('table'): + # Extract section title (remove numbering) + section = line.split('.', 1)[-1].strip() if '.' in line else line + if section: + paths.append(section) + + context['section_paths'] = paths + context['current_section_index'] = 0 + except Exception as e: + print(f"ERROR parsing TOC: {e}", file=sys.stderr) + # Fallback to generic sections + context['section_paths'] = ['Introduction', 'Methods', 'Results', 'Discussion'] + context['current_section_index'] = 0 + + section_paths = context.get('section_paths', []) + current_index = context.get('current_section_index', 0) + + if not section_paths: + result = "ERROR: No section paths available." + elif current_index >= len(section_paths): + # All sections complete + context['writing_stage'] = 'paper_review' + result = "All sections written! Moving to paper review stage. Type !next to proceed." else: - result = "FINISH_CORE_CONTENT:Core content writing is complete. Use !next to proceed to framing_content." - context['writing_stage'] = 'framing_content' + current_path = section_paths[current_index] + context['current_section_path'] = current_path + result = f"ROUTE_SELECT_SOURCES:{current_path}" - core_content_agent: + source_selector: type: llm config: provider: openai model: gpt-4-turbo + memory_enabled: true + max_history: 10 system_prompt: | - You are a scientific writer. Your task is to write the content for a single section of a paper. - The full table of contents is: {{ context.table_of_contents | tojson }} - The paper summary is: {{ context.brainstorming_summary }} - The relevant research is: {{ context.deep_research_sources | tojson }} - - {% if context.vetting_sources and context.vetting_sources|length > 0 %} - The vetted sources that should be referenced throughout the paper: + You are helping select relevant sources for a specific section of the paper. + + Current section: {{ context.current_section_path }} + + Available vetted sources: + {% if context.vetting_sources %} {% for source in context.vetting_sources %} - {% if source is mapping %} - - {{ source.get('citation', 'No citation') }} - Summary: {{ source.get('summary', 'No summary')[:200] }}{% if source.get('summary', '')|length > 200 %}...{% endif %} - - {% endif %} + {{ loop.index }}. {{ source.citation if source.citation else 'No citation' }} + Summary: {{ source.summary[:200] if source.summary else 'No summary' }}... {% endfor %} {% endif %} - - You must ONLY write the content for the section: '{{ context.current_section_to_write }}'. - Do NOT write any other sections. Write in a clear, academic, active voice. - Reference the vetted sources where appropriate by mentioning author names and years. - If the user provides feedback, refine the text. If they seem happy, instruct them to type `!accept` to finalize this section. - # ============================================ - # Framing Content Agent - # ============================================ - framing_agent: + Please review the list and tell the user which sources seem most relevant for this section. + Ask if they want to include these sources or if they want to find additional sources specific to this section. + When they confirm, output: SELECT_COMPLETE + + source_finder: type: llm config: provider: openai model: gpt-4-turbo + memory_enabled: true + max_history: 15 system_prompt: | - You are an academic writer. Start by introducing yourself and explaining: "I'll now write the Abstract and Conclusion sections for your paper. The Abstract will provide a 150-250 word summary of the entire paper, while the Conclusion will synthesize the key findings and implications from the main body. These framing sections will reflect what is learned and expressed in your paper. Please let me know if you'd like me to proceed, or if you have specific directions for these sections." + You are a research specialist finding additional sources for a specific section. - Once the user confirms or provides input, write a compelling Abstract (150-250 words) and Conclusion section - based on the full paper body below. These sections should reflect what is learned and expressed in the main - body of the text. + Paper topic: {{ context.paper_details.topic }} + Current section: {{ context.current_section_path }} + Paper focus: {{ context.brainstorming_summary }} - Full paper body: {{ context.paper_content | tojson }} + Help the user find additional academic sources specifically relevant to this section. + Suggest real academic papers, journal articles, or books that would be appropriate. - Format your response with clear section headers: + For each source provide: + - Full citation + - Brief summary (2-3 sentences) + - URL/DOI (use real links like doi.org, arxiv.org, pubmed.gov) - Abstract: - [Your abstract text here] + When the user is satisfied with the sources, output: FIND_COMPLETE - Conclusion: - [Your conclusion text here] + section_writer: + type: llm + config: + provider: openai + model: gpt-4-turbo + memory_enabled: true + max_history: 20 + system_prompt: | + You are writing section: {{ context.current_section_path }} - framing_saver: + Paper topic: {{ context.paper_details.topic }} + Paper focus: {{ context.brainstorming_summary }} + Target length: {{ context.paper_details.length }} words total + Target audience: {{ context.paper_details.audience }} + + Table of Contents: + {{ context.table_of_contents }} + + Available sources: + {% if context.vetting_sources %} + {% for source in context.vetting_sources %} + - {{ source.citation if source.citation else 'No citation' }} + {% endfor %} + {% endif %} + + INSTRUCTIONS: + Write ONLY this section ({{ context.current_section_path }}). Do not write subsections or other sections. + Use academic tone and cite sources appropriately using proper citation format. + Incorporate the relevant sources naturally into the text. + + After presenting your draft, ask if the user wants to refine it or use !accept to move to the next section. + + section_writer_saver: type: tool config: tools: - - name: save_framing + - name: save_section code: | - # Combine paper content with framing - paper_content = context.get('paper_content', {}) - paper_content['Abstract'] = input_data.split('Conclusion:')[0] if 'Conclusion:' in input_data else input_data - paper_content['Conclusion'] = input_data.split('Conclusion:')[1] if 'Conclusion:' in input_data else '' - context['paper_content'] = paper_content - context['final_paper_text'] = '\n\n'.join(paper_content.values()) + path = context.get('current_section_path', 'unknown') + context.setdefault('section_content', {})[path] = input_data + result = input_data + + section_accept_handler: + type: tool + config: + tools: + - name: accept_section + code: | + current_index = context.get('current_section_index', 0) + context['current_section_index'] = current_index + 1 + result = "ROUTE_NEXT_SECTION:" + + # ============================================ + # PAPER REVIEW STAGE + # ============================================ + + paper_review_controller: + type: tool + config: + tools: + - name: review_controller + code: | + import sys + print(f"DEBUG paper_review_controller", file=sys.stderr) + + # Assemble all sections into full paper + section_content = context.get('section_content', {}) + if not section_content: + result = "ERROR: No sections found. Please complete section writing stage first." + else: + # Build full paper text + full_text = f"# {context.get('paper_details', {}).get('topic', 'Scientific Paper')}\n\n" + + # Add sections in order + section_paths = context.get('section_paths', []) + for path in section_paths: + if path in section_content: + full_text += f"## {path}\n\n{section_content[path]}\n\n" + + context['assembled_paper'] = full_text + result = "ROUTE_REVIEW_PAPER:" + full_text[:500] + + paper_review_agent: + type: llm + config: + provider: openai + model: gpt-4-turbo + memory_enabled: true + max_history: 20 + system_prompt: | + You are reviewing the complete assembled paper. + + Here is the full paper content: + + {{ context.get('assembled_paper', '') }} + + Review the paper for: + - Consistency and logical flow between sections + - Grammar, spelling, and style + - Proper citation format and usage + - Logical coherence and argument strength + - Transitions between sections + + Provide specific feedback on issues found. The user can: + - Discuss refinements to specific sections + - Make changes across the document + - Use !accept or !next when satisfied to proceed to LaTeX generation + + paper_review_saver: + type: tool + config: + tools: + - name: save_review + code: | + context['reviewed_paper'] = input_data result = input_data # ============================================ - # Proofreading Agent + # LATEX GENERATION STAGE # ============================================ - proofreading_agent: + + latex_controller: + type: tool + config: + tools: + - name: latex_ctrl + code: | + import sys + print(f"DEBUG latex_controller", file=sys.stderr) + + # Multi-step workflow + if not context.get('latex_structure'): + result = "ROUTE_GEN_STRUCTURE:" + elif not context.get('latex_sections_complete'): + # Convert sections one by one + section_paths = context.get('section_paths', []) + latex_sections = context.get('latex_sections', {}) + current_latex_index = context.get('current_latex_index', 0) + + if current_latex_index < len(section_paths): + section_path = section_paths[current_latex_index] + context['current_latex_section'] = section_path + result = f"ROUTE_CONVERT_SECTION:{section_path}" + else: + context['latex_sections_complete'] = True + result = "ROUTE_ASSEMBLE_LATEX:" + elif not context.get('latex_source'): + result = "ROUTE_ASSEMBLE_LATEX:" + elif not context.get('latex_compiled'): + result = "ROUTE_COMPILE_LATEX:" + + + latex_structure_gen: type: llm config: provider: openai model: gpt-4-turbo + memory_enabled: false system_prompt: | - You are an expert proofreader. Immediately begin proofreading the paper below. Review the following paper for logical fallacies, grammatical errors, and typos. - Improve the writing style, ensuring an active voice. Provide the corrected, full text of the paper. + You are helping generate a LaTeX document structure for a scientific paper. - {% if context.final_paper_text %} - Paper to review: {{ context.final_paper_text }} - {% elif context.paper_content %} - Paper sections to review and combine: - {% for section, content in context.paper_content.items() %} - ## {{ section }} - {{ content }} + Paper topic: {{ context.paper_details.topic }} + Target audience: {{ context.paper_details.audience }} - {% endfor %} - {% else %} - No paper content available to proofread. Please ensure previous stages have been completed. - {% endif %} + Table of Contents: + {{ context.table_of_contents }} - {% if context.vetting_sources and context.vetting_sources|length > 0 %} - Ensure all the following vetted sources are properly referenced: - {% for source in context.vetting_sources %} - {% if source is mapping %} - - {{ source.get('citation', 'Citation unavailable') }} - {% endif %} - {% endfor %} - {% endif %} + Generate a complete LaTeX preamble with appropriate document class, packages, and metadata. + Include packages for: amsmath, graphicx, hyperref, cite, geometry + Set reasonable margins (1 inch). + Include title, author, and date fields. - proofreading_saver: + Output ONLY the LaTeX preamble (from \documentclass to \begin{document}, not including sections). + After providing the structure, the system will automatically save it. + + latex_structure_saver: type: tool config: tools: - - name: save_proofread + - name: save_latex_structure code: | - context['proofread_paper'] = input_data - result = input_data + # Save the LaTeX structure/preamble to context + context['latex_structure'] = input_data + result = f"LaTeX structure saved. Proceeding to convert sections..." - # ============================================ - # Formatting Agent - # ============================================ - latex_formatter: + latex_section_converter: type: llm config: - provider: google - model: gemini-1.5-pro - max_tokens: 8192 + provider: openai + model: gpt-4-turbo + memory_enabled: false system_prompt: | - You are a LaTeX expert specializing in scientific papers. Immediately convert the content below into a compilable LaTeX document using the 'article' class with proper citations and bibliography. + You are converting a section of the paper to LaTeX format. - {% if context.proofread_paper %} - Plain text: {{ context.proofread_paper }} - {% elif context.final_paper_text %} - Plain text: {{ context.final_paper_text }} - {% elif context.paper_content %} - Plain text: - {% for section, content in context.paper_content.items() %} - # {{ section }} - {{ content }} + Current section: {{ context.current_latex_section }} - {% endfor %} - {% elif context.paper_details or context.brainstorming_summary or context.vetting_sources %} - Based on the paper requirements and research gathered, create a comprehensive scientific paper in LaTeX format. + Section content (markdown/plain text): + {{ context.section_content.get(context.current_latex_section, '') }} - Paper Requirements: - {% if context.paper_details %} - - Topic: {{ context.paper_details.topic }} - - Target Length: {{ context.paper_details.length }} words - - Audience: {{ context.paper_details.audience }} - - Publication: {{ context.paper_details.publication }} - - Format: {{ context.paper_details.format }} - - Additional Requirements: {{ context.paper_details.other }} - {% endif %} + Convert this section to LaTeX format: + - Use \section{} for the section title + - Escape special characters: & % $ # _ { } ~ ^ + - Convert markdown formatting to LaTeX equivalents + - Keep citations in proper format [citation] + - Use proper LaTeX commands for emphasis, bold, etc. - {% if context.brainstorming_summary %} - Paper Summary and Direction: - {{ context.brainstorming_summary }} - {% endif %} + Output ONLY the LaTeX code for this section (no preamble, no \begin{document}). + After providing the conversion, the system will automatically save it. - {% if context.vetting_sources and context.vetting_sources|length > 0 %} - CRITICAL: You MUST integrate the following vetted sources throughout the paper. Each source MUST be properly cited using \cite{} commands and included in the bibliography using \bibitem{}. Create citation keys from author surnames and years. - - Vetted Sources (MUST be integrated and cited): - {% for source in context.vetting_sources %} - {% if source is mapping and source.get('citation') %} - - Citation: {{ source.citation }} - - Summary: {{ source.get('summary', 'No summary available') }} - {% if source.get('link') %} - - Link: {{ source.link }} - {% endif %} - - {% endif %} - {% endfor %} - {% endif %} - - REQUIREMENTS for the LaTeX document: - 1. Use \documentclass{article} with proper packages (amsmath, amsfonts, amssymb, natbib or biblatex) - 2. Create a complete scientific paper with these sections: - - Title page with author and affiliation placeholders - - Abstract (150-250 words) - - Introduction (with background and citations from vetted sources) - - Literature Review (MUST extensively cite and discuss the vetted sources) - - Methods/Methodology - - Results/Analysis - - Discussion (integrating findings with vetted sources) - - Conclusion - - References section using \begin{thebibliography} with \bibitem entries - 3. CRITICAL: Every vetted source MUST appear as: - - A \cite{key} command in the text - - A \bibitem{key} entry in the bibliography - 4. Write substantial, well-researched content based on the vetted sources and requirements - 5. Use proper LaTeX formatting, equations, and structure - - {% else %} - Since no content was provided from previous stages, please create a sample scientific paper in LaTeX format with the following structure: - - Title page - - Abstract - - Introduction - - Methods - - Results - - Discussion - - Conclusion - - References - Use placeholder content that demonstrates proper LaTeX formatting. - {% endif %} - - formatting_saver: + latex_section_saver: type: tool config: tools: - - name: save_latex + - name: save_latex_section code: | + import sys + print(f"DEBUG latex_section_saver", file=sys.stderr) + + # Save the converted LaTeX section + current_section = context.get('current_latex_section', '') + if not context.get('latex_sections'): + context['latex_sections'] = {} + + context['latex_sections'][current_section] = input_data + + # Increment index to move to next section + current_index = context.get('current_latex_index', 0) + context['current_latex_index'] = current_index + 1 + + result = f"Saved LaTeX for section: {current_section}" + + latex_assembler: + type: llm + config: + provider: openai + model: gpt-3.5-turbo + memory_enabled: false + system_prompt: | + You are assembling the complete LaTeX document from its parts. + + LaTeX preamble: + {{ context.latex_structure }} + + Sections: + {% for path in context.section_paths %} + {{ context.latex_sections.get(path, '') }} + {% endfor %} + + Combine these into a complete LaTeX document: + 1. Start with the preamble + 2. Add \begin{document} + 3. Add \maketitle + 4. Add all sections in order + 5. End with \end{document} + + Output the COMPLETE LaTeX source code ready for compilation. + After providing the document, the system will automatically save and compile it. + + latex_assembler_saver: + type: tool + config: + tools: + - name: save_complete_latex + code: | + # Save the complete LaTeX source context['latex_source'] = input_data - result = f"Here is your formatted LaTeX document:\n\n```latex\n{input_data}\n```\n\nThe LaTeX source has been generated and is ready for use. You can copy this code and compile it with any LaTeX compiler (like pdflatex, xelatex, or lualatex) to generate a PDF." + result = f"Complete LaTeX document assembled ({len(input_data)} characters). Ready to compile." -# Routes - Stream-based routing for V2 + latex_compiler: + type: tool + config: + tools: + - name: compile_latex + code: | + import sys + import subprocess + import tempfile + import os + import shutil + print(f"DEBUG latex_compiler", file=sys.stderr) + + latex_source = context.get('latex_source', '') + if not latex_source: + result = "ERROR: No LaTeX source to compile" + else: + # Create temp directory for compilation + temp_dir = tempfile.mkdtemp() + tex_file = os.path.join(temp_dir, 'paper.tex') + + try: + # Write LaTeX source + with open(tex_file, 'w') as f: + f.write(latex_source) + + # Compile with pdflatex + proc = subprocess.run( + ['pdflatex', '-interaction=nonstopmode', 'paper.tex'], + cwd=temp_dir, + capture_output=True, + text=True, + timeout=60 + ) + + pdf_file = os.path.join(temp_dir, 'paper.pdf') + + if os.path.exists(pdf_file): + # Success! Move PDF to permanent location + output_dir = '/tmp/papers' + os.makedirs(output_dir, exist_ok=True) + final_pdf = os.path.join(output_dir, 'paper.pdf') + shutil.copy(pdf_file, final_pdf) + + context['latex_compiled'] = True + context['pdf_path'] = final_pdf + file_size = os.path.getsize(final_pdf) + result = f"✅ LaTeX compiled successfully! PDF saved to: {final_pdf} ({file_size} bytes)" + else: + # Compilation failed - extract errors + errors = proc.stdout + context['latex_errors'] = errors + context['latex_compiled'] = False + + # Check if we should try to fix + fix_attempts = context.get('latex_fix_attempts', 0) + if fix_attempts < 3: + result = f"ROUTE_FIX_LATEX:LaTeX compilation failed (attempt {fix_attempts + 1}/3). Errors:\n{errors[-1000:]}" + else: + result = f"LaTeX compilation failed after 3 attempts. Final errors:\n{errors[-1000:]}" + + finally: + # Cleanup temp directory + shutil.rmtree(temp_dir, ignore_errors=True) + + latex_fixer: + type: llm + config: + provider: openai + model: gpt-4-turbo + memory_enabled: false + system_prompt: | + You are fixing LaTeX compilation errors. + + Current LaTeX source: + {{ context.latex_source }} + + Compilation errors: + {{ context.latex_errors[-2000:] if context.latex_errors else 'No errors available' }} + + Fix the LaTeX errors. Common issues: + - Unescaped special characters: & % $ # _ { } ~ ^ + - Missing packages (add to preamble) + - Unclosed environments + - Invalid commands + - Missing braces + + Output the COMPLETE corrected LaTeX source code. + The system will automatically save and retry compilation. + + latex_fixer_saver: + type: tool + config: + tools: + - name: save_fixed_latex + code: | + # Save the fixed LaTeX source + context['latex_source'] = input_data + + # Increment fix attempts + fix_attempts = context.get('latex_fix_attempts', 0) + context['latex_fix_attempts'] = fix_attempts + 1 + + # Reset compiled flag so it will try again + context['latex_compiled'] = False + + result = f"LaTeX fixes applied (attempt {fix_attempts + 1}). Retrying compilation..." + +# Routes - Complete routing with all stages routes: - # Main processing stream with conditional routing main: type: stream stream_type: cold operators: - # First, run the workflow controller to determine routing - type: map params: agent: workflow_controller - # Then route based on the result - type: switch params: cases: + # Command handler routing - condition: type: content_contains text: "GOTO_COMMAND_HANDLER" @@ -876,7 +1107,6 @@ routes: - type: map params: agent: command_handler - # Command handler may return routing instructions, process them - type: switch params: cases: @@ -884,11 +1114,6 @@ routes: type: content_contains text: "GOTO_INTRO" operators: - - type: transform - params: - type: replace - old: "GOTO_INTRO:" - new: "" - type: map params: agent: intro_agent @@ -899,117 +1124,10 @@ routes: - type: map params: agent: discovery_controller - - type: switch - params: - cases: - - condition: - type: content_contains - text: "ROUTE_ASK_TOPIC" - operators: - - type: transform - params: - type: replace - old: "ROUTE_ASK_TOPIC:" - new: "" - - type: map - params: - agent: ask_topic - - type: map - params: - agent: discovery_controller - - condition: - type: content_contains - text: "ROUTE_ASK_LENGTH" - operators: - - type: transform - params: - type: replace - old: "ROUTE_ASK_LENGTH:" - new: "" - - type: map - params: - agent: ask_length - - type: map - params: - agent: discovery_controller - - condition: - type: content_contains - text: "ROUTE_ASK_AUDIENCE" - operators: - - type: transform - params: - type: replace - old: "ROUTE_ASK_AUDIENCE:" - new: "" - - type: map - params: - agent: ask_audience - - type: map - params: - agent: discovery_controller - - condition: - type: content_contains - text: "ROUTE_ASK_PUBLICATION" - operators: - - type: transform - params: - type: replace - old: "ROUTE_ASK_PUBLICATION:" - new: "" - - type: map - params: - agent: ask_publication - - type: map - params: - agent: discovery_controller - - condition: - type: content_contains - text: "ROUTE_ASK_FORMAT" - operators: - - type: transform - params: - type: replace - old: "ROUTE_ASK_FORMAT:" - new: "" - - type: map - params: - agent: ask_format - - type: map - params: - agent: discovery_controller - - condition: - type: content_contains - text: "ROUTE_ASK_OTHER" - operators: - - type: transform - params: - type: replace - old: "ROUTE_ASK_OTHER:" - new: "" - - type: map - params: - agent: ask_other - - type: map - params: - agent: discovery_controller - - condition: - type: content_contains - text: "DISCOVERY_RESPONSE:" - operators: - - type: transform - params: - type: replace - old: "DISCOVERY_RESPONSE:" - new: "" - condition: type: content_contains text: "GOTO_BRAINSTORMING" operators: - - type: transform - params: - type: replace - old: "GOTO_BRAINSTORMING:" - new: "" - type: map params: agent: brainstorming_agent @@ -1020,11 +1138,6 @@ routes: type: content_contains text: "GOTO_VETTING" operators: - - type: transform - params: - type: replace - old: "GOTO_VETTING:" - new: "" - type: map params: agent: vetting_agent @@ -1035,11 +1148,6 @@ routes: type: content_contains text: "GOTO_STRUCTURE" operators: - - type: transform - params: - type: replace - old: "GOTO_STRUCTURE:" - new: "" - type: map params: agent: structure_agent @@ -1048,107 +1156,36 @@ routes: agent: structure_saver - condition: type: content_contains - text: "GOTO_DEEP_RESEARCH" + text: "GOTO_SECTION_WRITING" operators: - - type: transform - params: - type: replace - old: "GOTO_DEEP_RESEARCH:" - new: "" - type: map params: - agent: deep_research_agent - - type: map - params: - agent: deep_research_saver + agent: section_writing_controller - condition: type: content_contains - text: "GOTO_CORE_CONTENT" + text: "GOTO_PAPER_REVIEW" operators: - - type: transform - params: - type: replace - old: "GOTO_CORE_CONTENT:" - new: "" - type: map params: - agent: core_content_manager - - type: switch - params: - cases: - - condition: - type: content_contains - text: "WRITE_SECTION:" - operators: - - type: map - params: - agent: core_content_agent - - condition: - type: content_contains - text: "FINISH_CORE_CONTENT:" - operators: - - type: transform - params: - type: replace - old: "FINISH_CORE_CONTENT:" - new: "" + agent: paper_review_controller - condition: type: content_contains - text: "GOTO_FRAMING_CONTENT" + text: "GOTO_LATEX_GENERATION" operators: - - type: transform - params: - type: replace - old: "GOTO_FRAMING_CONTENT:" - new: "" - type: map params: - agent: framing_agent - - type: map - params: - agent: framing_saver - - condition: - type: content_contains - text: "GOTO_PROOFREADING" - operators: - - type: transform - params: - type: replace - old: "GOTO_PROOFREADING:" - new: "" - - type: map - params: - agent: proofreading_agent - - type: map - params: - agent: proofreading_saver - - condition: - type: content_contains - text: "GOTO_FORMATTING" - operators: - - type: transform - params: - type: replace - old: "GOTO_FORMATTING:" - new: "" - - type: map - params: - agent: latex_formatter - - type: map - params: - agent: formatting_saver + agent: latex_controller + + # Direct stage routing (without command handler) - condition: type: content_contains text: "GOTO_INTRO" operators: - - type: transform - params: - type: replace - old: "GOTO_INTRO:" - new: "" - type: map params: agent: intro_agent + + # Discovery stage with sub-routes - condition: type: content_contains text: "GOTO_DISCOVERY" @@ -1163,11 +1200,6 @@ routes: type: content_contains text: "ROUTE_ASK_TOPIC" operators: - - type: transform - params: - type: replace - old: "ROUTE_ASK_TOPIC:" - new: "" - type: map params: agent: ask_topic @@ -1178,11 +1210,6 @@ routes: type: content_contains text: "ROUTE_ASK_LENGTH" operators: - - type: transform - params: - type: replace - old: "ROUTE_ASK_LENGTH:" - new: "" - type: map params: agent: ask_length @@ -1193,11 +1220,6 @@ routes: type: content_contains text: "ROUTE_ASK_AUDIENCE" operators: - - type: transform - params: - type: replace - old: "ROUTE_ASK_AUDIENCE:" - new: "" - type: map params: agent: ask_audience @@ -1208,11 +1230,6 @@ routes: type: content_contains text: "ROUTE_ASK_PUBLICATION" operators: - - type: transform - params: - type: replace - old: "ROUTE_ASK_PUBLICATION:" - new: "" - type: map params: agent: ask_publication @@ -1223,11 +1240,6 @@ routes: type: content_contains text: "ROUTE_ASK_FORMAT" operators: - - type: transform - params: - type: replace - old: "ROUTE_ASK_FORMAT:" - new: "" - type: map params: agent: ask_format @@ -1238,166 +1250,203 @@ routes: type: content_contains text: "ROUTE_ASK_OTHER" operators: - - type: transform - params: - type: replace - old: "ROUTE_ASK_OTHER:" - new: "" - type: map params: agent: ask_other - type: map params: agent: discovery_controller - - condition: - type: content_contains - text: "DISCOVERY_RESPONSE:" - operators: - - type: transform - params: - type: replace - old: "DISCOVERY_RESPONSE:" - new: "" + + # Brainstorming stage - condition: type: content_contains text: "GOTO_BRAINSTORMING" operators: - - type: transform - params: - type: replace - old: "GOTO_BRAINSTORMING:" - new: "" - type: map params: agent: brainstorming_agent - type: map params: agent: brainstorming_saver + + # Vetting stage - condition: type: content_contains text: "GOTO_VETTING" operators: - - type: transform - params: - type: replace - old: "GOTO_VETTING:" - new: "" - type: map params: agent: vetting_agent - type: map params: agent: vetting_saver + + - condition: + type: content_contains + text: "ROUTE_VETTING_ACTION" + operators: + - type: map + params: + agent: vetting_action_agent + - type: map + params: + agent: vetting_controller + + # Structure stage - condition: type: content_contains text: "GOTO_STRUCTURE" operators: - - type: transform - params: - type: replace - old: "GOTO_STRUCTURE:" - new: "" - type: map params: agent: structure_agent - type: map params: agent: structure_saver + + # ============================================= + # SECTION WRITING STAGE ROUTING + # ============================================= - condition: type: content_contains - text: "GOTO_DEEP_RESEARCH" + text: "GOTO_SECTION_WRITING" operators: - - type: transform - params: - type: replace - old: "GOTO_DEEP_RESEARCH:" - new: "" - type: map params: - agent: deep_research_agent - - type: map - params: - agent: deep_research_saver + agent: section_writing_controller + - condition: type: content_contains - text: "GOTO_CORE_CONTENT" + text: "ROUTE_SELECT_SOURCES" operators: - - type: transform - params: - type: replace - old: "GOTO_CORE_CONTENT:" - new: "" - type: map params: - agent: core_content_manager - - type: switch - params: - cases: - - condition: - type: content_contains - text: "WRITE_SECTION:" - operators: - - type: map - params: - agent: core_content_agent - - condition: - type: content_contains - text: "FINISH_CORE_CONTENT:" - operators: - - type: transform - params: - type: replace - old: "FINISH_CORE_CONTENT:" - new: "" + agent: source_selector + - condition: type: content_contains - text: "GOTO_FRAMING_CONTENT" + text: "SELECT_COMPLETE" operators: - - type: transform - params: - type: replace - old: "GOTO_FRAMING_CONTENT:" - new: "" - type: map params: - agent: framing_agent - - type: map - params: - agent: framing_saver + agent: source_finder + - condition: type: content_contains - text: "GOTO_PROOFREADING" + text: "FIND_COMPLETE" operators: - - type: transform - params: - type: replace - old: "GOTO_PROOFREADING:" - new: "" - type: map params: - agent: proofreading_agent + agent: section_writer - type: map params: - agent: proofreading_saver + agent: section_writer_saver + - condition: type: content_contains - text: "GOTO_FORMATTING" + text: "ROUTE_NEXT_SECTION" operators: - - type: transform - params: - type: replace - old: "GOTO_FORMATTING:" - new: "" - type: map params: - agent: latex_formatter + agent: section_writing_controller + + # ============================================= + # PAPER REVIEW STAGE ROUTING + # ============================================= + - condition: + type: content_contains + text: "GOTO_PAPER_REVIEW" + operators: - type: map params: - agent: formatting_saver + agent: paper_review_controller + + - condition: + type: content_contains + text: "ROUTE_REVIEW_PAPER" + operators: + - type: map + params: + agent: paper_review_agent + - type: map + params: + agent: paper_review_saver + + # ============================================= + # LATEX GENERATION STAGE ROUTING + # ============================================= + - condition: + type: content_contains + text: "GOTO_LATEX_GENERATION" + operators: + - type: map + params: + agent: latex_controller + + - condition: + type: content_contains + text: "ROUTE_GEN_STRUCTURE" + operators: + - type: map + params: + agent: latex_structure_gen + - type: map + params: + agent: latex_structure_saver + - type: map + params: + agent: latex_controller + + - condition: + type: content_contains + text: "ROUTE_CONVERT_SECTION" + operators: + - type: map + params: + agent: latex_section_converter + - type: map + params: + agent: latex_section_saver + - type: map + params: + agent: latex_controller + + - condition: + type: content_contains + text: "ROUTE_ASSEMBLE_LATEX" + operators: + - type: map + params: + agent: latex_assembler + - type: map + params: + agent: latex_assembler_saver + + - condition: + type: content_contains + text: "ROUTE_COMPILE_LATEX" + operators: + - type: map + params: + agent: latex_compiler + + - condition: + type: content_contains + text: "ROUTE_FIX_LATEX" + operators: + - type: map + params: + agent: latex_fixer + - type: map + params: + agent: latex_fixer_saver + - type: map + params: + agent: latex_compiler + publications: - __output__ -# Connect input to the main stream merges: - sources: [__input__] target: main