Skip to content

Commit fc68e85

Browse files
author
weiesky.wangc
committed
feat(chat): support Claude Code 2.x JSONL transcripts with tool_result images (1.7.15)
- feat: v2-transcript-normalizer converts new top-level-message JSONL into legacy entries (per-session grouping, /clear segmentation, message.id assistant-row merging, uuid dedup), wired into cold/local/live ingest; base64 tool_result images render via the existing extractToolResultImages chain - fix: live split-row merged tool_use blocks re-paired via _toolUses (label/input/Read/Edit state no longer lost); live /clear keeps the entry.timestamp === messages[0]._timestamp invariant and skips empty snapshots; string-content assistant rows merge without dropping content - ui: tool-result images open the full-screen ImageLightbox (ToolResultView + simplified-mode inline under the tool pill, memoized); oversized placeholder unified via formatOversizedImagePlaceholder - fix: synthetic entries no longer render undefined status/method; per-message timestamps survive applyBatchEntryTimestamps; delta-reconstructor excludes _syntheticV2 repair candidates - test: 4 new test files (normalizer/incremental/image-pipeline/should-inline) + guards in delta-reconstructor/timestamp-assignment/client-safe-imports; all suites green
1 parent 8c8b96e commit fc68e85

22 files changed

Lines changed: 1505 additions & 59 deletions

history.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## 1.7.15 (2026-08-03)
4+
5+
- feat(chat): **render tool_result images from Claude Code 2.x session logs** — new `server/lib/v2-transcript-normalizer.js` (CLIENT-SAFE) converts the new top-level-`message` JSONL format into legacy entries (per-session grouping, `/clear` segmentation, `message.id` assistant-row merging, `uuid` dedup), wired into cold/local/live ingest. The existing `extractToolResultImages``ToolResultView` chain then renders base64 images unchanged.
6+
- ui(chat): **tool-result images open the full-screen ImageLightbox** — click-to-zoom (ChatImage pattern), `cursor: zoom-in`.
7+
- ui(chat): **simplified mode inlines tool-result images** — with "show full tool content" off, tool results with images render them directly under the tool pill (memoized, `loading="lazy"`); the hover preview keeps the truncated text only. New `shouldInlineToolImages` / `formatOversizedImagePlaceholder` predicates unify the oversized placeholder across ToolResultView and the pill.
8+
- fix(chat): synthetic entries no longer render "undefined" status/method; per-message timestamps survive `applyBatchEntryTimestamps` so v2 bubbles keep real times and the "view request" jump works.
9+
310
## 1.7.14 (2026-08-01)
411

512
- prompt(kimi): **anti-loop guardrails in the Kimi system-prompt presets**`kimi-k3` and `kimi-k2.7-code` gain self-regulation rules: one wide read over many small reads, a hard "same file twice → never a third time" repetition check that names the offset/limit re-read pattern, a convergence budget (partial report beats endless exploration), and a forced self-assessment line every ten tool calls. Real-trace evidence: a K3 reviewer subagent read `src/App.jsx` 251 times oscillating `limit 40↔50` at the same offset, emitting zero text across 342 turns.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cc-viewer",
3-
"version": "1.7.14",
3+
"version": "1.7.15",
44
"description": "Claude Code logging, visualization, and management toolkit — launch a web viewer alongside Claude Code with full request/response tracing, proxy, and mobile support",
55
"license": "MIT",
66
"main": "server.js",

server/lib/delta-reconstructor.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,9 @@ export function reconstructEntries(entries) {
244244
*/
245245
function _tryRepairFromCandidate(brokenEntry, expectedCount, candidate) {
246246
if (!candidate.mainAgent || candidate.teammate || !Array.isArray(candidate.body?.messages)) return false;
247+
// V2 transcript synthetic entries are never a valid repair source for legacy
248+
// delta rows — their messages are a different conversation's content.
249+
if (candidate._syntheticV2) return false;
247250
const candidateMsgs = candidate.body.messages;
248251
const candidateTotal = candidate._totalMessageCount || candidateMsgs.length;
249252
const isFullEntry = !candidate._deltaFormat || isCheckpointEntry(candidate);

0 commit comments

Comments
 (0)