Skip to content

Commit d2be44b

Browse files
author
SqlRush
committed
Unwrap nested remote event payloads
1 parent 702fd1d commit d2be44b

4 files changed

Lines changed: 43 additions & 1 deletion

File tree

docs/cc-100-roadmap.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,8 @@ M7 补充:prompt history `LogEntry` 读取现在接受 `sessionID`/`session`/`
418418

419419
本轮补充:contract image source 解码现在接受 `mediaType`/`mimeType`/`contentType``base64`/`payload` 等 source 字段别名,并支持顶层 image block 直接携带媒体类型和 base64 数据,transcript resume 会保留为规范 `ImageSource`
420420

421+
本轮补充:remote history `SDKEvent` payload materialization 现在会递归解包 `payload`/`data`/`body` 内的 `record`/`entry`/`item`/`event`/`result`/`response`/`output` wrapper,减少远端事件多层包装导致的消息丢失。
422+
421423
### M7: TUI Renderer And Interaction
422424

423425
目标:还原交互式 Claude Code 体验。

docs/first-second-parity-audit.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ M7 progress now includes:
313313
- `internal/tui`: interaction script single-step JSON now unwraps `step`/`scriptStep`/`interactionStep`/`record`/`entry`/`item`/`event` objects in arrays, JSONL records, and wrapper-object step lists.
314314
- `internal/tui`: interaction script top-level wrappers now accept record-array aliases such as `records`/`recordedSteps`/`events`/`entries`/`items`/`actions`/`timeline`.
315315
- `internal/tui`: interaction script loading now recurses through outer API/fixture wrappers such as `data`/`payload`/`body`/`result`/`response`/`recording`/`session`/`run`.
316+
- `internal/contracts`/`internal/session`: remote history `SDKEvent` message extraction now recurses through nested payload wrappers such as `record`/`entry`/`item`/`event`/`result`/`response`/`output`.
316317

317318
Still missing for full M6/M7 parity:
318319

internal/contracts/session.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,23 @@ func sdkEventMessageFromRaw(raw json.RawMessage, eventType SDKEventType) *Messag
305305
if err := json.Unmarshal(raw, &fields); err != nil {
306306
return nil
307307
}
308-
for _, name := range []string{"message", "serialized_message", "serializedMessage", "payload", "data", "body"} {
308+
for _, name := range []string{
309+
"message",
310+
"message_payload",
311+
"messagePayload",
312+
"serialized_message",
313+
"serializedMessage",
314+
"payload",
315+
"data",
316+
"body",
317+
"record",
318+
"entry",
319+
"item",
320+
"event",
321+
"result",
322+
"response",
323+
"output",
324+
} {
309325
if nested := sdkEventMessageFromRaw(fields[name], eventType); nested != nil {
310326
return nested
311327
}

internal/session/remote_history_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,29 @@ func TestRemoteHistoryTranscriptMessagesAcceptsEventPayloadAliases(t *testing.T)
11071107
}
11081108
}
11091109

1110+
func TestRemoteHistoryTranscriptMessagesAcceptsNestedEventPayloadWrappers(t *testing.T) {
1111+
var response sessionEventsResponse
1112+
if err := json.Unmarshal([]byte(`{"events":[
1113+
{"eventType":"user","eventId":"evt_u1","sessionID":"s_nested","createdAt":"2026-01-01T00:00:01Z","payload":{"record":{"role":"user","text":"hi"}}},
1114+
{"eventType":"assistant","eventId":"evt_a1","sessionID":"s_nested","parentMessageID":"evt_u1","createdAt":"2026-01-01T00:00:02Z","data":{"entry":{"role":"assistant","message":"hello"}}}
1115+
]}`), &response); err != nil {
1116+
t.Fatal(err)
1117+
}
1118+
messages := RemoteHistoryTranscriptMessages(response.Events)
1119+
if len(messages) != 2 || messages[0].UUID != "evt_u1" || messages[1].UUID != "evt_a1" {
1120+
t.Fatalf("messages = %#v", messages)
1121+
}
1122+
if messages[0].Message == nil || len(messages[0].Message.Content) != 1 || messages[0].Message.Content[0].Text != "hi" {
1123+
t.Fatalf("user nested payload = %#v", messages[0].Message)
1124+
}
1125+
if messages[1].Message == nil || len(messages[1].Message.Content) != 1 || messages[1].Message.Content[0].Text != "hello" {
1126+
t.Fatalf("assistant nested payload = %#v", messages[1].Message)
1127+
}
1128+
if messages[1].ParentUUID == nil || *messages[1].ParentUUID != "evt_u1" || messages[1].Message.ParentUUID == nil || *messages[1].Message.ParentUUID != "evt_u1" {
1129+
t.Fatalf("parent linkage = %#v message=%#v", messages[1].ParentUUID, messages[1].Message)
1130+
}
1131+
}
1132+
11101133
func TestRemoteHistoryTranscriptMessagesAcceptsNumericIDAliases(t *testing.T) {
11111134
var response sessionEventsResponse
11121135
if err := json.Unmarshal([]byte(`{"events":[{"type":"user","id":101,"sessionId":7,"timestamp":"2026-01-01T00:00:01Z","message":{"type":"user","content":[{"type":"text","text":"hi"}]}},{"type":"assistant","eventId":102,"sessionId":7,"parentMessageID":101,"timestamp":"2026-01-01T00:00:02Z","message":{"type":"assistant","content":[{"type":"text","text":"hello"}]}}]}`), &response); err != nil {

0 commit comments

Comments
 (0)