Skip to content

Commit 801a939

Browse files
author
SqlRush
committed
Extract inline fenced microcompact summaries
1 parent 12392c2 commit 801a939

6 files changed

Lines changed: 39 additions & 31 deletions

File tree

docs/cc-100-roadmap.md

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

615615
本轮补充:microcompact disk cache loader 现在也接受 provider-style `choices`/`outputs`/`candidates`/`generations`/`results` 等响应数组 wrapper,并可从 `message.content``output.content``content.parts[].text` 和 fenced `json` code block 中恢复 summary,同时保留外层 cache metadata。
616616

617+
本轮补充:microcompact disk cache loader 现在也会解包一行内 fenced JSON summary payload,例如 `json {...}` 与 opening fence 在同一行的 provider/SDK 输出,不再把整段 code fence 当作可见摘要文本。
618+
617619
本轮补充:transcript metadata loader 现在先递归解包 JSON:API/resource、GraphQL edge/node、`included`、collection/list/values 等 wrapper,再做 metadata type 分类;full transcript、lightweight metadata 和 transcript index 都能恢复 wrapped title/task/tag/worktree/content-replacement/context-collapse metadata。
618620

619621
本轮补充:transcript metadata type 现在接受 compact/camel aliases,例如 `aiTitle``lastPrompt``taskSummary``contentReplacement``fileHistorySnapshot``speculationAccept``contextCollapseSnapshot`;full transcript、lightweight metadata 和 transcript index 共用同一归一化。

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ test/parity/ # golden tests against TS/official behavior
332332
- 本轮补充:microcompact disk cache loader 的 summary array 元素现在也接受完整 contract message object,可把 message list 与 content-block 混合数组恢复成可见摘要文本。
333333
- 本轮补充:microcompact disk cache loader 现在会把 `value` 字段中的 text content-block object 识别为 direct summary payload,同时继续从同一 `value` object 中补 digest、version、timestamp 等 cache metadata,避免 `value` 作为 summary/cache wrapper 双义字段时丢摘要或 sidecar 信息。
334334
- 本轮补充:microcompact disk cache loader 现在也接受 provider-style `choices`/`outputs`/`candidates`/`generations`/`results` 等响应数组 wrapper,并可从 `message.content``output.content``content.parts[].text` 和 fenced `json` code block 中恢复 summary,同时保留外层 cache metadata。
335+
- 本轮补充:microcompact disk cache loader 现在也会解包一行内 fenced JSON summary payload,例如 `json {...}` 与 opening fence 在同一行的 provider/SDK 输出,不再把整段 code fence 当作可见摘要文本。
335336
- 本轮补充:contract content block 与 microcompact cache loader 现在把 provider `output_text`/`outputText` content block 归一为可见 text,OpenAI Responses 风格 `output[].content[].type="output_text"` cache payload 可恢复 summary,而 reasoning/tool/image blocks 继续跳过。
336337
- 本轮补充:microcompact disk cache loader 的 summary-like 字段现在也接受 `body``markdown``description`/`details``finalSummary``summaryContent``resultText``completionText``responseText``messageText` 等 direct/provider aliases,并在 nested cache entry、JSON:API/resource 和 provider-style response wrapper 中统一恢复可见摘要文本。
337338

docs/first-second-parity-audit.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@ M7 progress now includes:
550550
- `internal/session`: prompt-history pasted-content containers now accept aliases such as `pastedContent`/`pasted_content`, `pasteContents`/`paste_contents`, `pastes`, and `attachments`/`attachment`, matching interaction script fixture shapes for runtime and stored history.
551551
- `internal/session`: prompt-history pasted image loading now accepts content-block-style `source`/`imageSource` objects, nested JSON:API/GraphQL-style source wrappers, data URL aliases, and source URL/URI/cache-path aliases; stored image entries with inline source data or a current-session image-cache file now restore base64 content into prompt image blocks instead of keeping only metadata, including same-ID cache fallback, media-type inference when history metadata omits the original MIME type, symlink escape guards before reading cached image bytes, and restored path re-indexing for later image metadata/source lookup.
552552
- `internal/compact`: microcompact disk cache loading now accepts broader summary-like direct and provider aliases including `body`, `markdown`, `description`/`details`, `finalSummary`, `summaryContent`, `plainText`/`displayText`, `answerText`, `refusal`, `resultText`, `completionText`, `responseText`, and `messageText`; provider summary recovery also follows wrapper-only `value`/`payload`/`data` chains without failing on non-summary metadata, preserving visible summaries through nested cache entries, JSON:API/resource envelopes, and provider-style response wrappers.
553+
- `internal/compact`: microcompact provider and cache summary extraction now unwraps inline fenced JSON payloads where the fence language and JSON object are on the same line, so SDK/model outputs no longer preserve the whole code fence as visible summary text.
553554

554555
Still missing for full M6/M7 parity:
555556

internal/compact/compact_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,10 @@ func TestLoadMicroResultAcceptsProviderStyleResponseWrappers(t *testing.T) {
888888
if err != nil {
889889
t.Fatal(err)
890890
}
891+
inlineFencedSummary, err := json.Marshal("```json {\"summary\":\"choice inline fenced summary\"} ```")
892+
if err != nil {
893+
t.Fatal(err)
894+
}
891895
for _, tc := range []struct {
892896
digest string
893897
payload string
@@ -950,6 +954,22 @@ func TestLoadMicroResultAcceptsProviderStyleResponseWrappers(t *testing.T) {
950954
}`,
951955
want: "choice fenced summary",
952956
},
957+
{
958+
digest: "choices-inline-fenced-message",
959+
payload: `{
960+
"choices": [
961+
{
962+
"message": {
963+
"content": ` + string(inlineFencedSummary) + `
964+
}
965+
}
966+
],
967+
"cacheKey": "choices-inline-fenced-message",
968+
"cacheVersion": "microcompact.v1",
969+
"createdAt": 100
970+
}`,
971+
want: "choice inline fenced summary",
972+
},
953973
{
954974
digest: "output-message",
955975
payload: `{
@@ -1574,6 +1594,7 @@ func TestRunnerAcceptsProviderWrappedSummaryResponses(t *testing.T) {
15741594
}
15751595
}]
15761596
}` + "\n```",
1597+
"choices_inline_fenced_message_content": "```json " + `{"choices":[{"message":{"content":[{"type":"text","text":"provider inline fenced summary"}]}}]}` + " ```",
15771598
"candidate_parts_text": `{
15781599
"candidates": [{
15791600
"content": {

internal/compact/micro.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -751,11 +751,7 @@ func microSummaryTextJSONPayload(text string) (string, bool) {
751751
return "", false
752752
}
753753
afterFence := text[start+3:]
754-
lineEnd := strings.IndexAny(afterFence, "\r\n")
755-
if lineEnd < 0 {
756-
return "", false
757-
}
758-
content := strings.TrimLeft(afterFence[lineEnd:], "\r\n")
754+
content := strings.TrimSpace(afterFence)
759755
end := strings.Index(content, "```")
760756
if end >= 0 {
761757
content = content[:end]
@@ -764,6 +760,18 @@ func microSummaryTextJSONPayload(text string) (string, bool) {
764760
if strings.HasPrefix(content, "{") || strings.HasPrefix(content, "[") {
765761
return content, true
766762
}
763+
if lineEnd := strings.IndexAny(content, "\r\n"); lineEnd >= 0 {
764+
candidate := strings.TrimSpace(strings.TrimLeft(content[lineEnd:], "\r\n"))
765+
if strings.HasPrefix(candidate, "{") || strings.HasPrefix(candidate, "[") {
766+
return candidate, true
767+
}
768+
}
769+
if fieldEnd := strings.IndexAny(content, " \t"); fieldEnd >= 0 {
770+
candidate := strings.TrimSpace(content[fieldEnd:])
771+
if strings.HasPrefix(candidate, "{") || strings.HasPrefix(candidate, "[") {
772+
return candidate, true
773+
}
774+
}
767775
return "", false
768776
}
769777

internal/compact/runner.go

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -168,30 +168,5 @@ func providerWrappedSummaryText(raw string) (string, bool) {
168168
}
169169

170170
func providerWrappedSummaryPayload(raw string) (string, bool) {
171-
raw = strings.TrimSpace(raw)
172-
if raw == "" {
173-
return "", false
174-
}
175-
if raw[0] == '{' || raw[0] == '[' {
176-
return raw, true
177-
}
178-
start := strings.Index(raw, "```")
179-
if start < 0 {
180-
return "", false
181-
}
182-
afterFence := raw[start+3:]
183-
lineEnd := strings.IndexAny(afterFence, "\r\n")
184-
if lineEnd < 0 {
185-
return "", false
186-
}
187-
content := strings.TrimLeft(afterFence[lineEnd:], "\r\n")
188-
end := strings.Index(content, "```")
189-
if end >= 0 {
190-
content = content[:end]
191-
}
192-
content = strings.TrimSpace(content)
193-
if content == "" || (content[0] != '{' && content[0] != '[') {
194-
return "", false
195-
}
196-
return content, true
171+
return microSummaryTextJSONPayload(raw)
197172
}

0 commit comments

Comments
 (0)