Skip to content

Commit ec3c9cb

Browse files
committed
Improve workflow stability
1 parent ff5b858 commit ec3c9cb

14 files changed

+883
-400
lines changed

config/mcp_tool_definitions.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ def get_code_implementation_tools() -> List[Dict[str, Any]]:
2525
Get tool definitions for code implementation
2626
"""
2727
return [
28-
MCPToolDefinitions._get_read_file_tool(),
28+
# MCPToolDefinitions._get_read_file_tool(),
2929
# MCPToolDefinitions._get_read_multiple_files_tool(),
30-
MCPToolDefinitions._get_read_code_mem_tool(),
30+
# MCPToolDefinitions._get_read_code_mem_tool(),
3131
MCPToolDefinitions._get_write_file_tool(),
3232
# MCPToolDefinitions._get_write_multiple_files_tool(),
3333
# MCPToolDefinitions._get_execute_python_tool(),
34-
MCPToolDefinitions._get_execute_bash_tool(),
34+
# MCPToolDefinitions._get_execute_bash_tool(),
3535
]
3636

3737
@staticmethod

config/mcp_tool_definitions_index.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,18 @@ def get_code_implementation_tools() -> List[Dict[str, Any]]:
2525
Get tool definitions for code implementation
2626
"""
2727
return [
28-
MCPToolDefinitions._get_read_file_tool(),
29-
MCPToolDefinitions._get_read_multiple_files_tool(),
30-
MCPToolDefinitions._get_read_code_mem_tool(),
28+
# MCPToolDefinitions._get_read_file_tool(),
29+
# MCPToolDefinitions._get_read_multiple_files_tool(),
30+
# MCPToolDefinitions._get_read_code_mem_tool(),
3131
MCPToolDefinitions._get_write_file_tool(),
32-
MCPToolDefinitions._get_write_multiple_files_tool(),
33-
MCPToolDefinitions._get_execute_python_tool(),
34-
MCPToolDefinitions._get_execute_bash_tool(),
32+
# MCPToolDefinitions._get_write_multiple_files_tool(),
33+
# MCPToolDefinitions._get_execute_python_tool(),
34+
# MCPToolDefinitions._get_execute_bash_tool(),
3535
MCPToolDefinitions._get_search_code_references_tool(),
36-
MCPToolDefinitions._get_search_code_tool(),
37-
MCPToolDefinitions._get_file_structure_tool(),
38-
MCPToolDefinitions._get_set_workspace_tool(),
39-
MCPToolDefinitions._get_operation_history_tool(),
36+
# MCPToolDefinitions._get_search_code_tool(),
37+
# MCPToolDefinitions._get_file_structure_tool(),
38+
# MCPToolDefinitions._get_set_workspace_tool(),
39+
# MCPToolDefinitions._get_operation_history_tool(),
4040
]
4141

4242
@staticmethod

prompts/code_prompts.py

Lines changed: 34 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,21 @@
6161
PAPER_DOWNLOADER_PROMPT = """You are a precise paper downloader that processes input from PaperInputAnalyzerAgent.
6262
6363
Task: Handle paper according to input type and save to "./deepcode_lab/papers/id/id.md"
64-
Note: Generate id (id is a number) by counting files in "./deepcode_lab/papers/" directory and increment by 1.
64+
Note: The paper ID will be provided at the start of the message as "PAPER_ID=<number>". Use this EXACT number.
6565
66-
CRITICAL RULE: NEVER use write_file tool to create paper content directly. Always use file-downloader tools for PDF/document conversion.
66+
CRITICAL RULES:
67+
- Use the EXACT paper ID provided in the message (PAPER_ID=X).
68+
- Save path MUST be: ./deepcode_lab/papers/{PAPER_ID}/{PAPER_ID}.md
6769
6870
Processing Rules:
6971
1. URL Input (input_type = "url"):
70-
- Use "file-downloader" tool to download paper
72+
- Use download_file_to tool with: url=<url>, destination="./deepcode_lab/papers/{PAPER_ID}/", filename="{PAPER_ID}.md"
7173
- Extract metadata (title, authors, year)
7274
- Return saved file path and metadata
7375
7476
2. File Input (input_type = "file"):
75-
- Copy file to "./deepcode_lab/papers/id/" using move_file_to tool (preserves original)
76-
- The move_file_to tool will automatically convert PDF/documents to .md format
77+
- Use move_file_to tool with: source=<file_path>, destination="./deepcode_lab/papers/{PAPER_ID}/{PAPER_ID}.md"
78+
- The tool will automatically convert PDF/documents to .md format
7779
- NEVER manually extract content or use write_file - let the conversion tools handle this
7880
- Note: Original file is preserved, only a copy is placed in target directory
7981
- Return new saved file path and metadata
@@ -100,16 +102,26 @@
100102
"requirements": ["requirement1", "requirement2"]
101103
}
102104
103-
Output Format (DO NOT MODIFY):
105+
CRITICAL OUTPUT RESTRICTIONS:
106+
- RETURN ONLY RAW JSON - NO TEXT BEFORE OR AFTER
107+
- NO markdown code blocks (```json)
108+
- NO explanatory text or descriptions
109+
- NO tool call information
110+
- NO analysis summaries
111+
- JUST THE JSON OBJECT BELOW
112+
113+
Output Format (MANDATORY - EXACT FORMAT):
104114
{
105115
"status": "success|failure",
106-
"paper_path": "path to paper file or null for text input",
116+
"paper_path": "./deepcode_lab/papers/{PAPER_ID}/{PAPER_ID}.md (or null for text input)",
107117
"metadata": {
108118
"title": "extracted or provided title",
109119
"authors": ["extracted or provided authors"],
110120
"year": "extracted or provided year"
111121
}
112122
}
123+
124+
Example: If PAPER_ID=14, then paper_path should be "./deepcode_lab/papers/14/14.md"
113125
"""
114126

115127
PAPER_REFERENCE_ANALYZER_PROMPT = """You are an expert academic paper reference analyzer specializing in computer science and machine learning.
@@ -1045,11 +1057,10 @@
10451057
**IMPLEMENTATION APPROACH**:
10461058
Build incrementally using multiple tool calls. For each step:
10471059
1. **Identify** what needs to be implemented from the paper
1048-
2. **Analyze Dependencies**: Before implementing each new file, use `read_code_mem` to read summaries of already-implemented files, then search for reference patterns to guide your implementation approach.
1049-
3. **Implement** one component at a time
1050-
4. **Test** immediately to catch issues early
1051-
5. **Integrate** with existing components
1052-
6. **Verify** against paper specifications
1060+
2. **Implement** one component at a time
1061+
3. **Test** immediately to catch issues early
1062+
4. **Integrate** with existing components
1063+
5. **Verify** against paper specifications
10531064
10541065
**TOOL CALLING STRATEGY**:
10551066
1. ⚠️ **SINGLE FUNCTION CALL PER MESSAGE**: Each message may perform only one function call. You will see the result of the function right after sending the message. If you need to perform multiple actions, you can always send more messages with subsequent function calls. Do some reasoning before your actions, describing what function calls you are going to use and how they fit into your plan.
@@ -1059,8 +1070,7 @@
10591070
- **Reference only**: Use `search_code_references(indexes_path="indexes", target_file=the_file_you_want_to_implement, keywords=the_keywords_you_want_to_search)` for reference, NOT as implementation standard
10601071
- **Core principle**: Original paper requirements take absolute priority over any reference code found
10611072
3. **TOOL EXECUTION STRATEGY**:
1062-
- ⚠️**Development Cycle (for each new file implementation)**: `read_code_mem` (check existing implementations in Working Directory, use `read_file` as fallback if memory unavailable) → `search_code_references` (OPTIONAL reference check from indexes library in working directory) → `write_file` (implement based on original paper) → `execute_python` (if should test)
1063-
- **Environment Setup**: `write_file` (requirements.txt) → `execute_bash` (pip install) → `execute_python` (verify)
1073+
- ⚠️**Development Cycle (for each new file implementation)**: `search_code_references` (OPTIONAL reference check from indexes library in working directory) → `write_file` (implement based on original paper)
10641074
10651075
4. **CRITICAL**: Use bash and python tools to ACTUALLY REPLICATE the paper yourself - do not provide instructions.
10661076
@@ -1104,11 +1114,10 @@
11041114
**IMPLEMENTATION APPROACH**:
11051115
Build incrementally using multiple tool calls. For each step:
11061116
1. **Identify** what needs to be implemented from the paper
1107-
2. **Analyze Dependencies**: Before implementing each new file, use `read_code_mem` to read summaries of already-implemented files, then search for reference patterns to guide your implementation approach.
1108-
3. **Implement** one component at a time
1109-
4. **Test** immediately to catch issues early
1110-
5. **Integrate** with existing components
1111-
6. **Verify** against paper specifications
1117+
2. **Implement** one component at a time
1118+
3. **Test** immediately to catch issues early
1119+
4. **Integrate** with existing components
1120+
5. **Verify** against paper specifications
11121121
11131122
**TOOL CALLING STRATEGY**:
11141123
1. ⚠️ **SINGLE FUNCTION CALL PER MESSAGE**: Each message may perform only one function call. You will see the result of the function right after sending the message. If you need to perform multiple actions, you can always send more messages with subsequent function calls. Do some reasoning before your actions, describing what function calls you are going to use and how they fit into your plan.
@@ -1118,10 +1127,7 @@
11181127
- **Reference only**: Use `search_code_references(indexes_path="indexes", target_file=the_file_you_want_to_implement, keywords=the_keywords_you_want_to_search)` for reference, NOT as implementation standard
11191128
- **Core principle**: Original paper requirements take absolute priority over any reference code found
11201129
3. **TOOL EXECUTION STRATEGY**:
1121-
- ⚠️**Development Cycle (for each new file implementation)**: `read_code_mem` (check existing implementations in Working Directory, use `read_file` as fallback if memory unavailable`) → `search_code_references` (OPTIONAL reference check from `/home/agent/indexes`) → `write_file` (implement based on original paper) → `execute_python` (if needed to verify implementation)
1122-
- **File Verification**: Use `execute_bash` and `execute_python` when needed to check implementation completeness
1123-
1124-
4. **CRITICAL**: Use bash and python tools when needed to CHECK and VERIFY implementation completeness - do not provide instructions. These tools help validate that your implementation files are syntactically correct and properly structured.
1130+
- ⚠️**Development Cycle (for each new file implementation)**: `search_code_references` (OPTIONAL reference check from `/home/agent/indexes`) → `write_file` (implement based on original paper)
11251131
11261132
**Execution Guidelines**:
11271133
- **Plan First**: Before each action, explain your reasoning and which function you'll use
@@ -1213,24 +1219,16 @@
12131219
**IMPLEMENTATION APPROACH**:
12141220
Build incrementally using multiple tool calls. For each step:
12151221
1. **Identify** what needs to be implemented from the requirements
1216-
2. **Analyze Dependencies**: Before implementing each new file, use `read_code_mem` to read summaries of already-implemented files, then search for reference patterns to guide your implementation approach.
1217-
3. **Implement** one component at a time
1218-
4. **Verify** optionally using `execute_python` or `execute_bash` to check implementation completeness if needed
1219-
5. **Integrate** with existing components
1220-
6. **Validate** against requirement specifications
1222+
2. **Implement** one component at a time
1223+
3. **Verify** optionally using `execute_python` or `execute_bash` to check implementation completeness if needed
1224+
4. **Integrate** with existing components
1225+
5. **Validate** against requirement specifications
12211226
12221227
**TOOL CALLING STRATEGY**:
12231228
1. ⚠️ **SINGLE FUNCTION CALL PER MESSAGE**: Each message may perform only one function call. You will see the result of the function right after sending the message. If you need to perform multiple actions, you can always send more messages with subsequent function calls. Do some reasoning before your actions, describing what function calls you are going to use and how they fit into your plan.
12241229
12251230
2. **TOOL EXECUTION STRATEGY**:
1226-
- **Development Cycle (for each new file implementation)**: `read_code_mem` (check existing implementations in Working Directory, use `read_file` as fallback if memory unavailable) → `write_file` (implement) → **Optional Verification**: `execute_python` or `execute_bash` (if needed to check implementation)
1227-
- **File Verification**: Use `execute_bash` and `execute_python` when needed to verify implementation completeness.
1228-
1229-
3. **CRITICAL**: Use `execute_bash` and `execute_python` tools when needed to CHECK and VERIFY file implementation completeness - do not provide instructions. These tools are essential for:
1230-
- Checking file syntax and import correctness (`execute_python`)
1231-
- Verifying file structure and dependencies (`execute_bash` for listing, `execute_python` for imports)
1232-
- Validating that implemented files are syntactically correct and can be imported
1233-
- Ensuring code implementation meets basic functionality requirements
1231+
- **Development Cycle (for each new file implementation)**: `write_file` (implement)
12341232
12351233
**Execution Guidelines**:
12361234
- **Plan First**: Before each action, explain your reasoning and which function you'll use
@@ -1348,10 +1346,6 @@
13481346
## TRADITIONAL APPROACH: Full Document Reading
13491347
Read the complete document to ensure comprehensive coverage of all algorithmic details:
13501348
1351-
1. **Locate and read the markdown (.md) file** in the paper directory
1352-
2. **Analyze the entire document** to capture all algorithms, methods, and formulas
1353-
3. **Extract complete implementation details** without missing any components
1354-
13551349
# DETAILED EXTRACTION PROTOCOL
13561350
13571351
## 1. COMPREHENSIVE ALGORITHM SCAN
@@ -1511,10 +1505,6 @@
15111505
## TRADITIONAL APPROACH: Complete Document Analysis
15121506
Read the entire document systematically to ensure comprehensive understanding:
15131507
1514-
1. **Locate and read the markdown (.md) file** in the paper directory
1515-
2. **Analyze the complete document structure** from introduction to conclusion
1516-
3. **Extract all conceptual frameworks** and implementation requirements
1517-
15181508
# COMPREHENSIVE ANALYSIS PROTOCOL
15191509
15201510
## 1. COMPLETE PAPER STRUCTURAL ANALYSIS
@@ -1678,17 +1668,6 @@
16781668
1. **Comprehensive Paper Analysis**: Complete paper structure, components, and requirements
16791669
2. **Complete Algorithm Extraction**: All algorithms, formulas, pseudocode, and technical details
16801670
1681-
Plus you can access the complete paper document by reading the markdown file directly.
1682-
1683-
# TRADITIONAL DOCUMENT ACCESS
1684-
1685-
## Direct Paper Reading
1686-
For any additional details needed beyond the provided analyses:
1687-
1688-
1. **Read the complete markdown (.md) file** in the paper directory
1689-
2. **Access any section directly** without token limitations for smaller documents
1690-
3. **Cross-reference information** across the entire document as needed
1691-
16921671
# OBJECTIVE
16931672
Create an implementation plan so detailed that a developer can reproduce the ENTIRE paper without reading it.
16941673

tools/code_indexer.py

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,37 +25,7 @@
2525

2626
# MCP Agent imports for LLM
2727
import yaml
28-
from utils.llm_utils import get_preferred_llm_class
29-
30-
31-
def get_default_models(config_path: str = "mcp_agent.config.yaml"):
32-
"""
33-
Get default models from configuration file.
34-
35-
Args:
36-
config_path: Path to the configuration file
37-
38-
Returns:
39-
dict: Dictionary with 'anthropic' and 'openai' default models
40-
"""
41-
try:
42-
if os.path.exists(config_path):
43-
with open(config_path, "r", encoding="utf-8") as f:
44-
config = yaml.safe_load(f)
45-
46-
anthropic_model = config.get("anthropic", {}).get(
47-
"default_model", "claude-sonnet-4-20250514"
48-
)
49-
openai_model = config.get("openai", {}).get("default_model", "o3-mini")
50-
51-
return {"anthropic": anthropic_model, "openai": openai_model}
52-
else:
53-
print(f"Config file {config_path} not found, using default models")
54-
return {"anthropic": "claude-sonnet-4-20250514", "openai": "o3-mini"}
55-
56-
except Exception as e:
57-
print(f"Error reading config file {config_path}: {e}")
58-
return {"anthropic": "claude-sonnet-4-20250514", "openai": "o3-mini"}
28+
from utils.llm_utils import get_preferred_llm_class, get_default_models
5929

6030

6131
@dataclass

tools/pdf_downloader.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,8 +1098,21 @@ async def download_file_to(
10981098
Status message about the download operation
10991099
"""
11001100
# 确定文件名
1101+
1102+
url = URLExtractor.extract_urls(url)[0]
1103+
1104+
if not filename:
1105+
filename = URLExtractor.infer_filename_from_url(url)
1106+
11011107
if not filename:
11021108
filename = URLExtractor.infer_filename_from_url(url)
1109+
else:
1110+
name_source, extension_source = os.path.splitext(os.path.basename(URLExtractor.infer_filename_from_url(url)))
1111+
name_destination, extension_destination = os.path.splitext(os.path.basename(filename))
1112+
if extension_source:
1113+
filename = name_destination + extension_source
1114+
else:
1115+
filename = name_destination + extension_destination
11031116

11041117
# 确定完整路径
11051118
if destination:
@@ -1203,6 +1216,14 @@ async def move_file_to(
12031216
# 确定文件名
12041217
if not filename:
12051218
filename = os.path.basename(source)
1219+
else:
1220+
name_source, extension_source = os.path.splitext(os.path.basename(source))
1221+
name_destination, extension_destination = os.path.splitext(os.path.basename(filename))
1222+
if extension_source:
1223+
filename = name_destination + extension_source
1224+
else:
1225+
filename = name_destination + extension_destination
1226+
12061227

12071228
# 确定完整路径
12081229
if destination:
@@ -1215,6 +1236,7 @@ async def move_file_to(
12151236
target_path = destination
12161237
else: # 是目录
12171238
target_path = os.path.join(destination, filename)
1239+
12181240
else:
12191241
target_path = filename
12201242

utils/file_processor.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,10 +282,25 @@ async def process_file_input(
282282
if isinstance(file_input, str):
283283
import re
284284

285+
# Try to extract path from backticks first
285286
file_path_match = re.search(r"`([^`]+\.md)`", file_input)
286287
if file_path_match:
287288
paper_path = file_path_match.group(1)
288289
file_input = {"paper_path": paper_path}
290+
else:
291+
# Try to extract from "Saved Path:" or similar patterns
292+
path_patterns = [
293+
r"[Ss]aved [Pp]ath[:\s]+([^\s\n]+\.md)",
294+
r"[Pp]aper [Pp]ath[:\s]+([^\s\n]+\.md)",
295+
r"[Ff]ile[:\s]+([^\s\n]+\.md)",
296+
r"[Oo]utput[:\s]+([^\s\n]+\.md)",
297+
]
298+
for pattern in path_patterns:
299+
match = re.search(pattern, file_input)
300+
if match:
301+
paper_path = match.group(1)
302+
file_input = {"paper_path": paper_path}
303+
break
289304

290305
# Extract paper directory path
291306
paper_dir = cls.extract_file_path(file_input)

utils/llm_utils.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,40 @@ def get_preferred_llm_class(config_path: str = "mcp_agent.secrets.yaml") -> Type
5353
return OpenAIAugmentedLLM
5454

5555

56+
def get_token_limits(config_path: str = "mcp_agent.config.yaml") -> Tuple[int, int]:
57+
"""
58+
Get token limits from configuration.
59+
60+
Args:
61+
config_path: Path to the main configuration file
62+
63+
Returns:
64+
tuple: (base_max_tokens, retry_max_tokens)
65+
"""
66+
# Default values that work with qwen/qwen-max (32768 total context)
67+
default_base = 20000
68+
default_retry = 15000
69+
70+
try:
71+
if os.path.exists(config_path):
72+
with open(config_path, "r", encoding="utf-8") as f:
73+
config = yaml.safe_load(f)
74+
75+
openai_config = config.get("openai", {})
76+
base_tokens = openai_config.get("base_max_tokens", default_base)
77+
retry_tokens = openai_config.get("retry_max_tokens", default_retry)
78+
79+
print(f"⚙️ Token limits from config: base={base_tokens}, retry={retry_tokens}")
80+
return base_tokens, retry_tokens
81+
else:
82+
print(f"⚠️ Config file {config_path} not found, using defaults: base={default_base}, retry={default_retry}")
83+
return default_base, default_retry
84+
except Exception as e:
85+
print(f"⚠️ Error reading token config from {config_path}: {e}")
86+
print(f"🔧 Falling back to default token limits: base={default_base}, retry={default_retry}")
87+
return default_base, default_retry
88+
89+
5690
def get_default_models(config_path: str = "mcp_agent.config.yaml"):
5791
"""
5892
Get default models from configuration file.

0 commit comments

Comments
 (0)