@skroyc/librarian 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/CHANGELOG.md +176 -0
  2. package/LICENSE +210 -0
  3. package/README.md +614 -0
  4. package/biome.jsonc +9 -0
  5. package/dist/agents/context-schema.d.ts +17 -0
  6. package/dist/agents/context-schema.d.ts.map +1 -0
  7. package/dist/agents/context-schema.js +16 -0
  8. package/dist/agents/context-schema.js.map +1 -0
  9. package/dist/agents/react-agent.d.ts +38 -0
  10. package/dist/agents/react-agent.d.ts.map +1 -0
  11. package/dist/agents/react-agent.js +719 -0
  12. package/dist/agents/react-agent.js.map +1 -0
  13. package/dist/agents/tool-runtime.d.ts +7 -0
  14. package/dist/agents/tool-runtime.d.ts.map +1 -0
  15. package/dist/agents/tool-runtime.js +2 -0
  16. package/dist/agents/tool-runtime.js.map +1 -0
  17. package/dist/cli.d.ts +4 -0
  18. package/dist/cli.d.ts.map +1 -0
  19. package/dist/cli.js +172 -0
  20. package/dist/cli.js.map +1 -0
  21. package/dist/config.d.ts +4 -0
  22. package/dist/config.d.ts.map +1 -0
  23. package/dist/config.js +243 -0
  24. package/dist/config.js.map +1 -0
  25. package/dist/index.d.ts +41 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +470 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/tools/file-finding.tool.d.ts +24 -0
  30. package/dist/tools/file-finding.tool.d.ts.map +1 -0
  31. package/dist/tools/file-finding.tool.js +198 -0
  32. package/dist/tools/file-finding.tool.js.map +1 -0
  33. package/dist/tools/file-listing.tool.d.ts +12 -0
  34. package/dist/tools/file-listing.tool.d.ts.map +1 -0
  35. package/dist/tools/file-listing.tool.js +132 -0
  36. package/dist/tools/file-listing.tool.js.map +1 -0
  37. package/dist/tools/file-reading.tool.d.ts +9 -0
  38. package/dist/tools/file-reading.tool.d.ts.map +1 -0
  39. package/dist/tools/file-reading.tool.js +112 -0
  40. package/dist/tools/file-reading.tool.js.map +1 -0
  41. package/dist/tools/grep-content.tool.d.ts +27 -0
  42. package/dist/tools/grep-content.tool.d.ts.map +1 -0
  43. package/dist/tools/grep-content.tool.js +229 -0
  44. package/dist/tools/grep-content.tool.js.map +1 -0
  45. package/dist/utils/file-utils.d.ts +2 -0
  46. package/dist/utils/file-utils.d.ts.map +1 -0
  47. package/dist/utils/file-utils.js +28 -0
  48. package/dist/utils/file-utils.js.map +1 -0
  49. package/dist/utils/logger.d.ts +32 -0
  50. package/dist/utils/logger.d.ts.map +1 -0
  51. package/dist/utils/logger.js +177 -0
  52. package/dist/utils/logger.js.map +1 -0
  53. package/dist/utils/path-utils.d.ts +2 -0
  54. package/dist/utils/path-utils.d.ts.map +1 -0
  55. package/dist/utils/path-utils.js +9 -0
  56. package/dist/utils/path-utils.js.map +1 -0
  57. package/package.json +84 -0
  58. package/src/agents/context-schema.ts +61 -0
  59. package/src/agents/react-agent.ts +928 -0
  60. package/src/agents/tool-runtime.ts +21 -0
  61. package/src/cli.ts +206 -0
  62. package/src/config.ts +309 -0
  63. package/src/index.ts +628 -0
  64. package/src/tools/file-finding.tool.ts +324 -0
  65. package/src/tools/file-listing.tool.ts +212 -0
  66. package/src/tools/file-reading.tool.ts +154 -0
  67. package/src/tools/grep-content.tool.ts +325 -0
  68. package/src/utils/file-utils.ts +39 -0
  69. package/src/utils/logger.ts +295 -0
  70. package/src/utils/path-utils.ts +17 -0
  71. package/tsconfig.json +37 -0
  72. package/tsconfig.test.json +17 -0
@@ -0,0 +1,198 @@
1
+ import { tool } from "langchain";
2
+ import { z } from "zod";
3
+ import fs from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { logger } from "../utils/logger.js";
6
+ async function findFiles(searchPath, patterns, options = {}) {
7
+ const { exclude = [], recursive = true, maxResults = 1000, includeHidden = false, } = options;
8
+ const foundFiles = [];
9
+ const processedPaths = new Set();
10
+ for (const pattern of patterns) {
11
+ const effectivePattern = recursive && !pattern.includes("**") && !pattern.includes("/")
12
+ ? `**/${pattern}`
13
+ : pattern;
14
+ const matchingFiles = await simpleGlobSearch(searchPath, effectivePattern, {
15
+ recursive,
16
+ includeHidden,
17
+ });
18
+ for (const file of matchingFiles) {
19
+ if (foundFiles.length >= maxResults) {
20
+ break;
21
+ }
22
+ if (processedPaths.has(file)) {
23
+ continue;
24
+ }
25
+ processedPaths.add(file);
26
+ const relativePath = path.relative(searchPath, file);
27
+ if (exclude.some((excl) => simpleMatch(relativePath, excl))) {
28
+ continue;
29
+ }
30
+ foundFiles.push(file);
31
+ }
32
+ if (foundFiles.length >= maxResults) {
33
+ break;
34
+ }
35
+ }
36
+ return foundFiles.slice(0, maxResults);
37
+ }
38
+ async function handleDirectoryEntry(entry, basePath, pattern, options, results) {
39
+ const fullPath = path.join(basePath, entry.name);
40
+ if (pattern === "**" || pattern.includes("**") || options.recursive) {
41
+ const basePattern = pattern.split("/")[0] || pattern;
42
+ if (simpleMatch(entry.name, basePattern)) {
43
+ results.push(fullPath);
44
+ }
45
+ if (options.recursive) {
46
+ const subDirResults = await simpleGlobSearch(fullPath, pattern, options);
47
+ results.push(...subDirResults);
48
+ }
49
+ }
50
+ }
51
+ function handleFileEntry(entry, basePath, pattern, results) {
52
+ const fullPath = path.join(basePath, entry.name);
53
+ const relativePath = path.relative(basePath, fullPath);
54
+ const basePattern = pattern.includes("**/")
55
+ ? pattern.split("**/")[1] || ""
56
+ : pattern;
57
+ if (simpleMatch(entry.name, basePattern) ||
58
+ simpleMatch(relativePath, basePattern)) {
59
+ results.push(fullPath);
60
+ }
61
+ }
62
+ async function simpleGlobSearch(basePath, pattern, options) {
63
+ const results = [];
64
+ try {
65
+ const entries = await fs.readdir(basePath, { withFileTypes: true });
66
+ for (const entry of entries) {
67
+ if (!options.includeHidden && entry.name.startsWith(".")) {
68
+ continue;
69
+ }
70
+ if (entry.isDirectory()) {
71
+ await handleDirectoryEntry(entry, basePath, pattern, options, results);
72
+ }
73
+ else if (entry.isFile()) {
74
+ handleFileEntry(entry, basePath, pattern, results);
75
+ }
76
+ }
77
+ }
78
+ catch {
79
+ return [];
80
+ }
81
+ return results;
82
+ }
83
+ function simpleMatch(str, pattern) {
84
+ if (pattern === str) {
85
+ return true;
86
+ }
87
+ const regexPattern = pattern
88
+ .replace(/\./g, "\\.")
89
+ .replace(/\*/g, ".*")
90
+ .replace(/\?/g, ".");
91
+ const regex = new RegExp(`^${regexPattern}$`);
92
+ return regex.test(str);
93
+ }
94
+ export const fileFindTool = tool(async ({ searchPath = ".", patterns, exclude = [], recursive = true, maxResults = 1000, includeHidden = false, }, config) => {
95
+ const timingId = logger.timingStart("fileFind");
96
+ logger.info("TOOL", "file_find called", {
97
+ searchPath,
98
+ patterns,
99
+ exclude,
100
+ recursive,
101
+ maxResults,
102
+ includeHidden,
103
+ });
104
+ try {
105
+ const workingDir = config?.context?.workingDir;
106
+ if (!workingDir) {
107
+ throw new Error("Context with workingDir is required for file operations");
108
+ }
109
+ logger.debug("TOOL", "Working directory", {
110
+ workingDir: workingDir.replace(Bun.env.HOME || "", "~"),
111
+ });
112
+ const resolvedPath = path.resolve(workingDir, searchPath);
113
+ const resolvedWorkingDir = path.resolve(workingDir);
114
+ const relativePath = path.relative(resolvedWorkingDir, resolvedPath);
115
+ logger.debug("TOOL", "Path validation", {
116
+ resolvedPath: resolvedPath.replace(Bun.env.HOME || "", "~"),
117
+ resolvedWorkingDir: resolvedWorkingDir.replace(Bun.env.HOME || "", "~"),
118
+ relativePath,
119
+ validated: !relativePath.startsWith(".."),
120
+ });
121
+ if (relativePath.startsWith("..")) {
122
+ logger.error("PATH", "Search path escapes working directory sandbox", undefined, { searchPath, relativePath });
123
+ throw new Error(`Search path "${searchPath}" attempts to escape the working directory sandbox`);
124
+ }
125
+ const stats = await fs.stat(resolvedPath);
126
+ if (!stats.isDirectory()) {
127
+ logger.error("TOOL", "Search path is not a directory", undefined, {
128
+ searchPath,
129
+ });
130
+ throw new Error(`Search path "${searchPath}" is not a directory`);
131
+ }
132
+ const foundFiles = await findFiles(resolvedPath, patterns || ["*"], {
133
+ exclude,
134
+ recursive,
135
+ maxResults,
136
+ includeHidden,
137
+ });
138
+ logger.timingEnd(timingId, "TOOL", "file_find completed");
139
+ logger.debug("TOOL", "File search successful", {
140
+ searchPath,
141
+ foundCount: foundFiles.length,
142
+ patterns,
143
+ });
144
+ if (foundFiles.length === 0) {
145
+ return `No files found matching patterns: ${patterns?.join(", ") || "*"}`;
146
+ }
147
+ let output = `Found ${foundFiles.length} files matching patterns [${patterns?.join(", ") || "*"}]:\n\n`;
148
+ for (const file of foundFiles) {
149
+ const relativePath = path.relative(resolvedPath, file);
150
+ output += `${relativePath}\n`;
151
+ }
152
+ return output;
153
+ }
154
+ catch (error) {
155
+ logger.error("TOOL", "file_find failed", error instanceof Error ? error : new Error(String(error)), { searchPath, patterns });
156
+ return `Error finding files: ${error.message}`;
157
+ }
158
+ }, {
159
+ name: "find_files",
160
+ description: `Discovers files using glob patterns. Respects .gitignore.
161
+ Usage
162
+ - Fast file pattern matching command that works with any codebase size
163
+ - Supports glob patterns like "**/*.js" or "src/**/*.ts"
164
+ - Returns matching file paths sorted
165
+ - Use this command when you need to find files by name patterns
166
+ - When you are doing an open ended search that may require multiple rounds of globbing and grepping, use the Task tool instead
167
+ - You can call multiple commands in a single response. It is always better to speculatively perform multiple searches in parallel if they are potentially useful.
168
+ `,
169
+ schema: z.object({
170
+ searchPath: z
171
+ .string()
172
+ .describe("The directory path to search in, relative to the working directory"),
173
+ patterns: z
174
+ .array(z.string())
175
+ .describe("Array of glob patterns to match files (e.g., ['*.js', '*.ts'])"),
176
+ exclude: z
177
+ .array(z.string())
178
+ .optional()
179
+ .default([])
180
+ .describe("Array of patterns to exclude from results. Defaults to none"),
181
+ recursive: z
182
+ .boolean()
183
+ .optional()
184
+ .default(true)
185
+ .describe("Whether to search recursively in subdirectories. Defaults to `true`"),
186
+ maxResults: z
187
+ .number()
188
+ .optional()
189
+ .default(100)
190
+ .describe("Maximum number of files to return. Maximum of 100 by default"),
191
+ includeHidden: z
192
+ .boolean()
193
+ .optional()
194
+ .default(false)
195
+ .describe("Whether to include hidden files and directories. Defaults to `false`"),
196
+ }),
197
+ });
198
+ //# sourceMappingURL=file-finding.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-finding.tool.js","sourceRoot":"","sources":["../../src/tools/file-finding.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { z } from "zod";
2
+ export declare const fileListTool: import("langchain").DynamicStructuredTool<z.ZodObject<{
3
+ directoryPath: z.ZodString;
4
+ includeHidden: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
5
+ }, z.core.$strip>, {
6
+ directoryPath: string;
7
+ includeHidden: boolean;
8
+ }, {
9
+ directoryPath: string;
10
+ includeHidden?: boolean | undefined;
11
+ }, string>;
12
+ //# sourceMappingURL=file-listing.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-listing.tool.d.ts","sourceRoot":"","sources":["../../src/tools/file-listing.tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAuHxB,eAAO,MAAM,YAAY;;;;;;;;;UA2FxB,CAAC"}
@@ -0,0 +1,132 @@
1
+ import { tool } from "langchain";
2
+ import { z } from "zod";
3
+ import fs from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { logger } from "../utils/logger.js";
6
+ async function shouldIgnoreFile(filePath) {
7
+ const basename = path.basename(filePath);
8
+ if (basename.startsWith(".") && basename !== ".env") {
9
+ const ignoredItems = [
10
+ "node_modules",
11
+ ".git",
12
+ ".DS_Store",
13
+ ".idea",
14
+ ".vscode",
15
+ ".pytest_cache",
16
+ ];
17
+ if (ignoredItems.includes(basename)) {
18
+ return true;
19
+ }
20
+ }
21
+ const commonBuildDirs = ["dist", "build", "out", "target", "coverage"];
22
+ if (commonBuildDirs.includes(basename) &&
23
+ (await fs
24
+ .stat(filePath)
25
+ .then((s) => s.isDirectory())
26
+ .catch(() => false))) {
27
+ return true;
28
+ }
29
+ return false;
30
+ }
31
+ async function listDirectory(dirPath, includeHidden = false) {
32
+ const entries = await fs.readdir(dirPath, { withFileTypes: true });
33
+ const fileEntries = [];
34
+ for (const entry of entries) {
35
+ if (!includeHidden && entry.name.startsWith(".")) {
36
+ continue;
37
+ }
38
+ const fullPath = path.join(dirPath, entry.name);
39
+ try {
40
+ if (!includeHidden && (await shouldIgnoreFile(fullPath))) {
41
+ continue;
42
+ }
43
+ const stats = await fs.stat(fullPath);
44
+ const name = path.basename(fullPath);
45
+ logger.debug("TOOL", "Processing file entry", {
46
+ name,
47
+ isDirectory: stats.isDirectory(),
48
+ });
49
+ const metadata = {
50
+ name,
51
+ path: fullPath,
52
+ isDirectory: stats.isDirectory(),
53
+ size: stats.isFile() ? stats.size : undefined,
54
+ modified: stats.mtime,
55
+ permissions: stats.mode?.toString(8),
56
+ };
57
+ fileEntries.push(metadata);
58
+ }
59
+ catch {
60
+ }
61
+ }
62
+ fileEntries.sort((a, b) => {
63
+ if (a.isDirectory !== b.isDirectory) {
64
+ return a.isDirectory ? -1 : 1;
65
+ }
66
+ return a.name.localeCompare(b.name);
67
+ });
68
+ return {
69
+ entries: fileEntries,
70
+ totalCount: fileEntries.length,
71
+ filteredCount: fileEntries.length,
72
+ };
73
+ }
74
+ export const fileListTool = tool(async ({ directoryPath = ".", includeHidden = false }, config) => {
75
+ const timingId = logger.timingStart("fileList");
76
+ logger.info("TOOL", "file_list called", { directoryPath, includeHidden });
77
+ try {
78
+ const workingDir = config?.context?.workingDir;
79
+ if (!workingDir) {
80
+ throw new Error("Context with workingDir is required for file operations");
81
+ }
82
+ logger.debug("TOOL", "Working directory", {
83
+ workingDir: workingDir.replace(Bun.env.HOME || "", "~"),
84
+ });
85
+ const resolvedPath = path.resolve(workingDir, directoryPath);
86
+ const resolvedWorkingDir = path.resolve(workingDir);
87
+ const relativePath = path.relative(resolvedWorkingDir, resolvedPath);
88
+ logger.debug("TOOL", "Path validation", {
89
+ resolvedPath: resolvedPath.replace(Bun.env.HOME || "", "~"),
90
+ resolvedWorkingDir: resolvedWorkingDir.replace(Bun.env.HOME || "", "~"),
91
+ relativePath,
92
+ validated: !relativePath.startsWith(".."),
93
+ });
94
+ if (relativePath.startsWith("..")) {
95
+ logger.error("PATH", "Directory path escapes working directory sandbox", undefined, { directoryPath, relativePath });
96
+ throw new Error(`Directory path "${directoryPath}" attempts to escape working directory sandbox`);
97
+ }
98
+ const listing = await listDirectory(resolvedPath, includeHidden);
99
+ let result = `Contents of directory: ${resolvedPath}\n\n`;
100
+ result += `Total entries: ${listing.totalCount}\n\n`;
101
+ for (const entry of listing.entries) {
102
+ const type = entry.isDirectory ? "DIR" : "FILE";
103
+ const size = entry.size ? ` (${entry.size} bytes)` : "";
104
+ const lineCount = entry.lineCount ? ` (${entry.lineCount} lines)` : "";
105
+ result += `${type} ${entry.name}${size}${lineCount}\n`;
106
+ }
107
+ logger.timingEnd(timingId, "TOOL", "file_list completed");
108
+ logger.debug("TOOL", "Directory listing successful", {
109
+ directoryPath,
110
+ entryCount: listing.totalCount,
111
+ dirCount: listing.entries.filter((e) => e.isDirectory).length,
112
+ fileCount: listing.entries.filter((e) => !e.isDirectory).length,
113
+ });
114
+ return result;
115
+ }
116
+ catch (error) {
117
+ logger.error("TOOL", "list failed", error instanceof Error ? error : new Error(String(error)), { directoryPath });
118
+ return `Error listing directory: ${error.message}`;
119
+ }
120
+ }, {
121
+ name: "list",
122
+ description: "List the contents of a directory with metadata. Use this to understand the structure of a repository or directory.",
123
+ schema: z.object({
124
+ directoryPath: z.string().describe("The directory path to list"),
125
+ includeHidden: z
126
+ .boolean()
127
+ .optional()
128
+ .default(false)
129
+ .describe("Whether to include hidden files and directories. Defaults to `false`"),
130
+ }),
131
+ });
132
+ //# sourceMappingURL=file-listing.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-listing.tool.js","sourceRoot":"","sources":["../../src/tools/file-listing.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { z } from "zod";
2
+ export declare const fileReadTool: import("langchain").DynamicStructuredTool<z.ZodObject<{
3
+ filePath: z.ZodString;
4
+ }, z.core.$strip>, {
5
+ filePath: string;
6
+ }, {
7
+ filePath: string;
8
+ }, string>;
9
+ //# sourceMappingURL=file-reading.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-reading.tool.d.ts","sourceRoot":"","sources":["../../src/tools/file-reading.tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAoDxB,eAAO,MAAM,YAAY;;;;;;UAoGxB,CAAC"}
@@ -0,0 +1,112 @@
1
+ import { tool } from "langchain";
2
+ import { z } from "zod";
3
+ import path from "node:path";
4
+ import { logger } from "../utils/logger.js";
5
+ import { isTextFile } from "../utils/file-utils.js";
6
+ function isImageFile(filePath) {
7
+ const imageExtensions = new Set([
8
+ ".png",
9
+ ".jpg",
10
+ ".jpeg",
11
+ ".gif",
12
+ ".bmp",
13
+ ".webp",
14
+ ".svg",
15
+ ".ico",
16
+ ".tiff",
17
+ ".tif",
18
+ ]);
19
+ const ext = path.extname(filePath).toLowerCase();
20
+ return imageExtensions.has(ext);
21
+ }
22
+ function isAudioFile(filePath) {
23
+ const audioExtensions = new Set([
24
+ ".mp3",
25
+ ".wav",
26
+ ".ogg",
27
+ ".flac",
28
+ ".m4a",
29
+ ".aac",
30
+ ".wma",
31
+ ".opus",
32
+ ".webm",
33
+ ]);
34
+ const ext = path.extname(filePath).toLowerCase();
35
+ return audioExtensions.has(ext);
36
+ }
37
+ async function readFileContent(filePath) {
38
+ try {
39
+ return await Bun.file(filePath).text();
40
+ }
41
+ catch (error) {
42
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
43
+ throw new Error(`Failed to read file: ${errorMessage}`);
44
+ }
45
+ }
46
+ export const fileReadTool = tool(async ({ filePath }, config) => {
47
+ const timingId = logger.timingStart("fileRead");
48
+ logger.info("TOOL", "file_read called", { filePath });
49
+ try {
50
+ const workingDir = config?.context?.workingDir;
51
+ if (!workingDir) {
52
+ throw new Error("Context with workingDir is required for file operations");
53
+ }
54
+ logger.debug("TOOL", "Working directory", {
55
+ workingDir: workingDir.replace(Bun.env.HOME || "", "~"),
56
+ });
57
+ const resolvedPath = path.resolve(workingDir, filePath);
58
+ const resolvedWorkingDir = path.resolve(workingDir);
59
+ const relativePath = path.relative(resolvedWorkingDir, resolvedPath);
60
+ logger.debug("TOOL", "Path validation", {
61
+ resolvedPath: resolvedPath.replace(Bun.env.HOME || "", "~"),
62
+ resolvedWorkingDir: resolvedWorkingDir.replace(Bun.env.HOME || "", "~"),
63
+ relativePath,
64
+ validated: !relativePath.startsWith(".."),
65
+ });
66
+ if (relativePath.startsWith("..")) {
67
+ logger.error("PATH", "File path escapes working directory sandbox", undefined, { filePath, relativePath });
68
+ throw new Error(`File path "${filePath}" attempts to escape the working directory sandbox`);
69
+ }
70
+ if (isImageFile(resolvedPath) || isAudioFile(resolvedPath)) {
71
+ logger.debug("TOOL", "File is media file", {
72
+ filePath,
73
+ fileType: isImageFile(resolvedPath) ? "image" : "audio",
74
+ });
75
+ return `This is a media file (${isImageFile(resolvedPath) ? "image" : "audio"}). Media files cannot be read as text. Path: ${filePath}`;
76
+ }
77
+ const isText = await isTextFile(resolvedPath);
78
+ if (!isText) {
79
+ logger.debug("TOOL", "File is not a text file", { filePath });
80
+ return `This file is not a text file and cannot be read as text. Path: ${filePath}`;
81
+ }
82
+ logger.debug("TOOL", "File type validated as text", { filePath });
83
+ const content = await readFileContent(resolvedPath);
84
+ const maxContentLength = 50_000;
85
+ if (content.length > maxContentLength) {
86
+ logger.debug("TOOL", "File content truncated", {
87
+ filePath,
88
+ originalSize: content.length,
89
+ maxSize: maxContentLength,
90
+ });
91
+ logger.timingEnd(timingId, "TOOL", "file_read completed (truncated)");
92
+ return `File content is too large (${content.length} characters). First ${maxContentLength} characters:\n\n${content.substring(0, maxContentLength)}\n\n[Content truncated due to length]`;
93
+ }
94
+ logger.timingEnd(timingId, "TOOL", "file_read completed");
95
+ logger.debug("TOOL", "File read successful", {
96
+ filePath,
97
+ contentLength: content.length,
98
+ });
99
+ return `Content of file: ${filePath}\n\n${content}`;
100
+ }
101
+ catch (error) {
102
+ logger.error("TOOL", "file_read failed", error instanceof Error ? error : new Error(String(error)), { filePath });
103
+ return `Error reading file: ${error.message}`;
104
+ }
105
+ }, {
106
+ name: "file_read",
107
+ description: "Read the contents of a file. Use this to examine the content of a specific file.",
108
+ schema: z.object({
109
+ filePath: z.string().describe("The path to the file to read"),
110
+ }),
111
+ });
112
+ //# sourceMappingURL=file-reading.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-reading.tool.js","sourceRoot":"","sources":["../../src/tools/file-reading.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { z } from "zod";
2
+ export declare const grepContentTool: import("langchain").DynamicStructuredTool<z.ZodObject<{
3
+ searchPath: z.ZodString;
4
+ query: z.ZodString;
5
+ patterns: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
6
+ caseSensitive: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
7
+ regex: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
8
+ recursive: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
9
+ maxResults: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
10
+ }, z.core.$strip>, {
11
+ searchPath: string;
12
+ query: string;
13
+ patterns: string[];
14
+ caseSensitive: boolean;
15
+ regex: boolean;
16
+ recursive: boolean;
17
+ maxResults: number;
18
+ }, {
19
+ searchPath: string;
20
+ query: string;
21
+ patterns?: string[] | undefined;
22
+ caseSensitive?: boolean | undefined;
23
+ regex?: boolean | undefined;
24
+ recursive?: boolean | undefined;
25
+ maxResults?: number | undefined;
26
+ }, string>;
27
+ //# sourceMappingURL=grep-content.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep-content.tool.d.ts","sourceRoot":"","sources":["../../src/tools/grep-content.tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgNxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;UAmH3B,CAAC"}