Skip to content

Commit 28a6243

Browse files
Copilotdata-douser
andauthored
fix: capture suggestion alongside unknownEntries for "did you mean?" hints
The hint is now stored at determination time rather than re-computed in the error loop (where it was always undefined). When both kebab-case and camelCase forms are provided (e.g. source-root + sourceRoot), the duplicate is now rejected with a "did you mean?" suggestion instead of being silently ignored. Agent-Logs-Url: https://github.com/advanced-security/codeql-development-mcp-server/sessions/02a09bd4-39e4-4e83-968e-8562405a9f4c Co-authored-by: data-douser <70299490+data-douser@users.noreply.github.com>
1 parent 92af8e0 commit 28a6243

4 files changed

Lines changed: 20 additions & 19 deletions

File tree

server/dist/codeql-development-mcp-server.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -188611,14 +188611,12 @@ function buildEnhancedToolSchema(shape) {
188611188611
const suggestion = suggestPropertyName(key, knownKeys);
188612188612
if (suggestion && !(suggestion in data) && !(suggestion in normalized)) {
188613188613
normalized[suggestion] = value;
188614-
} else if (suggestion && (suggestion in data || suggestion in normalized)) {
188615188614
} else {
188616-
unknownEntries.push({ key, value });
188615+
unknownEntries.push({ key, hint: suggestion });
188617188616
}
188618188617
}
188619188618
}
188620-
for (const { key } of unknownEntries) {
188621-
const hint = suggestPropertyName(key, knownKeys);
188619+
for (const { key, hint } of unknownEntries) {
188622188620
const message = hint ? `unknown property '${key}' \u2014 did you mean '${hint}'?` : `unknown property '${key}'`;
188623188621
ctx.addIssue({
188624188622
code: external_exports.ZodIssueCode.custom,

server/dist/codeql-development-mcp-server.js.map

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/src/lib/param-normalization.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export function buildEnhancedToolSchema(
7878
.passthrough()
7979
.transform((data, ctx) => {
8080
const normalized: Record<string, unknown> = {};
81-
const unknownEntries: Array<{ key: string; value: unknown }> = [];
81+
const unknownEntries: Array<{ key: string; hint?: string }> = [];
8282

8383
for (const [key, value] of Object.entries(data)) {
8484
if (knownKeys.has(key)) {
@@ -90,18 +90,17 @@ export function buildEnhancedToolSchema(
9090
if (suggestion && !(suggestion in data) && !(suggestion in normalized)) {
9191
// Silently normalize to the canonical kebab-case key
9292
normalized[suggestion] = value;
93-
} else if (suggestion && (suggestion in data || suggestion in normalized)) {
94-
// Both forms provided — prefer the canonical (kebab-case) key,
95-
// silently ignore the alias
9693
} else {
97-
unknownEntries.push({ key, value });
94+
// Either no suggestion (truly unknown) or the canonical key is
95+
// already present. Capture the suggestion so the error message
96+
// can include a "did you mean?" hint.
97+
unknownEntries.push({ key, hint: suggestion });
9898
}
9999
}
100100
}
101101

102-
// Report truly unknown properties with "did you mean?" hints
103-
for (const { key } of unknownEntries) {
104-
const hint = suggestPropertyName(key, knownKeys);
102+
// Report unknown / duplicate properties with "did you mean?" hints
103+
for (const { key, hint } of unknownEntries) {
105104
const message = hint
106105
? `unknown property '${key}' — did you mean '${hint}'?`
107106
: `unknown property '${key}'`;

server/test/src/lib/param-normalization.test.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -167,17 +167,21 @@ describe('buildEnhancedToolSchema', () => {
167167
}
168168
});
169169

170-
it('should prefer kebab-case when both forms are provided', () => {
170+
it('should reject duplicate when both kebab-case and camelCase forms are provided', () => {
171171
const schema = buildEnhancedToolSchema(shape);
172172
const result = schema.safeParse({
173173
database: '/path/to/db',
174174
'source-root': '/canonical/path',
175175
sourceRoot: '/alias/path',
176176
});
177-
expect(result.success).toBe(true);
178-
if (result.success) {
179-
expect(result.data['source-root']).toBe('/canonical/path');
180-
expect(result.data).not.toHaveProperty('sourceRoot');
177+
expect(result.success).toBe(false);
178+
if (!result.success) {
179+
const messages = result.error.issues.map((i) => i.message);
180+
expect(messages).toEqual(
181+
expect.arrayContaining([
182+
expect.stringContaining("unknown property 'sourceRoot' — did you mean 'source-root'?"),
183+
]),
184+
);
181185
}
182186
});
183187

0 commit comments

Comments
 (0)