Repository navigation
fix(pretty): coerce string offset and limit in readCall line range - #2
Conversation
6d5f241 to
a07d28b
Compare
a07d28b to
f78e267
Compare
|
@hypnguyen1209 could you take a look at the two small fix PRs I have open here when you get a chance? Both are one-liner changes with tests attached — details are in each description. |
hypnguyen1209
left a comment
There was a problem hiding this comment.
Good catch and a correct diagnosis: "1" + "2000" concatenates before the - 1 coerces, hence lines 1–11999. The coercion is in the right place (the summary is the only consumer, the public type stays honest), and the regression tests pin the exact shapes you saw from glm-5.3-flash. Typecheck and the full suite (132 tests) pass on your branch locally, and I have approved the CI run.
One non-blocking nit, since the point of this change is that the arguments cannot be trusted: a non-numeric string such as offset: "abc" now renders as lines NaN–NaN. Guarding with Number.isFinite (inline suggestion) keeps a bad value out of the range the same way a missing one is, without changing anything for the cases you fixed. Happy to merge either way.
| const offset = args.offset ? Number(args.offset) : undefined; | ||
| const limit = args.limit ? Number(args.limit) : undefined; |
There was a problem hiding this comment.
| const offset = args.offset ? Number(args.offset) : undefined; | |
| const limit = args.limit ? Number(args.limit) : undefined; | |
| const offset = Number.isFinite(Number(args.offset)) && args.offset ? Number(args.offset) : undefined; | |
| const limit = Number.isFinite(Number(args.limit)) && args.limit ? Number(args.limit) : undefined; |
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,
and treat a value that is not a finite number (a non-numeric string, an object)
as absent, the same as an omitted one.
f78e267 to
2a87183
Compare
|
Guarded with |
- Edit results render from details.patch (pi's unified patch with hunk headers) instead of details.diff, so side-by-side split, word-level emphasis and the old/new gutter finally work for edit; the patch's file headers and trailing newline are stripped so the result matches the pre-apply preview (#1 by @iamxeph). - The read summary coerces string-typed offset/limit before computing the line range, so "1" + "2000" no longer reads as lines 1-11999, and a non-numeric value is left out of the range (#2 by @iamxeph).
Problem
When an LLM provides tool call arguments with string-typed numbers (e.g.
offset: "1",limit: "2000", as observed with models likeglm-5.3-flash), thereadtool summary displays bizarre, inflated line ranges such as:lines 1–11999(foroffset: "1",limit: "2000")lines 1046–1046399(foroffset: "1046",limit: "400")Root Cause
In
src/summary.ts,readCallcalculates the end of the line range as follows:While
argsis 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:
(args.offset ?? 1)evaluates to"1"(string).("1") + args.limitevaluates to"1" + "2000"="12000"(string concatenation due to+associativity)."12000" - 1coerces to a number via subtraction, resulting in11999.Solution
Explicitly coerce
args.offsetandargs.limitto numbers usingNumber()before calculating the range:This prevents string concatenation while preserving the exact original logic and public type definition.
Verification
test/pretty.test.tsverifying string-typed arguments foroffsetandlimit.tsc --noEmit: clean (0 errors).node --test test/pretty.test.ts: all 32 tests passed (0 failed).