fix(contextual): inject date_context + language in run_contextual_stream

Use _build_system_prompt helper so the contextual agent gets the
same system-prompt slots as home/floating runners — most importantly
{date_context} so the agent can reason about due dates when
creating/updating tasks.

Also makes the session_id contract on run_contextual_stream explicit
(was reading via context['_debug']) and tightens the tool-list test.
This commit is contained in:
Roberto
2026-05-14 21:17:54 +02:00
parent 2b71469e86
commit 5e42b2abb1
2 changed files with 16 additions and 7 deletions

View File

@@ -404,6 +404,12 @@ Rules:
5. Notes: you can read note bodies via `get_page_details({entityType:'note'})`. You CANNOT edit, summarize-to-replace, or append. Tell the user "note editing is coming in a later release" if asked.
6. Be concise. Default to 1-3 short paragraphs. Bullet lists fine. Don't restate the user's request.
7. Never expose ids in prose. Use names. Ids only travel through tool calls.
# Date context
{date_context}
# Language
{language_instruction}
"""
_TASK_BRIEF_RESEARCH_SYSTEM_PROMPT = """\
@@ -1600,21 +1606,22 @@ async def run_contextual_stream(
Mirrors run_floating_stream's plumbing but injects the rendered scope
block into the system prompt and exposes the contextual tool set.
Note-edit tools (propose_note_edit) are intentionally excluded.
*context contract*: callers MUST include ``context["_debug"]["session_id"]``
(a non-empty str) so that ``_session_id_from_context`` can extract it for
tracing and episode storage downstream. The WS handler in device_ws.py
satisfies this by always populating ``_debug`` before calling this function.
"""
from app.schemas.contextual import ContextualScope, render_scope_block # noqa: PLC0415
prepared_context = await _prepare_context(message, context)
trace_id = _trace_id_from_context(prepared_context)
template, langfuse_prompt = get_prompt_or_fallback(
"contextual_system", _CONTEXTUAL_SYSTEM_PROMPT,
system_prompt, langfuse_prompt = _build_system_prompt(
"contextual_system", _CONTEXTUAL_SYSTEM_PROMPT, prepared_context,
)
scope_block = render_scope_block(scope)
# Build system prompt: Langfuse template (or fallback) + scope injection.
# The contextual prompt has no per-request slots like {date_context}, so
# we just append the scope block directly.
system_prompt = template + f"\n\n## Current view\n{scope_block}"
system_prompt += _language_instruction(prepared_context)
system_prompt = system_prompt + f"\n\n## Current view\n{scope_block}"
tools = _contextual_tools(user_id, trace_id)

View File

@@ -70,5 +70,7 @@ async def test_run_contextual_stream_includes_scope_block(monkeypatch):
"at least one entity-create tool must be present"
)
assert "create_timeline" in names, "create_timeline tool must be included"
# Note edit tools must NOT be exposed.
assert "propose_note_edit" not in names, "propose_note_edit must be excluded"