deepcode-hku 1.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. cli/__init__.py +18 -0
  2. cli/cli_app.py +296 -0
  3. cli/cli_interface.py +744 -0
  4. cli/cli_launcher.py +155 -0
  5. cli/main_cli.py +243 -0
  6. cli/workflows/__init__.py +11 -0
  7. cli/workflows/cli_workflow_adapter.py +336 -0
  8. deepcode.py +219 -0
  9. deepcode_hku-1.0.1.dist-info/METADATA +695 -0
  10. deepcode_hku-1.0.1.dist-info/RECORD +44 -0
  11. deepcode_hku-1.0.1.dist-info/WHEEL +5 -0
  12. deepcode_hku-1.0.1.dist-info/entry_points.txt +2 -0
  13. deepcode_hku-1.0.1.dist-info/licenses/LICENSE +21 -0
  14. deepcode_hku-1.0.1.dist-info/top_level.txt +6 -0
  15. tools/__init__.py +0 -0
  16. tools/code_implementation_server.py +1045 -0
  17. tools/code_indexer.py +1657 -0
  18. tools/code_reference_indexer.py +486 -0
  19. tools/command_executor.py +324 -0
  20. tools/git_command.py +356 -0
  21. tools/pdf_converter.py +640 -0
  22. tools/pdf_downloader.py +1370 -0
  23. tools/pdf_utils.py +52 -0
  24. ui/__init__.py +43 -0
  25. ui/app.py +13 -0
  26. ui/components.py +1450 -0
  27. ui/handlers.py +773 -0
  28. ui/layout.py +106 -0
  29. ui/streamlit_app.py +38 -0
  30. ui/styles.py +2116 -0
  31. utils/__init__.py +17 -0
  32. utils/cli_interface.py +459 -0
  33. utils/dialogue_logger.py +671 -0
  34. utils/file_processor.py +426 -0
  35. utils/simple_llm_logger.py +198 -0
  36. workflows/__init__.py +31 -0
  37. workflows/agent_orchestration_engine.py +1371 -0
  38. workflows/agents/__init__.py +13 -0
  39. workflows/agents/code_implementation_agent.py +1093 -0
  40. workflows/agents/memory_agent_concise.py +923 -0
  41. workflows/agents/memory_agent_concise_index.py +935 -0
  42. workflows/code_implementation_workflow.py +924 -0
  43. workflows/code_implementation_workflow_index.py +931 -0
  44. workflows/codebase_index_workflow.py +726 -0
@@ -0,0 +1,1371 @@
1
+ """
2
+ Intelligent Agent Orchestration Engine for Research-to-Code Automation
3
+
4
+ This module serves as the core orchestration engine that coordinates multiple specialized
5
+ AI agents to automate the complete research-to-code transformation pipeline:
6
+
7
+ 1. Research Analysis Agent - Intelligent content processing and extraction
8
+ 2. Workspace Infrastructure Agent - Automated environment synthesis
9
+ 3. Code Architecture Agent - AI-driven design and planning
10
+ 4. Reference Intelligence Agent - Automated knowledge discovery
11
+ 5. Repository Acquisition Agent - Intelligent code repository management
12
+ 6. Codebase Intelligence Agent - Advanced relationship analysis
13
+ 7. Code Implementation Agent - AI-powered code synthesis
14
+
15
+ Core Features:
16
+ - Multi-agent coordination with intelligent task distribution
17
+ - Local environment automation for seamless deployment
18
+ - Real-time progress monitoring with comprehensive error handling
19
+ - Adaptive workflow optimization based on processing requirements
20
+ - Advanced intelligence analysis with configurable performance modes
21
+
22
+ Architecture:
23
+ - Async/await based high-performance agent coordination
24
+ - Modular agent design with specialized role separation
25
+ - Intelligent resource management and optimization
26
+ - Comprehensive logging and monitoring infrastructure
27
+ """
28
+
29
+ import asyncio
30
+ import json
31
+ import os
32
+ import re
33
+ import yaml
34
+ from typing import Callable, Dict, Optional, Tuple
35
+
36
+ # MCP Agent imports
37
+ from mcp_agent.agents.agent import Agent
38
+ from mcp_agent.workflows.llm.augmented_llm_anthropic import AnthropicAugmentedLLM
39
+ from mcp_agent.workflows.llm.augmented_llm_openai import OpenAIAugmentedLLM
40
+ from mcp_agent.workflows.llm.augmented_llm import RequestParams
41
+ from mcp_agent.workflows.parallel.parallel_llm import ParallelLLM
42
+
43
+ # Local imports
44
+ from prompts.code_prompts import (
45
+ PAPER_INPUT_ANALYZER_PROMPT,
46
+ PAPER_DOWNLOADER_PROMPT,
47
+ PAPER_REFERENCE_ANALYZER_PROMPT,
48
+ PAPER_ALGORITHM_ANALYSIS_PROMPT,
49
+ PAPER_CONCEPT_ANALYSIS_PROMPT,
50
+ CODE_PLANNING_PROMPT,
51
+ CHAT_AGENT_PLANNING_PROMPT,
52
+ )
53
+ from utils.file_processor import FileProcessor
54
+ from workflows.code_implementation_workflow import CodeImplementationWorkflow
55
+ from workflows.code_implementation_workflow_index import (
56
+ CodeImplementationWorkflowWithIndex,
57
+ )
58
+
59
+ # Environment configuration
60
+ os.environ["PYTHONDONTWRITEBYTECODE"] = "1" # Prevent .pyc file generation
61
+
62
+
63
+ def get_preferred_llm_class(config_path: str = "mcp_agent.secrets.yaml"):
64
+ """
65
+ Automatically select the LLM class based on API key availability in configuration.
66
+
67
+ Reads from YAML config file and returns AnthropicAugmentedLLM if anthropic.api_key
68
+ is available, otherwise returns OpenAIAugmentedLLM.
69
+
70
+ Args:
71
+ config_path: Path to the YAML configuration file
72
+
73
+ Returns:
74
+ class: The preferred LLM class
75
+ """
76
+ try:
77
+ # Try to read the configuration file
78
+ if os.path.exists(config_path):
79
+ with open(config_path, "r", encoding="utf-8") as f:
80
+ config = yaml.safe_load(f)
81
+
82
+ # Check for anthropic API key in config
83
+ anthropic_config = config.get("anthropic", {})
84
+ anthropic_key = anthropic_config.get("api_key", "")
85
+
86
+ if anthropic_key and anthropic_key.strip() and not anthropic_key == "":
87
+ # print("šŸ¤– Using AnthropicAugmentedLLM (Anthropic API key found in config)")
88
+ return AnthropicAugmentedLLM
89
+ else:
90
+ # print("šŸ¤– Using OpenAIAugmentedLLM (Anthropic API key not configured)")
91
+ return OpenAIAugmentedLLM
92
+ else:
93
+ print(f"šŸ¤– Config file {config_path} not found, using OpenAIAugmentedLLM")
94
+ return OpenAIAugmentedLLM
95
+
96
+ except Exception as e:
97
+ print(f"šŸ¤– Error reading config file {config_path}: {e}")
98
+ print("šŸ¤– Falling back to OpenAIAugmentedLLM")
99
+ return OpenAIAugmentedLLM
100
+
101
+
102
+ def extract_clean_json(llm_output: str) -> str:
103
+ """
104
+ Extract clean JSON from LLM output, removing all extra text and formatting.
105
+
106
+ Args:
107
+ llm_output: Raw LLM output
108
+
109
+ Returns:
110
+ str: Clean JSON string
111
+ """
112
+ try:
113
+ # Try to parse the entire output as JSON first
114
+ json.loads(llm_output.strip())
115
+ return llm_output.strip()
116
+ except json.JSONDecodeError:
117
+ pass
118
+
119
+ # Remove markdown code blocks
120
+ if "```json" in llm_output:
121
+ pattern = r"```json\s*(.*?)\s*```"
122
+ match = re.search(pattern, llm_output, re.DOTALL)
123
+ if match:
124
+ json_text = match.group(1).strip()
125
+ try:
126
+ json.loads(json_text)
127
+ return json_text
128
+ except json.JSONDecodeError:
129
+ pass
130
+
131
+ # Find JSON object starting with {
132
+ lines = llm_output.split("\n")
133
+ json_lines = []
134
+ in_json = False
135
+ brace_count = 0
136
+
137
+ for line in lines:
138
+ stripped = line.strip()
139
+ if not in_json and stripped.startswith("{"):
140
+ in_json = True
141
+ json_lines = [line]
142
+ brace_count = stripped.count("{") - stripped.count("}")
143
+ elif in_json:
144
+ json_lines.append(line)
145
+ brace_count += stripped.count("{") - stripped.count("}")
146
+ if brace_count == 0:
147
+ break
148
+
149
+ if json_lines:
150
+ json_text = "\n".join(json_lines).strip()
151
+ try:
152
+ json.loads(json_text)
153
+ return json_text
154
+ except json.JSONDecodeError:
155
+ pass
156
+
157
+ # Last attempt: use regex to find JSON
158
+ pattern = r"\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}"
159
+ matches = re.findall(pattern, llm_output, re.DOTALL)
160
+ for match in matches:
161
+ try:
162
+ json.loads(match)
163
+ return match
164
+ except json.JSONDecodeError:
165
+ continue
166
+
167
+ # If all methods fail, return original output
168
+ return llm_output
169
+
170
+
171
+ async def run_research_analyzer(prompt_text: str, logger) -> str:
172
+ """
173
+ Run the research analysis workflow using ResearchAnalyzerAgent.
174
+
175
+ Args:
176
+ prompt_text: Input prompt text containing research information
177
+ logger: Logger instance for logging information
178
+
179
+ Returns:
180
+ str: Analysis result from the agent
181
+ """
182
+ try:
183
+ # Log input information for debugging
184
+ print("šŸ“Š Starting research analysis...")
185
+ print(f"Input prompt length: {len(prompt_text) if prompt_text else 0}")
186
+ print(f"Input preview: {prompt_text[:200] if prompt_text else 'None'}...")
187
+
188
+ if not prompt_text or prompt_text.strip() == "":
189
+ raise ValueError(
190
+ "Empty or None prompt_text provided to run_research_analyzer"
191
+ )
192
+
193
+ analyzer_agent = Agent(
194
+ name="ResearchAnalyzerAgent",
195
+ instruction=PAPER_INPUT_ANALYZER_PROMPT,
196
+ server_names=["brave"],
197
+ )
198
+
199
+ async with analyzer_agent:
200
+ print("analyzer: Connected to server, calling list_tools...")
201
+ try:
202
+ tools = await analyzer_agent.list_tools()
203
+ print(
204
+ "Tools available:",
205
+ tools.model_dump() if hasattr(tools, "model_dump") else str(tools),
206
+ )
207
+ except Exception as e:
208
+ print(f"Failed to list tools: {e}")
209
+
210
+ try:
211
+ analyzer = await analyzer_agent.attach_llm(get_preferred_llm_class())
212
+ print("āœ… LLM attached successfully")
213
+ except Exception as e:
214
+ print(f"āŒ Failed to attach LLM: {e}")
215
+ raise
216
+
217
+ # Set higher token output for research analysis
218
+ analysis_params = RequestParams(
219
+ max_tokens=6144,
220
+ temperature=0.3,
221
+ )
222
+
223
+ print(
224
+ f"šŸ”„ Making LLM request with params: max_tokens={analysis_params.max_tokens}, temperature={analysis_params.temperature}"
225
+ )
226
+
227
+ try:
228
+ raw_result = await analyzer.generate_str(
229
+ message=prompt_text, request_params=analysis_params
230
+ )
231
+
232
+ print("āœ… LLM request completed")
233
+ print(f"Raw result type: {type(raw_result)}")
234
+ print(f"Raw result length: {len(raw_result) if raw_result else 0}")
235
+
236
+ if not raw_result:
237
+ print("āŒ CRITICAL: raw_result is empty or None!")
238
+ print("This could indicate:")
239
+ print("1. LLM API call failed silently")
240
+ print("2. API rate limiting or quota exceeded")
241
+ print("3. Network connectivity issues")
242
+ print("4. MCP server communication problems")
243
+ raise ValueError("LLM returned empty result")
244
+
245
+ except Exception as e:
246
+ print(f"āŒ LLM generation failed: {e}")
247
+ print(f"Exception type: {type(e)}")
248
+ raise
249
+
250
+ # Clean LLM output to ensure only pure JSON is returned
251
+ try:
252
+ clean_result = extract_clean_json(raw_result)
253
+ print(f"Raw LLM output: {raw_result}")
254
+ print(f"Cleaned JSON output: {clean_result}")
255
+
256
+ # Log to SimpleLLMLogger
257
+ if hasattr(logger, "log_response"):
258
+ logger.log_response(
259
+ clean_result,
260
+ model="ResearchAnalyzer",
261
+ agent="ResearchAnalyzerAgent",
262
+ )
263
+
264
+ if not clean_result or clean_result.strip() == "":
265
+ print("āŒ CRITICAL: clean_result is empty after JSON extraction!")
266
+ print(f"Original raw_result was: {raw_result}")
267
+ raise ValueError("JSON extraction resulted in empty output")
268
+
269
+ return clean_result
270
+
271
+ except Exception as e:
272
+ print(f"āŒ JSON extraction failed: {e}")
273
+ print(f"Raw result was: {raw_result}")
274
+ raise
275
+
276
+ except Exception as e:
277
+ print(f"āŒ run_research_analyzer failed: {e}")
278
+ print(f"Exception details: {type(e).__name__}: {str(e)}")
279
+ raise
280
+
281
+
282
+ async def run_resource_processor(analysis_result: str, logger) -> str:
283
+ """
284
+ Run the resource processing workflow using ResourceProcessorAgent.
285
+
286
+ Args:
287
+ analysis_result: Result from the research analyzer
288
+ logger: Logger instance for logging information
289
+
290
+ Returns:
291
+ str: Processing result from the agent
292
+ """
293
+ processor_agent = Agent(
294
+ name="ResourceProcessorAgent",
295
+ instruction=PAPER_DOWNLOADER_PROMPT,
296
+ server_names=["filesystem", "file-downloader"],
297
+ )
298
+
299
+ async with processor_agent:
300
+ print("processor: Connected to server, calling list_tools...")
301
+ tools = await processor_agent.list_tools()
302
+ print(
303
+ "Tools available:",
304
+ tools.model_dump() if hasattr(tools, "model_dump") else str(tools),
305
+ )
306
+
307
+ processor = await processor_agent.attach_llm(get_preferred_llm_class())
308
+
309
+ # Set higher token output for resource processing
310
+ processor_params = RequestParams(
311
+ max_tokens=4096,
312
+ temperature=0.2,
313
+ )
314
+
315
+ return await processor.generate_str(
316
+ message=analysis_result, request_params=processor_params
317
+ )
318
+
319
+
320
+ async def run_code_analyzer(paper_dir: str, logger) -> str:
321
+ """
322
+ Run the code analysis workflow using multiple agents for comprehensive code planning.
323
+
324
+ This function orchestrates three specialized agents:
325
+ - ConceptAnalysisAgent: Analyzes system architecture and conceptual framework
326
+ - AlgorithmAnalysisAgent: Extracts algorithms, formulas, and technical details
327
+ - CodePlannerAgent: Integrates outputs into a comprehensive implementation plan
328
+
329
+ Args:
330
+ paper_dir: Directory path containing the research paper and related resources
331
+ logger: Logger instance for logging information
332
+
333
+ Returns:
334
+ str: Comprehensive analysis result from the coordinated agents
335
+ """
336
+ concept_analysis_agent = Agent(
337
+ name="ConceptAnalysisAgent",
338
+ instruction=PAPER_CONCEPT_ANALYSIS_PROMPT,
339
+ server_names=["filesystem"],
340
+ )
341
+ algorithm_analysis_agent = Agent(
342
+ name="AlgorithmAnalysisAgent",
343
+ instruction=PAPER_ALGORITHM_ANALYSIS_PROMPT,
344
+ server_names=["filesystem", "brave"],
345
+ )
346
+ code_planner_agent = Agent(
347
+ name="CodePlannerAgent",
348
+ instruction=CODE_PLANNING_PROMPT,
349
+ server_names=["brave"],
350
+ )
351
+
352
+ code_aggregator_agent = ParallelLLM(
353
+ fan_in_agent=code_planner_agent,
354
+ fan_out_agents=[concept_analysis_agent, algorithm_analysis_agent],
355
+ llm_factory=get_preferred_llm_class(),
356
+ )
357
+
358
+ # Set higher token output limit
359
+ enhanced_params = RequestParams(
360
+ max_tokens=26384,
361
+ temperature=0.3,
362
+ )
363
+
364
+ # Concise message for multi-agent paper analysis and code planning
365
+ message = f"""Analyze the research paper in directory: {paper_dir}
366
+
367
+ Please locate and analyze the markdown (.md) file containing the research paper. Based on your analysis, generate a comprehensive code reproduction plan that includes:
368
+
369
+ 1. Complete system architecture and component breakdown
370
+ 2. All algorithms, formulas, and implementation details
371
+ 3. Detailed file structure and implementation roadmap
372
+
373
+ The goal is to create a reproduction plan detailed enough for independent implementation."""
374
+
375
+ result = await code_aggregator_agent.generate_str(
376
+ message=message, request_params=enhanced_params
377
+ )
378
+ print(f"Code analysis result: {result}")
379
+ return result
380
+
381
+
382
+ async def github_repo_download(search_result: str, paper_dir: str, logger) -> str:
383
+ """
384
+ Download GitHub repositories based on search results.
385
+
386
+ Args:
387
+ search_result: Result from GitHub repository search
388
+ paper_dir: Directory where the paper and its code will be stored
389
+ logger: Logger instance for logging information
390
+
391
+ Returns:
392
+ str: Download result
393
+ """
394
+ github_download_agent = Agent(
395
+ name="GithubDownloadAgent",
396
+ instruction="Download github repo to the directory {paper_dir}/code_base".format(
397
+ paper_dir=paper_dir
398
+ ),
399
+ server_names=["filesystem", "github-downloader"],
400
+ )
401
+
402
+ async with github_download_agent:
403
+ print("GitHub downloader: Downloading repositories...")
404
+ downloader = await github_download_agent.attach_llm(get_preferred_llm_class())
405
+
406
+ # Set higher token output for GitHub download
407
+ github_params = RequestParams(
408
+ max_tokens=4096,
409
+ temperature=0.1,
410
+ )
411
+
412
+ return await downloader.generate_str(
413
+ message=search_result, request_params=github_params
414
+ )
415
+
416
+
417
+ async def paper_reference_analyzer(analysis_result: str, logger) -> str:
418
+ """
419
+ Run the paper reference analysis and GitHub repository workflow.
420
+
421
+ Args:
422
+ analysis_result: Result from the paper analyzer
423
+ logger: Logger instance for logging information
424
+
425
+ Returns:
426
+ str: Reference analysis result
427
+ """
428
+ reference_analysis_agent = Agent(
429
+ name="ReferenceAnalysisAgent",
430
+ instruction=PAPER_REFERENCE_ANALYZER_PROMPT,
431
+ server_names=["filesystem", "brave", "fetch"],
432
+ )
433
+
434
+ async with reference_analysis_agent:
435
+ print("Reference analyzer: Connected to server, analyzing references...")
436
+ analyzer = await reference_analysis_agent.attach_llm(get_preferred_llm_class())
437
+
438
+ # Set higher token output for reference analysis
439
+ reference_params = RequestParams(
440
+ max_tokens=30000,
441
+ temperature=0.2,
442
+ )
443
+
444
+ reference_result = await analyzer.generate_str(
445
+ message=analysis_result, request_params=reference_params
446
+ )
447
+ return reference_result
448
+
449
+
450
+ async def _process_input_source(input_source: str, logger) -> str:
451
+ """
452
+ Process and validate input source (file path or URL).
453
+
454
+ Args:
455
+ input_source: Input source (file path or analysis result)
456
+ logger: Logger instance
457
+
458
+ Returns:
459
+ str: Processed input source
460
+ """
461
+ if input_source.startswith("file://"):
462
+ file_path = input_source[7:]
463
+ if os.name == "nt" and file_path.startswith("/"):
464
+ file_path = file_path.lstrip("/")
465
+ return file_path
466
+ return input_source
467
+
468
+
469
+ async def orchestrate_research_analysis_agent(
470
+ input_source: str, logger, progress_callback: Optional[Callable] = None
471
+ ) -> Tuple[str, str]:
472
+ """
473
+ Orchestrate intelligent research analysis and resource processing automation.
474
+
475
+ This agent coordinates multiple AI components to analyze research content
476
+ and process associated resources with automated workflow management.
477
+
478
+ Args:
479
+ input_source: Research input source for analysis
480
+ logger: Logger instance for process tracking
481
+ progress_callback: Progress callback function for workflow monitoring
482
+
483
+ Returns:
484
+ tuple: (analysis_result, resource_processing_result)
485
+ """
486
+ # Step 1: Research Analysis
487
+ if progress_callback:
488
+ progress_callback(
489
+ 10, "šŸ“Š Analyzing research content and extracting key information..."
490
+ )
491
+ analysis_result = await run_research_analyzer(input_source, logger)
492
+
493
+ # Add brief pause for system stability
494
+ await asyncio.sleep(5)
495
+
496
+ # Step 2: Download Processing
497
+ if progress_callback:
498
+ progress_callback(
499
+ 25, "šŸ“„ Processing downloads and preparing document structure..."
500
+ )
501
+ download_result = await run_resource_processor(analysis_result, logger)
502
+
503
+ return analysis_result, download_result
504
+
505
+
506
+ async def synthesize_workspace_infrastructure_agent(
507
+ download_result: str, logger, workspace_dir: Optional[str] = None
508
+ ) -> Dict[str, str]:
509
+ """
510
+ Synthesize intelligent research workspace infrastructure with automated structure generation.
511
+
512
+ This agent autonomously creates and configures the optimal workspace architecture
513
+ for research project implementation with AI-driven path optimization.
514
+
515
+ Args:
516
+ download_result: Resource processing result from analysis agent
517
+ logger: Logger instance for infrastructure tracking
518
+ workspace_dir: Optional workspace directory path for environment customization
519
+
520
+ Returns:
521
+ dict: Comprehensive workspace infrastructure metadata
522
+ """
523
+ # Parse download result to get file information
524
+ result = await FileProcessor.process_file_input(
525
+ download_result, base_dir=workspace_dir
526
+ )
527
+ paper_dir = result["paper_dir"]
528
+
529
+ # Log workspace infrastructure synthesis
530
+ print("šŸ—ļø Intelligent workspace infrastructure synthesized:")
531
+ print(f" Base workspace environment: {workspace_dir or 'auto-detected'}")
532
+ print(f" Research workspace: {paper_dir}")
533
+ print(" AI-driven path optimization: active")
534
+
535
+ return {
536
+ "paper_dir": paper_dir,
537
+ "standardized_text": result["standardized_text"],
538
+ "reference_path": os.path.join(paper_dir, "reference.txt"),
539
+ "initial_plan_path": os.path.join(paper_dir, "initial_plan.txt"),
540
+ "download_path": os.path.join(paper_dir, "github_download.txt"),
541
+ "index_report_path": os.path.join(paper_dir, "codebase_index_report.txt"),
542
+ "implementation_report_path": os.path.join(
543
+ paper_dir, "code_implementation_report.txt"
544
+ ),
545
+ "workspace_dir": workspace_dir,
546
+ }
547
+
548
+
549
+ async def orchestrate_reference_intelligence_agent(
550
+ dir_info: Dict[str, str], logger, progress_callback: Optional[Callable] = None
551
+ ) -> str:
552
+ """
553
+ Orchestrate intelligent reference analysis with automated research discovery.
554
+
555
+ This agent autonomously processes research references and discovers
556
+ related work using advanced AI-powered analysis algorithms.
557
+
558
+ Args:
559
+ dir_info: Workspace infrastructure metadata
560
+ logger: Logger instance for intelligence tracking
561
+ progress_callback: Progress callback function for monitoring
562
+
563
+ Returns:
564
+ str: Comprehensive reference intelligence analysis result
565
+ """
566
+ if progress_callback:
567
+ progress_callback(50, "🧠 Orchestrating reference intelligence discovery...")
568
+
569
+ reference_path = dir_info["reference_path"]
570
+
571
+ # Check if reference analysis already exists
572
+ if os.path.exists(reference_path):
573
+ print(f"Found existing reference analysis at {reference_path}")
574
+ with open(reference_path, "r", encoding="utf-8") as f:
575
+ return f.read()
576
+
577
+ # Execute reference analysis
578
+ reference_result = await paper_reference_analyzer(
579
+ dir_info["standardized_text"], logger
580
+ )
581
+
582
+ # Save reference analysis result
583
+ with open(reference_path, "w", encoding="utf-8") as f:
584
+ f.write(reference_result)
585
+ print(f"Reference analysis saved to {reference_path}")
586
+
587
+ return reference_result
588
+
589
+
590
+ async def orchestrate_code_planning_agent(
591
+ dir_info: Dict[str, str], logger, progress_callback: Optional[Callable] = None
592
+ ):
593
+ """
594
+ Orchestrate intelligent code planning with automated design analysis.
595
+
596
+ This agent autonomously generates optimal code reproduction plans and implementation
597
+ strategies using AI-driven code analysis and planning principles.
598
+
599
+ Args:
600
+ dir_info: Workspace infrastructure metadata
601
+ logger: Logger instance for planning tracking
602
+ progress_callback: Progress callback function for monitoring
603
+ """
604
+ if progress_callback:
605
+ progress_callback(40, "šŸ—ļø Synthesizing intelligent code architecture...")
606
+
607
+ initial_plan_path = dir_info["initial_plan_path"]
608
+
609
+ # Check if initial plan already exists
610
+ if not os.path.exists(initial_plan_path):
611
+ initial_plan_result = await run_code_analyzer(dir_info["paper_dir"], logger)
612
+ with open(initial_plan_path, "w", encoding="utf-8") as f:
613
+ f.write(initial_plan_result)
614
+ print(f"Initial plan saved to {initial_plan_path}")
615
+
616
+
617
+ async def automate_repository_acquisition_agent(
618
+ reference_result: str,
619
+ dir_info: Dict[str, str],
620
+ logger,
621
+ progress_callback: Optional[Callable] = None,
622
+ ):
623
+ """
624
+ Automate intelligent repository acquisition with AI-guided selection.
625
+
626
+ This agent autonomously identifies, evaluates, and acquires relevant
627
+ repositories using intelligent filtering and automated download protocols.
628
+
629
+ Args:
630
+ reference_result: Reference intelligence analysis result
631
+ dir_info: Workspace infrastructure metadata
632
+ logger: Logger instance for acquisition tracking
633
+ progress_callback: Progress callback function for monitoring
634
+ """
635
+ if progress_callback:
636
+ progress_callback(60, "šŸ¤– Automating intelligent repository acquisition...")
637
+
638
+ await asyncio.sleep(5) # Brief pause for stability
639
+
640
+ try:
641
+ download_result = await github_repo_download(
642
+ reference_result, dir_info["paper_dir"], logger
643
+ )
644
+
645
+ # Save download results
646
+ with open(dir_info["download_path"], "w", encoding="utf-8") as f:
647
+ f.write(download_result)
648
+ print(f"GitHub download results saved to {dir_info['download_path']}")
649
+
650
+ # Verify if any repositories were actually downloaded
651
+ code_base_path = os.path.join(dir_info["paper_dir"], "code_base")
652
+ if os.path.exists(code_base_path):
653
+ downloaded_repos = [
654
+ d
655
+ for d in os.listdir(code_base_path)
656
+ if os.path.isdir(os.path.join(code_base_path, d))
657
+ and not d.startswith(".")
658
+ ]
659
+
660
+ if downloaded_repos:
661
+ print(
662
+ f"Successfully downloaded {len(downloaded_repos)} repositories: {downloaded_repos}"
663
+ )
664
+ else:
665
+ print(
666
+ "GitHub download phase completed, but no repositories were found in the code_base directory"
667
+ )
668
+ print("This might indicate:")
669
+ print(
670
+ "1. No relevant repositories were identified in the reference analysis"
671
+ )
672
+ print(
673
+ "2. Repository downloads failed due to access permissions or network issues"
674
+ )
675
+ print(
676
+ "3. The download agent encountered errors during the download process"
677
+ )
678
+ else:
679
+ print(f"Code base directory was not created: {code_base_path}")
680
+
681
+ except Exception as e:
682
+ print(f"Error during GitHub repository download: {e}")
683
+ # Still save the error information
684
+ error_message = f"GitHub download failed: {str(e)}"
685
+ with open(dir_info["download_path"], "w", encoding="utf-8") as f:
686
+ f.write(error_message)
687
+ print(f"GitHub download error saved to {dir_info['download_path']}")
688
+ raise e # Re-raise to be handled by the main pipeline
689
+
690
+
691
+ async def orchestrate_codebase_intelligence_agent(
692
+ dir_info: Dict[str, str], logger, progress_callback: Optional[Callable] = None
693
+ ) -> Dict:
694
+ """
695
+ Orchestrate intelligent codebase analysis with automated knowledge extraction.
696
+
697
+ This agent autonomously processes and indexes codebases using advanced
698
+ AI algorithms for intelligent relationship mapping and knowledge synthesis.
699
+
700
+ Args:
701
+ dir_info: Workspace infrastructure metadata
702
+ logger: Logger instance for intelligence tracking
703
+ progress_callback: Progress callback function for monitoring
704
+
705
+ Returns:
706
+ dict: Comprehensive codebase intelligence analysis result
707
+ """
708
+ if progress_callback:
709
+ progress_callback(70, "🧮 Orchestrating codebase intelligence analysis...")
710
+
711
+ print(
712
+ "Initiating intelligent codebase analysis with AI-powered relationship mapping..."
713
+ )
714
+ await asyncio.sleep(2) # Brief pause before starting indexing
715
+
716
+ # Check if code_base directory exists and has content
717
+ code_base_path = os.path.join(dir_info["paper_dir"], "code_base")
718
+ if not os.path.exists(code_base_path):
719
+ print(f"Code base directory not found: {code_base_path}")
720
+ return {
721
+ "status": "skipped",
722
+ "message": "No code base directory found - skipping indexing",
723
+ }
724
+
725
+ # Check if there are any repositories in the code_base directory
726
+ try:
727
+ repo_dirs = [
728
+ d
729
+ for d in os.listdir(code_base_path)
730
+ if os.path.isdir(os.path.join(code_base_path, d)) and not d.startswith(".")
731
+ ]
732
+
733
+ if not repo_dirs:
734
+ print(f"No repositories found in {code_base_path}")
735
+ print("This might be because:")
736
+ print("1. GitHub download phase didn't complete successfully")
737
+ print("2. No relevant repositories were identified for download")
738
+ print("3. Repository download failed due to access issues")
739
+ print("Continuing with code implementation without codebase indexing...")
740
+
741
+ # Save a report about the skipped indexing
742
+ skip_report = {
743
+ "status": "skipped",
744
+ "reason": "no_repositories_found",
745
+ "message": f"No repositories found in {code_base_path}",
746
+ "suggestions": [
747
+ "Check if GitHub download phase completed successfully",
748
+ "Verify if relevant repositories were identified in reference analysis",
749
+ "Check network connectivity and GitHub access permissions",
750
+ ],
751
+ }
752
+
753
+ with open(dir_info["index_report_path"], "w", encoding="utf-8") as f:
754
+ f.write(str(skip_report))
755
+ print(f"Indexing skip report saved to {dir_info['index_report_path']}")
756
+
757
+ return skip_report
758
+
759
+ except Exception as e:
760
+ print(f"Error checking code base directory: {e}")
761
+ return {
762
+ "status": "error",
763
+ "message": f"Error checking code base directory: {str(e)}",
764
+ }
765
+
766
+ try:
767
+ from workflows.codebase_index_workflow import run_codebase_indexing
768
+
769
+ print(f"Found {len(repo_dirs)} repositories to index: {repo_dirs}")
770
+
771
+ # Run codebase index workflow
772
+ index_result = await run_codebase_indexing(
773
+ paper_dir=dir_info["paper_dir"],
774
+ initial_plan_path=dir_info["initial_plan_path"],
775
+ config_path="mcp_agent.secrets.yaml",
776
+ logger=logger,
777
+ )
778
+
779
+ # Log indexing results
780
+ if index_result["status"] == "success":
781
+ print("Code indexing completed successfully!")
782
+ print(
783
+ f"Indexed {index_result['statistics']['total_repositories'] if index_result.get('statistics') else len(index_result['output_files'])} repositories"
784
+ )
785
+ print(f"Generated {len(index_result['output_files'])} index files")
786
+
787
+ # Save indexing results to file
788
+ with open(dir_info["index_report_path"], "w", encoding="utf-8") as f:
789
+ f.write(str(index_result))
790
+ print(f"Indexing report saved to {dir_info['index_report_path']}")
791
+
792
+ elif index_result["status"] == "warning":
793
+ print(f"Code indexing completed with warnings: {index_result['message']}")
794
+ else:
795
+ print(f"Code indexing failed: {index_result['message']}")
796
+
797
+ return index_result
798
+
799
+ except Exception as e:
800
+ print(f"Error during codebase indexing workflow: {e}")
801
+ print("Continuing with code implementation despite indexing failure...")
802
+
803
+ # Save error report
804
+ error_report = {
805
+ "status": "error",
806
+ "message": str(e),
807
+ "phase": "codebase_indexing",
808
+ "recovery_action": "continuing_with_code_implementation",
809
+ }
810
+
811
+ with open(dir_info["index_report_path"], "w", encoding="utf-8") as f:
812
+ f.write(str(error_report))
813
+ print(f"Indexing error report saved to {dir_info['index_report_path']}")
814
+
815
+ return error_report
816
+
817
+
818
+ async def synthesize_code_implementation_agent(
819
+ dir_info: Dict[str, str],
820
+ logger,
821
+ progress_callback: Optional[Callable] = None,
822
+ enable_indexing: bool = True,
823
+ ) -> Dict:
824
+ """
825
+ Synthesize intelligent code implementation with automated development.
826
+
827
+ This agent autonomously generates high-quality code implementations using
828
+ AI-powered development strategies and intelligent code synthesis algorithms.
829
+
830
+ Args:
831
+ dir_info: Workspace infrastructure metadata
832
+ logger: Logger instance for implementation tracking
833
+ progress_callback: Progress callback function for monitoring
834
+ enable_indexing: Whether to enable code reference indexing for enhanced implementation
835
+
836
+ Returns:
837
+ dict: Comprehensive code implementation synthesis result
838
+ """
839
+ if progress_callback:
840
+ progress_callback(85, "šŸ”¬ Synthesizing intelligent code implementation...")
841
+
842
+ print(
843
+ "Launching intelligent code synthesis with AI-driven implementation strategies..."
844
+ )
845
+ await asyncio.sleep(3) # Brief pause before starting implementation
846
+
847
+ try:
848
+ # Create code implementation workflow instance based on indexing preference
849
+ if enable_indexing:
850
+ print(
851
+ "šŸ” Using enhanced code implementation workflow with reference indexing..."
852
+ )
853
+ code_workflow = CodeImplementationWorkflowWithIndex()
854
+ else:
855
+ print("⚔ Using standard code implementation workflow (fast mode)...")
856
+ code_workflow = CodeImplementationWorkflow()
857
+
858
+ # Check if initial plan file exists
859
+ if os.path.exists(dir_info["initial_plan_path"]):
860
+ print(f"Using initial plan from {dir_info['initial_plan_path']}")
861
+
862
+ # Run code implementation workflow with pure code mode
863
+ implementation_result = await code_workflow.run_workflow(
864
+ plan_file_path=dir_info["initial_plan_path"],
865
+ target_directory=dir_info["paper_dir"],
866
+ pure_code_mode=True, # Focus on code implementation, skip testing
867
+ )
868
+
869
+ # Log implementation results
870
+ if implementation_result["status"] == "success":
871
+ print("Code implementation completed successfully!")
872
+ print(f"Code directory: {implementation_result['code_directory']}")
873
+
874
+ # Save implementation results to file
875
+ with open(
876
+ dir_info["implementation_report_path"], "w", encoding="utf-8"
877
+ ) as f:
878
+ f.write(str(implementation_result))
879
+ print(
880
+ f"Implementation report saved to {dir_info['implementation_report_path']}"
881
+ )
882
+
883
+ else:
884
+ print(
885
+ f"Code implementation failed: {implementation_result.get('message', 'Unknown error')}"
886
+ )
887
+
888
+ return implementation_result
889
+ else:
890
+ print(
891
+ f"Initial plan file not found at {dir_info['initial_plan_path']}, skipping code implementation"
892
+ )
893
+ return {
894
+ "status": "warning",
895
+ "message": "Initial plan not found - code implementation skipped",
896
+ }
897
+
898
+ except Exception as e:
899
+ print(f"Error during code implementation workflow: {e}")
900
+ return {"status": "error", "message": str(e)}
901
+
902
+
903
+ async def run_chat_planning_agent(user_input: str, logger) -> str:
904
+ """
905
+ Run the chat-based planning agent for user-provided coding requirements.
906
+
907
+ This agent transforms user's coding description into a comprehensive implementation plan
908
+ that can be directly used for code generation. It handles both academic and engineering
909
+ requirements with intelligent context adaptation.
910
+
911
+ Args:
912
+ user_input: User's coding requirements and description
913
+ logger: Logger instance for logging information
914
+
915
+ Returns:
916
+ str: Comprehensive implementation plan in YAML format
917
+ """
918
+ try:
919
+ print("šŸ’¬ Starting chat-based planning agent...")
920
+ print(f"Input length: {len(user_input) if user_input else 0}")
921
+ print(f"Input preview: {user_input[:200] if user_input else 'None'}...")
922
+
923
+ if not user_input or user_input.strip() == "":
924
+ raise ValueError(
925
+ "Empty or None user_input provided to run_chat_planning_agent"
926
+ )
927
+
928
+ # Create the chat planning agent
929
+ chat_planning_agent = Agent(
930
+ name="ChatPlanningAgent",
931
+ instruction=CHAT_AGENT_PLANNING_PROMPT,
932
+ server_names=[
933
+ "brave"
934
+ ], # Add tools if needed for web search or other capabilities
935
+ )
936
+
937
+ async with chat_planning_agent:
938
+ print("chat_planning: Connected to server, calling list_tools...")
939
+ try:
940
+ tools = await chat_planning_agent.list_tools()
941
+ print(
942
+ "Tools available:",
943
+ tools.model_dump() if hasattr(tools, "model_dump") else str(tools),
944
+ )
945
+ except Exception as e:
946
+ print(f"Failed to list tools: {e}")
947
+
948
+ try:
949
+ planner = await chat_planning_agent.attach_llm(
950
+ get_preferred_llm_class()
951
+ )
952
+ print("āœ… LLM attached successfully")
953
+ except Exception as e:
954
+ print(f"āŒ Failed to attach LLM: {e}")
955
+ raise
956
+
957
+ # Set higher token output for comprehensive planning
958
+ planning_params = RequestParams(
959
+ max_tokens=8192, # Higher token limit for detailed plans
960
+ temperature=0.2, # Lower temperature for more structured output
961
+ )
962
+
963
+ print(
964
+ f"šŸ”„ Making LLM request with params: max_tokens={planning_params.max_tokens}, temperature={planning_params.temperature}"
965
+ )
966
+
967
+ # Format the input message for the agent
968
+ formatted_message = f"""Please analyze the following coding requirements and generate a comprehensive implementation plan:
969
+
970
+ User Requirements:
971
+ {user_input}
972
+
973
+ Please provide a detailed implementation plan that covers all aspects needed for successful development."""
974
+
975
+ try:
976
+ raw_result = await planner.generate_str(
977
+ message=formatted_message, request_params=planning_params
978
+ )
979
+
980
+ print("āœ… Planning request completed")
981
+ print(f"Raw result type: {type(raw_result)}")
982
+ print(f"Raw result length: {len(raw_result) if raw_result else 0}")
983
+
984
+ if not raw_result:
985
+ print("āŒ CRITICAL: raw_result is empty or None!")
986
+ raise ValueError("Chat planning agent returned empty result")
987
+
988
+ except Exception as e:
989
+ print(f"āŒ Planning generation failed: {e}")
990
+ print(f"Exception type: {type(e)}")
991
+ raise
992
+
993
+ # Log to SimpleLLMLogger
994
+ if hasattr(logger, "log_response"):
995
+ logger.log_response(
996
+ raw_result, model="ChatPlanningAgent", agent="ChatPlanningAgent"
997
+ )
998
+
999
+ if not raw_result or raw_result.strip() == "":
1000
+ print("āŒ CRITICAL: Planning result is empty!")
1001
+ raise ValueError("Chat planning agent produced empty output")
1002
+
1003
+ print("šŸŽÆ Chat planning completed successfully")
1004
+ print(f"Planning result preview: {raw_result[:500]}...")
1005
+
1006
+ return raw_result
1007
+
1008
+ except Exception as e:
1009
+ print(f"āŒ run_chat_planning_agent failed: {e}")
1010
+ print(f"Exception details: {type(e).__name__}: {str(e)}")
1011
+ raise
1012
+
1013
+
1014
+ async def execute_multi_agent_research_pipeline(
1015
+ input_source: str,
1016
+ logger,
1017
+ progress_callback: Optional[Callable] = None,
1018
+ enable_indexing: bool = True,
1019
+ ) -> str:
1020
+ """
1021
+ Execute the complete intelligent multi-agent research orchestration pipeline.
1022
+
1023
+ This is the main AI orchestration engine that coordinates autonomous research workflow agents:
1024
+ - Local workspace automation for seamless environment management
1025
+ - Intelligent research analysis with automated content processing
1026
+ - AI-driven code architecture synthesis and design automation
1027
+ - Reference intelligence discovery with automated knowledge extraction (optional)
1028
+ - Codebase intelligence orchestration with automated relationship analysis (optional)
1029
+ - Intelligent code implementation synthesis with AI-powered development
1030
+
1031
+ Args:
1032
+ input_source: Research input source (file path, URL, or preprocessed analysis)
1033
+ logger: Logger instance for comprehensive workflow intelligence tracking
1034
+ progress_callback: Progress callback function for real-time monitoring
1035
+ enable_indexing: Whether to enable advanced intelligence analysis (default: True)
1036
+
1037
+ Returns:
1038
+ str: The comprehensive pipeline execution result with status and outcomes
1039
+ """
1040
+ try:
1041
+ # Phase 0: Workspace Setup
1042
+ if progress_callback:
1043
+ progress_callback(5, "šŸ”„ Setting up workspace for file processing...")
1044
+
1045
+ print("šŸš€ Initializing intelligent multi-agent research orchestration system")
1046
+
1047
+ # Setup local workspace directory
1048
+ workspace_dir = os.path.join(os.getcwd(), "deepcode_lab")
1049
+ os.makedirs(workspace_dir, exist_ok=True)
1050
+
1051
+ print("šŸ“ Working environment: local")
1052
+ print(f"šŸ“‚ Workspace directory: {workspace_dir}")
1053
+ print("āœ… Workspace status: ready")
1054
+
1055
+ # Log intelligence functionality status
1056
+ if enable_indexing:
1057
+ print("🧠 Advanced intelligence analysis enabled - comprehensive workflow")
1058
+ else:
1059
+ print("⚔ Optimized mode - advanced intelligence analysis disabled")
1060
+
1061
+ # Phase 1: Input Processing and Validation
1062
+ input_source = await _process_input_source(input_source, logger)
1063
+
1064
+ # Phase 2: Research Analysis and Resource Processing (if needed)
1065
+ if isinstance(input_source, str) and (
1066
+ input_source.endswith((".pdf", ".docx", ".txt", ".html", ".md"))
1067
+ or input_source.startswith(("http", "file://"))
1068
+ ):
1069
+ (
1070
+ analysis_result,
1071
+ download_result,
1072
+ ) = await orchestrate_research_analysis_agent(
1073
+ input_source, logger, progress_callback
1074
+ )
1075
+ else:
1076
+ download_result = input_source # Use input directly if already processed
1077
+
1078
+ # Phase 3: Workspace Infrastructure Synthesis
1079
+ if progress_callback:
1080
+ progress_callback(
1081
+ 40, "šŸ—ļø Synthesizing intelligent workspace infrastructure..."
1082
+ )
1083
+
1084
+ dir_info = await synthesize_workspace_infrastructure_agent(
1085
+ download_result, logger, workspace_dir
1086
+ )
1087
+ await asyncio.sleep(30)
1088
+
1089
+ # Phase 4: Code Planning Orchestration
1090
+ await orchestrate_code_planning_agent(dir_info, logger, progress_callback)
1091
+
1092
+ # Phase 5: Reference Intelligence (only when indexing is enabled)
1093
+ if enable_indexing:
1094
+ reference_result = await orchestrate_reference_intelligence_agent(
1095
+ dir_info, logger, progress_callback
1096
+ )
1097
+ else:
1098
+ print("šŸ”¶ Skipping reference intelligence analysis (fast mode enabled)")
1099
+ # Create empty reference analysis result to maintain file structure consistency
1100
+ reference_result = "Reference intelligence analysis skipped - fast mode enabled for optimized processing"
1101
+ with open(dir_info["reference_path"], "w", encoding="utf-8") as f:
1102
+ f.write(reference_result)
1103
+
1104
+ # Phase 6: Repository Acquisition Automation (optional)
1105
+ if enable_indexing:
1106
+ await automate_repository_acquisition_agent(
1107
+ reference_result, dir_info, logger, progress_callback
1108
+ )
1109
+ else:
1110
+ print("šŸ”¶ Skipping automated repository acquisition (fast mode enabled)")
1111
+ # Create empty download result file to maintain file structure consistency
1112
+ with open(dir_info["download_path"], "w", encoding="utf-8") as f:
1113
+ f.write(
1114
+ "Automated repository acquisition skipped - fast mode enabled for optimized processing"
1115
+ )
1116
+
1117
+ # Phase 7: Codebase Intelligence Orchestration (optional)
1118
+ if enable_indexing:
1119
+ index_result = await orchestrate_codebase_intelligence_agent(
1120
+ dir_info, logger, progress_callback
1121
+ )
1122
+ else:
1123
+ print("šŸ”¶ Skipping codebase intelligence orchestration (fast mode enabled)")
1124
+ # Create a skipped indexing result
1125
+ index_result = {
1126
+ "status": "skipped",
1127
+ "reason": "fast_mode_enabled",
1128
+ "message": "Codebase intelligence orchestration skipped for optimized processing",
1129
+ }
1130
+ with open(dir_info["index_report_path"], "w", encoding="utf-8") as f:
1131
+ f.write(str(index_result))
1132
+
1133
+ # Phase 8: Code Implementation Synthesis
1134
+ implementation_result = await synthesize_code_implementation_agent(
1135
+ dir_info, logger, progress_callback, enable_indexing
1136
+ )
1137
+
1138
+ # Final Status Report
1139
+ if enable_indexing:
1140
+ pipeline_summary = (
1141
+ f"Multi-agent research pipeline completed for {dir_info['paper_dir']}"
1142
+ )
1143
+ else:
1144
+ pipeline_summary = f"Multi-agent research pipeline completed (fast mode) for {dir_info['paper_dir']}"
1145
+
1146
+ # Add indexing status to summary
1147
+ if not enable_indexing:
1148
+ pipeline_summary += (
1149
+ "\n⚔ Fast mode: GitHub download and codebase indexing skipped"
1150
+ )
1151
+ elif index_result["status"] == "skipped":
1152
+ pipeline_summary += f"\nšŸ”¶ Codebase indexing: {index_result['message']}"
1153
+ elif index_result["status"] == "error":
1154
+ pipeline_summary += (
1155
+ f"\nāŒ Codebase indexing failed: {index_result['message']}"
1156
+ )
1157
+ elif index_result["status"] == "success":
1158
+ pipeline_summary += "\nāœ… Codebase indexing completed successfully"
1159
+
1160
+ # Add implementation status to summary
1161
+ if implementation_result["status"] == "success":
1162
+ pipeline_summary += "\nšŸŽ‰ Code implementation completed successfully!"
1163
+ pipeline_summary += (
1164
+ f"\nšŸ“ Code generated in: {implementation_result['code_directory']}"
1165
+ )
1166
+ return pipeline_summary
1167
+ elif implementation_result["status"] == "warning":
1168
+ pipeline_summary += (
1169
+ f"\nāš ļø Code implementation: {implementation_result['message']}"
1170
+ )
1171
+ return pipeline_summary
1172
+ else:
1173
+ pipeline_summary += (
1174
+ f"\nāŒ Code implementation failed: {implementation_result['message']}"
1175
+ )
1176
+ return pipeline_summary
1177
+
1178
+ except Exception as e:
1179
+ print(f"Error in execute_multi_agent_research_pipeline: {e}")
1180
+ raise e
1181
+
1182
+
1183
+ # Backward compatibility alias (deprecated)
1184
+ async def paper_code_preparation(
1185
+ input_source: str, logger, progress_callback: Optional[Callable] = None
1186
+ ) -> str:
1187
+ """
1188
+ Deprecated: Use execute_multi_agent_research_pipeline instead.
1189
+
1190
+ Args:
1191
+ input_source: Input source
1192
+ logger: Logger instance
1193
+ progress_callback: Progress callback function
1194
+
1195
+ Returns:
1196
+ str: Pipeline result
1197
+ """
1198
+ print(
1199
+ "paper_code_preparation is deprecated. Use execute_multi_agent_research_pipeline instead."
1200
+ )
1201
+ return await execute_multi_agent_research_pipeline(
1202
+ input_source, logger, progress_callback
1203
+ )
1204
+
1205
+
1206
+ async def execute_chat_based_planning_pipeline(
1207
+ user_input: str,
1208
+ logger,
1209
+ progress_callback: Optional[Callable] = None,
1210
+ enable_indexing: bool = True,
1211
+ ) -> str:
1212
+ """
1213
+ Execute the chat-based planning and implementation pipeline.
1214
+
1215
+ This pipeline is designed for users who provide coding requirements directly through chat,
1216
+ bypassing the traditional paper analysis phases (Phase 0-7) and jumping directly to
1217
+ planning and code implementation.
1218
+
1219
+ Pipeline Flow:
1220
+ - Chat Planning: Transform user input into implementation plan
1221
+ - Workspace Setup: Create necessary directory structure
1222
+ - Code Implementation: Generate code based on the plan
1223
+
1224
+ Args:
1225
+ user_input: User's coding requirements and description
1226
+ logger: Logger instance for comprehensive workflow tracking
1227
+ progress_callback: Progress callback function for real-time monitoring
1228
+ enable_indexing: Whether to enable code reference indexing for enhanced implementation
1229
+
1230
+ Returns:
1231
+ str: The pipeline execution result with status and outcomes
1232
+ """
1233
+ try:
1234
+ print("šŸš€ Initializing chat-based planning and implementation pipeline")
1235
+ print("šŸ’¬ Chat mode: Direct user requirements to code implementation")
1236
+
1237
+ # Phase 0: Workspace Setup
1238
+ if progress_callback:
1239
+ progress_callback(5, "šŸ”„ Setting up workspace for file processing...")
1240
+
1241
+ # Setup local workspace directory
1242
+ workspace_dir = os.path.join(os.getcwd(), "deepcode_lab")
1243
+ os.makedirs(workspace_dir, exist_ok=True)
1244
+
1245
+ print("šŸ“ Working environment: local")
1246
+ print(f"šŸ“‚ Workspace directory: {workspace_dir}")
1247
+ print("āœ… Workspace status: ready")
1248
+
1249
+ # Phase 1: Chat-Based Planning
1250
+ if progress_callback:
1251
+ progress_callback(
1252
+ 30,
1253
+ "šŸ’¬ Generating comprehensive implementation plan from user requirements...",
1254
+ )
1255
+
1256
+ print("🧠 Running chat-based planning agent...")
1257
+ planning_result = await run_chat_planning_agent(user_input, logger)
1258
+
1259
+ # Phase 2: Workspace Infrastructure Synthesis
1260
+ if progress_callback:
1261
+ progress_callback(
1262
+ 50, "šŸ—ļø Synthesizing intelligent workspace infrastructure..."
1263
+ )
1264
+
1265
+ # Create workspace directory structure for chat mode
1266
+ # First, let's create a temporary directory structure that mimics a paper workspace
1267
+ import time
1268
+
1269
+ # Generate a unique paper directory name
1270
+ timestamp = str(int(time.time()))
1271
+ paper_name = f"chat_project_{timestamp}"
1272
+
1273
+ # Use workspace directory
1274
+ chat_paper_dir = os.path.join(workspace_dir, "papers", paper_name)
1275
+
1276
+ os.makedirs(chat_paper_dir, exist_ok=True)
1277
+
1278
+ # Create a synthetic markdown file with user requirements
1279
+ markdown_content = f"""# User Coding Requirements
1280
+
1281
+ ## Project Description
1282
+ This is a coding project generated from user requirements via chat interface.
1283
+
1284
+ ## User Requirements
1285
+ {user_input}
1286
+
1287
+ ## Generated Implementation Plan
1288
+ The following implementation plan was generated by the AI chat planning agent:
1289
+
1290
+ ```yaml
1291
+ {planning_result}
1292
+ ```
1293
+
1294
+ ## Project Metadata
1295
+ - **Input Type**: Chat Input
1296
+ - **Generation Method**: AI Chat Planning Agent
1297
+ - **Timestamp**: {timestamp}
1298
+ """
1299
+
1300
+ # Save the markdown file
1301
+ markdown_file_path = os.path.join(chat_paper_dir, f"{paper_name}.md")
1302
+ with open(markdown_file_path, "w", encoding="utf-8") as f:
1303
+ f.write(markdown_content)
1304
+
1305
+ print(f"šŸ’¾ Created chat project workspace: {chat_paper_dir}")
1306
+ print(f"šŸ“„ Saved requirements to: {markdown_file_path}")
1307
+
1308
+ # Create a download result that matches FileProcessor expectations
1309
+ synthetic_download_result = json.dumps(
1310
+ {
1311
+ "status": "success",
1312
+ "paper_path": markdown_file_path,
1313
+ "input_type": "chat_input",
1314
+ "paper_info": {
1315
+ "title": "User-Provided Coding Requirements",
1316
+ "source": "chat_input",
1317
+ "description": "Implementation plan generated from user requirements",
1318
+ },
1319
+ }
1320
+ )
1321
+
1322
+ dir_info = await synthesize_workspace_infrastructure_agent(
1323
+ synthetic_download_result, logger, workspace_dir
1324
+ )
1325
+ await asyncio.sleep(10) # Brief pause for file system operations
1326
+
1327
+ # Phase 3: Save Planning Result
1328
+ if progress_callback:
1329
+ progress_callback(70, "šŸ“ Saving implementation plan...")
1330
+
1331
+ # Save the planning result to the initial_plan.txt file (same location as Phase 4 in original pipeline)
1332
+ initial_plan_path = dir_info["initial_plan_path"]
1333
+ with open(initial_plan_path, "w", encoding="utf-8") as f:
1334
+ f.write(planning_result)
1335
+ print(f"šŸ’¾ Implementation plan saved to {initial_plan_path}")
1336
+
1337
+ # Phase 4: Code Implementation Synthesis (same as Phase 8 in original pipeline)
1338
+ if progress_callback:
1339
+ progress_callback(85, "šŸ”¬ Synthesizing intelligent code implementation...")
1340
+
1341
+ implementation_result = await synthesize_code_implementation_agent(
1342
+ dir_info, logger, progress_callback, enable_indexing
1343
+ )
1344
+
1345
+ # Final Status Report
1346
+ pipeline_summary = f"Chat-based planning and implementation pipeline completed for {dir_info['paper_dir']}"
1347
+
1348
+ # Add implementation status to summary
1349
+ if implementation_result["status"] == "success":
1350
+ pipeline_summary += "\nšŸŽ‰ Code implementation completed successfully!"
1351
+ pipeline_summary += (
1352
+ f"\nšŸ“ Code generated in: {implementation_result['code_directory']}"
1353
+ )
1354
+ pipeline_summary += (
1355
+ "\nšŸ’¬ Generated from user requirements via chat interface"
1356
+ )
1357
+ return pipeline_summary
1358
+ elif implementation_result["status"] == "warning":
1359
+ pipeline_summary += (
1360
+ f"\nāš ļø Code implementation: {implementation_result['message']}"
1361
+ )
1362
+ return pipeline_summary
1363
+ else:
1364
+ pipeline_summary += (
1365
+ f"\nāŒ Code implementation failed: {implementation_result['message']}"
1366
+ )
1367
+ return pipeline_summary
1368
+
1369
+ except Exception as e:
1370
+ print(f"Error in execute_chat_based_planning_pipeline: {e}")
1371
+ raise e