paradiseDev commited on
Commit
95747b0
·
verified ·
1 Parent(s): c16d40e

Delete modal_implementation.py

Browse files
Files changed (1) hide show
  1. modal_implementation.py +0 -848
modal_implementation.py DELETED
@@ -1,848 +0,0 @@
1
- """
2
- Modal Implementation for AutoGPT-like Agent with MCO Integration
3
-
4
- This file implements a real AutoGPT-like agent using Modal that integrates with the MCO MCP server
5
- for orchestration. The agent can perform code review tasks and generate MCO workflow files.
6
- """
7
-
8
- import os
9
- import json
10
- import subprocess
11
- import tempfile
12
- import time
13
- from pathlib import Path
14
- import anthropic
15
- import modal
16
- import requests
17
- from bs4 import BeautifulSoup
18
-
19
- # Define the Modal app
20
- app = modal.App("mco-autogpt-agent")
21
-
22
- # Base image with required dependencies
23
- image = modal.Image.debian_slim().pip_install(
24
- "anthropic",
25
- "requests",
26
- "python-dotenv",
27
- "beautifulsoup4",
28
- "numpy",
29
- "pandas",
30
- "matplotlib"
31
- )
32
-
33
- # Create a volume for persistent storage
34
- volume = modal.Volume.from_name("mco-agent-volume", create_if_missing=True)
35
-
36
- # Environment setup
37
- env = {
38
- "ANTHROPIC_API_KEY": os.environ.get("ANTHROPIC_API_KEY", ""),
39
- "MCO_CONFIG_DIR": "/data/mco-config"
40
- }
41
-
42
- class MCPClient:
43
- """Client for interacting with MCO MCP server via subprocess"""
44
-
45
- def __init__(self, config_dir, orchestration_id=None):
46
- self.config_dir = config_dir
47
- self.orchestration_id = orchestration_id
48
- self.mco_server_process = None
49
-
50
- def _ensure_server_running(self):
51
- """Ensure the MCO MCP server is running"""
52
- if self.mco_server_process is None:
53
- # Start the MCO MCP server
54
- env = os.environ.copy()
55
- env["MCO_CONFIG_DIR"] = self.config_dir
56
-
57
- # Use MCP Inspector to start the server
58
- self.mco_server_process = subprocess.Popen(
59
- ["npx", "@modelcontextprotocol/inspector", "node", "mco-mcp-server.js"],
60
- env=env,
61
- stdin=subprocess.PIPE,
62
- stdout=subprocess.PIPE,
63
- stderr=subprocess.PIPE,
64
- text=True
65
- )
66
-
67
- # Wait for server to initialize
68
- time.sleep(2)
69
-
70
- def _call_tool(self, tool_name, params):
71
- """Call an MCO tool via MCP Inspector"""
72
- self._ensure_server_running()
73
-
74
- # Create temporary file for tool call
75
- with tempfile.NamedTemporaryFile(mode='w+', suffix='.json', delete=False) as f:
76
- json.dump({
77
- "name": tool_name,
78
- "arguments": params
79
- }, f)
80
- tool_file = f.name
81
-
82
- # Call the tool using MCP Inspector
83
- result = subprocess.run(
84
- ["npx", "@modelcontextprotocol/inspector", "call-tool", "--tool-file", tool_file],
85
- capture_output=True,
86
- text=True
87
- )
88
-
89
- # Clean up temporary file
90
- os.unlink(tool_file)
91
-
92
- # Parse and return result
93
- try:
94
- return json.loads(result.stdout)
95
- except json.JSONDecodeError:
96
- return {"error": "Failed to parse tool result", "stdout": result.stdout, "stderr": result.stderr}
97
-
98
- def start_orchestration(self, config=None):
99
- """Start a new orchestration workflow"""
100
- config = config or {}
101
- result = self._call_tool("start_orchestration", {"config": config})
102
-
103
- if "orchestration_id" in result:
104
- self.orchestration_id = result["orchestration_id"]
105
-
106
- return result
107
-
108
- def get_next_directive(self):
109
- """Get the next directive from the orchestration"""
110
- if not self.orchestration_id:
111
- raise ValueError("No active orchestration")
112
-
113
- return self._call_tool("get_next_directive", {"orchestration_id": self.orchestration_id})
114
-
115
- def complete_step(self, step_id, result):
116
- """Complete a step in the orchestration"""
117
- if not self.orchestration_id:
118
- raise ValueError("No active orchestration")
119
-
120
- return self._call_tool("complete_step", {
121
- "orchestration_id": self.orchestration_id,
122
- "step_id": step_id,
123
- "result": result
124
- })
125
-
126
- def get_workflow_status(self):
127
- """Get the current status of the workflow"""
128
- if not self.orchestration_id:
129
- raise ValueError("No active orchestration")
130
-
131
- return self._call_tool("get_workflow_status", {"orchestration_id": self.orchestration_id})
132
-
133
- def get_persistent_context(self):
134
- """Get the persistent context for the workflow"""
135
- if not self.orchestration_id:
136
- raise ValueError("No active orchestration")
137
-
138
- return self._call_tool("get_persistent_context", {"orchestration_id": self.orchestration_id})
139
-
140
- def cleanup(self):
141
- """Clean up resources"""
142
- if self.mco_server_process:
143
- self.mco_server_process.terminate()
144
- self.mco_server_process = None
145
-
146
- class AutoGPTAgent:
147
- """AutoGPT-like agent that can be orchestrated by MCO"""
148
-
149
- def __init__(self, task, config_dir, orchestration_id=None):
150
- self.task = task
151
- self.config_dir = config_dir
152
- self.mcp_client = MCPClient(config_dir, orchestration_id)
153
- self.memory = []
154
- self.thinking_log = []
155
- self.orchestration_log = []
156
- self.client = anthropic.Anthropic()
157
-
158
- def run(self):
159
- """Run the agent with MCO orchestration"""
160
- # Log the start of orchestration
161
- self.orchestration_log.append({
162
- "timestamp": time.time(),
163
- "event": "orchestration_start",
164
- "task": self.task
165
- })
166
-
167
- # If no orchestration ID, start new orchestration
168
- if not self.mcp_client.orchestration_id:
169
- config = {"task": self.task}
170
- start_result = self.mcp_client.start_orchestration(config)
171
-
172
- self.orchestration_log.append({
173
- "timestamp": time.time(),
174
- "event": "orchestration_created",
175
- "orchestration_id": self.mcp_client.orchestration_id
176
- })
177
-
178
- results = []
179
-
180
- # Main agent loop
181
- while True:
182
- # Get next directive from MCO
183
- directive = self.mcp_client.get_next_directive()
184
-
185
- self.orchestration_log.append({
186
- "timestamp": time.time(),
187
- "event": "directive_received",
188
- "directive_type": directive.get("type"),
189
- "step_id": directive.get("step_id")
190
- })
191
-
192
- if directive.get("type") == "complete":
193
- # Workflow is complete
194
- self.orchestration_log.append({
195
- "timestamp": time.time(),
196
- "event": "orchestration_complete"
197
- })
198
- break
199
-
200
- # Check for injected context
201
- if directive.get("injected_context"):
202
- self.orchestration_log.append({
203
- "timestamp": time.time(),
204
- "event": "context_injected",
205
- "context_type": list(directive.get("injected_context", {}).keys())
206
- })
207
-
208
- # Process directive
209
- result = self._process_directive(directive)
210
- results.append(result)
211
-
212
- # Complete step
213
- complete_result = self.mcp_client.complete_step(directive["step_id"], result)
214
-
215
- self.orchestration_log.append({
216
- "timestamp": time.time(),
217
- "event": "step_completed",
218
- "step_id": directive["step_id"],
219
- "status": complete_result.get("status")
220
- })
221
-
222
- # Clean up
223
- self.mcp_client.cleanup()
224
-
225
- return {
226
- "results": results,
227
- "thinking_log": self.thinking_log,
228
- "orchestration_log": self.orchestration_log
229
- }
230
-
231
- def _process_directive(self, directive):
232
- """Process a directive from MCO"""
233
- # Extract information from directive
234
- instruction = directive["instruction"]
235
- context = directive["persistent_context"]
236
- injected = directive.get("injected_context", {})
237
-
238
- # Add to memory
239
- self.memory.append({
240
- "role": "system",
241
- "content": f"Directive: {instruction}\nContext: {json.dumps(context)}"
242
- })
243
-
244
- if injected:
245
- self.memory.append({
246
- "role": "system",
247
- "content": f"Additional context: {json.dumps(injected)}"
248
- })
249
-
250
- # Generate thinking process
251
- thinking = self._generate_thinking(instruction, context, injected)
252
-
253
- # Log thinking
254
- self.thinking_log.append({
255
- "timestamp": time.time(),
256
- "directive": instruction,
257
- "thinking": thinking
258
- })
259
-
260
- # Execute tools based on thinking
261
- tool_results = self._execute_tools(thinking)
262
-
263
- # Generate summary
264
- summary = self._generate_summary(instruction, thinking, tool_results)
265
-
266
- return {
267
- "thinking": thinking,
268
- "tool_results": tool_results,
269
- "summary": summary
270
- }
271
-
272
- def _generate_thinking(self, instruction, context, injected):
273
- """Generate thinking process using Claude"""
274
- # Prepare prompt for Claude
275
- prompt = f"""
276
- <task>{instruction}</task>
277
-
278
- <context>
279
- {json.dumps(context, indent=2)}
280
- </context>
281
-
282
- {"<injected>" + json.dumps(injected, indent=2) + "</injected>" if injected else ""}
283
-
284
- <memory>
285
- {self._format_memory()}
286
- </memory>
287
-
288
- <available_tools>
289
- - execute_code(code: str, language: str) -> Executes code and returns the result
290
- - search_web(query: str) -> Searches the web and returns results
291
- - read_file(path: str) -> Reads a file and returns its content
292
- - write_file(path: str, content: str) -> Writes content to a file
293
- - analyze_code(code: str, language: str) -> Analyzes code for issues
294
- </available_tools>
295
-
296
- <thinking>
297
- """
298
-
299
- # Call Claude API
300
- message = self.client.messages.create(
301
- model="claude-3-5-sonnet-20240229",
302
- max_tokens=2000,
303
- messages=[{"role": "user", "content": prompt}],
304
- stop_sequences=["</thinking>"]
305
- )
306
-
307
- return message.content[0].text
308
-
309
- def _execute_tools(self, thinking):
310
- """Extract and execute tools from thinking"""
311
- # Extract tool calls
312
- tool_calls = self._extract_tool_calls(thinking)
313
-
314
- results = []
315
- for tool_call in tool_calls:
316
- tool_name = tool_call["name"]
317
- tool_args = tool_call["args"]
318
-
319
- # Execute the appropriate tool
320
- if tool_name == "execute_code":
321
- result = self._execute_code(tool_args.get("code", ""), tool_args.get("language", "python"))
322
- elif tool_name == "search_web":
323
- result = self._search_web(tool_args.get("query", ""))
324
- elif tool_name == "read_file":
325
- result = self._read_file(tool_args.get("path", ""))
326
- elif tool_name == "write_file":
327
- result = self._write_file(tool_args.get("path", ""), tool_args.get("content", ""))
328
- elif tool_name == "analyze_code":
329
- result = self._analyze_code(tool_args.get("code", ""), tool_args.get("language", ""))
330
- else:
331
- result = {"error": f"Unknown tool: {tool_name}"}
332
-
333
- results.append({
334
- "tool": tool_name,
335
- "args": tool_args,
336
- "result": result
337
- })
338
-
339
- # Add to memory
340
- self.memory.append({
341
- "role": "function",
342
- "name": tool_name,
343
- "content": json.dumps(result)
344
- })
345
-
346
- return results
347
-
348
- def _generate_summary(self, instruction, thinking, tool_results):
349
- """Generate a summary of the results"""
350
- # Prepare prompt for Claude
351
- prompt = f"""
352
- <instruction>{instruction}</instruction>
353
-
354
- <thinking>
355
- {thinking}
356
- </thinking>
357
-
358
- <tool_results>
359
- {json.dumps(tool_results, indent=2)}
360
- </tool_results>
361
-
362
- Please provide a concise summary of the results and how they address the instruction.
363
- """
364
-
365
- # Call Claude API
366
- message = self.client.messages.create(
367
- model="claude-3-5-sonnet-20240229",
368
- max_tokens=1000,
369
- messages=[{"role": "user", "content": prompt}]
370
- )
371
-
372
- return message.content[0].text
373
-
374
- def _extract_tool_calls(self, thinking):
375
- """Extract tool calls from thinking text"""
376
- tool_calls = []
377
-
378
- # Simple regex-like extraction (in a real implementation, use proper parsing)
379
- lines = thinking.split("\n")
380
- for i, line in enumerate(lines):
381
- if "execute_code(" in line or "search_web(" in line or "read_file(" in line or "write_file(" in line or "analyze_code(" in line:
382
- # Extract tool name
383
- tool_name = line.split("(")[0].strip()
384
-
385
- # Find the closing parenthesis
386
- code_block = ""
387
- j = i
388
- while j < len(lines) and ")" not in lines[j]:
389
- code_block += lines[j] + "\n"
390
- j += 1
391
-
392
- if j < len(lines):
393
- code_block += lines[j].split(")")[0]
394
-
395
- # Parse arguments
396
- args = {}
397
- if tool_name == "execute_code":
398
- args = {"code": code_block, "language": "python"}
399
- elif tool_name == "search_web":
400
- args = {"query": code_block.strip()}
401
- elif tool_name == "read_file":
402
- args = {"path": code_block.strip()}
403
- elif tool_name == "write_file":
404
- parts = code_block.split(",", 1)
405
- if len(parts) == 2:
406
- args = {"path": parts[0].strip(), "content": parts[1].strip()}
407
- elif tool_name == "analyze_code":
408
- args = {"code": code_block, "language": "python"}
409
-
410
- tool_calls.append({
411
- "name": tool_name,
412
- "args": args
413
- })
414
-
415
- return tool_calls
416
-
417
- def _format_memory(self):
418
- """Format memory for inclusion in prompt"""
419
- formatted = ""
420
- for item in self.memory[-5:]: # Only include the last 5 memory items
421
- if item["role"] == "system":
422
- formatted += f"System: {item['content']}\n\n"
423
- elif item["role"] == "function":
424
- formatted += f"Function {item['name']}: {item['content']}\n\n"
425
- return formatted
426
-
427
- # Tool implementations
428
- def _execute_code(self, code, language):
429
- """Execute code in a sandbox environment"""
430
- if language.lower() != "python":
431
- return {"error": f"Unsupported language: {language}"}
432
-
433
- try:
434
- # Create a temporary file
435
- with tempfile.NamedTemporaryFile(mode='w+', suffix='.py', delete=False) as f:
436
- f.write(code)
437
- temp_file = f.name
438
-
439
- # Execute the code
440
- result = subprocess.run(
441
- ["python", temp_file],
442
- capture_output=True,
443
- text=True,
444
- timeout=10
445
- )
446
-
447
- # Clean up
448
- os.unlink(temp_file)
449
-
450
- return {
451
- "stdout": result.stdout,
452
- "stderr": result.stderr,
453
- "returncode": result.returncode
454
- }
455
- except Exception as e:
456
- return {"error": str(e)}
457
-
458
- def _search_web(self, query):
459
- """Search the web for information"""
460
- try:
461
- # Use a search API (simplified for demo)
462
- response = requests.get(
463
- "https://api.duckduckgo.com/",
464
- params={"q": query, "format": "json"}
465
- )
466
-
467
- return response.json()
468
- except Exception as e:
469
- return {"error": str(e)}
470
-
471
- def _read_file(self, path):
472
- """Read a file from the agent's workspace"""
473
- try:
474
- full_path = Path(self.config_dir) / path
475
- with open(full_path, 'r') as f:
476
- content = f.read()
477
- return {"content": content}
478
- except Exception as e:
479
- return {"error": str(e)}
480
-
481
- def _write_file(self, path, content):
482
- """Write content to a file in the agent's workspace"""
483
- try:
484
- full_path = Path(self.config_dir) / path
485
- # Ensure directory exists
486
- full_path.parent.mkdir(parents=True, exist_ok=True)
487
-
488
- with open(full_path, 'w') as f:
489
- f.write(content)
490
- return {"success": True, "path": str(full_path)}
491
- except Exception as e:
492
- return {"error": str(e)}
493
-
494
- def _analyze_code(self, code, language):
495
- """Analyze code for issues"""
496
- # In a real implementation, use a code analysis tool
497
- # For demo, use Claude to analyze
498
- prompt = f"""
499
- <code language="{language}">
500
- {code}
501
- </code>
502
-
503
- Please analyze this code for:
504
- 1. Bugs and errors
505
- 2. Security issues
506
- 3. Performance concerns
507
- 4. Style and best practices
508
-
509
- Provide specific line numbers and detailed explanations.
510
- """
511
-
512
- message = self.client.messages.create(
513
- model="claude-3-5-sonnet-20240229",
514
- max_tokens=1500,
515
- messages=[{"role": "user", "content": prompt}]
516
- )
517
-
518
- return {"analysis": message.content[0].text}
519
-
520
- class CodeReviewAgent(AutoGPTAgent):
521
- """Specialized agent for code review tasks"""
522
-
523
- def __init__(self, task, config_dir, orchestration_id=None):
524
- super().__init__(task, config_dir, orchestration_id)
525
-
526
- def review_code(self, code_files):
527
- """Review multiple code files"""
528
- results = {}
529
-
530
- for file_path, code in code_files.items():
531
- # Determine language
532
- language = self._detect_language(file_path)
533
-
534
- # Analyze code
535
- analysis = self._analyze_code(code, language)
536
-
537
- # Generate suggestions
538
- suggestions = self._suggest_improvements(code, analysis, language)
539
-
540
- # Create test cases
541
- test_cases = self._generate_test_cases(code, language)
542
-
543
- # Compile results
544
- results[file_path] = {
545
- "language": language,
546
- "analysis": analysis,
547
- "suggestions": suggestions,
548
- "test_cases": test_cases
549
- }
550
-
551
- return results
552
-
553
- def _detect_language(self, file_path):
554
- """Detect programming language from file extension"""
555
- ext = Path(file_path).suffix.lower()
556
-
557
- language_map = {
558
- ".py": "python",
559
- ".js": "javascript",
560
- ".ts": "typescript",
561
- ".java": "java",
562
- ".c": "c",
563
- ".cpp": "c++",
564
- ".cs": "c#",
565
- ".go": "go",
566
- ".rb": "ruby",
567
- ".php": "php",
568
- ".swift": "swift",
569
- ".kt": "kotlin",
570
- ".rs": "rust",
571
- ".html": "html",
572
- ".css": "css",
573
- ".sql": "sql"
574
- }
575
-
576
- return language_map.get(ext, "unknown")
577
-
578
- def _suggest_improvements(self, code, analysis, language):
579
- """Generate improvement suggestions"""
580
- prompt = f"""
581
- <code language="{language}">
582
- {code}
583
- </code>
584
-
585
- <analysis>
586
- {analysis.get('analysis', '')}
587
- </analysis>
588
-
589
- Please suggest specific improvements to address the issues identified in the analysis.
590
- Include code snippets showing the improved version.
591
- """
592
-
593
- message = self.client.messages.create(
594
- model="claude-3-5-sonnet-20240229",
595
- max_tokens=1500,
596
- messages=[{"role": "user", "content": prompt}]
597
- )
598
-
599
- return {"suggestions": message.content[0].text}
600
-
601
- def _generate_test_cases(self, code, language):
602
- """Generate test cases for the code"""
603
- prompt = f"""
604
- <code language="{language}">
605
- {code}
606
- </code>
607
-
608
- Please generate comprehensive test cases for this code.
609
- Include:
610
- 1. Unit tests for individual functions/methods
611
- 2. Edge case tests
612
- 3. Integration tests if applicable
613
-
614
- Provide the test code in the same language as the original code.
615
- """
616
-
617
- message = self.client.messages.create(
618
- model="claude-3-5-sonnet-20240229",
619
- max_tokens=1500,
620
- messages=[{"role": "user", "content": prompt}]
621
- )
622
-
623
- return {"test_cases": message.content[0].text}
624
-
625
- def generate_snlp_files(self, review_type, language_focus):
626
- """Generate MCO SNLP files for a code review workflow"""
627
- # Generate mco.core
628
- core_content = self._generate_core_file(review_type, language_focus)
629
-
630
- # Generate mco.sc
631
- sc_content = self._generate_sc_file(review_type, language_focus)
632
-
633
- # Generate mco.features
634
- features_content = self._generate_features_file(review_type, language_focus)
635
-
636
- # Generate mco.styles
637
- styles_content = self._generate_styles_file(review_type, language_focus)
638
-
639
- # Write files to config directory
640
- self._write_file("mco.core", core_content)
641
- self._write_file("mco.sc", sc_content)
642
- self._write_file("mco.features", features_content)
643
- self._write_file("mco.styles", styles_content)
644
-
645
- return {
646
- "mco.core": core_content,
647
- "mco.sc": sc_content,
648
- "mco.features": features_content,
649
- "mco.styles": styles_content
650
- }
651
-
652
- def _generate_core_file(self, review_type, language_focus):
653
- """Generate mco.core file content"""
654
- return f"""// MCO Core Configuration
655
-
656
- @workflow "Code Review Assistant"
657
- >This is an AI assistant that performs thorough code reviews for {language_focus} code with a focus on {review_type}.
658
- >The workflow follows a structured progression to ensure comprehensive and reliable code reviews.
659
-
660
- @description "Multi-step code review workflow with progressive revelation"
661
- >This workflow demonstrates MCO's progressive revelation capability - core requirements stay persistent while features and styles are strategically injected at optimal moments.
662
- >The agent should maintain focus on the current step while building upon previous work.
663
-
664
- @version "1.0.0"
665
-
666
- // Data Section - Persistent state throughout workflow
667
- @data
668
- language: "{language_focus}"
669
- review_type: "{review_type}"
670
- code_files: []
671
- issues_found: {{}}
672
- suggestions: {{}}
673
- test_results: {{}}
674
- >Focus on building reliable, autonomous code review workflows that complete successfully without human intervention.
675
- >The agent should maintain context across all steps and build upon previous work iteratively.
676
- >Use the data variables to track state and progress throughout the workflow.
677
-
678
- // Agents Section - Workflow execution structure
679
- @agents
680
- orchestrator:
681
- name: "MCO Orchestrator"
682
- description: "Manages workflow state and progressive revelation"
683
- model: "claude-3-5-sonnet"
684
- steps:
685
- - "Understand the code review requirements and scope"
686
- - "Analyze code structure and organization"
687
- - "Identify bugs, errors, and potential issues"
688
- - "Evaluate code quality and adherence to best practices"
689
- - "Generate improvement suggestions with examples"
690
- - "Create comprehensive review report with actionable recommendations"
691
- """
692
-
693
- def _generate_sc_file(self, review_type, language_focus):
694
- """Generate mco.sc file content"""
695
- return f"""// MCO Success Criteria
696
-
697
- @goal "Create a comprehensive code review system for {language_focus} code"
698
- >The goal is to build a reliable, autonomous code review system that can analyze {language_focus} code,
699
- >identify issues, suggest improvements, and generate test cases with a focus on {review_type}.
700
-
701
- @success_criteria
702
- - "Correctly identify syntax errors and bugs in {language_focus} code"
703
- - "Provide specific, actionable suggestions for code improvement"
704
- - "Generate relevant test cases that cover edge cases"
705
- - "Maintain consistent focus on {review_type} aspects"
706
- - "Produce a well-organized, comprehensive review report"
707
- - "Complete the entire workflow without human intervention"
708
- >The success criteria define what a successful code review should accomplish.
709
- >Each criterion should be measurable and verifiable.
710
-
711
- @target_audience "Software developers and code reviewers"
712
- >The primary users are software developers who want automated code reviews for their {language_focus} projects.
713
- >They need detailed, actionable feedback to improve their code quality and reliability.
714
-
715
- @developer_vision "Reliable, consistent code reviews that improve code quality"
716
- >The vision is to create a system that provides the same level of detail and insight as a human code reviewer,
717
- >but with greater consistency and without the limitations of human reviewers (fatigue, bias, etc.).
718
- """
719
-
720
- def _generate_features_file(self, review_type, language_focus):
721
- """Generate mco.features file content"""
722
- return f"""// MCO Features
723
-
724
- @feature "Static Analysis"
725
- >Perform static analysis of {language_focus} code to identify syntax errors, potential bugs, and code smells.
726
- >Use language-specific rules and best practices to evaluate code quality.
727
-
728
- @feature "Security Scanning"
729
- >Scan code for security vulnerabilities such as injection flaws, authentication issues, and data exposure risks.
730
- >Prioritize findings based on severity and potential impact.
731
-
732
- @feature "Performance Optimization"
733
- >Identify performance bottlenecks and inefficient algorithms or data structures.
734
- >Suggest optimizations that improve execution speed and resource usage.
735
-
736
- @feature "Code Style Enforcement"
737
- >Check adherence to coding standards and style guidelines for {language_focus}.
738
- >Ensure consistent formatting, naming conventions, and documentation.
739
-
740
- @feature "Test Coverage Analysis"
741
- >Evaluate the completeness of test coverage for the codebase.
742
- >Identify untested code paths and suggest additional test cases.
743
-
744
- @feature "Refactoring Suggestions"
745
- >Recommend code refactoring to improve maintainability, readability, and extensibility.
746
- >Provide specific examples of refactored code.
747
- """
748
-
749
- def _generate_styles_file(self, review_type, language_focus):
750
- """Generate mco.styles file content"""
751
- return f"""// MCO Styles
752
-
753
- @style "Comprehensive"
754
- >Provide detailed analysis covering all aspects of the code, including syntax, semantics, style, and architecture.
755
- >Leave no stone unturned in the review process.
756
-
757
- @style "Actionable"
758
- >Focus on providing specific, actionable feedback that can be immediately implemented.
759
- >Include code examples and clear instructions for addressing issues.
760
-
761
- @style "Educational"
762
- >Explain the reasoning behind each suggestion to help developers learn and improve.
763
- >Reference relevant documentation, best practices, and design patterns.
764
-
765
- @style "Prioritized"
766
- >Organize findings by severity and impact to help developers focus on the most important issues first.
767
- >Clearly distinguish between critical issues and minor suggestions.
768
-
769
- @style "Balanced"
770
- >Acknowledge both strengths and weaknesses in the code to provide a balanced perspective.
771
- >Highlight well-implemented patterns and clever solutions alongside areas for improvement.
772
-
773
- @style "Collaborative"
774
- >Frame feedback in a collaborative, constructive manner rather than being overly critical.
775
- >Use language that encourages improvement rather than assigning blame.
776
- """
777
-
778
- # Modal functions
779
- @app.function(
780
- image=image,
781
- volumes={"/data": volume},
782
- timeout=600,
783
- secrets=[modal.Secret.from_name("anthropic-api-key")]
784
- )
785
- def run_agent(task, config_dir="/data/mco-config", orchestration_id=None):
786
- """Run the AutoGPT-like agent with MCO orchestration"""
787
- agent = AutoGPTAgent(task, config_dir, orchestration_id)
788
- return agent.run()
789
-
790
- @app.function(
791
- image=image,
792
- volumes={"/data": volume},
793
- timeout=600,
794
- secrets=[modal.Secret.from_name("anthropic-api-key")]
795
- )
796
- def run_code_review(code_files, review_type, language_focus, config_dir="/data/mco-config", orchestration_id=None):
797
- """Run a code review using the specialized agent"""
798
- agent = CodeReviewAgent(f"Review {language_focus} code with focus on {review_type}", config_dir, orchestration_id)
799
-
800
- # Generate SNLP files
801
- snlp_files = agent.generate_snlp_files(review_type, language_focus)
802
-
803
- # Run the agent with MCO orchestration
804
- results = agent.run()
805
-
806
- # Add code review results
807
- if code_files:
808
- review_results = agent.review_code(code_files)
809
- results["code_review"] = review_results
810
-
811
- return results
812
-
813
- @app.function(
814
- image=image,
815
- volumes={"/data": volume},
816
- secrets=[modal.Secret.from_name("anthropic-api-key")]
817
- )
818
- def generate_snlp_files(review_type, language_focus, config_dir="/data/mco-config"):
819
- """Generate SNLP files for a code review workflow"""
820
- agent = CodeReviewAgent(f"Generate SNLP files for {language_focus} code review", config_dir)
821
- return agent.generate_snlp_files(review_type, language_focus)
822
-
823
- @app.function(
824
- image=image,
825
- volumes={"/data": volume},
826
- secrets=[modal.Secret.from_name("anthropic-api-key")]
827
- )
828
- def execute_code(code, language="python"):
829
- """Execute code in a sandbox environment"""
830
- agent = AutoGPTAgent("Execute code", "/data/mco-config")
831
- return agent._execute_code(code, language)
832
-
833
- @app.function(
834
- image=image,
835
- secrets=[modal.Secret.from_name("anthropic-api-key")]
836
- )
837
- def search_web(query):
838
- """Search the web for information"""
839
- agent = AutoGPTAgent("Search web", "/data/mco-config")
840
- return agent._search_web(query)
841
-
842
- # Note: Web endpoint removed - HuggingFace Space will call functions directly via Python client
843
-
844
- if __name__ == "__main__":
845
- # For local testing
846
- print("Running agent locally...")
847
- result = run_agent("Create a simple code review workflow for Python")
848
- print(json.dumps(result, indent=2))