Skip to content

fix(pretty): coerce string offset and limit in readCall line range - #2

Open
iamxeph wants to merge 1 commit into
pifydev:mainfrom
iamxeph:fix/read-line-range-coercion
Open

iamxeph wants to merge 1 commit into
pifydev:mainfrom
iamxeph:fix/read-line-range-coercion

Conversation

@iamxeph

@iamxeph iamxeph commented Sep 29, 2026

Copy link
Copy Markdown

Problem

When an LLM provides tool call arguments with string-typed numbers (e.g. offset: "1", limit: "2000", as observed with models like glm-5.3-flash), the read tool summary displays bizarre, inflated line ranges such as:

  • lines 1–11999 (for offset: "1", limit: "2000")
  • lines 1046–1046399 (for offset: "1046", limit: "400")

Root Cause

In src/summary.ts, readCall calculates the end of the line range as follows:

const range =
  args.offset || args.limit
    ? theme.fg("dim", ` · lines ${args.offset ?? 1}${args.limit ? `–${(args.offset ?? 1) + args.limit - 1}` : "+"}`)
    : "";

While args is typed as { offset?: number; limit?: number }, TypeScript types are erased at runtime. Tool call arguments deserialized from LLM responses may carry string values.
In JavaScript:

  1. (args.offset ?? 1) evaluates to "1" (string).
  2. ("1") + args.limit evaluates to "1" + "2000" = "12000" (string concatenation due to + associativity).
  3. "12000" - 1 coerces to a number via subtraction, resulting in 11999.

Solution

Explicitly coerce args.offset and args.limit to numbers using Number() before calculating the range:

const offset = args.offset ? Number(args.offset) : undefined;
const limit = args.limit ? Number(args.limit) : undefined;
const range =
  offset || limit
    ? theme.fg("dim", ` · lines ${offset ?? 1}${limit ? `–${(offset ?? 1) + limit - 1}` : "+"}`)
    : "";

This prevents string concatenation while preserving the exact original logic and public type definition.

Verification

  • Added regression tests in test/pretty.test.ts verifying string-typed arguments for offset and limit.
  • Ran tsc --noEmit: clean (0 errors).
  • Ran node --test test/pretty.test.ts: all 32 tests passed (0 failed).

When LLMs pass tool arguments with string-typed numbers (e.g. offset: "1",
limit: "2000"), JavaScript evaluates `("1" + "2000") - 1` as `11999`
instead of `2000`, causing bizarre line ranges like "lines 1–11999".

Explicitly parse numeric arguments with Number() before calculating the range.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant