dallin's feedback

This commit is contained in:
Patrick Erichsen
2025-10-16 18:46:55 -07:00
parent bf9a19ada5
commit ecbb4e272d
5 changed files with 43 additions and 23 deletions

View File

@@ -1,6 +1,6 @@
import { ToolPolicy } from "@continuedev/terminal-security";
import { Tool } from "../..";
import { resolveInputPath } from "../../util/pathResolver";
import { ResolvedPath, resolveInputPath } from "../../util/pathResolver";
import { BUILT_IN_GROUP_NAME, BuiltInToolNames } from "../builtIn";
import { evaluateFileAccessPolicy } from "../policies/fileAccess";
@@ -49,7 +49,10 @@ export const readFileTool: Tool = {
basePolicy: ToolPolicy,
parsedArgs: Record<string, unknown>,
): ToolPolicy => {
const resolvedPath = parsedArgs._resolvedPath as any;
const resolvedPath = parsedArgs._resolvedPath as
| ResolvedPath
| null
| undefined;
if (!resolvedPath) return basePolicy;
return evaluateFileAccessPolicy(basePolicy, resolvedPath.isWithinWorkspace);

View File

@@ -1,6 +1,6 @@
import { ToolPolicy } from "@continuedev/terminal-security";
import { Tool } from "../..";
import { resolveInputPath } from "../../util/pathResolver";
import { ResolvedPath, resolveInputPath } from "../../util/pathResolver";
import { BUILT_IN_GROUP_NAME, BuiltInToolNames } from "../builtIn";
import { evaluateFileAccessPolicy } from "../policies/fileAccess";
@@ -66,7 +66,7 @@ export const readFileRangeTool: Tool = {
basePolicy: ToolPolicy,
parsedArgs: Record<string, unknown>,
): ToolPolicy => {
const resolvedPath = parsedArgs._resolvedPath as any;
const resolvedPath = parsedArgs._resolvedPath as ResolvedPath | null | undefined;
if (!resolvedPath) return basePolicy;
return evaluateFileAccessPolicy(basePolicy, resolvedPath.isWithinWorkspace);

View File

@@ -3,13 +3,15 @@ import * as path from "path";
import { IDE } from "..";
import { normalizeDisplayPath, resolveInputPath } from "./pathResolver";
import * as ideUtils from "./ideUtils";
import * as uri from "./uri";
// Mock the resolveRelativePathInDir function
jest.mock("./ideUtils");
jest.mock("./uri");
describe("resolveUserProvidedPath", () => {
const mockIde = {
getWorkspaceDirs: jest.fn().mockResolvedValue(["/workspace"]),
getWorkspaceDirs: jest.fn().mockResolvedValue(["file:///workspace"]),
fileExists: jest.fn(),
} as unknown as IDE;
@@ -29,6 +31,24 @@ describe("resolveUserProvidedPath", () => {
return null;
}
);
// Setup the mock for findUriInDirs
(uri.findUriInDirs as jest.Mock).mockImplementation((uri, dirUriCandidates) => {
for (const dir of dirUriCandidates) {
if (uri.startsWith(dir)) {
return {
uri,
relativePathOrBasename: uri.slice(dir.length + 1),
foundInDir: dir,
};
}
}
return {
uri,
relativePathOrBasename: uri.split('/').pop() || '',
foundInDir: null,
};
});
});
describe("file:// URIs", () => {

View File

@@ -3,6 +3,7 @@ import * as path from "path";
import { IDE } from "..";
import { resolveRelativePathInDir } from "./ideUtils";
import { localPathToUri } from "./pathToUri";
import { findUriInDirs } from "./uri";
export interface ResolvedPath {
uri: string;
@@ -12,23 +13,15 @@ export interface ResolvedPath {
}
/**
* Checks if a path is within any of the workspace directories
* Checks if a URI is within any of the workspace directories
*/
async function isPathWithinWorkspace(
async function isUriWithinWorkspace(
ide: IDE,
absolutePath: string
uri: string
): Promise<boolean> {
const workspaceDirs = await ide.getWorkspaceDirs();
const normalizedPath = path.normalize(absolutePath).toLowerCase();
for (const dir of workspaceDirs) {
const normalizedDir = path.normalize(dir).toLowerCase();
if (normalizedPath.startsWith(normalizedDir)) {
return true;
}
}
return false;
const { foundInDir } = findUriInDirs(uri, workspaceDirs);
return foundInDir !== null;
}
/**
@@ -52,7 +45,7 @@ export async function resolveInputPath(
const uri = trimmedPath;
// Extract path from URI for display
const displayPath = decodeURIComponent(uri.slice(7));
const isWithinWorkspace = await isPathWithinWorkspace(ide, displayPath);
const isWithinWorkspace = await isUriWithinWorkspace(ide, uri);
return {
uri,
displayPath,
@@ -87,7 +80,7 @@ export async function resolveInputPath(
if (expandedPath.startsWith("\\\\")) {
const networkPath = expandedPath.replace(/\\/g, "/");
const uri = "file:" + networkPath; // file://server/share format
const isWithinWorkspace = await isPathWithinWorkspace(ide, expandedPath);
const isWithinWorkspace = await isUriWithinWorkspace(ide, uri);
return {
uri,
displayPath: expandedPath,
@@ -97,7 +90,7 @@ export async function resolveInputPath(
}
// Convert absolute path to URI
const uri = localPathToUri(expandedPath);
const isWithinWorkspace = await isPathWithinWorkspace(ide, expandedPath);
const isWithinWorkspace = await isUriWithinWorkspace(ide, uri);
return {
uri,
displayPath: expandedPath,

View File

@@ -38,8 +38,12 @@ async function evaluateToolPolicy(
)?.defaultToolPolicy ??
DEFAULT_TOOL_SETTING;
// Use preprocessed arguments if available, otherwise fall back to parsed arguments
const args = toolCallState.processedArgs || toolCallState.parsedArgs || {};
// Merge parsed and preprocessed arguments to ensure we have both original args and any added metadata
// processedArgs may add metadata like _resolvedPath but should include all parsedArgs fields
const args = {
...toolCallState.parsedArgs,
...toolCallState.processedArgs,
};
const toolName = toolCallState.toolCall.function.name;
const result = await ideMessenger.request("tools/evaluatePolicy", {