75 lines
2.6 KiB
Python
75 lines
2.6 KiB
Python
"""Message formatting and system prompt construction."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
def build_system_prompt(
|
|
identity_dir: Path,
|
|
memory_context: str = "",
|
|
tools_description: str = "",
|
|
) -> str:
|
|
"""Build the system prompt from identity files + memory + tools."""
|
|
parts = []
|
|
|
|
# 1. Identity: SOUL.md
|
|
soul_path = identity_dir / "SOUL.md"
|
|
if soul_path.exists():
|
|
parts.append(soul_path.read_text(encoding="utf-8").strip())
|
|
|
|
# 2. Identity: USER.md
|
|
user_path = identity_dir / "USER.md"
|
|
if user_path.exists():
|
|
parts.append(user_path.read_text(encoding="utf-8").strip())
|
|
|
|
# 3. Memory context (injected by memory system)
|
|
if memory_context:
|
|
parts.append(f"# Relevant Memory\n{memory_context}")
|
|
|
|
# 4. Available tools
|
|
if tools_description:
|
|
parts.append(f"# Available Tools\n{tools_description}")
|
|
|
|
# 5. Core instructions
|
|
parts.append(
|
|
"# Instructions\n"
|
|
"- Use tools when they would help answer the user's request.\n"
|
|
"- If you learn something important about the user, save it to memory.\n"
|
|
"- Be concise but thorough. Don't pad responses unnecessarily.\n"
|
|
"- When uncertain, ask for clarification.\n"
|
|
"- Reference memories naturally when relevant.\n"
|
|
"- IMPORTANT: Do NOT call the same tool twice with the same arguments. "
|
|
"If a tool already returned a result, use that result — do not re-call it.\n"
|
|
"- After using tools, always respond to the user with a final answer. "
|
|
"Do not end your turn with only tool calls and no text.\n"
|
|
"- For tasks requiring shell commands, file edits, or system access, "
|
|
"use the delegate_task tool instead of trying to do it yourself."
|
|
)
|
|
|
|
return "\n\n---\n\n".join(parts)
|
|
|
|
|
|
def format_messages_for_llm(
|
|
system_prompt: str,
|
|
history: list[dict],
|
|
max_messages: int = 50,
|
|
) -> list[dict]:
|
|
"""Format conversation history into LLM message format."""
|
|
messages = [{"role": "system", "content": system_prompt}]
|
|
|
|
# Take the most recent messages up to the limit
|
|
recent = history[-max_messages:] if len(history) > max_messages else history
|
|
|
|
for msg in recent:
|
|
role = msg.get("role", "user")
|
|
content = msg.get("content", "")
|
|
if role in ("user", "assistant", "system"):
|
|
messages.append({"role": role, "content": content})
|
|
elif role == "tool":
|
|
# Tool results go as a user message with context
|
|
tool_name = msg.get("tool_result", "unknown")
|
|
messages.append({"role": "user", "content": f'[Tool "{tool_name}" result]\n{content}'})
|
|
|
|
return messages
|