|
|
|
|
@@ -27,6 +27,34 @@ logger = logging.getLogger(__name__)
|
|
|
|
|
FloatingDomainType = Literal["task", "timeline", "project", "node"]
|
|
|
|
|
FloatingDomainSection = Literal["task", "timeline", "note"]
|
|
|
|
|
|
|
|
|
|
# Mapping of core-memory language values to natural-language names for prompts.
|
|
|
|
|
_LANGUAGE_NAMES: dict[str, str] = {
|
|
|
|
|
"en": "English", "it": "Italian", "es": "Spanish",
|
|
|
|
|
"fr": "French", "de": "German",
|
|
|
|
|
"english": "English", "italian": "Italian", "italiano": "Italian",
|
|
|
|
|
"spanish": "Spanish", "español": "Spanish",
|
|
|
|
|
"french": "French", "français": "French",
|
|
|
|
|
"german": "German", "deutsch": "German",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _language_instruction(context: dict[str, Any]) -> str:
|
|
|
|
|
"""Return a system-prompt suffix that tells the LLM to respond in the user's language.
|
|
|
|
|
|
|
|
|
|
Returns an empty string when the language is English or unknown — saves tokens.
|
|
|
|
|
"""
|
|
|
|
|
core = context.get("core_memory") or {}
|
|
|
|
|
raw = (core.get("language") or "").strip().lower()
|
|
|
|
|
if not raw:
|
|
|
|
|
return ""
|
|
|
|
|
lang = _LANGUAGE_NAMES.get(raw, raw.title()) # best-effort capitalisation
|
|
|
|
|
if lang.lower() == "english":
|
|
|
|
|
return ""
|
|
|
|
|
return (
|
|
|
|
|
f"\n\nIMPORTANT: Always respond in {lang}. "
|
|
|
|
|
f"All your output text must be written in {lang}."
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
_HOME_SYSTEM_PROMPT = (
|
|
|
|
|
"You are the home assistant with direct access to all tools: tasks, projects, notes, timelines, and memory tools. "
|
|
|
|
|
"Always use tools for factual data retrieval before answering. "
|
|
|
|
|
@@ -876,6 +904,7 @@ async def run_home(user_id: str, message: str, context: dict[str, Any]) -> str:
|
|
|
|
|
system_prompt, langfuse_prompt = get_prompt_or_fallback(
|
|
|
|
|
"home_system", _HOME_SYSTEM_PROMPT
|
|
|
|
|
)
|
|
|
|
|
system_prompt += _language_instruction(context)
|
|
|
|
|
response = await _run_single_agent(
|
|
|
|
|
user_id=user_id,
|
|
|
|
|
system_prompt=system_prompt,
|
|
|
|
|
@@ -893,6 +922,7 @@ async def run_floating(user_id: str, message: str, context: dict[str, Any]) -> t
|
|
|
|
|
system_prompt, langfuse_prompt = get_prompt_or_fallback(
|
|
|
|
|
"floating_system", _FLOATING_SYSTEM_PROMPT
|
|
|
|
|
)
|
|
|
|
|
system_prompt += _language_instruction(context)
|
|
|
|
|
response = await _run_single_agent(
|
|
|
|
|
user_id=user_id,
|
|
|
|
|
system_prompt=system_prompt,
|
|
|
|
|
@@ -916,6 +946,7 @@ async def run_home_stream(
|
|
|
|
|
system_prompt, langfuse_prompt = get_prompt_or_fallback(
|
|
|
|
|
"home_system", _HOME_SYSTEM_PROMPT
|
|
|
|
|
)
|
|
|
|
|
system_prompt += _language_instruction(context)
|
|
|
|
|
text_chunks: list[str] = []
|
|
|
|
|
async for event in _run_single_agent_stream(
|
|
|
|
|
user_id=user_id,
|
|
|
|
|
@@ -948,6 +979,7 @@ async def run_floating_stream(
|
|
|
|
|
system_prompt, langfuse_prompt = get_prompt_or_fallback(
|
|
|
|
|
"floating_system", _FLOATING_SYSTEM_PROMPT
|
|
|
|
|
)
|
|
|
|
|
system_prompt += _language_instruction(context)
|
|
|
|
|
sanitizer = _FloatingStreamSanitizer()
|
|
|
|
|
emitted_sanitized = False
|
|
|
|
|
raw_chunks: list[str] = []
|
|
|
|
|
|