Add/Update wolf/runner.py by Wolf

This commit is contained in:
2026-04-05 17:59:25 +00:00
parent f9e4f40f05
commit fcfbb7f106

114
wolf/runner.py Normal file
View 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.
"""