Add/Update wolf/runner.py by Wolf
This commit is contained in:
114
wolf/runner.py
Normal file
114
wolf/runner.py
Normal file
@@ -0,0 +1,114 @@
|
||||
import logging
|
||||
import json
|
||||
import time
|
||||
from typing import Dict, Any, List, Optional
|
||||
from .models import ModelFactory
|
||||
from .gitea import GiteaClient
|
||||
from .task import Task
|
||||
|
||||
class AgentRunner:
|
||||
"""
|
||||
Agent runner for Wolf.
|
||||
"""
|
||||
def __init__(self, gitea_client: GiteaClient, config: Dict[str, Any]):
|
||||
self.gitea = gitea_client
|
||||
self.config = config
|
||||
|
||||
def execute_task(self, task: Task):
|
||||
"""
|
||||
Execute a task through a specified model.
|
||||
"""
|
||||
logging.info(f"Executing task {task.id} with model {task.assigned_model} via {task.assigned_provider}")
|
||||
|
||||
# 1. Craft the prompt
|
||||
prompt = self._craft_prompt(task)
|
||||
|
||||
# 2. Get the model client
|
||||
provider_config = self.config.get('providers', {}).get(task.assigned_provider, {})
|
||||
client = ModelFactory.get_client(
|
||||
task.assigned_provider,
|
||||
api_key=provider_config.get('api_key'),
|
||||
base_url=provider_config.get('base_url')
|
||||
)
|
||||
|
||||
# 3. Generate response
|
||||
try:
|
||||
response = client.generate(prompt, task.assigned_model, system_prompt="You are an expert software engineer.")
|
||||
logging.info(f"Generated response for task {task.id}")
|
||||
except Exception as e:
|
||||
logging.error(f"Error generating response for task {task.id}: {e}")
|
||||
return None
|
||||
|
||||
# 4. Parse the response (assuming model returns a JSON or specific format)
|
||||
# For simplicity, we'll assume the model returns a JSON with 'files' and 'commit_message'
|
||||
# If not, we'll try to extract it.
|
||||
try:
|
||||
# Try to find JSON in the response
|
||||
if "```json" in response:
|
||||
json_str = response.split("```json")[1].split("```")[0].strip()
|
||||
result = json.loads(json_str)
|
||||
else:
|
||||
result = json.loads(response)
|
||||
except Exception as e:
|
||||
logging.warning(f"Failed to parse JSON from response for task {task.id}: {e}")
|
||||
# Fallback: Treat entire response as a single file change if possible
|
||||
result = {
|
||||
"files": [{"path": "solution.py", "content": response}],
|
||||
"commit_message": f"Solution for task {task.id}"
|
||||
}
|
||||
|
||||
# 5. Commit the output back to a feature branch
|
||||
branch_name = f"wolf-task-{task.id}-{int(time.time())}"
|
||||
try:
|
||||
self.gitea.create_branch(task.repo_owner, task.repo_name, branch_name)
|
||||
for file_change in result.get('files', []):
|
||||
path = file_change['path']
|
||||
content = file_change['content']
|
||||
|
||||
# Check if file exists to update or create
|
||||
existing_file = self.gitea.get_file(task.repo_owner, task.repo_name, path)
|
||||
if existing_file:
|
||||
self.gitea.update_file(
|
||||
task.repo_owner, task.repo_name, path, content,
|
||||
branch_name, existing_file['sha'],
|
||||
message=result.get('commit_message', f"Update {path} by Wolf")
|
||||
)
|
||||
else:
|
||||
self.gitea.create_file(
|
||||
task.repo_owner, task.repo_name, path, content,
|
||||
branch_name, message=result.get('commit_message', f"Create {path} by Wolf")
|
||||
)
|
||||
|
||||
# 6. Create PR
|
||||
pr_title = f"Wolf Task: {task.title}"
|
||||
pr_body = f"This PR was generated by Wolf using model {task.assigned_model} via {task.assigned_provider}.\n\nTask Description:\n{task.description}"
|
||||
pr = self.gitea.create_pull_request(task.repo_owner, task.repo_name, pr_title, pr_body, branch_name)
|
||||
logging.info(f"Created PR {pr['number']} for task {task.id}")
|
||||
return pr
|
||||
except Exception as e:
|
||||
logging.error(f"Error committing changes or creating PR for task {task.id}: {e}")
|
||||
return None
|
||||
|
||||
def _craft_prompt(self, task: Task):
|
||||
"""
|
||||
Craft the prompt for the model.
|
||||
"""
|
||||
return f"""
|
||||
You are an expert software engineer. Your task is to solve the following coding problem:
|
||||
|
||||
Title: {task.title}
|
||||
Description: {task.description}
|
||||
|
||||
Please provide the solution as a JSON object with the following structure:
|
||||
{{
|
||||
"files": [
|
||||
{{
|
||||
"path": "path/to/file.py",
|
||||
"content": "file content here"
|
||||
}}
|
||||
],
|
||||
"commit_message": "A meaningful commit message"
|
||||
}}
|
||||
|
||||
Ensure the code is correct, well-documented, and follows best practices.
|
||||
"""
|
||||
Reference in New Issue
Block a user