Initial commit: VoIdeaAI - voice-first AI idea assistant
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
"""Agent triggers - automated execution mechanisms."""
|
||||
|
||||
import asyncio
|
||||
import subprocess
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable
|
||||
|
||||
from app.agents.base import AgentResult, AgentTrigger
|
||||
from app.agents.registry import registry
|
||||
|
||||
|
||||
class TriggerManager:
|
||||
"""Manages agent triggers and execution scheduling."""
|
||||
|
||||
def __init__(self):
|
||||
self._cron_tasks: list[asyncio.Task] = []
|
||||
self._running = False
|
||||
|
||||
async def trigger_pre_commit(self, files: list[str]) -> dict[str, AgentResult]:
|
||||
"""Trigger agents on pre-commit hook.
|
||||
|
||||
Args:
|
||||
files: List of changed files
|
||||
|
||||
Returns:
|
||||
Dict of agent -> result
|
||||
"""
|
||||
results = {}
|
||||
|
||||
context = {
|
||||
"trigger": "pre_commit",
|
||||
"files": files,
|
||||
}
|
||||
|
||||
audit_result = await registry.run_agent("audit_agent", {
|
||||
"action": "quick",
|
||||
"paths": self._get_affected_paths(files),
|
||||
})
|
||||
results["audit_agent"] = audit_result
|
||||
|
||||
doc_result = await registry.run_agent("doc_agent", {
|
||||
"action": "update_readme",
|
||||
"files": files,
|
||||
})
|
||||
results["doc_agent"] = doc_result
|
||||
|
||||
return results
|
||||
|
||||
async def trigger_push(self, branch: str) -> dict[str, AgentResult]:
|
||||
"""Trigger agents on git push.
|
||||
|
||||
Args:
|
||||
branch: Branch name
|
||||
|
||||
Returns:
|
||||
Dict of agent -> result
|
||||
"""
|
||||
results = {}
|
||||
|
||||
context = {
|
||||
"trigger": "push",
|
||||
"branch": branch,
|
||||
}
|
||||
|
||||
if branch in ("main", "develop"):
|
||||
spec_result = await registry.run_agent("spec_agent", context)
|
||||
results["spec_agent"] = spec_result
|
||||
|
||||
doc_result = await registry.run_agent("doc_agent", context)
|
||||
results["doc_agent"] = doc_result
|
||||
|
||||
return results
|
||||
|
||||
async def trigger_cron(self) -> dict[str, AgentResult]:
|
||||
"""Trigger agents on scheduled cron.
|
||||
|
||||
Returns:
|
||||
Dict of agent -> result
|
||||
"""
|
||||
results = {}
|
||||
|
||||
audit_result = await registry.run_agent("audit_agent", {
|
||||
"action": "full",
|
||||
"paths": ["app"],
|
||||
})
|
||||
results["audit_agent"] = audit_result
|
||||
|
||||
observer_result = await registry.run_agent("observer_agent", {
|
||||
"action": "report",
|
||||
"period": "daily",
|
||||
})
|
||||
results["observer_agent"] = observer_result
|
||||
|
||||
evolution_result = await registry.run_agent("evolution_agent", {
|
||||
"action": "analyze",
|
||||
})
|
||||
results["evolution_agent"] = evolution_result
|
||||
|
||||
return results
|
||||
|
||||
async def trigger_manual(
|
||||
self,
|
||||
agent_name: str,
|
||||
context: dict[str, Any] | None = None,
|
||||
) -> AgentResult:
|
||||
"""Trigger a specific agent manually.
|
||||
|
||||
Args:
|
||||
agent_name: Agent name
|
||||
context: Optional context
|
||||
|
||||
Returns:
|
||||
AgentResult
|
||||
"""
|
||||
return await registry.run_agent(agent_name, context)
|
||||
|
||||
def _get_affected_paths(self, files: list[str]) -> list[str]:
|
||||
"""Get affected paths from file list.
|
||||
|
||||
Args:
|
||||
files: List of file paths
|
||||
|
||||
Returns:
|
||||
List of unique directory paths
|
||||
"""
|
||||
paths = set()
|
||||
for file in files:
|
||||
parts = Path(file).parts
|
||||
if len(parts) > 1 and parts[0] == "app":
|
||||
paths.add(parts[1])
|
||||
return list(paths) if paths else ["app"]
|
||||
|
||||
|
||||
class PreCommitHook:
|
||||
"""Pre-commit hook integration."""
|
||||
|
||||
@staticmethod
|
||||
def install() -> None:
|
||||
"""Install pre-commit hook."""
|
||||
project_root = Path(__file__).parent.parent.parent
|
||||
hook_dir = project_root / ".git" / "hooks"
|
||||
|
||||
if not hook_dir.exists():
|
||||
return
|
||||
|
||||
hook_content = """#!/bin/sh
|
||||
# VoIdea Pre-commit Hook
|
||||
|
||||
python -m app.agents.triggers.pre_commit
|
||||
"""
|
||||
|
||||
hook_path = hook_dir / "pre-commit"
|
||||
hook_path.write_text(hook_content, encoding="utf-8")
|
||||
|
||||
@staticmethod
|
||||
async def run() -> dict[str, Any]:
|
||||
"""Run pre-commit checks.
|
||||
|
||||
Returns:
|
||||
Check results
|
||||
"""
|
||||
manager = TriggerManager()
|
||||
project_root = Path(__file__).parent.parent.parent
|
||||
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["git", "diff", "--cached", "--name-only"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
cwd=str(project_root),
|
||||
)
|
||||
files = result.stdout.strip().split("\n")
|
||||
files = [f for f in files if f]
|
||||
except Exception:
|
||||
files = []
|
||||
|
||||
if not files:
|
||||
return {"status": "skipped", "message": "No files to check"}
|
||||
|
||||
results = await manager.trigger_pre_commit(files)
|
||||
|
||||
failed = [name for name, result in results.items() if not result.success]
|
||||
|
||||
return {
|
||||
"status": "passed" if not failed else "failed",
|
||||
"failed_agents": failed,
|
||||
"results": {name: r.message for name, r in results.items()},
|
||||
}
|
||||
|
||||
|
||||
async def run_agent_manually(
|
||||
agent_name: str,
|
||||
action: str | None = None,
|
||||
**kwargs: Any,
|
||||
) -> AgentResult:
|
||||
"""Convenience function to run an agent manually.
|
||||
|
||||
Args:
|
||||
agent_name: Name of agent to run
|
||||
action: Optional action to perform
|
||||
**kwargs: Additional context
|
||||
|
||||
Returns:
|
||||
AgentResult
|
||||
"""
|
||||
context = kwargs if not action else {"action": action, **kwargs}
|
||||
return await registry.run_agent(agent_name, context)
|
||||
Reference in New Issue
Block a user