Skip to content

Commit 261638f

Browse files
author
SqlRush
committed
Accept fenced provider remote history pages
1 parent 8458d72 commit 261638f

5 files changed

Lines changed: 34 additions & 11 deletions

File tree

docs/cc-100-roadmap.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ M6 补充:remote history event-list 现在接受 `value`/`values`/`resources`/
120120

121121
M6 补充:remote history response parser 现在会解包 `payload`/`response`/`result`/`body` 等通用响应外壳,外壳内的 event list、pagination、links 会继续递归解析。
122122

123-
M6 补充:remote history response parser 现在也接受 provider-style `choices`/`outputs`/`candidates`/`generations` wrapper,可从 `message.content`、content-block array 和 `content.parts[].text` 中恢复 event page JSON,并保留 pagination 继续驱动 `before_id` 续抓。
123+
M6 补充:remote history response parser 现在也接受 provider-style `choices`/`outputs`/`candidates`/`generations` wrapper,可从 `message.content`、content-block array 和 `content.parts[].text` 中恢复 event page JSON(包括 fenced `json` code block),并保留 pagination 继续驱动 `before_id` 续抓。
124124

125125
M6 补充:remote history response parser 现在接受 JSON:API `included` collection,会过滤非事件资源,并递归解包 `resource`/`attributes`/`properties` 后用外层 resource id 作为事件 ID fallback。
126126

@@ -530,7 +530,7 @@ M7 补充:prompt history `LogEntry` 读取现在接受 `sessionID`/`session`/`
530530

531531
本轮补充:compact runner 的 summary 响应现在也接受 provider-style `choices`/`outputs`/`candidates`/`generations` wrapper,可在构建 compact plan 前从 `message.content`、content-block array 和 `content.parts[].text` 中恢复 visible summary text。
532532

533-
本轮补充:remote history response parser 现在也接受 provider-style `choices`/`outputs`/`candidates`/`generations` wrapper,可从 `message.content`、content-block array 和 `content.parts[].text` 中恢复 event page JSON,并保留 pagination 继续驱动 `before_id` 续抓。
533+
本轮补充:remote history response parser 现在也接受 provider-style `choices`/`outputs`/`candidates`/`generations` wrapper,可从 `message.content`、content-block array 和 `content.parts[].text` 中恢复 event page JSON(包括 fenced `json` code block),并保留 pagination 继续驱动 `before_id` 续抓。
534534

535535
本轮补充:microcompact disk cache loader 现在读取 Go 默认、camelCase、snake_case 和相邻实现常见字段别名/包装形态,包括 `result`/`data`/`cache`/`value` wrapper、`content`/`text` summary、`cacheKey`/`key`/`hash` digest、cache-hit 别名、计数字段别名/数字字符串、RFC3339/Unix 秒/Unix 毫秒时间字段,以及 `createdAt` + `ttlSeconds`/`ttlMs`/`expiresIn`/`maxAge` 等相对 TTL 推导,提升 cached microcompact 文件在不同实现/版本间的恢复率。
536536

docs/claude-code-go-rewrite-plan.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ test/parity/ # golden tests against TS/official behavior
214214
- 本轮补充:remote history 在 JSON:API `relationships.events.data` 只有 resource identifier 时,会继续使用 top-level `included` 中的真实事件 resource,避免把 `{type,id}` 标识符误当作空事件遮蔽完整 payload。
215215
- 本轮补充:remote history response parser 现在也接受 JSON:API `included` collection,会过滤非事件资源,并递归解包 `resource`/`attributes`/`properties` 后保留外层 resource id 作为事件 ID fallback。
216216
- 本轮补充:remote history response parser 会解包 `payload`/`response`/`result`/`body` 等通用响应外壳,外壳内的 event list、pagination、links 会继续递归解析。
217-
- 本轮补充:remote history response parser 现在也接受 provider-style `choices`/`outputs`/`candidates`/`generations` wrapper,可从 `message.content`、content-block array 和 `content.parts[].text` 中恢复 event page JSON,并保留 pagination 继续驱动 `before_id` 续抓。
217+
- 本轮补充:remote history response parser 现在也接受 provider-style `choices`/`outputs`/`candidates`/`generations` wrapper,可从 `message.content`、content-block array 和 `content.parts[].text` 中恢复 event page JSON(包括 fenced `json` code block),并保留 pagination 继续驱动 `before_id` 续抓。
218218
- 本轮补充:remote history `SDKEvent` 本体接受 `eventType`/`event_type`/`role` 类型别名、`createdAt`/`created_at` 时间戳别名,以及 `payload`/`data`/`body`/`serializedMessage` message payload 别名;payload 只有 `role`/`content` 时也能 materialize 成 transcript message。
219219
- 本轮补充:transcript resume 的嵌套 content block 接受 `toolUseId`/`toolUseID``isError``cacheControl``cacheReference` 字段别名,并保留 cache edit 的 `cacheReference`
220220
- 本轮补充:transcript resume 的 nested content block `id`/`tool_use_id`/`toolUseId` 现在接受 JSON number,并保留为字符串 tool-use ID。

docs/first-second-parity-audit.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ M6 progress now includes:
143143
- `internal/memory`: session-memory recall and relevant-memory model selectors now recurse through GraphQL/JSON:API selection wrappers such as `data`, `payload`, `body`, `resource`, `attributes`, `properties`, `attrs`, `viewer`, `edge`, `node`, `nodes`, and `edges`, preserving model-ranked session IDs and memory paths from API-shaped responses.
144144
- `internal/memory`: session-memory recall and relevant-memory model selectors now also unwrap provider-style `choices`, `outputs`, `candidates`, and `generations` responses, recovering JSON selection payloads from nested `message.content`, content-block arrays, and `content.parts[].text`.
145145
- `internal/memory`: model-backed memory fact extraction now also unwraps provider-style `choices`, `outputs`, `candidates`, and `generations` responses, recovering JSON facts payloads from nested `message.content`, content-block arrays, and `content.parts[].text`.
146-
- `internal/session`: remote-history response parsing now also unwraps provider-style `choices`, `outputs`, `candidates`, and `generations` responses, recovering event page JSON plus pagination from nested `message.content`, content-block arrays, and `content.parts[].text`.
146+
- `internal/session`: remote-history response parsing now also unwraps provider-style `choices`, `outputs`, `candidates`, and `generations` responses, recovering event page JSON plus pagination from nested `message.content`, content-block arrays, `content.parts[].text`, and fenced `json` code blocks.
147147
- `internal/session`: project session listing and pagination, prompt-history lock/buffered flush/field aliases, lightweight transcript index/title/text-preview inference, line-offset transcript indexing/window/byte-budget-window/parent-chain/resume/tail/byte-budget-tail loading, AI-title/last-prompt/task/agent/PR/worktree transcript metadata loading and type/field aliases, transcript message/session UUID field aliases, tombstone metadata loading with target/session/reason aliases and delete/relink replay, agent-scoped content replacement metadata/record field-alias loading, session-scoped metadata reappend including AI-title/last-prompt/task-summary, streaming transcript search snippets for resume/search UI, official `subagents/agent-*.jsonl` transcript layout with legacy sidechain listing, agent metadata sidecar read/write/field aliases, sidechain runtime start/append/finish/cancel/fail summary bridging plus parent-chain append/finish, sidechain manager orchestration for spawn/append/finish/cancel/fail/list/resume, sidechain state/list/resume support with content-field aliases, sidechain resume context construction, sidechain conversation and agent-scoped content-replacement reconstruction, transcript tail/window loading and byte-budget tail loading for bounded-memory resume/UI paths, lightweight transcript metadata loading, remote-history token refresh retry, page-field/event-list/records/entries/last-id/cursor/event-id/has-next aliases plus wrapped-data/links/paging/bare-array/keyed-event-map responses, before_id resume, fallback field fill, and duplicate-aware parent linking during transcript materialization.
148148
- `internal/session`: transcript full loader and line-offset index now accept top-level record UUID aliases such as `messageUuid`, `messageUUID`, `message_id`, `messageId`, and `id`, plus parent message UUID/ID aliases for progress bridge and indexed resume paths.
149149
- `internal/session`: indexed resume chains now distinguish budget-truncated parents from genuinely missing parents, exposing both markers while preserving bounded transcript reads.

internal/session/remote_history.go

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,8 +1060,8 @@ func remoteHistoryProviderTextFromRaw(raw json.RawMessage, depth int, allowScala
10601060
var text string
10611061
if err := json.Unmarshal(raw, &text); err == nil {
10621062
text = strings.TrimSpace(text)
1063-
if allowScalar && remoteHistoryProviderTextLooksJSON(text) {
1064-
return text, true
1063+
if allowScalar {
1064+
return remoteHistoryProviderJSONPayload(text)
10651065
}
10661066
return "", false
10671067
}
@@ -1081,10 +1081,7 @@ func remoteHistoryProviderTextFromRaw(raw json.RawMessage, depth int, allowScala
10811081
return "", false
10821082
}
10831083
text = strings.Join(parts, "\n")
1084-
if remoteHistoryProviderTextLooksJSON(text) {
1085-
return text, true
1086-
}
1087-
return "", false
1084+
return remoteHistoryProviderJSONPayload(text)
10881085
}
10891086
if raw[0] != '{' {
10901087
return "", false
@@ -1119,6 +1116,32 @@ func remoteHistoryProviderTextLooksJSON(text string) bool {
11191116
return strings.HasPrefix(text, "{") || strings.HasPrefix(text, "[")
11201117
}
11211118

1119+
func remoteHistoryProviderJSONPayload(text string) (string, bool) {
1120+
text = strings.TrimSpace(text)
1121+
if remoteHistoryProviderTextLooksJSON(text) {
1122+
return text, true
1123+
}
1124+
start := strings.Index(text, "```")
1125+
if start < 0 {
1126+
return "", false
1127+
}
1128+
afterFence := text[start+3:]
1129+
lineEnd := strings.IndexAny(afterFence, "\r\n")
1130+
if lineEnd < 0 {
1131+
return "", false
1132+
}
1133+
content := strings.TrimLeft(afterFence[lineEnd:], "\r\n")
1134+
end := strings.Index(content, "```")
1135+
if end >= 0 {
1136+
content = content[:end]
1137+
}
1138+
content = strings.TrimSpace(content)
1139+
if remoteHistoryProviderTextLooksJSON(content) {
1140+
return content, true
1141+
}
1142+
return "", false
1143+
}
1144+
11221145
func jsonNumberString(data []byte) (string, bool) {
11231146
decoder := json.NewDecoder(bytes.NewReader(data))
11241147
decoder.UseNumber()

internal/session/remote_history_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ func TestFetchRemoteHistoryAcceptsProviderResponseWrappers(t *testing.T) {
540540
case "choices":
541541
wrapper = map[string]any{
542542
"choices": []any{map[string]any{
543-
"message": map[string]any{"content": string(pageData)},
543+
"message": map[string]any{"content": "```json\n" + string(pageData) + "\n```"},
544544
}},
545545
}
546546
case "candidates":

0 commit comments

Comments
 (0)