Files
can-you-assist/src/cya/llm/prompt.py
tegwick 019f6e7dc7 Implement CYA-WP-0008 llm-connect adapter integration.
Wire LLMConnectAdapter behind the existing LLMAdapter seam with config-driven
selection, graceful degradation, --offline mode, and bounded session context.
Add unit tests, integration docs, and update README/SCOPE/AGENTS.
2026-06-22 10:36:10 +02:00

73 lines
2.7 KiB
Python

"""Prompt construction for llm-connect delegation (CYA-WP-0008)."""
from __future__ import annotations
import json
from typing import Any
from cya.llm.adapter import AssistanceRequest
_DEFAULT_SYSTEM = """You are cya, a console-native assistant for practical local work from the shell.
Help the user with command-line tasks: repository inspection, file workflows, command
suggestion, command explanation, and local context summarization.
Be concise and practical. When suggesting shell commands, explain risks briefly.
Do not claim to have executed anything — the user runs commands themselves.
Reference the provided context when it is relevant."""
def default_system_prompt() -> str:
return _DEFAULT_SYSTEM
def build_assistance_prompt(request: AssistanceRequest, *, system_prompt: str | None = None) -> tuple[str, str]:
"""Return (system_prompt, user_prompt) for llm-connect execute_prompt."""
system = system_prompt or default_system_prompt()
parts: list[str] = []
context = request.context or {}
session_turns = context.get("session_turns")
if session_turns:
parts.append("## Recent conversation")
for turn in session_turns:
parts.append(f"User: {turn.get('user', '')}")
parts.append(f"Assistant: {turn.get('assistant', '')}")
envelope = {k: v for k, v in context.items() if k not in ("session_turns", "memory")}
if envelope:
parts.append("## Local context")
parts.append(_summarize_context(envelope))
memory = context.get("memory")
if isinstance(memory, dict) and memory.get("items"):
parts.append("## Activated memory")
for item in memory["items"][:8]:
parts.append(f"- [{item.get('kind', '?')}] {item.get('key', '?')}: {item.get('value', '')}")
parts.append("## Current request")
parts.append(request.user_request.strip())
return system, "\n\n".join(parts)
def _summarize_context(envelope: dict[str, Any]) -> str:
"""Compact, JSON-safe context summary to stay within prompt budget."""
summary: dict[str, Any] = {}
if envelope.get("cwd"):
summary["cwd"] = envelope["cwd"]
if envelope.get("git"):
git = envelope["git"]
summary["git"] = {
k: git[k]
for k in ("branch", "status_short", "workdir", "is_repo")
if k in git
}
if envelope.get("top_level"):
names = [e.get("name") for e in envelope["top_level"][:30] if e.get("name")]
summary["top_level"] = names
if envelope.get("env"):
summary["env"] = envelope["env"]
if envelope.get("notes"):
summary["notes"] = envelope["notes"][:5]
return json.dumps(summary, indent=2, default=str)