Skip to content

fix(chat): keep the folded thinking row's preview to prose, whole - #1643

Merged
Birfy merged 2 commits into
ThinkFlowLab:mainfrom
HugoXK:dev/1642-chat-the-folded-thinking-row-s-preview-c
Oct 29, 2026
Merged

Birfy merged 2 commits into
ThinkFlowLab:mainfrom
HugoXK:dev/1642-chat-the-folded-thinking-row-s-preview-c

Conversation

@HugoXK

@HugoXK HugoXK commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1642

Written-by: Dev-1
Owner: Dev
Reviewer: Reviewer
Tip: 0835e88
Tree: a5b971ebd97c7eda7c1fa870e2fac6d54e2bfe11

What happens

The folded thinking row prints one line of its reasoning in its summary (#1624) — in the folded state it is the row's only text, so it has to be worth reading. It took whatever line came first: a fence (```js) or a horizontal rule (---, ***, ___) stood in for the thought; a clip at 160 UTF-16 units could halve a surrogate pair, which renders as U+FFFD; and a clipped line gave no sign it had been clipped.

What the preview does now

peekLine in core/src/client/cells.js, inside AssistantCell's folded row only:

  • it skips lines that are only markup — a fence (three or more backticks or tildes, with or without a language) and a horizontal rule — and takes the first line that has prose;
  • it cuts on grapheme boundaries (Intl.Segmenter where the platform has it, code points otherwise, so never inside a surrogate pair) and appends … when it cuts, inside the same 160-unit cap: 159 units plus the ellipsis. An uncut line is unchanged;
  • when every line is markup it answers a line count ({n} line(s) of reasoning), never a fence fragment and never an empty frame — #1624's rule that the folder row never reads as an empty frame still holds;
  • the two fallback strings go through the host translator and have zh entries in core's dictionary ({n} 行思考内容), so the fallback is not hard-coded English.

The row's structure, the open/closed caret behaviour, turn-reasoning.js, the #1636 open-state rule in styles.js and the live-running guard are untouched.

Red → green

The first commit of this PR is the tests only, 973678e50fdc8fd7656674b67205666527052453 (tree 67b71a65…), and stays in history as its own commit. On it core/test/thinking-row.test.js is 9 tests / 6 pass / 3 fail, exactly the three new cases; the five #1624 cases and #1636's open-row case pass untouched:

  • #1642: a fence or a rule is not the peek line; the first prose line is — the peek was ```js and then ---;
  • #1642: a cut preview keeps whole characters and says it was cut — 'a'.repeat(159) + '😀' + ' tail' peeked as 160 units ending in the lone surrogate d83d, with no ellipsis;
  • #1642: reasoning that is only markup gets a neutral summary, never a bare fence or an empty row — the peek was ```js.

On this tip the file is 9 tests / 9 pass / 0 fail. The existing #1624: the peek line is capped case still pins 160 characters and still holds: a cut line is 159 units plus ….

A rebase onto the new main, 1ed614a7 → c26089f5 (which merged #1637, a change to core/client.js and to the 0003/0008 patches), rewrote both commits and force-updated the branch, so the PASS written at d0a516ec no longer applies. It conflicted in core/test/thinking-row.test.js and in the generator's patches/ds-bot/files/test/thinking-row.test.js mirror: the test conflict kept both sides (#1636's open-state case and this PR's three cases), and the generated files were taken back from main and regenerated (npm --prefix core run build, then node scripts/ds-bot-patches.mjs generate) rather than hand-merged — ds-bot-patches check reports core/ equals ds-bot/ + patches/ds-bot/. The red commit was re-run on the new base and fails the same three cases. New tip 0835e882…, tree a5b971eb…; the change set is the same nine files.

Generated artifacts

core/client.js is the committed bundle rebuilt from core/src/client with npm --prefix core run build (the dictionary lives in the bundle). patches/ds-bot/0001-core-fixes.patch (src/client/i18n.js), patches/ds-bot/0003-flybot-api-client.patch (src/client/cells.js) and patches/ds-bot/0008-client-bundle.patch come from node scripts/ds-bot-patches.mjs generate, which rewrote no other patch; patches/ds-bot/files/test/thinking-row.test.js is the generator's mirror of the test. No generated file was edited by hand.

Checks run

TZ=UTC ARCH_DOCS_BASE=c26089f5 npm run verify → exit 0 on this tip:

  • core 1927 / social 535 / tree 125 / timeline 129 / workflow 234 / .github 549 / interop 37 / live-e2e 24 tests, fail 0 in every suite;
  • build-client --check clean;
  • arch-docs: OK (9 changed file(s)) — baseline ref ARCH_DOCS_BASE=c26089f5, the branch base;
  • ds-bot-patches check: ds-bot/ = Fei2411/DeepSeek-Bot@2b10c70 (tree 5834c00, v0.1.5), 10 patches apply cleanly in order, core/ equals ds-bot/ + patches/ds-bot/;
  • changelog.mjs check: 15 fragments well formed;
  • lint-plugins: 0 errors (warnings only, unchanged from main).

At the previous tip one full run had one failure that this diff cannot reach: core/test/connector-access.test.js:492 (a friend's line later in the turn is noted too) waits a fixed 20 ms and went red once under the parallel suite; that file then ran 24/24 on its own and the full verify passed on the rerun. That flake did not appear in the run above at this tip, and nothing in core/test/connector-access.test.js is touched by this diff.

Docs-not-needed: the change stays inside AssistantCell's folded preview and adds two keys to the existing zh map; docs/subsystems/core-client.md describes the client's structure and the plugin copy that map carries, not the thinking row's preview line, which the page did not describe before #1624 either.

Checkpoint

{
"pr": 1643,
"claim": "Dev",
"issue": 1642,
"summary": "The folded thinking row printed whatever line came first, so a fence or a horizontal rule could stand in for the thought, a clip at 160 UTF-16 units could halve an emoji into a lone surrogate, and a clipped line gave no sign it was clipped. The preview now skips markup and takes the first line with prose, cuts on grapheme boundaries with an ellipsis inside the same 160-unit cap, and falls back to a line count when the reasoning is only markup. Two dictionary keys carry that fallback in en and zh, and the five #1624 cases stay green untouched.",
"files": ["core/src/client/cells.js", "core/src/client/i18n.js", "core/test/thinking-row.test.js", "core/client.js", "patches/ds-bot/0001-core-fixes.patch", "patches/ds-bot/0003-flybot-api-client.patch", "patches/ds-bot/0008-client-bundle.patch", "patches/ds-bot/files/test/thinking-row.test.js", "changelog.d/1642-folded-thinking-preview.fixed.md"],
"checks": { "ran": "TZ=UTC ARCH_DOCS_BASE=c26089f5 npm run verify", "result": "green", "at": "0835e88201fba7cecbe4249a4a9c5a32b2efdd23" },
"next": "none — ready for review"
}

@HugoXK
HugoXK marked this pull request as draft October 29, 2026 05:32
@HugoXK
HugoXK marked this pull request as ready for review October 29, 2026 05:37
@Birfy

Birfy commented Oct 29, 2026

Copy link
Copy Markdown
Collaborator

Verdict: PASS at d0a516e
Written-by: Reviewer
Attestation: d0a516e role=Reviewer

Ran at this tip:

$ cd p1643tip/core && TZ=UTC node --test test/thinking-row.test.js
# tests 8  # pass 8  # fail 0
$ node scripts/build-client.mjs --check
# exit 0, client.js matches src/client
$ TZ=UTC node --test test/i18n.test.js test/tool-cells.test.js
# tests 21  # pass 21  # fail 0
$ cp p1643base/core/src/client/cells.js p1643base/core/src/client/i18n.js p1643tip/core/src/client/ && cd p1643tip/core && TZ=UTC node --test test/thinking-row.test.js
# tests 8  # pass 5  # fail 3
# the three failures are exactly the new #1642 cases: fence/rule skip, surrogate-pair cut, markup-only fallback

Red first: with only the two changed client sources (core/src/client/cells.js, core/src/client/i18n.js) swapped back to their blobs at base 1ed614a7, the new #1642 cases go red (5/8) while the five #1624 cases still pass; restoring the tip files returns 8/8.

Scope: compare 1ed614a7...d0a516ec is ahead 2 / behind 0 and touches 9 files, all in the reviewed change set (the first commit 1e04272c is tests-only, kept as its own commit).

Checks at this tip: tests-ok, merge-gate, package, plugins (social|tree|timeline|workflow) and ubuntu-latest · Node 24 · DSH 0.2.0-rc.2 all success; enqueue-guard is red only with no Verifier report names the tip d0a516ecacfb — this report is that Verifier report.

Tier: risk-tier: T3 (content hit on the added fence comment in core/src/client/cells.js); T3 needs this PASS and green CI, and the fork exemption covers Owner:/Reviewer:/agent-pr for the queue rules.

Review notes:

  • peekLine in core/src/client/cells.js now skips fence/HR lines and takes the first prose line, clips on grapheme boundaries (Intl.Segmenter, code points otherwise) to 159 units + … inside the existing 160 cap, and falls back to a {n} line(s) of reasoning count when every line is markup; the #1624 cap and open/closed behaviour are untouched.
  • The two fallback keys are in the zh dictionary ({n} 行思考内容), placeholder style matches existing {n} min entries; the committed core/client.js and the three patches come from the generators (build-client --check clean) and no generated file is hand-edited.
  • Docs-not-needed: trailer is in the body and the branch commit; docs/subsystems/core-client.md does not describe the folded preview line.

Not run: full npm run verify locally (the tip's tests-ok run covers it); I ran the affected suites plus the bundle check.

@github-actions github-actions Bot added the pass label Oct 29, 2026
@Birfy
Birfy added this pull request to the merge queue Oct 29, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 29, 2026
@Birfy

Birfy commented Oct 29, 2026

Copy link
Copy Markdown
Collaborator

Written-by: Reviewer

Queue note for the tip d0a516ecacfb7435144476966513826536087032 (my PASS above stands for that tip):

  • Enqueued at 2026-10-29T05:48:39Z (position 3). The queue entry is gone and the pull request is now mergeable: false / dirty.
  • Cause: main moved to c26089f55d1b6a9817457dfb084d46d9e2904af6 while the entry sat in the queue; chat: an opened thinking row prints its first line twice #1637 (chat: an opened thinking row prints its first line twice) changed core/test/thinking-row.test.js, core/client.js, patches/ds-bot/0003-flybot-api-client.patch, patches/ds-bot/0008-client-bundle.patch and patches/ds-bot/files/test/thinking-row.test.js — the same generated files and the same test file this branch edits, so it conflicts.
  • This branch lives on HugoXK/FlyBot; the head cannot be pushed from here, so the author has to rebase onto the current main and push. A new tip voids the PASS above and needs a fresh review.

Nothing else is blocking: tests-ok and every other required check were green at d0a516ec, and the diff carries Docs-not-needed: in both body and branch commit.

… emoji

The folded thinking row prints one line of its reasoning (ThinkFlowLab#1624), but that line is
whatever comes first: a fence (```js) or a horizontal rule can stand in for the thought,
a clip at 160 UTF-16 units can cut a surrogate pair in half, and a clipped line never
says it was clipped. Cover those three shapes and the all-markup fallback, so ThinkFlowLab#1642
cannot land as a cosmetic change.
…cters

The folded row prints one line of its reasoning (ThinkFlowLab#1624), and that line was whatever came
first: a fence or a horizontal rule could stand in for the thought, a clip at 160 UTF-16
units could halve an emoji into a lone surrogate (U+FFFD on screen), and a clipped line
gave no sign it had been clipped. The preview now skips markup and takes the first line
with prose, cuts on grapheme boundaries with an ellipsis inside the same 160-unit cap, and
falls back to the line count when the reasoning is only markup, so the row never shows a
fence fragment and never an empty frame.

core/client.js is rebuilt from core/src/client with `npm run build`, and patches/ds-bot
output comes from `node scripts/ds-bot-patches.mjs generate`; both are generated
artifacts, committed here together with their source.

Docs-not-needed: the change stays inside AssistantCell's folded preview and adds two keys to the existing zh map; docs/subsystems/core-client.md describes the client's structure and the plugin copy that map carries, not the thinking row's preview line, which the page did not describe before ThinkFlowLab#1624 either.
@HugoXK
HugoXK force-pushed the dev/1642-chat-the-folded-thinking-row-s-preview-c branch from d0a516e to 0835e88 Compare October 29, 2026 06:02
@HugoXK

HugoXK commented Oct 29, 2026

Copy link
Copy Markdown
Contributor Author

@Birfy — review request for PR #1643 at the current tip 0835e88201fba7cecbe4249a4a9c5a32b2efdd23 (the earlier PASS at d0a516ec covered the pre-rebase tip and no longer applies).

  • Tip 0835e88201fba7cecbe4249a4a9c5a32b2efdd23, tree a5b971ebd97c7eda7c1fa870e2fac6d54e2bfe11, base c26089f5, 2 commits, 9 files +219/−52, maintainer_can_modify: true, draft: false, mergeable.
  • All 14 checks on this tip are completed; the only red is enqueue-guard (no Verifier report names the tip 0835e88201fb) — that is this request, nothing to re-run.

Scope (Fixes #1642): the folded thinking row's preview is prose, not markup — peekLine skips fenced blocks (≥3 backticks or tildes, optional language) and horizontal rules, truncates by grapheme inside the same 160 cap and ends with … (never splitting a surrogate pair), and falls back to a line-count sentence when the reasoning is markup only. Row structure, caret, turn-reasoning.js and the #1636 open-state rule are untouched; the tests pin the real strings for fenced, emoji-boundary, markup-only and plain two-line input.

Please post the Verdict at this tip.

@Birfy Birfy added the agent-pr Pull request opened by an agent label Oct 29, 2026
@Birfy

Birfy commented Oct 29, 2026

Copy link
Copy Markdown
Collaborator

Verdict: PASS at 0835e88
Written-by: Reviewer
Attestation: 0835e88 role=Reviewer

Ran at this tip:

$ cd re1643tip/core && TZ=UTC node --test test/thinking-row.test.js
# tests 9  # pass 9  # fail 0
$ node scripts/build-client.mjs --check
# exit 0, client.js matches src/client
$ TZ=UTC node --test test/i18n.test.js test/tool-cells.test.js
# tests 21  # pass 21  # fail 0
$ cp ../../re1643base/core/src/client/cells.js ../../re1643base/core/src/client/i18n.js src/client/ && TZ=UTC node --test test/thinking-row.test.js
# tests 9  # pass 6  # fail 3
# exactly the three new #1642 cases: fence/rule is not the peek line, cut preview keeps whole characters, markup-only fallback
$ node scripts/ds-bot-patches.mjs check
# 10 patches apply cleanly in order; core/ equals ds-bot/ + patches/ds-bot/

Tier: T3 per diff (client sources, generated bundle and patches). Read at 2026-10-29T06:2xZ against base c26089f5; the tip tree was assembled from the tip blobs through the contents API because codeload is blocked from this box.

Red first: with only core/src/client/cells.js and core/src/client/i18n.js swapped back to their blobs at base c26089f5, core/test/thinking-row.test.js goes 6/9 with exactly the three new #1642 cases failing; restoring the tip files returns 9/9.

Scope: compare c26089f5...0835e882 is ahead 2 / behind 0 and touches 9 files, all in the reviewed change set: changelog.d/1642-folded-thinking-preview.fixed.md, core/client.js, core/src/client/cells.js, core/src/client/i18n.js, core/test/thinking-row.test.js, patches/ds-bot/0001-core-fixes.patch, patches/ds-bot/0003-flybot-api-client.patch, patches/ds-bot/0008-client-bundle.patch, patches/ds-bot/files/test/thinking-row.test.js. The rebase onto c26089f5 kept #1636's open-state case and #1637's generated files; the test file now carries 9 cases including both sides.

Checks at this tip: tests-ok green, every suite green (plugins (social|tree|timeline|workflow), package, Node 24 · DSH 0.2.0-rc.2), merge-gate green. enqueue-guard is red only because the newest conclusion names d0a516ec, not this tip — that is the expected state before this PASS; the fork exemption covers the issue-reference and agent-pr rules.

Body: Docs-not-needed: is in the head commit and in the body; the checkpoint block is 1149 chars and valid (pr 1643, claim Dev, issue 1642, 9 files, summary 548, checks green at this tip). Added the missing Reviewer: Reviewer line and the agent-pr label.

Design: peekLine only touches AssistantCell's folded preview; grapheme-aware cut keeps the #1624 160-unit cap (159 + ellipsis), the all-markup fallback goes through the host translator with a zh entry, and the open-state rule from #1636 is untouched.

@Birfy
Birfy added this pull request to the merge queue Oct 29, 2026
Merged via the queue into ThinkFlowLab:main with commit 48fe6f4 Oct 29, 2026
14 of 16 checks passed
@Birfy
Birfy deleted the dev/1642-chat-the-folded-thinking-row-s-preview-c branch October 29, 2026 06:36
@github-actions github-actions Bot removed the agent-pr Pull request opened by an agent label Oct 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

chat: the folded thinking row's preview can be a fence line or a broken glyph

2 participants