Skip to content

Commit 672fbbd

Browse files
committed
feat: add readFile tool
1 parent 71a33a2 commit 672fbbd

File tree

5 files changed

+96
-10
lines changed

5 files changed

+96
-10
lines changed

package-lock.json

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

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@
120120
"mustache": "^4.2.0",
121121
"url-parse": "^1.5.10",
122122
"vanilla-picker": "^2.12.3",
123-
"yargs": "^17.7.2"
123+
"yargs": "^17.7.2",
124+
"zod": "^3.25.47"
124125
},
125126
"browserslist": "cover 100%,not android < 5"
126-
}
127+
}

src/pages/aiAssistant/assistant.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
updateConversation,
2020
} from "./db";
2121
import { SYSTEM_PROMPT } from "./system_prompt";
22+
import { allTools } from "./tools";
2223

2324
export default function openAIAssistantPage() {
2425
// References
@@ -38,17 +39,18 @@ export default function openAIAssistantPage() {
3839

3940
const GEMINI_API_KEY = ""; // Replace
4041

41-
const searchTool = {
42-
googleSearch: {},
43-
};
4442
const agentCheckpointer = new MemorySaver();
4543
const model = new ChatGoogleGenerativeAI({
4644
model: "gemini-2.0-flash",
4745
apiKey: GEMINI_API_KEY,
4846
});
47+
48+
// Get all tools as an array for the agent including search
49+
const toolsArray = Object.values(allTools);
50+
4951
const agent = createReactAgent({
5052
llm: model,
51-
tools: [searchTool],
53+
tools: toolsArray,
5254
checkpointSaver: agentCheckpointer,
5355
stateModifier: SYSTEM_PROMPT,
5456
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { readFile } from "./readFile";
2+
3+
// Export all tools as a single object
4+
export const allTools = {
5+
readFile,
6+
};
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { StructuredTool } from "@langchain/core/tools";
2+
import fsOperation from "fileSystem";
3+
import { addedFolder } from "lib/openFolder";
4+
import { z } from "zod";
5+
6+
/**
7+
* Tool for reading file contents in Acode
8+
*/
9+
class ReadFileTool extends StructuredTool {
10+
name = "readFile";
11+
description = "Reads the content of the given file in the project.";
12+
schema = z.object({
13+
path: z
14+
.string()
15+
.describe(
16+
"The relative path of the file to read. This path should never be absolute, and the first component of the path should always be a root directory in a project (opened in sidebar). For example, if root directories are 'directory1' and 'directory2', to access 'file.txt' in 'directory1', use 'directory1/file.txt'. To access 'file.txt' in 'directory2', use 'directory2/file.txt'.",
17+
),
18+
startLine: z
19+
.number()
20+
.min(1)
21+
.optional()
22+
.describe("line number to start reading on (1-based index)"),
23+
endLine: z
24+
.number()
25+
.min(1)
26+
.optional()
27+
.describe("line number to end reading on (1-based index, inclusive)"),
28+
});
29+
30+
async _call({ path, startLine, endLine }) {
31+
try {
32+
// Split the path to get project name and file path
33+
const pathParts = path.split("/");
34+
const projectName = pathParts[0];
35+
const filePath = pathParts.slice(1).join("/");
36+
37+
// Find the project in addedFolder array
38+
const project = addedFolder.find(
39+
(folder) => folder.title === projectName,
40+
);
41+
if (!project) {
42+
return `Error: Project '${projectName}' not found in opened projects`;
43+
}
44+
45+
// Construct the full file URL
46+
const fileUrl = project.url + "/" + filePath;
47+
48+
// Read the file content
49+
const content = await fsOperation(fileUrl).readFile("utf8");
50+
51+
// If startLine or endLine are specified, filter the content
52+
if (startLine !== undefined || endLine !== undefined) {
53+
const lines = content.split("\n");
54+
const start = startLine ? startLine - 1 : 0;
55+
const end = endLine ? endLine : lines.length;
56+
return lines.slice(start, end).join("\n");
57+
}
58+
59+
return content;
60+
} catch (error) {
61+
return `Error reading file: ${error.message}`;
62+
}
63+
}
64+
}
65+
66+
export const readFile = new ReadFileTool();

0 commit comments

Comments
 (0)