fix(sequentialthinking): harden thought-box rendering and validation#4100
Open
1060996408 wants to merge 2 commits intomodelcontextprotocol:mainfrom
Open
Conversation
…ield validation formatThought: - pad the header row so its right border lines up with the rest of the box (previously hung in mid-air when the thought was longer than the header) - account for chalk's ANSI escape bytes when measuring header width - render multi-line thoughts as one row per line, expand tabs to a fixed width so terminal tab stops can't break the right border - wrap thought lines whose display width exceeds 80 columns at grapheme boundaries, so the box never overflows a typical terminal - new displayWidth helper uses Intl.Segmenter to count terminal columns correctly for CJK ideographs, SMP-plane emoji (💭🔄🌿), ZWJ-joined emoji like 👨💻, and VS-16 variation selectors processThought: - stop mutating the caller-supplied input object when auto-adjusting totalThoughts; work on a local copy and report the adjusted value in the response as before new validateThoughtData: - cross-field semantic checks Zod's field-level shape can't express: revisesThought is required (and must precede thoughtNumber) when isRevision is true; same for branchFromThought / branchId lib.ts line coverage: 84.93% → 100%. Tests in lib.test.ts: 14 → 41. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ire validator - read the server version from package.json at startup so MCP clients see the same version that npm publishes; previously the McpServer was constructed with a hardcoded "0.2.0" while package.json had drifted to 0.6.2. - extract the tool handler into a named, exported handleSequentialThinkingTool so tests can exercise the SDK-facing contract (structuredContent shape, isError pass-through) without booting the stdio server. - guard runServer() with an ESM "is main module" check so importing index.ts from a test file does not auto-start the stdio loop. - call the new validateThoughtData up-front so cross-field violations return a well-formed isError response instead of silently rendering "(revising thought undefined)" or dropping branch data on the floor. Adds a new __tests__/index.test.ts covering the success path, isError pass-through, and the two validator failure modes. index.ts line coverage: 0% → 80%. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Hardens the
sequentialthinkingreference server against several real-world inputs that currently render incorrectly or are silently ignored, and reports the right package version to MCP clients.Server Details
sequentialthinkingformatThoughtrendering,processThoughtAPI contract, server version reporting, cross-field input validationMotivation and Context
While reading through the smallest reference server, the existing test output itself revealed alignment problems in the rendered thought box. Pulling the thread surfaced 11 distinct issues, all in
lib.ts/index.ts:formatThought│of the header line hung in mid-air.formatThoughtheader.lengthincluded chalk's ANSI escape bytes, inflating the computed border width.formatThought\nbroke the box layout (subsequent lines escaped the right border).displayWidth(new)displayWidth💭🔄🌿— the prefixes the server itself emits) were counted as 1 column.displayWidth👨💻were counted as 5 columns instead of 2.formatThought\tcharacters were emitted verbatim; terminals advance to the next tab stop and broke the right border.formatThoughtprocessThoughttotalThoughtsmutated the caller-supplied input object.index.tsMcpServerwas constructed with a hardcoded"0.2.0"whilepackage.jsonhad drifted to0.6.2, so clients saw a stale version inserverInfo.isRevision: truewithoutrevisesThoughtsilently rendered(revising thought undefined);branchFromThoughtwithoutbranchIdsilently dropped the branch entry.How Has This Been Tested?
npm testinsrc/sequentialthinking— 46 / 46 passing (was 14 / 14 before)npm run build— clean under TypeScript strict modeserverInfo.versioncorrectly reports0.6.2, andtools/callwithisRevision: trueand norevisesThoughtreturns a well-formedisErrorresponse ("revisesThought is required when isRevision is true") instead of rendering(revising thought undefined).Coverage gain:
lib.ts: 84.93 % → 100 % line, 91.35 % branchindex.ts: 0 % → 80 % line (handler is now extracted and tested)Breaking Changes
None. All changes are backward-compatible:
thoughtHistorycontent are unchanged.isErrorresponses. A client that was relying on the broken behaviour would have been seeing nonsense; the new error message points at the actual problem.Types of changes
validateThoughtDataChecklist
.jsimport suffix)Additional context
Intl.Segmenter— no new dependencies.displayWidthandwrapToWidthare exported fromlib.tsso they are independently unit-tested and could be reused by other servers if useful.index.tsis now an exportedhandleSequentialThinkingToolfunction. The auto-start ofrunServer()is guarded by an ESMimport.meta.url === pathToFileURL(process.argv[1]).hrefcheck so importing the module in tests does not boot the stdio loop.fix(sequentialthinking): harden thought-box rendering and add cross-field validation— alllib.tschangesrefactor(sequentialthinking): sync server version, extract handler, wire validator— allindex.tschanges🤖 Generated with Claude Code