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.
77 lines
2.4 KiB
Python
77 lines
2.4 KiB
Python
"""Tests for run_contextual_stream.
|
|
|
|
These tests monkeypatch _run_single_agent_stream (the actual internal runner)
|
|
rather than the plan's fictional _run_agent_loop, matching the real
|
|
deep_agent.py architecture.
|
|
"""
|
|
import pytest
|
|
from unittest.mock import AsyncMock, MagicMock, patch
|
|
from app.schemas.contextual import ContextualScope
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_run_contextual_stream_includes_scope_block(monkeypatch):
|
|
"""run_contextual_stream must inject the scope block into the system prompt
|
|
and include get_page_details in the tool list while excluding note-edit tools."""
|
|
import app.core.deep_agent as deep_agent
|
|
|
|
captured = {}
|
|
|
|
async def fake_stream(
|
|
*,
|
|
user_id,
|
|
system_prompt,
|
|
message,
|
|
context,
|
|
agent_name="agent",
|
|
tools=None,
|
|
conversation_history=None,
|
|
**kwargs,
|
|
):
|
|
captured["sys"] = system_prompt
|
|
captured["tool_names"] = [getattr(t, "name", str(t)) for t in (tools or [])]
|
|
captured["agent_name"] = agent_name
|
|
# Async generator that yields nothing — still satisfies the protocol.
|
|
if False:
|
|
yield # pragma: no cover
|
|
|
|
monkeypatch.setattr(deep_agent, "_run_single_agent_stream", fake_stream)
|
|
|
|
scope = ContextualScope(
|
|
page="project",
|
|
entity_type="project",
|
|
entity_id="p1",
|
|
entity_name="Acme",
|
|
counts={"tasks": 1, "notes": 0, "milestones": 0},
|
|
)
|
|
|
|
context = {
|
|
"conversation_history": [],
|
|
"_debug": {"session_id": "s1"},
|
|
}
|
|
|
|
results = []
|
|
async for item in deep_agent.run_contextual_stream(
|
|
user_id="user1",
|
|
message="hi",
|
|
context=context,
|
|
scope=scope,
|
|
):
|
|
results.append(item)
|
|
|
|
assert "Acme" in captured["sys"], "scope block must appear in system prompt"
|
|
assert "Current view" in captured["sys"], "section header must be present"
|
|
|
|
names = captured["tool_names"]
|
|
assert "get_page_details" in names, "get_page_details tool must be included"
|
|
|
|
# Entity-create tools: at least one of these must be present.
|
|
assert any(n in names for n in ("create_task", "create_note", "update_task")), (
|
|
"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"
|