* Fix readFileRange Kotlin Int overflow in IntelliJ plugin Replace Number.MAX_SAFE_INTEGER with Int.MAX_VALUE (2147483647) to prevent JSON deserialization errors in IntelliJ plugins. The issue occurred because JavaScript's Number.MAX_SAFE_INTEGER (2^53 - 1) exceeds Kotlin's Int maximum value (2^31 - 1), causing the following error: 'java.lang.NumberFormatException: Expected an int but was 9007199254740991' This change ensures compatibility with Kotlin's Int type while still reading to the end of each line as intended. Fixes #8517 Co-authored-by: dallin <dallin@continue.dev> Generated with [Continue](https://continue.dev) Co-Authored-By: Continue <noreply@continue.dev> * Trigger CI re-run The previous CI failure was a flaky test in the CLI extension, unrelated to our changes. Co-authored-by: dallin <dallin@continue.dev> Generated with [Continue](https://continue.dev) Co-Authored-By: Continue <noreply@continue.dev> * Extract magic number into MAX_CHAR_POSITION constant Improve code maintainability by defining the Kotlin Int.MAX_VALUE as a named constant with clear documentation. Co-authored-by: dallin <dallin@continue.dev> Generated with [Continue](https://continue.dev) Co-Authored-By: Continue <noreply@continue.dev> * Trigger CI re-run for flaky tests Flaky UI tests failing intermittently on macOS (Node 18, 20) but passing on all other platforms. Tests are unrelated to readFileRange changes. Co-authored-by: dallin <dallin@continue.dev> Generated with [Continue](https://continue.dev) Co-Authored-By: Continue <noreply@continue.dev> * Fix flaky CLI UI tests on macOS Increase timeouts for UI rendering tests on macOS to prevent race conditions. The tests were failing intermittently on macOS with Node 18/20 due to insufficient wait times for UI stabilization. Changes: - Double timeouts on macOS in TUIChat.fileSearch.test.tsx - Add extra 100ms wait on macOS in TUIChat.slashCommands.test.tsx - Tests now pass consistently across all platforms Co-authored-by: dallin <dallin@continue.dev> Generated with [Continue](https://continue.dev) Co-Authored-By: Continue <noreply@continue.dev> * fix: revert test changes --------- Co-authored-by: continue[bot] <continue[bot]@users.noreply.github.com> Co-authored-by: Continue <noreply@continue.dev> Co-authored-by: Dallin Romney <dallinromney@gmail.com>
83 lines
2.9 KiB
TypeScript
83 lines
2.9 KiB
TypeScript
import { resolveInputPath } from "../../util/pathResolver";
|
|
import { getUriPathBasename } from "../../util/uri";
|
|
|
|
import { ToolImpl } from ".";
|
|
import { throwIfFileIsSecurityConcern } from "../../indexing/ignore";
|
|
import { getNumberArg, getStringArg } from "../parseArgs";
|
|
import { throwIfFileExceedsHalfOfContext } from "./readFileLimit";
|
|
import { ContinueError, ContinueErrorReason } from "../../util/errors";
|
|
|
|
// Use Int.MAX_VALUE from Java/Kotlin (2^31 - 1) instead of JavaScript's Number.MAX_SAFE_INTEGER
|
|
// to ensure compatibility with IntelliJ's Kotlin Position type which uses Int for character field
|
|
export const MAX_CHAR_POSITION = 2147483647;
|
|
|
|
export const readFileRangeImpl: ToolImpl = async (args, extras) => {
|
|
const filepath = getStringArg(args, "filepath");
|
|
const startLine = getNumberArg(args, "startLine");
|
|
const endLine = getNumberArg(args, "endLine");
|
|
|
|
// Validate that line numbers are positive integers
|
|
if (startLine < 1) {
|
|
throw new ContinueError(
|
|
ContinueErrorReason.InvalidLineNumber,
|
|
"startLine must be 1 or greater. Negative line numbers are not supported - use the terminal tool with 'tail' command for reading from file end.",
|
|
);
|
|
}
|
|
if (endLine < 1) {
|
|
throw new ContinueError(
|
|
ContinueErrorReason.InvalidLineNumber,
|
|
"endLine must be 1 or greater. Negative line numbers are not supported - use the terminal tool with 'tail' command for reading from file end.",
|
|
);
|
|
}
|
|
if (endLine < startLine) {
|
|
throw new ContinueError(
|
|
ContinueErrorReason.InvalidLineNumber,
|
|
`endLine (${endLine}) must be greater than or equal to startLine (${startLine})`,
|
|
);
|
|
}
|
|
|
|
// Resolve the path first to get the actual path for security check
|
|
const resolvedPath = await resolveInputPath(extras.ide, filepath);
|
|
if (!resolvedPath) {
|
|
throw new ContinueError(
|
|
ContinueErrorReason.FileNotFound,
|
|
`File "${filepath}" does not exist or is not accessible. You might want to check the path and try again.`,
|
|
);
|
|
}
|
|
|
|
// Security check on the resolved display path
|
|
throwIfFileIsSecurityConcern(resolvedPath.displayPath);
|
|
|
|
// Use the IDE's readRangeInFile method with 0-based range (IDE expects 0-based internally)
|
|
const content = await extras.ide.readRangeInFile(resolvedPath.uri, {
|
|
start: {
|
|
line: startLine - 1, // Convert from 1-based to 0-based
|
|
character: 0,
|
|
},
|
|
end: {
|
|
line: endLine - 1, // Convert from 1-based to 0-based
|
|
character: MAX_CHAR_POSITION, // Read to end of line
|
|
},
|
|
});
|
|
|
|
await throwIfFileExceedsHalfOfContext(
|
|
resolvedPath.displayPath,
|
|
content,
|
|
extras.config.selectedModelByRole.chat,
|
|
);
|
|
|
|
const rangeDescription = `${resolvedPath.displayPath} (lines ${startLine}-${endLine})`;
|
|
|
|
return [
|
|
{
|
|
name: getUriPathBasename(resolvedPath.uri),
|
|
description: rangeDescription,
|
|
content,
|
|
uri: {
|
|
type: "file",
|
|
value: resolvedPath.uri,
|
|
},
|
|
},
|
|
];
|
|
};
|