mirror of
https://github.com/furyhawk/agent_alpha.git
synced 2026-07-21 10:35:34 +00:00
114 lines
4.1 KiB
Python
114 lines
4.1 KiB
Python
"""PydanticDeep assistant — deep agentic coding assistant.
|
|
|
|
PydanticDeep is built on PydanticAI and provides:
|
|
- Filesystem tools: ls, read_file, write_file, edit_file, glob, grep
|
|
- Task management: write_todos, planning subagent
|
|
- Subagent delegation
|
|
- Skills system (SKILL.md files)
|
|
- Memory persistence (MEMORY.md across sessions)
|
|
- Context file discovery (AGENTS.md, SOUL.md from workspace root)
|
|
- Built-in web search and web fetch
|
|
|
|
Backend types (set via PYDANTIC_DEEP_BACKEND_TYPE):
|
|
"state" — In-memory (default, no persistence)
|
|
"daytona" — Daytona cloud workspace (isolated, cloud-native)
|
|
|
|
Configuration via settings:
|
|
PYDANTIC_DEEP_BACKEND_TYPE : "state" | "daytona" (default: "state")
|
|
PYDANTIC_DEEP_INCLUDE_SUBAGENTS : enable subagent delegation (default: True)
|
|
PYDANTIC_DEEP_INCLUDE_SKILLS : enable skills system (default: True)
|
|
PYDANTIC_DEEP_INCLUDE_PLAN : enable planner subagent (default: True)
|
|
PYDANTIC_DEEP_INCLUDE_MEMORY : enable persistent MEMORY.md (default: True)
|
|
PYDANTIC_DEEP_INCLUDE_EXECUTE : enable shell execution (default: False)
|
|
PYDANTIC_DEEP_WEB_SEARCH : enable built-in web search (default: True)
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import time
|
|
from dataclasses import dataclass
|
|
from typing import Any
|
|
|
|
from pydantic_ai import Agent
|
|
|
|
from backend.repositories.memory_repository import MemoryRepository
|
|
from pydantic_deep.deps import DeepAgentDeps
|
|
|
|
|
|
class AgentService:
|
|
"""Thin orchestrator for agent execution.
|
|
|
|
Receives a pre-built ``Agent`` and its ``MemoryRepository`` via
|
|
constructor injection so the lifespan (or tests) control wiring.
|
|
No lazy initialisation — the agent is ready to run immediately.
|
|
"""
|
|
|
|
def __init__(self, agent: Agent[Any, str], memory_repo: MemoryRepository) -> None:
|
|
self._agent = agent
|
|
self._memory_repo = memory_repo
|
|
|
|
# ── Lifecycle ──────────────────────────────────────────────────────────
|
|
|
|
async def shutdown(self) -> None:
|
|
"""Release agent resources."""
|
|
self._agent = None
|
|
|
|
# ── Execution ──────────────────────────────────────────────────────────
|
|
|
|
async def ask(self, prompt: str, session_id: str | None = None) -> AskResult:
|
|
"""Send a prompt to the agent and return the text output with usage stats."""
|
|
di = DeepAgentDeps(backend=self._memory_repo.backend)
|
|
|
|
t0 = time.monotonic()
|
|
result = await self._agent.run(prompt, deps=di)
|
|
elapsed = time.monotonic() - t0
|
|
usage = result.usage
|
|
|
|
return AskResult(
|
|
output=result.output,
|
|
input_tokens=usage.input_tokens,
|
|
output_tokens=usage.output_tokens,
|
|
total_tokens=usage.input_tokens + usage.output_tokens,
|
|
elapsed_seconds=round(elapsed, 2),
|
|
)
|
|
|
|
|
|
@dataclass
|
|
class AskResult:
|
|
"""Result of a single agent ``ask()`` call with token usage information."""
|
|
|
|
output: str
|
|
"""The agent's text reply."""
|
|
|
|
input_tokens: int = 0
|
|
"""Number of prompt tokens sent to the model."""
|
|
|
|
output_tokens: int = 0
|
|
"""Number of completion tokens generated by the model."""
|
|
|
|
total_tokens: int = 0
|
|
"""Sum of input + output tokens."""
|
|
|
|
elapsed_seconds: float = 0.0
|
|
"""Wall-clock time in seconds the agent took to respond."""
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Singleton — wired once at startup by the lifespan hook in ``app.py``.
|
|
# Routes access it through ``get_service()``.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
_service: AgentService | None = None
|
|
|
|
|
|
def get_service() -> AgentService:
|
|
"""Return the singleton AgentService instance."""
|
|
assert _service is not None, "AgentService has not been initialised — did the lifespan run?"
|
|
return _service
|
|
|
|
|
|
def set_service(service: AgentService) -> None:
|
|
"""Set the module-level singleton (called by the lifespan hook)."""
|
|
global _service
|
|
_service = service
|