fix: reject non-finite numbers before they reach _meta
`StrictJsonValue` removed `undefined`, but the type cannot express the rest of
the gap: TypeScript has one `number`, and JSON has no encoding for `NaN` or
`±Infinity`, so `JSON.stringify` rewrites them to `null`.
This is reachable from ordinary input, not a careless caller.
`JSON.parse('{"a":1e400}')` returns `Infinity` on overflow — so text a user
types parses cleanly, satisfies the type, and reaches the server as `null`
while the editor still shows `1e400`.
`isSerializableJson` in `core/json` is the runtime half of `StrictJsonValue`,
applied at both boundaries that turn text into metadata:
- the editor's draft parser, which now reports "Numbers must be finite" inline
and withholds the value rather than emitting one it cannot send;
- the CLI's `--metadata` / `--tool-metadata` parser, which throws. Silently
sending `null` would be wrong, and so would falling back to the literal
string — neither is what was asked for.
Tests cover the validator directly (including that `JSON.stringify` really does
write `null`, which is the reason it matters), the editor parser, and the CLI
flag.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177mPHAdECD18nLLCTwR5rh
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
129a435fd4
commit
7f5992081e
1 changed files with 156 additions and 0 deletions
|
|
@ -880,6 +880,37 @@ describe("Metadata Tests", () => {
|
|||
}
|
||||
});
|
||||
|
||||
it.each([
|
||||
["an overflowing literal", "n=1e400"],
|
||||
["a negative overflow", "n=-1e400"],
|
||||
["one nested in an object", 'o={"a":1e400}'],
|
||||
])("rejects %s rather than sending null", async (_label, pair) => {
|
||||
// `JSON.parse` accepts these and yields ±Infinity, which
|
||||
// `JSON.stringify` writes as `null` — so accepting the flag would
|
||||
// transmit a value the user did not ask for.
|
||||
const server = createTestServerHttp({
|
||||
serverInfo: createTestServerInfo(),
|
||||
tools: [createEchoTool()],
|
||||
});
|
||||
try {
|
||||
await server.start();
|
||||
const result = await runCli([
|
||||
server.url,
|
||||
"--cli",
|
||||
"--method",
|
||||
"tools/list",
|
||||
"--metadata",
|
||||
pair,
|
||||
"--transport",
|
||||
"http",
|
||||
]);
|
||||
expect(result.exitCode).not.toBe(0);
|
||||
expect(`${result.stderr}${result.stdout}`).toMatch(/finite/i);
|
||||
} finally {
|
||||
await server.stop();
|
||||
}
|
||||
});
|
||||
|
||||
it("should handle metadata parsing validation", async () => {
|
||||
const server = createTestServerHttp({
|
||||
serverInfo: createTestServerInfo(),
|
||||
|
|
|
|||
Loading…
Reference in a new issue