You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
110 lines
3.0 KiB
110 lines
3.0 KiB
"""Runtime context injection for agent operation.
|
|
|
|
Generates dynamic context about the current pipeline state,
|
|
recent issues, and accumulated knowledge.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
import os
|
|
from datetime import datetime
|
|
from typing import Any, Dict
|
|
|
|
from agent_tools.database import query_pipeline_status
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def build_context(db_path: str) -> Dict[str, Any]:
|
|
"""Build a comprehensive context dict for the agent.
|
|
|
|
This is injected into the agent's prompt at session start.
|
|
"""
|
|
status = query_pipeline_status(db_path)
|
|
|
|
context = {
|
|
"timestamp": datetime.now().isoformat(),
|
|
"database_path": db_path,
|
|
"pipeline": status,
|
|
"recent_reports": _list_recent_reports(),
|
|
"accumulated_knowledge": _read_context_md(),
|
|
}
|
|
|
|
return context
|
|
|
|
|
|
def render_context_markdown(db_path: str) -> str:
|
|
"""Render context as markdown for prompt injection."""
|
|
ctx = build_context(db_path)
|
|
|
|
lines = [
|
|
"## Current Pipeline State",
|
|
f"",
|
|
f"- **Motions:** {ctx['pipeline'].get('motion_count', 0):,}",
|
|
f"- **Latest motion:** {ctx['pipeline'].get('latest_motion_date', 'N/A')}",
|
|
f"- **SVD windows:** {ctx['pipeline'].get('svd_window_count', 0)}",
|
|
f"- **Embeddings:** {ctx['pipeline'].get('embedding_count', 0):,}",
|
|
f"- **Healthy:** {'Yes' if ctx['pipeline'].get('healthy') else 'No'}",
|
|
f"",
|
|
]
|
|
|
|
recent = ctx.get("recent_reports", [])
|
|
if recent:
|
|
lines.extend([
|
|
"## Recent Reports",
|
|
f"",
|
|
])
|
|
for r in recent[:5]:
|
|
lines.append(f"- {r}")
|
|
lines.append("")
|
|
|
|
knowledge = ctx.get("accumulated_knowledge", "")
|
|
if knowledge:
|
|
lines.extend([
|
|
"## Accumulated Knowledge",
|
|
f"",
|
|
knowledge,
|
|
f"",
|
|
])
|
|
|
|
return "\n".join(lines)
|
|
|
|
|
|
def _list_recent_reports() -> list:
|
|
"""List recently generated reports."""
|
|
try:
|
|
reports_dir = "reports"
|
|
if not os.path.exists(reports_dir):
|
|
return []
|
|
files = sorted(
|
|
(f for f in os.listdir(reports_dir) if f.endswith(".md")),
|
|
key=lambda f: os.path.getmtime(os.path.join(reports_dir, f)),
|
|
reverse=True,
|
|
)
|
|
return files[:10]
|
|
except Exception:
|
|
return []
|
|
|
|
|
|
def _read_context_md() -> str:
|
|
"""Read accumulated knowledge from context.md."""
|
|
try:
|
|
path = os.path.join("agent_tools", "context.md")
|
|
if os.path.exists(path):
|
|
with open(path, "r", encoding="utf-8") as f:
|
|
return f.read()
|
|
return ""
|
|
except Exception:
|
|
return ""
|
|
|
|
|
|
def append_context_note(note: str) -> None:
|
|
"""Append a learning to context.md."""
|
|
try:
|
|
path = os.path.join("agent_tools", "context.md")
|
|
timestamp = datetime.now().isoformat()
|
|
with open(path, "a", encoding="utf-8") as f:
|
|
f.write(f"\n## {timestamp}\n\n{note}\n")
|
|
except Exception:
|
|
logger.exception("Failed to append context note")
|
|
|