forked from HKUDS/DeepCode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain_cli.py
More file actions
337 lines (285 loc) · 13.1 KB
/
main_cli.py
File metadata and controls
337 lines (285 loc) · 13.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
#!/usr/bin/env python3
"""
DeepCode CLI - Open-Source Code Agent
深度代码CLI - 开源代码智能体
🧬 Data Intelligence Lab @ HKU
⚡ Revolutionizing Research Reproducibility through Multi-Agent Architecture
"""
import os
import sys
import asyncio
import argparse
# 禁止生成.pyc文件
os.environ["PYTHONDONTWRITEBYTECODE"] = "1"
# 添加项目根目录到路径
current_dir = os.path.dirname(os.path.abspath(__file__))
parent_dir = os.path.dirname(current_dir)
if parent_dir not in sys.path:
sys.path.insert(0, parent_dir)
# 导入CLI应用
from cli.cli_app import CLIApp, Colors
def print_enhanced_banner():
"""显示增强版启动横幅"""
banner = f"""
{Colors.CYAN}╔══════════════════════════════════════════════════════════════════════════════╗
║ ║
║ {Colors.BOLD}{Colors.MAGENTA}🧬 DeepCode - Open-Source Code Agent{Colors.CYAN} ║
║ ║
║ {Colors.BOLD}{Colors.YELLOW}⚡ DATA INTELLIGENCE LAB @ HKU ⚡{Colors.CYAN} ║
║ ║
║ Revolutionizing research reproducibility through collaborative AI ║
║ Building the future where code is reproduced from natural language ║
║ ║
║ {Colors.BOLD}{Colors.GREEN}🤖 Key Features:{Colors.CYAN} ║
║ • Automated paper-to-code reproduction ║
║ • Multi-agent collaborative architecture ║
║ • Open-source and extensible design ║
║ • Join our growing research community ║
║ ║
╚══════════════════════════════════════════════════════════════════════════════╝{Colors.ENDC}
"""
print(banner)
def check_environment():
"""检查运行环境"""
print(f"{Colors.CYAN}🔍 Checking environment...{Colors.ENDC}")
# 检查Python版本
if sys.version_info < (3, 8):
print(
f"{Colors.FAIL}❌ Python 3.8+ required. Current: {sys.version}{Colors.ENDC}"
)
return False
print(f"{Colors.OKGREEN}✅ Python {sys.version.split()[0]} - OK{Colors.ENDC}")
# 检查必要模块
required_modules = [
("asyncio", "Async IO support"),
("pathlib", "Path handling"),
("typing", "Type hints"),
]
missing_modules = []
for module, desc in required_modules:
try:
__import__(module)
print(f"{Colors.OKGREEN}✅ {desc} - OK{Colors.ENDC}")
except ImportError:
missing_modules.append(module)
print(f"{Colors.FAIL}❌ {desc} - Missing{Colors.ENDC}")
if missing_modules:
print(
f"{Colors.FAIL}❌ Missing required modules: {', '.join(missing_modules)}{Colors.ENDC}"
)
return False
print(f"{Colors.OKGREEN}✅ Environment check passed{Colors.ENDC}")
return True
def parse_arguments():
"""解析命令行参数"""
parser = argparse.ArgumentParser(
description="DeepCode CLI - Open-Source Code Agent by Data Intelligence Lab @ HKU",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=f"""
{Colors.BOLD}Examples:{Colors.ENDC}
{Colors.CYAN}python main_cli.py{Colors.ENDC} # Interactive mode
{Colors.CYAN}python main_cli.py --file paper.pdf{Colors.ENDC} # Process file directly
{Colors.CYAN}python main_cli.py --url https://...{Colors.ENDC} # Process URL directly
{Colors.CYAN}python main_cli.py --chat "Build a web app..."{Colors.ENDC} # Process chat requirements
{Colors.CYAN}python main_cli.py --requirement "ML system for..."{Colors.ENDC} # Guided requirement analysis (NEW)
{Colors.CYAN}python main_cli.py --optimized{Colors.ENDC} # Use optimized mode
{Colors.CYAN}python main_cli.py --disable-segmentation{Colors.ENDC} # Disable document segmentation
{Colors.CYAN}python main_cli.py --segmentation-threshold 30000{Colors.ENDC} # Custom segmentation threshold
{Colors.BOLD}Pipeline Modes:{Colors.ENDC}
{Colors.GREEN}Comprehensive{Colors.ENDC}: Full intelligence analysis with indexing
{Colors.YELLOW}Optimized{Colors.ENDC}: Fast processing without indexing
{Colors.BLUE}Requirement Analysis{Colors.ENDC}: Guided Q&A to refine requirements (NEW)
{Colors.BOLD}Document Processing:{Colors.ENDC}
{Colors.BLUE}Smart Segmentation{Colors.ENDC}: Intelligent document segmentation for large papers
{Colors.MAGENTA}Supported Formats{Colors.ENDC}: PDF, DOCX, DOC, PPT, PPTX, XLS, XLSX, HTML, TXT, MD
""",
)
parser.add_argument(
"--file", "-f", type=str, help="Process a specific file (PDF, DOCX, TXT, etc.)"
)
parser.add_argument(
"--url", "-u", type=str, help="Process a research paper from URL"
)
parser.add_argument(
"--chat",
"-t",
type=str,
help="Process coding requirements via chat input (provide requirements as argument)",
)
parser.add_argument(
"--requirement",
"-r",
type=str,
help="Process requirements via guided analysis (provide initial idea as argument)",
)
parser.add_argument(
"--optimized",
"-o",
action="store_true",
help="Use optimized mode (skip indexing for faster processing)",
)
parser.add_argument(
"--disable-segmentation",
action="store_true",
help="Disable intelligent document segmentation (use traditional full-document processing)",
)
parser.add_argument(
"--segmentation-threshold",
type=int,
default=50000,
help="Document size threshold (characters) to trigger segmentation (default: 50000)",
)
parser.add_argument(
"--verbose", "-v", action="store_true", help="Enable verbose output"
)
return parser.parse_args()
async def run_direct_processing(app: CLIApp, input_source: str, input_type: str):
"""直接处理模式(非交互式)"""
try:
print(
f"\n{Colors.BOLD}{Colors.CYAN}🚀 Starting direct processing mode...{Colors.ENDC}"
)
print(f"{Colors.CYAN}Input: {input_source}{Colors.ENDC}")
print(f"{Colors.CYAN}Type: {input_type}{Colors.ENDC}")
print(
f"{Colors.CYAN}Mode: {'🧠 Comprehensive' if app.cli.enable_indexing else '⚡ Optimized'}{Colors.ENDC}"
)
# 初始化应用
init_result = await app.initialize_mcp_app()
if init_result["status"] != "success":
print(
f"{Colors.FAIL}❌ Initialization failed: {init_result['message']}{Colors.ENDC}"
)
return False
# 处理输入
result = await app.process_input(input_source, input_type)
if result["status"] == "success":
print(
f"\n{Colors.BOLD}{Colors.OKGREEN}🎉 Processing completed successfully!{Colors.ENDC}"
)
return True
else:
print(
f"\n{Colors.BOLD}{Colors.FAIL}❌ Processing failed: {result.get('error', 'Unknown error')}{Colors.ENDC}"
)
return False
except Exception as e:
print(f"\n{Colors.FAIL}❌ Direct processing error: {str(e)}{Colors.ENDC}")
return False
finally:
await app.cleanup_mcp_app()
async def run_requirement_analysis(app: CLIApp, initial_idea: str):
"""需求分析模式(非交互式) - NEW: matching UI version"""
try:
print(
f"\n{Colors.BOLD}{Colors.BLUE}🧠 Starting requirement analysis mode...{Colors.ENDC}"
)
print(f"{Colors.CYAN}Initial Idea: {initial_idea}{Colors.ENDC}")
# 初始化应用
init_result = await app.initialize_mcp_app()
if init_result["status"] != "success":
print(
f"{Colors.FAIL}❌ Initialization failed: {init_result['message']}{Colors.ENDC}"
)
return False
# 执行需求分析工作流
result = await app.process_requirement_analysis_non_interactive(initial_idea)
if result["status"] == "success":
print(
f"\n{Colors.BOLD}{Colors.OKGREEN}🎉 Requirement analysis completed successfully!{Colors.ENDC}"
)
return True
else:
print(
f"\n{Colors.BOLD}{Colors.FAIL}❌ Requirement analysis failed: {result.get('error', 'Unknown error')}{Colors.ENDC}"
)
return False
except Exception as e:
print(f"\n{Colors.FAIL}❌ Requirement analysis error: {str(e)}{Colors.ENDC}")
return False
finally:
await app.cleanup_mcp_app()
async def main():
"""主函数"""
# 解析命令行参数
args = parse_arguments()
# 显示横幅
print_enhanced_banner()
# 检查环境
if not check_environment():
print(
f"\n{Colors.FAIL}🚨 Environment check failed. Please fix the issues and try again.{Colors.ENDC}"
)
sys.exit(1)
try:
# 创建CLI应用
app = CLIApp()
# 设置配置 - 默认禁用索引功能以加快处理速度
if args.optimized:
app.cli.enable_indexing = False
print(
f"\n{Colors.YELLOW}⚡ Optimized mode enabled - indexing disabled{Colors.ENDC}"
)
else:
# 默认也禁用索引功能
app.cli.enable_indexing = False
print(
f"\n{Colors.YELLOW}⚡ Fast mode enabled - indexing disabled by default{Colors.ENDC}"
)
# Configure document segmentation settings
if hasattr(args, "disable_segmentation") and args.disable_segmentation:
print(
f"\n{Colors.MAGENTA}📄 Document segmentation disabled - using traditional processing{Colors.ENDC}"
)
app.cli.segmentation_enabled = False
app.cli.segmentation_threshold = args.segmentation_threshold
app.cli._save_segmentation_config()
else:
print(
f"\n{Colors.BLUE}📄 Smart document segmentation enabled (threshold: {args.segmentation_threshold} chars){Colors.ENDC}"
)
app.cli.segmentation_enabled = True
app.cli.segmentation_threshold = args.segmentation_threshold
app.cli._save_segmentation_config()
# 检查是否为直接处理模式
if args.file or args.url or args.chat or args.requirement:
if args.file:
# 验证文件存在
if not os.path.exists(args.file):
print(f"{Colors.FAIL}❌ File not found: {args.file}{Colors.ENDC}")
sys.exit(1)
# 使用 file:// 前缀保持与交互模式一致,确保文件被复制而非移动
file_url = f"file://{os.path.abspath(args.file)}"
success = await run_direct_processing(app, file_url, "file")
elif args.url:
success = await run_direct_processing(app, args.url, "url")
elif args.chat:
# 验证chat输入长度
if len(args.chat.strip()) < 20:
print(
f"{Colors.FAIL}❌ Chat input too short. Please provide more detailed requirements (at least 20 characters){Colors.ENDC}"
)
sys.exit(1)
success = await run_direct_processing(app, args.chat, "chat")
elif args.requirement:
# NEW: Requirement analysis mode
# 验证需求输入长度
if len(args.requirement.strip()) < 10:
print(
f"{Colors.FAIL}❌ Requirement input too short. Please provide more details (at least 10 characters){Colors.ENDC}"
)
sys.exit(1)
success = await run_requirement_analysis(app, args.requirement)
sys.exit(0 if success else 1)
else:
# 交互式模式
print(f"\n{Colors.CYAN}🎮 Starting interactive mode...{Colors.ENDC}")
await app.run_interactive_session()
except KeyboardInterrupt:
print(f"\n{Colors.WARNING}⚠️ Application interrupted by user{Colors.ENDC}")
sys.exit(1)
except Exception as e:
print(f"\n{Colors.FAIL}❌ Application errors: {str(e)}{Colors.ENDC}")
sys.exit(1)
if __name__ == "__main__":
asyncio.run(main())