Add --raw-strings flag to prevent numeric string coercion
Values like phone numbers, PINs, or codes with leading zeros (e.g. 000123) are auto-coerced to numbers by default. The --raw-strings flag (or --no-coerce alias) preserves them as strings. Note: Cannot use --raw as the flag name because it conflicts with the existing --raw output format shortcut in output-format.ts. Fixes: numeric strings being silently converted to numbers
This commit is contained in:
parent
30abe3d9a5
commit
3325d32d03
@ -17,6 +17,7 @@ export interface CallArgsParseResult {
|
||||
output: OutputFormat;
|
||||
timeoutMs?: number;
|
||||
ephemeral?: EphemeralServerSpec;
|
||||
rawStrings?: boolean;
|
||||
}
|
||||
|
||||
export function parseCallArguments(args: string[]): CallArgsParseResult {
|
||||
@ -68,6 +69,11 @@ export function parseCallArguments(args: string[]): CallArgsParseResult {
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
if (token === '--raw-strings' || token === '--no-coerce') {
|
||||
result.rawStrings = true;
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
if (token === '--args') {
|
||||
const value = args[index + 1];
|
||||
if (!value) {
|
||||
@ -168,12 +174,12 @@ export function parseCallArguments(args: string[]): CallArgsParseResult {
|
||||
}
|
||||
const parsed = parseKeyValueToken(token, positional[index + 1]);
|
||||
if (!parsed) {
|
||||
trailingPositional.push(coerceValue(token));
|
||||
trailingPositional.push(coerceValue(token, result.rawStrings));
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
index += parsed.consumed;
|
||||
const value = coerceValue(parsed.rawValue);
|
||||
const value = coerceValue(parsed.rawValue, result.rawStrings);
|
||||
if (parsed.key === 'tool' && !result.tool) {
|
||||
if (typeof value !== 'string') {
|
||||
throw new Error("Argument 'tool' must be a string value.");
|
||||
@ -273,7 +279,7 @@ function extractHttpCallExpression(raw: string): ReturnType<typeof parseCallExpr
|
||||
};
|
||||
}
|
||||
|
||||
function coerceValue(value: string): unknown {
|
||||
function coerceValue(value: string, rawStrings = false): unknown {
|
||||
const trimmed = value.trim();
|
||||
if (trimmed === '') {
|
||||
return '';
|
||||
@ -284,7 +290,8 @@ function coerceValue(value: string): unknown {
|
||||
if (trimmed === 'null' || trimmed === 'none') {
|
||||
return null;
|
||||
}
|
||||
if (!Number.isNaN(Number(trimmed)) && trimmed === `${Number(trimmed)}`) {
|
||||
// Skip numeric coercion when --raw-strings (or --no-coerce) flag is used
|
||||
if (!rawStrings && !Number.isNaN(Number(trimmed)) && trimmed === `${Number(trimmed)}`) {
|
||||
return Number(trimmed);
|
||||
}
|
||||
if ((trimmed.startsWith('{') && trimmed.endsWith('}')) || (trimmed.startsWith('[') && trimmed.endsWith(']'))) {
|
||||
|
||||
@ -49,4 +49,29 @@ describe('parseCallArguments', () => {
|
||||
);
|
||||
warnSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('coerces numeric strings to numbers by default', () => {
|
||||
const parsed = parseCallArguments(['server.tool', 'code=123456']);
|
||||
expect(parsed.args.code).toBe(123456);
|
||||
expect(typeof parsed.args.code).toBe('number');
|
||||
});
|
||||
|
||||
it('preserves numeric strings when --raw-strings flag is used', () => {
|
||||
const parsed = parseCallArguments(['--raw-strings', 'server.tool', 'code=123456']);
|
||||
expect(parsed.args.code).toBe('123456');
|
||||
expect(typeof parsed.args.code).toBe('string');
|
||||
expect(parsed.rawStrings).toBe(true);
|
||||
});
|
||||
|
||||
it('preserves leading zeros when --raw-strings flag is used', () => {
|
||||
const parsed = parseCallArguments(['--raw-strings', 'server.tool', 'pin=000123']);
|
||||
expect(parsed.args.pin).toBe('000123');
|
||||
expect(typeof parsed.args.pin).toBe('string');
|
||||
});
|
||||
|
||||
it('preserves numeric strings when --no-coerce alias is used', () => {
|
||||
const parsed = parseCallArguments(['--no-coerce', 'server.tool', 'id=007']);
|
||||
expect(parsed.args.id).toBe('007');
|
||||
expect(typeof parsed.args.id).toBe('string');
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user