Add typed item lifecycle events to the cloud client (#59066)

## What changed

Decode live item start and completion notifications as `TranscriptUpdate::ItemStarted` and `TranscriptUpdate::ItemCompleted`, with turn identity, lifecycle timestamps, and summaries for user messages, agent messages, reasoning, commands, and file changes.

Preserve structured agent questions even when message text is empty, optional command output and exit details, and command or patch status independently of lifecycle completion. Keep unsupported or incomplete items as opaque notifications and redact summary fields in debug output.

## Testing

Add fixtures covering lifecycle ordering alongside deltas, identity and timestamps, status and optional-field preservation, structured questions, opaque fallback, malformed payloads, thread ownership, and debug redaction.

GitOrigin-RevId: d6bf2d25ee85be17d895726c5072850a9851b55f
This commit is contained in:
Benjamin Carlsson
2026-11-03 05:43:27 +00:00
committed by copyberry
parent dbaead0106
commit 7ee5efad4a
9 changed files with 848 additions and 20 deletions
@@ -160,6 +160,10 @@ async fn attach_preserves_opaque_notifications_and_continues() {
let foreign_turn = b"\x0a\x01x\x12\x05\x22\x01u\x40\x01";
let opaque = [
message(/*tag*/ 100, b"unknown notification"),
notification(
/*tag*/ 27,
b"\x0a\x02\x4a\x00\x10\x03\x1a\x01t\x22\x01u",
), // Unsupported MCP item.
notification(/*tag*/ 21, foreign_turn),
notification(/*tag*/ 23, foreign_turn),
notification(/*tag*/ 32, &DELTA[..9]), // missing turn ID
@@ -288,3 +292,6 @@ fn notification_selection_handles_many_fragments_and_obsolete_malformed_messages
payload.extend(message(/*tag*/ 89, b"\xff"));
assert!(TranscriptEvent::decode("t", &payload).unwrap().is_none());
}
#[path = "item_tests.rs"]
mod items;