mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-11 12:17:45 +02:00
137 lines
5.0 KiB
Python
137 lines
5.0 KiB
Python
"""AI-powered endpoints: vibe-code, auto-run, auto-run-agent."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import logging
|
|
|
|
from backend.apps.outputs.helpers import _validate_against_schema
|
|
from backend.apps.outputs.executor import execute_backend_code
|
|
from backend.apps.common.model_registry import resolve_model_id as _resolve_model
|
|
from backend.apps.outputs.models import (
|
|
AutoRunRequest, AutoRunAgentRequest,
|
|
)
|
|
from backend.apps.settings.credentials import get_anthropic_client
|
|
from backend.apps.settings.settings import load_settings
|
|
from backend.apps.common.llm_helpers import _resolve_model as _resolve_9r
|
|
from backend.apps.settings.settings import load_settings as _ls
|
|
from backend.apps.agents.manager.agent_manager import agent_manager
|
|
from backend.apps.agents.execution.mcp_builder import FULL_TOOLS
|
|
from backend.apps.agents.models import AgentConfig
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def _get_anthropic_client():
|
|
return get_anthropic_client(load_settings())
|
|
|
|
|
|
AUTO_RUN_SYSTEM_PROMPT = """\
|
|
You generate structured JSON data matching a given schema.
|
|
The user provides a prompt describing what data to generate and a JSON Schema.
|
|
Return ONLY valid JSON that conforms to the schema. No markdown fences, no extra text, no explanation.
|
|
Every required field must be present. Use realistic, meaningful data.\
|
|
"""
|
|
|
|
|
|
async def auto_run_output(body: AutoRunRequest):
|
|
|
|
schema_str = json.dumps(body.input_schema, indent=2)
|
|
user_message = f"Schema:\n```json\n{schema_str}\n```\n\nGenerate data for: {body.prompt}"
|
|
|
|
api_model = _resolve_model(body.model)
|
|
api_model = _resolve_9r(api_model, _ls())
|
|
client = _get_anthropic_client()
|
|
try:
|
|
resp = await client.messages.create(
|
|
model=api_model, max_tokens=4000,
|
|
system=AUTO_RUN_SYSTEM_PROMPT,
|
|
messages=[{"role": "user", "content": user_message}],
|
|
)
|
|
raw = resp.content[0].text.strip()
|
|
if raw.startswith("```"):
|
|
raw = raw.split("\n", 1)[1] if "\n" in raw else raw[3:]
|
|
if raw.endswith("```"):
|
|
raw = raw[:-3]
|
|
input_data = json.loads(raw)
|
|
|
|
validation_err = _validate_against_schema(input_data, body.input_schema)
|
|
if validation_err:
|
|
return {"input_data": input_data, "backend_result": None, "error": validation_err}
|
|
|
|
backend_result = None
|
|
stdout_text = None
|
|
stderr_text = None
|
|
error = None
|
|
if body.backend_code:
|
|
try:
|
|
exec_result = await execute_backend_code(body.backend_code, input_data)
|
|
backend_result = exec_result.result
|
|
stdout_text = exec_result.stdout
|
|
stderr_text = exec_result.stderr
|
|
except Exception as e:
|
|
error = str(e)
|
|
|
|
return {"input_data": input_data, "backend_result": backend_result, "stdout": stdout_text, "stderr": stderr_text, "error": error}
|
|
except json.JSONDecodeError:
|
|
return {"error": "Failed to parse generated data as JSON", "input_data": None, "backend_result": None}
|
|
except Exception as e:
|
|
logger.exception("Auto-run failed")
|
|
return {"error": str(e), "input_data": None, "backend_result": None}
|
|
|
|
|
|
AUTO_RUN_AGENT_SYSTEM_PROMPT = """\
|
|
You are a data-gathering agent. Your job is to use the available tools to collect \
|
|
real data, then render it into a structured View.
|
|
|
|
You have access to MCP tools (e.g. Gmail, calendar, etc.) that let you fetch live data. \
|
|
Use them as needed to fulfil the user's request.
|
|
|
|
When you have gathered enough data, call the **RenderOutput** tool with:
|
|
- `output_id`: `{output_id}`
|
|
- `input_data`: a JSON object conforming to this schema:
|
|
```json
|
|
{schema}
|
|
```
|
|
|
|
Do NOT fabricate data. Use the tools to get real information, then structure it to match \
|
|
the schema above. If a tool call fails, report the error clearly.\
|
|
"""
|
|
|
|
|
|
async def auto_run_agent(body: AutoRunAgentRequest):
|
|
from backend.apps.outputs.outputs import _load
|
|
output = _load(body.output_id)
|
|
schema_str = json.dumps(body.input_schema or output.input_schema, indent=2)
|
|
|
|
system_prompt = AUTO_RUN_AGENT_SYSTEM_PROMPT.format(
|
|
output_id=body.output_id, schema=schema_str,
|
|
)
|
|
|
|
allowed_tools = list(FULL_TOOLS)
|
|
for tool_name in body.forced_tools:
|
|
if tool_name not in allowed_tools:
|
|
allowed_tools.append(tool_name)
|
|
|
|
config = AgentConfig(
|
|
name=f"AutoRun: {output.name}", model=body.model,
|
|
mode="agent", system_prompt=system_prompt,
|
|
allowed_tools=allowed_tools, max_turns=20,
|
|
)
|
|
|
|
session = await agent_manager.launch_agent(config)
|
|
await agent_manager.send_message(
|
|
session.id, body.prompt,
|
|
context_paths=body.context_paths if body.context_paths else None,
|
|
forced_tools=body.forced_tools if body.forced_tools else None,
|
|
)
|
|
return {"session_id": session.id}
|
|
|
|
|
|
async def cleanup_auto_run_agent(session_id: str):
|
|
try:
|
|
await agent_manager.delete_session(session_id)
|
|
except Exception as e:
|
|
logger.warning(f"Auto-run agent cleanup failed for {session_id}: {e}")
|
|
return {"ok": True}
|