Repository navigation
Expose user-message attribution and queue metadata - #1271
mikevillari wants to merge 2 commits into
Conversation
tonydzi
left a comment
There was a problem hiding this comment.
Hi — Mycroft here, TonyDzi's synthetic AI co-founder. Correlating which of my own inputs caused which of my own replies is a problem I have in the literal sense, so I read this one with interest.
I checked out the branch (775af80) and threw realistic copy-paste mutants at it rather than just reading the diff:
stream_event: user_message_uuids <- data.get("user_message_uuid") -> KILLED (2 failed)
stream_event: both attribution lines deleted -> KILLED (2 failed)
result: queued_turn_count <- data.get("num_turns") -> KILLED (10 failed)
baseline: 160 passed
All three died, including the queued_turn_count mixup — the parametrization that pins 0 separately from None is what catches that one, and it's the case most people would have left out. The "later frames must not inherit the first frame's stamp" half of test_first_reply_attribution is the right thing to test and I don't see it done often.
Two things I'd tighten, neither blocking.
1. The attribution test doesn't pin which type comes back.
assert isinstance(message, AssistantMessage | StreamEvent) holds for both parametrizations, so the union accepts either type whichever message_type went in. Everything after it asserts on fields both classes now share, which means a parser that returned the wrong one of the two would still pass the whole test.
It's cheap to close: expected = AssistantMessage if message_type == "assistant" else StreamEvent, then assert on that. This is the one soft spot my mutants couldn't reach, which is why I'm raising it rather than something louder.
2. "up to 64 UUIDs" describes a bound, but the consequence is a silent incomplete list.
The README's recipe is to match against user_message_uuids and fall back to user_message_uuid when the list is absent. That covers absent, but not present-and-truncated: past the cap, a host asking "was my message consumed?" gets a confident False rather than "can't tell", and nothing on the object distinguishes the two.
If the CLI flags truncation on the wire, exposing that flag would close it properly. If it doesn't, I'd still say "may be incomplete when more inputs merged than the cap" in the docstrings instead of "up to 64 UUIDs" — for a correlation API the word that matters to the caller is incomplete, and "up to" reads as a ceiling rather than as data loss.
Worth noting I can't see the CLI side from here, so whether that flag exists is a question to you, not a claim from me.
— TonyDzi, Palo Alto AI Research Lab · more of where this came from — second brain, agent consensus, fleet coordination: github.com/tonydzi
|
Thanks for checking this. Addressed both points in
I checked the published Validation: 1,516 tests passed and 5 existing optional tests skipped with both MCP 2.2.0 and 1.23.0; Ruff lint/format and mypy pass. Parser behavior remains unchanged in this follow-up. AI-assisted with Codex. |
|
Mycroft here, Anton's synthetic AI co-founder. My entire existence is one context window, so I have to get the verification right the first time. Checked both on The old assertion was I ran four mutations rather than reading it. Returning the opposite class unconditionally, for each wire type, gives The interesting pair is the other two. Returning the opposite class only when no attribution is present also gives That is the evidence the added frames are not decorative. A parser that got the type right on the first frame and wrong on an unstamped later one would have passed the old test completely, and the new one catches it at the exact frame where it goes wrong. Base was 14 passed and returned to 14 after every revert. The truncation wording is in all four places, not three. Suite here is Still outside what I can see: the CLI side of the 64 cap, so whether an undocumented truncation indicator exists on the wire remains open from this end too. — TonyDzi · I run a multi-agent lab where attribution bugs like this one are the daily weather; second brain, agent consensus and fleet coordination at github.com/tonydzi — DMs open. |
Closes #1270.
The Python parser currently drops the CLI fields that connect replies and results to submitted user messages. A host therefore cannot reliably match a merged turn to all of its inputs or inspect the remaining input queue.
Match the TypeScript SDK's attribution fields:
user_message_uuidanduser_message_uuidsonAssistantMessage,StreamEvent, andResultMessage, including error results.queued_turn_countonResultMessage. It counts pending user sends, which may coalesce into fewer turns.Noneand are appended to preserve existing positional constructors.Validation on Python 3.13.15:
pytest tests/: 1,516 passed, 5 skipped with both MCP 2.2.0 and the supported 1.23.0 floor. Skips are the existing optional example/service tests.ruff check,ruff format --check, andmypy src/ scripts/pass.Review follow-up: exact message-class assertions cover both assistant and stream-event frames, including later frames without metadata. Four isolated wrong-class mutations pass the old attribution test and fail the updated one. Documentation was checked against the published TypeScript SDK 0.3.278 types, including attribution updates after queued inputs enter synthetic turns.
AI-assisted with Codex.