Skip to content

Commit a02b3da

Browse files
committed
Fixes for PR review feedback
1 parent be03318 commit a02b3da

File tree

5 files changed

+48
-19
lines changed

5 files changed

+48
-19
lines changed

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

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -182939,7 +182939,6 @@ async function resolveQueryPath(params, logger2) {
182939182939

182940182940
// src/lib/result-processor.ts
182941182941
init_cli_executor();
182942-
init_cli_executor();
182943182942
import { basename as basename4, dirname as dirname4 } from "path";
182944182943
import { mkdirSync as mkdirSync7, readFileSync as readFileSync6 } from "fs";
182945182944
import { createHash as createHash2 } from "crypto";
@@ -182965,6 +182964,8 @@ async function extractQueryMetadata(queryPath) {
182965182964
mtime = fstatSync(fd).mtimeMs;
182966182965
const cached2 = metadataCache.get(queryPath);
182967182966
if (cached2 && cached2.mtime === mtime) {
182967+
metadataCache.delete(queryPath);
182968+
metadataCache.set(queryPath, cached2);
182968182969
return cached2.metadata;
182969182970
}
182970182971
queryContent = readFileSync4(fd, "utf-8");
@@ -183402,8 +183403,13 @@ var SqliteStore = class _SqliteStore {
183402183403
/**
183403183404
* Write the in-memory database to disk.
183404183405
*
183405-
* Uses write-to-temp + atomic rename so a crash mid-write cannot
183406-
* corrupt the database file.
183406+
* On platforms where `renameSync` can atomically replace the destination
183407+
* (for example, POSIX filesystems and Windows when the target is not
183408+
* locked), this uses a write-to-temp + atomic rename pattern so a crash
183409+
* mid-write cannot corrupt the existing database file. On some Windows
183410+
* configurations where `renameSync` fails because the destination is
183411+
* locked, we fall back to a direct overwrite, which is best-effort only
183412+
* and not fully crash-safe.
183407183413
*/
183408183414
flush() {
183409183415
if (this.flushTimer) {
@@ -183447,6 +183453,10 @@ var SqliteStore = class _SqliteStore {
183447183453
* Close the database (and flush remaining changes).
183448183454
*/
183449183455
close() {
183456+
if (this.flushTimer) {
183457+
globalThis.clearTimeout(this.flushTimer);
183458+
this.flushTimer = null;
183459+
}
183450183460
this.flushIfDirty();
183451183461
this.db?.close();
183452183462
this.db = null;
@@ -183582,11 +183592,11 @@ var SqliteStore = class _SqliteStore {
183582183592
sql += " WHERE " + conditions.join(" AND ");
183583183593
}
183584183594
sql += " ORDER BY updated_at DESC";
183585-
if (filter?.limit) {
183595+
if (filter?.limit !== void 0) {
183586183596
sql += " LIMIT $limit";
183587183597
params.$limit = filter.limit;
183588183598
}
183589-
if (filter?.offset) {
183599+
if (filter?.offset !== void 0) {
183590183600
sql += " OFFSET $offset";
183591183601
params.$offset = filter.offset;
183592183602
}
@@ -193731,11 +193741,11 @@ function registerQueryResultsCacheRetrieveTool(server) {
193731193741
"Retrieve cached query results with optional subset selection. Supports line ranges (for graphtext/CSV) and SARIF result indices and file filtering to return only the relevant portion.",
193732193742
{
193733193743
cacheKey: external_exports.string().describe("The cache key of the result to retrieve."),
193734-
lineRange: external_exports.tuple([external_exports.number(), external_exports.number()]).optional().describe("Line range [start, end] (1-indexed, inclusive). For graphtext/CSV output only."),
193735-
resultIndices: external_exports.tuple([external_exports.number(), external_exports.number()]).optional().describe("SARIF result index range [start, end] (0-indexed, inclusive). For SARIF output only."),
193744+
lineRange: external_exports.tuple([external_exports.number().int().min(1), external_exports.number().int().min(1)]).refine(([start, end]) => start <= end, { message: "lineRange start must be <= end" }).optional().describe("Line range [start, end] (1-indexed, inclusive). For graphtext/CSV output only."),
193745+
resultIndices: external_exports.tuple([external_exports.number().int().min(0), external_exports.number().int().min(0)]).refine(([start, end]) => start <= end, { message: "resultIndices start must be <= end" }).optional().describe("SARIF result index range [start, end] (0-indexed, inclusive). For SARIF output only."),
193736193746
fileFilter: external_exports.string().optional().describe("For SARIF: only include results whose file path contains this string."),
193737-
maxLines: external_exports.number().optional().describe("Maximum number of lines to return for line-based formats (default: 500)."),
193738-
maxResults: external_exports.number().optional().describe("Maximum number of SARIF results to return (default: 100).")
193747+
maxLines: external_exports.number().int().positive().optional().describe("Maximum number of lines to return for line-based formats (default: 500)."),
193748+
maxResults: external_exports.number().int().positive().optional().describe("Maximum number of SARIF results to return (default: 100).")
193739193749
},
193740193750
async ({ cacheKey: cacheKey2, lineRange, resultIndices, fileFilter, maxLines, maxResults }) => {
193741193751
const store = sessionDataManager.getStore();

server/src/lib/query-results-evaluator.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ export async function extractQueryMetadata(queryPath: string): Promise<QueryMeta
5656
mtime = fstatSync(fd).mtimeMs;
5757
const cached = metadataCache.get(queryPath);
5858
if (cached && cached.mtime === mtime) {
59+
// Refresh position in Map to implement true LRU behavior.
60+
metadataCache.delete(queryPath);
61+
metadataCache.set(queryPath, cached);
5962
return cached.metadata;
6063
}
6164
queryContent = readFileSync(fd, 'utf-8');

server/src/lib/result-processor.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@
99
import { basename, dirname } from 'path';
1010
import { mkdirSync, readFileSync } from 'fs';
1111
import { createHash } from 'crypto';
12-
import { executeCodeQLCommand, CLIExecutionResult } from './cli-executor';
13-
import { getActualCodeqlVersion } from './cli-executor';
12+
import { CLIExecutionResult, executeCodeQLCommand, getActualCodeqlVersion } from './cli-executor';
1413
import { evaluateQueryResults, extractQueryMetadata, QueryEvaluationResult } from './query-results-evaluator';
1514
import { resolveQueryPath } from './query-resolver';
1615
import { sessionDataManager } from './session-data-manager';

server/src/lib/sqlite-store.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,13 @@ export class SqliteStore {
252252
/**
253253
* Write the in-memory database to disk.
254254
*
255-
* Uses write-to-temp + atomic rename so a crash mid-write cannot
256-
* corrupt the database file.
255+
* On platforms where `renameSync` can atomically replace the destination
256+
* (for example, POSIX filesystems and Windows when the target is not
257+
* locked), this uses a write-to-temp + atomic rename pattern so a crash
258+
* mid-write cannot corrupt the existing database file. On some Windows
259+
* configurations where `renameSync` fails because the destination is
260+
* locked, we fall back to a direct overwrite, which is best-effort only
261+
* and not fully crash-safe.
257262
*/
258263
flush(): void {
259264
if (this.flushTimer) {
@@ -299,6 +304,10 @@ export class SqliteStore {
299304
* Close the database (and flush remaining changes).
300305
*/
301306
close(): void {
307+
if (this.flushTimer) {
308+
globalThis.clearTimeout(this.flushTimer);
309+
this.flushTimer = null;
310+
}
302311
this.flushIfDirty();
303312
this.db?.close();
304313
this.db = null;
@@ -458,11 +467,11 @@ export class SqliteStore {
458467
}
459468
sql += ' ORDER BY updated_at DESC';
460469

461-
if (filter?.limit) {
470+
if (filter?.limit !== undefined) {
462471
sql += ' LIMIT $limit';
463472
params.$limit = filter.limit;
464473
}
465-
if (filter?.offset) {
474+
if (filter?.offset !== undefined) {
466475
sql += ' OFFSET $offset';
467476
params.$offset = filter.offset;
468477
}

server/src/tools/cache-tools.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,19 @@ function registerQueryResultsCacheRetrieveTool(server: McpServer): void {
8383
'Retrieve cached query results with optional subset selection. Supports line ranges (for graphtext/CSV) and SARIF result indices and file filtering to return only the relevant portion.',
8484
{
8585
cacheKey: z.string().describe('The cache key of the result to retrieve.'),
86-
lineRange: z.tuple([z.number(), z.number()]).optional().describe('Line range [start, end] (1-indexed, inclusive). For graphtext/CSV output only.'),
87-
resultIndices: z.tuple([z.number(), z.number()]).optional().describe('SARIF result index range [start, end] (0-indexed, inclusive). For SARIF output only.'),
86+
lineRange: z
87+
.tuple([z.number().int().min(1), z.number().int().min(1)])
88+
.refine(([start, end]) => start <= end, { message: 'lineRange start must be <= end' })
89+
.optional()
90+
.describe('Line range [start, end] (1-indexed, inclusive). For graphtext/CSV output only.'),
91+
resultIndices: z
92+
.tuple([z.number().int().min(0), z.number().int().min(0)])
93+
.refine(([start, end]) => start <= end, { message: 'resultIndices start must be <= end' })
94+
.optional()
95+
.describe('SARIF result index range [start, end] (0-indexed, inclusive). For SARIF output only.'),
8896
fileFilter: z.string().optional().describe('For SARIF: only include results whose file path contains this string.'),
89-
maxLines: z.number().optional().describe('Maximum number of lines to return for line-based formats (default: 500).'),
90-
maxResults: z.number().optional().describe('Maximum number of SARIF results to return (default: 100).'),
97+
maxLines: z.number().int().positive().optional().describe('Maximum number of lines to return for line-based formats (default: 500).'),
98+
maxResults: z.number().int().positive().optional().describe('Maximum number of SARIF results to return (default: 100).'),
9199
},
92100
async ({ cacheKey, lineRange, resultIndices, fileFilter, maxLines, maxResults }) => {
93101
const store = sessionDataManager.getStore();

0 commit comments

Comments
 (0)