|
2 | 2 | schema/loop-back, session-id rollover, and the identity cache. These complement the |
3 | 3 | end-to-end adapter tests by exercising edge branches directly.""" |
4 | 4 |
|
| 5 | +import pytest |
| 6 | + |
5 | 7 | from datetime import datetime, timedelta, timezone |
6 | 8 | from types import SimpleNamespace |
7 | 9 |
|
@@ -58,29 +60,27 @@ async def test_intent_from_context_argument(): |
58 | 60 | assert out == ("do the thing", "context_parameter") |
59 | 61 |
|
60 | 62 |
|
61 | | -async def test_intent_skips_context_for_missing_capability_tool(): |
62 | | - # a get_more_tools call's context is a capability report, not a tool-call |
63 | | - # intent — but only while the SDK actually owns that name |
| 63 | +@pytest.mark.parametrize("report_missing", [False, True]) |
| 64 | +async def test_intent_captures_context_whatever_the_tool_is_called(report_missing): |
| 65 | + # Only host-dispatched tools reach intent resolution: PostHog's own virtual |
| 66 | + # tools are intercepted first and set their event's intent from their own |
| 67 | + # arguments. So a call named `get_more_tools` arriving here is the *host's* |
| 68 | + # tool, and its context is an ordinary intent. |
| 69 | + # |
| 70 | + # A name-based exemption used to live here and could only fire on that host |
| 71 | + # tool, silently dropping its `$mcp_intent` -- and only on an instance that |
| 72 | + # had not yet served a tools/list, which made it look intermittent. |
64 | 73 | out = await resolve_tool_call_intent( |
65 | | - _data(report_missing=True), |
| 74 | + _data(report_missing=report_missing), |
66 | 75 | _call(name="get_more_tools", args={"context": "need csv export"}), |
67 | 76 | ) |
68 | | - assert out is None |
69 | | - |
70 | | - |
71 | | -async def test_intent_keeps_context_for_a_real_tool_named_get_more_tools(): |
72 | | - # With report_missing off the SDK advertises no such tool, so one by that |
73 | | - # name is the host's own and its context is an ordinary intent. Interception |
74 | | - # has always been gated on report_missing, so dropping the intent here left |
75 | | - # a real tool dispatched but unattributed. |
76 | | - out = await resolve_tool_call_intent( |
77 | | - _data(), _call(name="get_more_tools", args={"context": "need csv export"}) |
78 | | - ) |
79 | 77 | assert out == ("need csv export", "context_parameter") |
80 | 78 |
|
81 | 79 |
|
82 | | -async def test_intent_keeps_context_when_a_real_tool_owns_the_name(): |
83 | | - # Same, via the listing-derived collision state rather than the switch. |
| 80 | +async def test_intent_is_independent_of_listing_derived_collision_state(): |
| 81 | + # Per-request by construction: nothing here reads state a tools/list wrote, |
| 82 | + # so a server with caller-specific catalogues cannot attribute one caller's |
| 83 | + # call from another caller's listing. |
84 | 84 | data = _data(report_missing=True) |
85 | 85 | data.virtual_tool_collisions.add(VIRTUAL_TOOL_MISSING_CAPABILITY) |
86 | 86 | out = await resolve_tool_call_intent( |
@@ -311,11 +311,13 @@ def test_resolve_conversation_id_disabled(): |
311 | 311 | assert resolve_conversation_id(False, {}, "t", "get_more_tools") == (None, False) |
312 | 312 |
|
313 | 313 |
|
314 | | -def test_resolve_conversation_id_skips_missing_capability_tool(): |
315 | | - assert resolve_conversation_id(True, {}, "get_more_tools", "get_more_tools") == ( |
316 | | - None, |
317 | | - False, |
318 | | - ) |
| 314 | +def test_resolve_conversation_id_exempts_no_tool_by_name(): |
| 315 | + # A name-based exemption cannot tell PostHog's virtual tool from a host tool |
| 316 | + # sharing the name, and got it wrong in the direction that matters: the |
| 317 | + # host's tool lost its handle. PostHog's virtual tools discard the resolved |
| 318 | + # handle on their own capture paths, so resolving one for them costs nothing. |
| 319 | + cid, minted = resolve_conversation_id(True, {}, "get_more_tools", "get_more_tools") |
| 320 | + assert minted is True and cid |
319 | 321 |
|
320 | 322 |
|
321 | 323 | def test_resolve_conversation_id_mints_for_a_shadowed_virtual_tool_name(): |
|
0 commit comments