Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions src/tools/preflight-check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,27 @@ import { loadPatterns, matchPatterns, formatPatternMatches } from "../lib/patter
// Helpers
// ---------------------------------------------------------------------------

/** Known non-file tokens that look like file paths */
const FALSE_POSITIVE_PATHS = new Set([
'node.js', 'next.js', 'vue.js', 'react.js', 'express.js', 'nest.js',
'bun.js', 'deno.js', 'nuxt.js', 'svelte.js', 'ember.js', 'angular.js',
'three.js', 'd3.js', 'p5.js', 'e2e.js',
]);

/** Extract file paths from prompt text */
function extractFilePaths(prompt: string): string[] {
export function extractFilePaths(prompt: string): string[] {
// Match sequences that look like paths: must contain a slash OR a known code extension
const CODE_EXTENSIONS = /\.(ts|tsx|js|jsx|mjs|cjs|json|yaml|yml|toml|md|css|scss|html|sql|sh|py|rb|go|rs|java|c|cpp|h|hpp|xml|env|lock|config|conf)$/;
const matches = prompt.match(/[\w\-./\\]+\.\w{1,6}/g) || [];
return [...new Set(matches)];
return [...new Set(
matches.filter(m => {
// Must have a slash (looks like a path) or a known code extension
if (FALSE_POSITIVE_PATHS.has(m.toLowerCase())) return false;
// Filter out version-like patterns: v1.2.3, 2.5x, etc.
if (/^v?\d+\.\d+/i.test(m)) return false;
return m.includes('/') || m.includes('\\') || CODE_EXTENSIONS.test(m);
})
)];
}

/** Verify files exist and return stats */
Expand Down
47 changes: 47 additions & 0 deletions tests/tools/preflight-check.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { describe, it, expect } from "vitest";
// We exported extractFilePaths so we can test it directly
import { extractFilePaths } from "../../src/tools/preflight-check.js";

describe("extractFilePaths", () => {
it("extracts paths with directories", () => {
expect(extractFilePaths("fix src/auth/jwt.ts line 42")).toEqual(["src/auth/jwt.ts"]);
});

it("extracts standalone files with code extensions", () => {
expect(extractFilePaths("update README.md and package.json")).toEqual([
"README.md",
"package.json",
]);
});

it("filters out Node.js and other framework names", () => {
expect(extractFilePaths("use Node.js and Vue.js")).toEqual([]);
});

it("filters out version numbers", () => {
expect(extractFilePaths("upgrade to v3.2.0 for 2.5x speed")).toEqual([]);
});

it("handles mixed real paths and false positives", () => {
const result = extractFilePaths(
"in Node.js v18.0, fix src/lib/triage.ts and update config.yaml"
);
expect(result).toEqual(["src/lib/triage.ts", "config.yaml"]);
});

it("deduplicates paths", () => {
expect(extractFilePaths("check src/index.ts then revisit src/index.ts")).toEqual([
"src/index.ts",
]);
});

it("returns empty for no file references", () => {
expect(extractFilePaths("fix the auth bug")).toEqual([]);
});

it("handles deeply nested paths", () => {
expect(extractFilePaths("look at src/lib/utils/helpers.ts")).toEqual([
"src/lib/utils/helpers.ts",
]);
});
});
Loading