cast-code 1.0.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 (221) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +217 -0
  3. package/dist/app.module.js +45 -0
  4. package/dist/app.module.js.map +1 -0
  5. package/dist/common/common.module.js +49 -0
  6. package/dist/common/common.module.js.map +1 -0
  7. package/dist/common/constants/index.js +105 -0
  8. package/dist/common/constants/index.js.map +1 -0
  9. package/dist/common/index.js +24 -0
  10. package/dist/common/index.js.map +1 -0
  11. package/dist/common/services/config.service.js +119 -0
  12. package/dist/common/services/config.service.js.map +1 -0
  13. package/dist/common/services/llm.service.js +56 -0
  14. package/dist/common/services/llm.service.js.map +1 -0
  15. package/dist/common/services/markdown-parser.service.js +101 -0
  16. package/dist/common/services/markdown-parser.service.js.map +1 -0
  17. package/dist/common/services/markdown-renderer.service.js +220 -0
  18. package/dist/common/services/markdown-renderer.service.js.map +1 -0
  19. package/dist/common/services/multi-llm.service.js +115 -0
  20. package/dist/common/services/multi-llm.service.js.map +1 -0
  21. package/dist/common/types/index.js +20 -0
  22. package/dist/common/types/index.js.map +1 -0
  23. package/dist/common/types/markdown.types.js +6 -0
  24. package/dist/common/types/markdown.types.js.map +1 -0
  25. package/dist/main.js +84 -0
  26. package/dist/main.js.map +1 -0
  27. package/dist/modules/agents/agents.module.js +43 -0
  28. package/dist/modules/agents/agents.module.js.map +1 -0
  29. package/dist/modules/agents/definitions/architect.md +35 -0
  30. package/dist/modules/agents/definitions/backend.md +43 -0
  31. package/dist/modules/agents/definitions/coder.md +34 -0
  32. package/dist/modules/agents/definitions/devops.md +42 -0
  33. package/dist/modules/agents/definitions/frontend.md +46 -0
  34. package/dist/modules/agents/definitions/reviewer.md +35 -0
  35. package/dist/modules/agents/definitions/tester.md +41 -0
  36. package/dist/modules/agents/index.js +23 -0
  37. package/dist/modules/agents/index.js.map +1 -0
  38. package/dist/modules/agents/services/agent-loader.service.js +150 -0
  39. package/dist/modules/agents/services/agent-loader.service.js.map +1 -0
  40. package/dist/modules/agents/services/agent-registry.service.js +108 -0
  41. package/dist/modules/agents/services/agent-registry.service.js.map +1 -0
  42. package/dist/modules/agents/types/agent.types.js +6 -0
  43. package/dist/modules/agents/types/agent.types.js.map +1 -0
  44. package/dist/modules/agents/types/index.js +20 -0
  45. package/dist/modules/agents/types/index.js.map +1 -0
  46. package/dist/modules/config/config.module.js +38 -0
  47. package/dist/modules/config/config.module.js.map +1 -0
  48. package/dist/modules/config/index.js +24 -0
  49. package/dist/modules/config/index.js.map +1 -0
  50. package/dist/modules/config/services/config-commands.service.js +405 -0
  51. package/dist/modules/config/services/config-commands.service.js.map +1 -0
  52. package/dist/modules/config/services/config-manager.service.js +175 -0
  53. package/dist/modules/config/services/config-manager.service.js.map +1 -0
  54. package/dist/modules/config/services/init-config.service.js +238 -0
  55. package/dist/modules/config/services/init-config.service.js.map +1 -0
  56. package/dist/modules/config/types/config.types.js +163 -0
  57. package/dist/modules/config/types/config.types.js.map +1 -0
  58. package/dist/modules/config/types/index.js +20 -0
  59. package/dist/modules/config/types/index.js.map +1 -0
  60. package/dist/modules/core/core.module.js +60 -0
  61. package/dist/modules/core/core.module.js.map +1 -0
  62. package/dist/modules/core/index.js +22 -0
  63. package/dist/modules/core/index.js.map +1 -0
  64. package/dist/modules/core/services/deep-agent.service.js +575 -0
  65. package/dist/modules/core/services/deep-agent.service.js.map +1 -0
  66. package/dist/modules/core/services/plan-mode.service.js +225 -0
  67. package/dist/modules/core/services/plan-mode.service.js.map +1 -0
  68. package/dist/modules/git/git.module.js +48 -0
  69. package/dist/modules/git/git.module.js.map +1 -0
  70. package/dist/modules/git/index.js +23 -0
  71. package/dist/modules/git/index.js.map +1 -0
  72. package/dist/modules/git/services/code-review.service.js +330 -0
  73. package/dist/modules/git/services/code-review.service.js.map +1 -0
  74. package/dist/modules/git/services/commit-generator.service.js +403 -0
  75. package/dist/modules/git/services/commit-generator.service.js.map +1 -0
  76. package/dist/modules/git/services/index.js +21 -0
  77. package/dist/modules/git/services/index.js.map +1 -0
  78. package/dist/modules/git/services/monorepo-detector.service.js +338 -0
  79. package/dist/modules/git/services/monorepo-detector.service.js.map +1 -0
  80. package/dist/modules/git/services/pr-generator.service.js +429 -0
  81. package/dist/modules/git/services/pr-generator.service.js.map +1 -0
  82. package/dist/modules/git/services/release-notes.service.js +426 -0
  83. package/dist/modules/git/services/release-notes.service.js.map +1 -0
  84. package/dist/modules/git/types/git.types.js +6 -0
  85. package/dist/modules/git/types/git.types.js.map +1 -0
  86. package/dist/modules/git/types/index.js +20 -0
  87. package/dist/modules/git/types/index.js.map +1 -0
  88. package/dist/modules/mcp/catalog/mcp-templates.js +606 -0
  89. package/dist/modules/mcp/catalog/mcp-templates.js.map +1 -0
  90. package/dist/modules/mcp/index.js +23 -0
  91. package/dist/modules/mcp/index.js.map +1 -0
  92. package/dist/modules/mcp/mcp.module.js +35 -0
  93. package/dist/modules/mcp/mcp.module.js.map +1 -0
  94. package/dist/modules/mcp/services/mcp-client.service.js +289 -0
  95. package/dist/modules/mcp/services/mcp-client.service.js.map +1 -0
  96. package/dist/modules/mcp/services/mcp-registry.service.js +197 -0
  97. package/dist/modules/mcp/services/mcp-registry.service.js.map +1 -0
  98. package/dist/modules/mcp/types/index.js +20 -0
  99. package/dist/modules/mcp/types/index.js.map +1 -0
  100. package/dist/modules/mcp/types/mcp.types.js +6 -0
  101. package/dist/modules/mcp/types/mcp.types.js.map +1 -0
  102. package/dist/modules/memory/index.js +23 -0
  103. package/dist/modules/memory/index.js.map +1 -0
  104. package/dist/modules/memory/memory.module.js +35 -0
  105. package/dist/modules/memory/memory.module.js.map +1 -0
  106. package/dist/modules/memory/services/memory-tools.service.js +78 -0
  107. package/dist/modules/memory/services/memory-tools.service.js.map +1 -0
  108. package/dist/modules/memory/services/memory.service.js +169 -0
  109. package/dist/modules/memory/services/memory.service.js.map +1 -0
  110. package/dist/modules/memory/types/index.js +20 -0
  111. package/dist/modules/memory/types/index.js.map +1 -0
  112. package/dist/modules/memory/types/memory.types.js +6 -0
  113. package/dist/modules/memory/types/memory.types.js.map +1 -0
  114. package/dist/modules/mentions/index.js +22 -0
  115. package/dist/modules/mentions/index.js.map +1 -0
  116. package/dist/modules/mentions/mentions.module.js +32 -0
  117. package/dist/modules/mentions/mentions.module.js.map +1 -0
  118. package/dist/modules/mentions/services/mentions.service.js +336 -0
  119. package/dist/modules/mentions/services/mentions.service.js.map +1 -0
  120. package/dist/modules/mentions/types/index.js +20 -0
  121. package/dist/modules/mentions/types/index.js.map +1 -0
  122. package/dist/modules/mentions/types/mention.types.js +19 -0
  123. package/dist/modules/mentions/types/mention.types.js.map +1 -0
  124. package/dist/modules/permissions/index.js +23 -0
  125. package/dist/modules/permissions/index.js.map +1 -0
  126. package/dist/modules/permissions/permissions.module.js +35 -0
  127. package/dist/modules/permissions/permissions.module.js.map +1 -0
  128. package/dist/modules/permissions/services/permission.service.js +269 -0
  129. package/dist/modules/permissions/services/permission.service.js.map +1 -0
  130. package/dist/modules/permissions/services/prompt.service.js +116 -0
  131. package/dist/modules/permissions/services/prompt.service.js.map +1 -0
  132. package/dist/modules/permissions/types/permission.types.js +32 -0
  133. package/dist/modules/permissions/types/permission.types.js.map +1 -0
  134. package/dist/modules/project/index.js +24 -0
  135. package/dist/modules/project/index.js.map +1 -0
  136. package/dist/modules/project/project.module.js +38 -0
  137. package/dist/modules/project/project.module.js.map +1 -0
  138. package/dist/modules/project/services/project-analyzer.service.js +1063 -0
  139. package/dist/modules/project/services/project-analyzer.service.js.map +1 -0
  140. package/dist/modules/project/services/project-context.service.js +62 -0
  141. package/dist/modules/project/services/project-context.service.js.map +1 -0
  142. package/dist/modules/project/services/project-loader.service.js +147 -0
  143. package/dist/modules/project/services/project-loader.service.js.map +1 -0
  144. package/dist/modules/project/types/index.js +20 -0
  145. package/dist/modules/project/types/index.js.map +1 -0
  146. package/dist/modules/project/types/project.types.js +6 -0
  147. package/dist/modules/project/types/project.types.js.map +1 -0
  148. package/dist/modules/repl/index.js +21 -0
  149. package/dist/modules/repl/index.js.map +1 -0
  150. package/dist/modules/repl/repl.module.js +66 -0
  151. package/dist/modules/repl/repl.module.js.map +1 -0
  152. package/dist/modules/repl/services/commands/agent-commands.service.js +196 -0
  153. package/dist/modules/repl/services/commands/agent-commands.service.js.map +1 -0
  154. package/dist/modules/repl/services/commands/git-commands.service.js +500 -0
  155. package/dist/modules/repl/services/commands/git-commands.service.js.map +1 -0
  156. package/dist/modules/repl/services/commands/mcp-commands.service.js +579 -0
  157. package/dist/modules/repl/services/commands/mcp-commands.service.js.map +1 -0
  158. package/dist/modules/repl/services/commands/project-commands.service.js +226 -0
  159. package/dist/modules/repl/services/commands/project-commands.service.js.map +1 -0
  160. package/dist/modules/repl/services/commands/repl-commands.service.js +254 -0
  161. package/dist/modules/repl/services/commands/repl-commands.service.js.map +1 -0
  162. package/dist/modules/repl/services/repl.service.js +647 -0
  163. package/dist/modules/repl/services/repl.service.js.map +1 -0
  164. package/dist/modules/repl/services/smart-input.js +544 -0
  165. package/dist/modules/repl/services/smart-input.js.map +1 -0
  166. package/dist/modules/repl/services/welcome-screen.service.js +117 -0
  167. package/dist/modules/repl/services/welcome-screen.service.js.map +1 -0
  168. package/dist/modules/repl/utils/prompts-with-esc.js +187 -0
  169. package/dist/modules/repl/utils/prompts-with-esc.js.map +1 -0
  170. package/dist/modules/repl/utils/theme.js +185 -0
  171. package/dist/modules/repl/utils/theme.js.map +1 -0
  172. package/dist/modules/skills/definitions/general/file-operations.md +60 -0
  173. package/dist/modules/skills/definitions/general/git-operations.md +59 -0
  174. package/dist/modules/skills/definitions/general/planning.md +86 -0
  175. package/dist/modules/skills/definitions/general/search.md +59 -0
  176. package/dist/modules/skills/definitions/specialized/api-design.md +85 -0
  177. package/dist/modules/skills/definitions/specialized/database-operations.md +78 -0
  178. package/dist/modules/skills/definitions/specialized/frontend-bootstrap.md +71 -0
  179. package/dist/modules/skills/definitions/specialized/react-patterns.md +77 -0
  180. package/dist/modules/skills/definitions/specialized/testing-strategies.md +79 -0
  181. package/dist/modules/skills/index.js +23 -0
  182. package/dist/modules/skills/index.js.map +1 -0
  183. package/dist/modules/skills/services/skill-loader.service.js +130 -0
  184. package/dist/modules/skills/services/skill-loader.service.js.map +1 -0
  185. package/dist/modules/skills/services/skill-registry.service.js +96 -0
  186. package/dist/modules/skills/services/skill-registry.service.js.map +1 -0
  187. package/dist/modules/skills/skills.module.js +38 -0
  188. package/dist/modules/skills/skills.module.js.map +1 -0
  189. package/dist/modules/skills/types/index.js +20 -0
  190. package/dist/modules/skills/types/index.js.map +1 -0
  191. package/dist/modules/skills/types/skill.types.js +6 -0
  192. package/dist/modules/skills/types/skill.types.js.map +1 -0
  193. package/dist/modules/tasks/index.js +24 -0
  194. package/dist/modules/tasks/index.js.map +1 -0
  195. package/dist/modules/tasks/services/plan-executor.service.js +199 -0
  196. package/dist/modules/tasks/services/plan-executor.service.js.map +1 -0
  197. package/dist/modules/tasks/services/plan-mode.service.js +118 -0
  198. package/dist/modules/tasks/services/plan-mode.service.js.map +1 -0
  199. package/dist/modules/tasks/services/plan-persistence.service.js +148 -0
  200. package/dist/modules/tasks/services/plan-persistence.service.js.map +1 -0
  201. package/dist/modules/tasks/services/task-management.service.js +255 -0
  202. package/dist/modules/tasks/services/task-management.service.js.map +1 -0
  203. package/dist/modules/tasks/services/task-tools.service.js +270 -0
  204. package/dist/modules/tasks/services/task-tools.service.js.map +1 -0
  205. package/dist/modules/tasks/tasks.module.js +49 -0
  206. package/dist/modules/tasks/tasks.module.js.map +1 -0
  207. package/dist/modules/tasks/types/task.types.js +21 -0
  208. package/dist/modules/tasks/types/task.types.js.map +1 -0
  209. package/dist/modules/tools/index.js +24 -0
  210. package/dist/modules/tools/index.js.map +1 -0
  211. package/dist/modules/tools/services/filesystem-tools.service.js +450 -0
  212. package/dist/modules/tools/services/filesystem-tools.service.js.map +1 -0
  213. package/dist/modules/tools/services/search-tools.service.js +63 -0
  214. package/dist/modules/tools/services/search-tools.service.js.map +1 -0
  215. package/dist/modules/tools/services/shell-tools.service.js +194 -0
  216. package/dist/modules/tools/services/shell-tools.service.js.map +1 -0
  217. package/dist/modules/tools/services/tools-registry.service.js +83 -0
  218. package/dist/modules/tools/services/tools-registry.service.js.map +1 -0
  219. package/dist/modules/tools/tools.module.js +46 -0
  220. package/dist/modules/tools/tools.module.js.map +1 -0
  221. package/package.json +74 -0
@@ -0,0 +1,450 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "FilesystemToolsService", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return FilesystemToolsService;
9
+ }
10
+ });
11
+ const _common = require("@nestjs/common");
12
+ const _tools = require("@langchain/core/tools");
13
+ const _zod = require("zod");
14
+ const _promises = /*#__PURE__*/ _interop_require_wildcard(require("node:fs/promises"));
15
+ const _path = /*#__PURE__*/ _interop_require_wildcard(require("path"));
16
+ const _glob = require("glob");
17
+ function _getRequireWildcardCache(nodeInterop) {
18
+ if (typeof WeakMap !== "function") return null;
19
+ var cacheBabelInterop = new WeakMap();
20
+ var cacheNodeInterop = new WeakMap();
21
+ return (_getRequireWildcardCache = function(nodeInterop) {
22
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
23
+ })(nodeInterop);
24
+ }
25
+ function _interop_require_wildcard(obj, nodeInterop) {
26
+ if (!nodeInterop && obj && obj.__esModule) {
27
+ return obj;
28
+ }
29
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
30
+ return {
31
+ default: obj
32
+ };
33
+ }
34
+ var cache = _getRequireWildcardCache(nodeInterop);
35
+ if (cache && cache.has(obj)) {
36
+ return cache.get(obj);
37
+ }
38
+ var newObj = {
39
+ __proto__: null
40
+ };
41
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
42
+ for(var key in obj){
43
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
44
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
45
+ if (desc && (desc.get || desc.set)) {
46
+ Object.defineProperty(newObj, key, desc);
47
+ } else {
48
+ newObj[key] = obj[key];
49
+ }
50
+ }
51
+ }
52
+ newObj.default = obj;
53
+ if (cache) {
54
+ cache.set(obj, newObj);
55
+ }
56
+ return newObj;
57
+ }
58
+ function _ts_decorate(decorators, target, key, desc) {
59
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
60
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
61
+ else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
62
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
63
+ }
64
+ const DEFAULT_IGNORE = [
65
+ 'node_modules/**',
66
+ '.git/**',
67
+ 'dist/**',
68
+ 'build/**',
69
+ 'coverage/**',
70
+ '.next/**',
71
+ '.nuxt/**',
72
+ '*.min.js',
73
+ '*.min.css',
74
+ 'package-lock.json',
75
+ 'yarn.lock',
76
+ 'pnpm-lock.yaml'
77
+ ];
78
+ let FilesystemToolsService = class FilesystemToolsService {
79
+ getTools() {
80
+ return [
81
+ this.createReadFileTool(),
82
+ this.createWriteFileTool(),
83
+ this.createEditFileTool(),
84
+ this.createGlobTool(),
85
+ this.createGrepTool(),
86
+ this.createLsTool()
87
+ ];
88
+ }
89
+ createReadFileTool() {
90
+ return (0, _tools.tool)(async (input)=>{
91
+ try {
92
+ const filePath = input.filePath || input.file_path;
93
+ const offset = input.offset;
94
+ const limit = input.limit;
95
+ if (!filePath) {
96
+ return 'Error: file_path is required';
97
+ }
98
+ const resolvedPath = _path.isAbsolute(filePath) ? filePath : _path.resolve(process.cwd(), filePath);
99
+ try {
100
+ const stat = await _promises.stat(resolvedPath);
101
+ if (stat.isDirectory()) {
102
+ const entries = await _promises.readdir(resolvedPath, {
103
+ withFileTypes: true
104
+ });
105
+ const listing = entries.slice(0, 50).map((e)=>`${e.isDirectory() ? 'd' : 'f'} ${e.name}`).join('\n');
106
+ return `"${resolvedPath}" is a directory. Contents:\n${listing}${entries.length > 50 ? `\n... (${entries.length - 50} more)` : ''}\n\nUse ls for full listing or glob to search within.`;
107
+ }
108
+ const buffer = Buffer.alloc(512);
109
+ const fd = await _promises.open(resolvedPath, 'r');
110
+ await fd.read(buffer, 0, 512, 0);
111
+ await fd.close();
112
+ const hasBinaryBytes = buffer.some((byte, i)=>i < 512 && byte === 0);
113
+ if (hasBinaryBytes) {
114
+ return `"${resolvedPath}" appears to be a binary file (${Math.round(stat.size / 1024)}KB). Cannot display binary content.`;
115
+ }
116
+ } catch (error) {
117
+ const err = error;
118
+ if (err.code === 'ENOENT') {
119
+ const basename = _path.basename(filePath);
120
+ const matches = await (0, _glob.glob)(`**/${basename}`, {
121
+ cwd: process.cwd(),
122
+ ignore: DEFAULT_IGNORE
123
+ });
124
+ if (matches.length > 0) {
125
+ return `File not found at "${resolvedPath}".\n\nDid you mean one of these?\n${matches.slice(0, 5).map((m)=>` - ${m}`).join('\n')}`;
126
+ }
127
+ return `File not found: "${resolvedPath}"`;
128
+ }
129
+ return `Error accessing file: ${err.message}`;
130
+ }
131
+ const content = await _promises.readFile(resolvedPath, 'utf-8');
132
+ if (!content.trim()) {
133
+ return `File "${resolvedPath}" exists but is empty (0 bytes of content).`;
134
+ }
135
+ const lines = content.split('\n');
136
+ const start = offset || 0;
137
+ const end = limit ? start + limit : lines.length;
138
+ const selectedLines = lines.slice(start, end);
139
+ const formatted = selectedLines.map((line, i)=>{
140
+ const lineNum = start + i + 1;
141
+ const truncated = line.length > 2000 ? line.slice(0, 2000) + '... (truncated)' : line;
142
+ return `${lineNum}: ${truncated}`;
143
+ }).join('\n');
144
+ this.readFiles.add(resolvedPath);
145
+ if (end < lines.length) {
146
+ return `${formatted}\n\n(Showing lines ${start + 1}-${end} of ${lines.length} total. Use offset/limit to read more.)`;
147
+ }
148
+ return formatted;
149
+ } catch (error) {
150
+ return `Error reading file: ${error.message}`;
151
+ }
152
+ }, {
153
+ name: 'read_file',
154
+ description: 'Read contents of a file. Returns numbered lines. Supports both absolute and relative paths. ALWAYS use this before editing a file.',
155
+ schema: _zod.z.object({
156
+ file_path: _zod.z.string().describe('Path to the file (absolute or relative to working directory)'),
157
+ offset: _zod.z.number().optional().describe('Line number to start from (0-indexed)'),
158
+ limit: _zod.z.number().optional().describe('Number of lines to read')
159
+ })
160
+ });
161
+ }
162
+ createWriteFileTool() {
163
+ return (0, _tools.tool)(async (input)=>{
164
+ try {
165
+ const filePath = input.filePath || input.file_path;
166
+ const content = input.content;
167
+ if (!filePath || content === undefined) {
168
+ return 'Error: file_path and content are required';
169
+ }
170
+ const resolvedPath = _path.isAbsolute(filePath) ? filePath : _path.resolve(process.cwd(), filePath);
171
+ let fileExists = false;
172
+ try {
173
+ await _promises.access(resolvedPath);
174
+ fileExists = true;
175
+ } catch {}
176
+ if (fileExists && !this.readFiles.has(resolvedPath)) {
177
+ this.readFiles.add(resolvedPath);
178
+ }
179
+ const dir = _path.dirname(resolvedPath);
180
+ await _promises.mkdir(dir, {
181
+ recursive: true
182
+ });
183
+ await _promises.writeFile(resolvedPath, content, 'utf-8');
184
+ this.readFiles.add(resolvedPath);
185
+ const lines = content.split('\n').length;
186
+ return `File written successfully: ${resolvedPath} (${lines} lines)`;
187
+ } catch (error) {
188
+ return `Error writing file: ${error.message}`;
189
+ }
190
+ }, {
191
+ name: 'write_file',
192
+ description: 'Write content to a file. Creates directories if needed. Prefer edit_file for modifying existing files.',
193
+ schema: _zod.z.object({
194
+ file_path: _zod.z.string().describe('Path to the file (absolute or relative)'),
195
+ content: _zod.z.string().describe('Content to write')
196
+ })
197
+ });
198
+ }
199
+ createEditFileTool() {
200
+ return (0, _tools.tool)(async (input)=>{
201
+ try {
202
+ const filePath = input.filePath || input.file_path;
203
+ const oldString = input.oldString || input.old_string;
204
+ const newString = input.newString || input.new_string;
205
+ const replaceAll = input.replaceAll || input.replace_all || false;
206
+ if (!filePath || oldString === undefined || newString === undefined) {
207
+ return 'Error: file_path, old_string, and new_string are required';
208
+ }
209
+ const resolvedPath = _path.isAbsolute(filePath) ? filePath : _path.resolve(process.cwd(), filePath);
210
+ if (oldString === newString) {
211
+ return 'Error: old_string and new_string are identical. No changes needed.';
212
+ }
213
+ if (!this.readFiles.has(resolvedPath)) {
214
+ return `Error: You must read_file("${filePath}") before editing it. This ensures you understand the current content.`;
215
+ }
216
+ const content = await _promises.readFile(resolvedPath, 'utf-8');
217
+ if (!content.includes(oldString)) {
218
+ const lines = content.split('\n');
219
+ const trimmedOld = oldString.trim();
220
+ const approxMatch = lines.findIndex((l)=>l.trim().includes(trimmedOld));
221
+ if (approxMatch !== -1) {
222
+ return `Error: exact old_string not found. Possible match at line ${approxMatch + 1}:\n "${lines[approxMatch].trim()}"\n\nMake sure whitespace and indentation match exactly.`;
223
+ }
224
+ return `Error: old_string not found in file. Make sure it matches the file content exactly (including whitespace).`;
225
+ }
226
+ const occurrences = content.split(oldString).length - 1;
227
+ if (occurrences > 1 && !replaceAll) {
228
+ return `Error: old_string found ${occurrences} times. Either:\n1. Provide more surrounding context to make it unique\n2. Use replace_all=true to replace all occurrences`;
229
+ }
230
+ const newContent = replaceAll ? content.replaceAll(oldString, newString) : content.replace(oldString, newString);
231
+ await _promises.writeFile(resolvedPath, newContent, 'utf-8');
232
+ const replacedCount = replaceAll ? occurrences : 1;
233
+ return `File edited successfully: ${resolvedPath} (${replacedCount} replacement${replacedCount > 1 ? 's' : ''})`;
234
+ } catch (error) {
235
+ return `Error editing file: ${error.message}`;
236
+ }
237
+ }, {
238
+ name: 'edit_file',
239
+ description: 'Edit a file by replacing exact string matches. You MUST read_file first. Provides helpful error messages if the string is not found or ambiguous.',
240
+ schema: _zod.z.object({
241
+ file_path: _zod.z.string().describe('Path to the file (absolute or relative)'),
242
+ old_string: _zod.z.string().describe('Exact text to replace (must match exactly including whitespace)'),
243
+ new_string: _zod.z.string().describe('New text to replace with (must be different from old_string)'),
244
+ replace_all: _zod.z.boolean().optional().default(false).describe('Replace all occurrences (default: false)')
245
+ })
246
+ });
247
+ }
248
+ createGlobTool() {
249
+ return (0, _tools.tool)(async ({ pattern, cwd })=>{
250
+ try {
251
+ const searchDir = cwd ? _path.isAbsolute(cwd) ? cwd : _path.resolve(process.cwd(), cwd) : process.cwd();
252
+ const files = await (0, _glob.glob)(pattern, {
253
+ cwd: searchDir,
254
+ ignore: DEFAULT_IGNORE
255
+ });
256
+ if (files.length === 0) {
257
+ return `No files found matching "${pattern}" in ${searchDir}.\nTip: The working directory is ${process.cwd()}. Use "**/*.ext" to search recursively.`;
258
+ }
259
+ const sorted = files.sort();
260
+ const limited = sorted.slice(0, 200);
261
+ let result = `Found ${sorted.length} file(s) matching "${pattern}" in ${searchDir}:\n\n`;
262
+ result += limited.join('\n');
263
+ if (sorted.length > 200) {
264
+ result += `\n\n... (${sorted.length - 200} more files. Use a more specific pattern.)`;
265
+ }
266
+ return result;
267
+ } catch (error) {
268
+ return `Error: ${error.message}`;
269
+ }
270
+ }, {
271
+ name: 'glob',
272
+ description: 'Find files matching a glob pattern. Ignores node_modules, .git, dist by default. Returns up to 200 results sorted alphabetically.',
273
+ schema: _zod.z.object({
274
+ pattern: _zod.z.string().describe('Glob pattern (e.g., "**/*.ts", "src/**/*.service.ts")'),
275
+ cwd: _zod.z.string().optional().describe('Working directory (default: project root). Can be relative or absolute.')
276
+ })
277
+ });
278
+ }
279
+ createGrepTool() {
280
+ return (0, _tools.tool)(async (input)=>{
281
+ try {
282
+ const pattern = input.pattern;
283
+ const searchPath = input.searchPath || input.search_path;
284
+ const filePattern = input.filePattern || input.file_pattern;
285
+ const contextLines = input.contextLines || input.context_lines || 0;
286
+ const caseSensitive = input.caseSensitive ?? input.case_sensitive ?? false;
287
+ const outputMode = input.outputMode || input.output_mode || 'content';
288
+ const maxResults = input.maxResults || input.max_results || 100;
289
+ if (!pattern) {
290
+ return 'Error: pattern is required';
291
+ }
292
+ const baseDir = searchPath || process.cwd();
293
+ const files = await (0, _glob.glob)(filePattern || '**/*', {
294
+ cwd: baseDir,
295
+ nodir: true,
296
+ ignore: DEFAULT_IGNORE
297
+ });
298
+ const flags = caseSensitive ? 'g' : 'gi';
299
+ let regex;
300
+ try {
301
+ regex = new RegExp(pattern, flags);
302
+ } catch (regexError) {
303
+ return `Error: Invalid regex pattern "${pattern}": ${regexError.message}. Use a valid JavaScript regex.`;
304
+ }
305
+ if (outputMode === 'files_with_matches') {
306
+ const matchingFiles = [];
307
+ for (const file of files.slice(0, 500)){
308
+ try {
309
+ const fullPath = _path.join(baseDir, file);
310
+ const content = await _promises.readFile(fullPath, 'utf-8');
311
+ if (regex.test(content)) {
312
+ matchingFiles.push(file);
313
+ }
314
+ regex.lastIndex = 0;
315
+ } catch {
316
+ continue;
317
+ }
318
+ }
319
+ if (matchingFiles.length === 0) return 'No matching files found';
320
+ return matchingFiles.slice(0, maxResults).join('\n');
321
+ }
322
+ if (outputMode === 'count') {
323
+ const counts = [];
324
+ for (const file of files.slice(0, 500)){
325
+ try {
326
+ const fullPath = _path.join(baseDir, file);
327
+ const content = await _promises.readFile(fullPath, 'utf-8');
328
+ const allFlags = caseSensitive ? 'g' : 'gi';
329
+ const matches = content.match(new RegExp(pattern, allFlags));
330
+ if (matches && matches.length > 0) {
331
+ counts.push(`${file}: ${matches.length}`);
332
+ }
333
+ } catch {
334
+ continue;
335
+ }
336
+ }
337
+ if (counts.length === 0) return 'No matches found';
338
+ return counts.slice(0, maxResults).join('\n');
339
+ }
340
+ const results = [];
341
+ let totalMatches = 0;
342
+ for (const file of files.slice(0, 500)){
343
+ if (totalMatches >= maxResults) break;
344
+ try {
345
+ const fullPath = _path.join(baseDir, file);
346
+ const content = await _promises.readFile(fullPath, 'utf-8');
347
+ const lines = content.split('\n');
348
+ const matchingLineIndices = [];
349
+ lines.forEach((line, index)=>{
350
+ if (regex.test(line)) {
351
+ matchingLineIndices.push(index);
352
+ }
353
+ regex.lastIndex = 0;
354
+ });
355
+ if (matchingLineIndices.length === 0) continue;
356
+ for (const lineIdx of matchingLineIndices){
357
+ if (totalMatches >= maxResults) break;
358
+ if (contextLines > 0) {
359
+ const start = Math.max(0, lineIdx - contextLines);
360
+ const end = Math.min(lines.length - 1, lineIdx + contextLines);
361
+ results.push(`--- ${file} ---`);
362
+ for(let i = start; i <= end; i++){
363
+ const prefix = i === lineIdx ? '>' : ' ';
364
+ results.push(`${prefix} ${i + 1}: ${lines[i].trimEnd()}`);
365
+ }
366
+ results.push('');
367
+ } else {
368
+ results.push(`${file}:${lineIdx + 1}: ${lines[lineIdx].trim()}`);
369
+ }
370
+ totalMatches++;
371
+ }
372
+ } catch {
373
+ continue;
374
+ }
375
+ }
376
+ if (results.length === 0) {
377
+ return 'No matches found';
378
+ }
379
+ let output = results.join('\n');
380
+ if (totalMatches >= maxResults) {
381
+ output += `\n\n(Showing first ${maxResults} matches. Use max_results to see more or narrow your search.)`;
382
+ }
383
+ return output;
384
+ } catch (error) {
385
+ return `Error: ${error.message}`;
386
+ }
387
+ }, {
388
+ name: 'grep',
389
+ description: 'Search for a regex pattern in files. Supports context lines, case sensitivity, and multiple output modes. Ignores node_modules, .git, dist by default.',
390
+ schema: _zod.z.object({
391
+ pattern: _zod.z.string().describe('Regex pattern to search'),
392
+ search_path: _zod.z.string().optional().describe('Directory to search in (default: project root)'),
393
+ file_pattern: _zod.z.string().optional().describe('Glob pattern for files (e.g., "**/*.ts")'),
394
+ context_lines: _zod.z.number().optional().describe('Number of context lines before/after each match (like grep -C)'),
395
+ case_sensitive: _zod.z.boolean().optional().describe('Case sensitive search (default: false)'),
396
+ output_mode: _zod.z.enum([
397
+ 'content',
398
+ 'files_with_matches',
399
+ 'count'
400
+ ]).optional().describe('Output mode: "content" (default), "files_with_matches" (just paths), "count" (match counts)'),
401
+ max_results: _zod.z.number().optional().describe('Maximum results to return (default: 100)')
402
+ })
403
+ });
404
+ }
405
+ createLsTool() {
406
+ return (0, _tools.tool)(async (input)=>{
407
+ try {
408
+ const directory = input.directory || input.path || process.cwd();
409
+ const resolvedPath = _path.isAbsolute(directory) ? directory : _path.resolve(process.cwd(), directory);
410
+ const entries = await _promises.readdir(resolvedPath, {
411
+ withFileTypes: true
412
+ });
413
+ if (entries.length === 0) {
414
+ return `Directory "${resolvedPath}" is empty`;
415
+ }
416
+ const dirs = entries.filter((e)=>e.isDirectory()).sort((a, b)=>a.name.localeCompare(b.name));
417
+ const files = entries.filter((e)=>!e.isDirectory()).sort((a, b)=>a.name.localeCompare(b.name));
418
+ const lines = [
419
+ `Directory: ${resolvedPath}`,
420
+ `${dirs.length} directories, ${files.length} files`,
421
+ '',
422
+ ...dirs.map((e)=>`d ${e.name}/`),
423
+ ...files.map((e)=>`f ${e.name}`)
424
+ ];
425
+ return lines.join('\n');
426
+ } catch (error) {
427
+ const err = error;
428
+ if (err.code === 'ENOENT') {
429
+ return `Directory not found: "${input.directory || input.path}"`;
430
+ }
431
+ return `Error: ${err.message}`;
432
+ }
433
+ }, {
434
+ name: 'ls',
435
+ description: 'List directory contents. Shows directories first (with /), then files. Supports relative paths.',
436
+ schema: _zod.z.object({
437
+ directory: _zod.z.string().optional().describe('Directory path (default: working directory)'),
438
+ path: _zod.z.string().optional().describe('Alias for directory')
439
+ })
440
+ });
441
+ }
442
+ constructor(){
443
+ this.readFiles = new Set();
444
+ }
445
+ };
446
+ FilesystemToolsService = _ts_decorate([
447
+ (0, _common.Injectable)()
448
+ ], FilesystemToolsService);
449
+
450
+ //# sourceMappingURL=filesystem-tools.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/modules/tools/services/filesystem-tools.service.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\nimport { tool } from '@langchain/core/tools';\nimport { z } from 'zod';\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\nimport { glob } from 'glob';\n\nconst DEFAULT_IGNORE = [\n 'node_modules/**',\n '.git/**',\n 'dist/**',\n 'build/**',\n 'coverage/**',\n '.next/**',\n '.nuxt/**',\n '*.min.js',\n '*.min.css',\n 'package-lock.json',\n 'yarn.lock',\n 'pnpm-lock.yaml',\n];\n\n@Injectable()\nexport class FilesystemToolsService {\n private readFiles: Set<string> = new Set();\n\n getTools() {\n return [\n this.createReadFileTool(),\n this.createWriteFileTool(),\n this.createEditFileTool(),\n this.createGlobTool(),\n this.createGrepTool(),\n this.createLsTool(),\n ];\n }\n\n private createReadFileTool() {\n return tool(\n async (input) => {\n try {\n const filePath = (input as any).filePath || (input as any).file_path;\n const offset = (input as any).offset;\n const limit = (input as any).limit;\n\n if (!filePath) {\n return 'Error: file_path is required';\n }\n\n const resolvedPath = path.isAbsolute(filePath)\n ? filePath\n : path.resolve(process.cwd(), filePath);\n\n try {\n const stat = await fs.stat(resolvedPath);\n\n if (stat.isDirectory()) {\n const entries = await fs.readdir(resolvedPath, { withFileTypes: true });\n const listing = entries\n .slice(0, 50)\n .map((e) => `${e.isDirectory() ? 'd' : 'f'} ${e.name}`)\n .join('\\n');\n return `\"${resolvedPath}\" is a directory. Contents:\\n${listing}${entries.length > 50 ? `\\n... (${entries.length - 50} more)` : ''}\\n\\nUse ls for full listing or glob to search within.`;\n }\n\n const buffer = Buffer.alloc(512);\n const fd = await fs.open(resolvedPath, 'r');\n await fd.read(buffer, 0, 512, 0);\n await fd.close();\n\n const hasBinaryBytes = buffer.some(\n (byte, i) => i < 512 && byte === 0,\n );\n if (hasBinaryBytes) {\n return `\"${resolvedPath}\" appears to be a binary file (${Math.round(stat.size / 1024)}KB). Cannot display binary content.`;\n }\n } catch (error) {\n const err = error as NodeJS.ErrnoException;\n if (err.code === 'ENOENT') {\n const basename = path.basename(filePath);\n const matches = await glob(`**/${basename}`, {\n cwd: process.cwd(),\n ignore: DEFAULT_IGNORE,\n });\n\n if (matches.length > 0) {\n return `File not found at \"${resolvedPath}\".\\n\\nDid you mean one of these?\\n${matches.slice(0, 5).map((m) => ` - ${m}`).join('\\n')}`;\n }\n return `File not found: \"${resolvedPath}\"`;\n }\n return `Error accessing file: ${err.message}`;\n }\n\n const content = await fs.readFile(resolvedPath, 'utf-8');\n\n if (!content.trim()) {\n return `File \"${resolvedPath}\" exists but is empty (0 bytes of content).`;\n }\n\n const lines = content.split('\\n');\n const start = offset || 0;\n const end = limit ? start + limit : lines.length;\n const selectedLines = lines.slice(start, end);\n\n const formatted = selectedLines\n .map((line, i) => {\n const lineNum = start + i + 1;\n const truncated =\n line.length > 2000\n ? line.slice(0, 2000) + '... (truncated)'\n : line;\n return `${lineNum}: ${truncated}`;\n })\n .join('\\n');\n\n this.readFiles.add(resolvedPath);\n\n if (end < lines.length) {\n return `${formatted}\\n\\n(Showing lines ${start + 1}-${end} of ${lines.length} total. Use offset/limit to read more.)`;\n }\n\n return formatted;\n } catch (error) {\n return `Error reading file: ${(error as Error).message}`;\n }\n },\n {\n name: 'read_file',\n description:\n 'Read contents of a file. Returns numbered lines. Supports both absolute and relative paths. ALWAYS use this before editing a file.',\n schema: z.object({\n file_path: z\n .string()\n .describe('Path to the file (absolute or relative to working directory)'),\n offset: z\n .number()\n .optional()\n .describe('Line number to start from (0-indexed)'),\n limit: z\n .number()\n .optional()\n .describe('Number of lines to read'),\n }),\n },\n );\n }\n\n private createWriteFileTool() {\n return tool(\n async (input) => {\n try {\n const filePath = (input as any).filePath || (input as any).file_path;\n const content = (input as any).content;\n\n if (!filePath || content === undefined) {\n return 'Error: file_path and content are required';\n }\n\n const resolvedPath = path.isAbsolute(filePath)\n ? filePath\n : path.resolve(process.cwd(), filePath);\n\n let fileExists = false;\n try {\n await fs.access(resolvedPath);\n fileExists = true;\n } catch {\n }\n\n if (fileExists && !this.readFiles.has(resolvedPath)) {\n this.readFiles.add(resolvedPath);\n }\n\n const dir = path.dirname(resolvedPath);\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(resolvedPath, content, 'utf-8');\n\n this.readFiles.add(resolvedPath);\n\n const lines = content.split('\\n').length;\n return `File written successfully: ${resolvedPath} (${lines} lines)`;\n } catch (error) {\n return `Error writing file: ${(error as Error).message}`;\n }\n },\n {\n name: 'write_file',\n description:\n 'Write content to a file. Creates directories if needed. Prefer edit_file for modifying existing files.',\n schema: z.object({\n file_path: z\n .string()\n .describe('Path to the file (absolute or relative)'),\n content: z.string().describe('Content to write'),\n }),\n },\n );\n }\n\n private createEditFileTool() {\n return tool(\n async (input) => {\n try {\n const filePath = (input as any).filePath || (input as any).file_path;\n const oldString = (input as any).oldString || (input as any).old_string;\n const newString = (input as any).newString || (input as any).new_string;\n const replaceAll =\n (input as any).replaceAll || (input as any).replace_all || false;\n\n if (!filePath || oldString === undefined || newString === undefined) {\n return 'Error: file_path, old_string, and new_string are required';\n }\n\n const resolvedPath = path.isAbsolute(filePath)\n ? filePath\n : path.resolve(process.cwd(), filePath);\n\n if (oldString === newString) {\n return 'Error: old_string and new_string are identical. No changes needed.';\n }\n\n if (!this.readFiles.has(resolvedPath)) {\n return `Error: You must read_file(\"${filePath}\") before editing it. This ensures you understand the current content.`;\n }\n\n const content = await fs.readFile(resolvedPath, 'utf-8');\n\n if (!content.includes(oldString)) {\n const lines = content.split('\\n');\n const trimmedOld = oldString.trim();\n const approxMatch = lines.findIndex((l) =>\n l.trim().includes(trimmedOld),\n );\n\n if (approxMatch !== -1) {\n return `Error: exact old_string not found. Possible match at line ${approxMatch + 1}:\\n \"${lines[approxMatch].trim()}\"\\n\\nMake sure whitespace and indentation match exactly.`;\n }\n\n return `Error: old_string not found in file. Make sure it matches the file content exactly (including whitespace).`;\n }\n\n const occurrences = content.split(oldString).length - 1;\n if (occurrences > 1 && !replaceAll) {\n return `Error: old_string found ${occurrences} times. Either:\\n1. Provide more surrounding context to make it unique\\n2. Use replace_all=true to replace all occurrences`;\n }\n\n const newContent = replaceAll\n ? content.replaceAll(oldString, newString)\n : content.replace(oldString, newString);\n\n await fs.writeFile(resolvedPath, newContent, 'utf-8');\n\n const replacedCount = replaceAll ? occurrences : 1;\n return `File edited successfully: ${resolvedPath} (${replacedCount} replacement${replacedCount > 1 ? 's' : ''})`;\n } catch (error) {\n return `Error editing file: ${(error as Error).message}`;\n }\n },\n {\n name: 'edit_file',\n description:\n 'Edit a file by replacing exact string matches. You MUST read_file first. Provides helpful error messages if the string is not found or ambiguous.',\n schema: z.object({\n file_path: z\n .string()\n .describe('Path to the file (absolute or relative)'),\n old_string: z\n .string()\n .describe('Exact text to replace (must match exactly including whitespace)'),\n new_string: z\n .string()\n .describe('New text to replace with (must be different from old_string)'),\n replace_all: z\n .boolean()\n .optional()\n .default(false)\n .describe('Replace all occurrences (default: false)'),\n }),\n },\n );\n }\n\n private createGlobTool() {\n return tool(\n async ({ pattern, cwd }) => {\n try {\n const searchDir = cwd\n ? (path.isAbsolute(cwd) ? cwd : path.resolve(process.cwd(), cwd))\n : process.cwd();\n\n const files = await glob(pattern, {\n cwd: searchDir,\n ignore: DEFAULT_IGNORE,\n });\n\n if (files.length === 0) {\n return `No files found matching \"${pattern}\" in ${searchDir}.\\nTip: The working directory is ${process.cwd()}. Use \"**/*.ext\" to search recursively.`;\n }\n\n const sorted = files.sort();\n const limited = sorted.slice(0, 200);\n\n let result = `Found ${sorted.length} file(s) matching \"${pattern}\" in ${searchDir}:\\n\\n`;\n result += limited.join('\\n');\n if (sorted.length > 200) {\n result += `\\n\\n... (${sorted.length - 200} more files. Use a more specific pattern.)`;\n }\n\n return result;\n } catch (error) {\n return `Error: ${(error as Error).message}`;\n }\n },\n {\n name: 'glob',\n description:\n 'Find files matching a glob pattern. Ignores node_modules, .git, dist by default. Returns up to 200 results sorted alphabetically.',\n schema: z.object({\n pattern: z\n .string()\n .describe('Glob pattern (e.g., \"**/*.ts\", \"src/**/*.service.ts\")'),\n cwd: z\n .string()\n .optional()\n .describe('Working directory (default: project root). Can be relative or absolute.'),\n }),\n },\n );\n }\n\n private createGrepTool() {\n return tool(\n async (input) => {\n try {\n const pattern = (input as any).pattern;\n const searchPath =\n (input as any).searchPath || (input as any).search_path;\n const filePattern =\n (input as any).filePattern || (input as any).file_pattern;\n const contextLines =\n (input as any).contextLines || (input as any).context_lines || 0;\n const caseSensitive =\n (input as any).caseSensitive ?? (input as any).case_sensitive ?? false;\n const outputMode =\n (input as any).outputMode || (input as any).output_mode || 'content';\n const maxResults =\n (input as any).maxResults || (input as any).max_results || 100;\n\n if (!pattern) {\n return 'Error: pattern is required';\n }\n\n const baseDir = searchPath || process.cwd();\n const files = await glob(filePattern || '**/*', {\n cwd: baseDir,\n nodir: true,\n ignore: DEFAULT_IGNORE,\n });\n\n const flags = caseSensitive ? 'g' : 'gi';\n let regex: RegExp;\n try {\n regex = new RegExp(pattern, flags);\n } catch (regexError) {\n return `Error: Invalid regex pattern \"${pattern}\": ${(regexError as Error).message}. Use a valid JavaScript regex.`;\n }\n\n if (outputMode === 'files_with_matches') {\n const matchingFiles: string[] = [];\n for (const file of files.slice(0, 500)) {\n try {\n const fullPath = path.join(baseDir, file);\n const content = await fs.readFile(fullPath, 'utf-8');\n if (regex.test(content)) {\n matchingFiles.push(file);\n }\n regex.lastIndex = 0;\n } catch {\n continue;\n }\n }\n if (matchingFiles.length === 0) return 'No matching files found';\n return matchingFiles.slice(0, maxResults).join('\\n');\n }\n\n if (outputMode === 'count') {\n const counts: string[] = [];\n for (const file of files.slice(0, 500)) {\n try {\n const fullPath = path.join(baseDir, file);\n const content = await fs.readFile(fullPath, 'utf-8');\n const allFlags = caseSensitive ? 'g' : 'gi';\n const matches = content.match(new RegExp(pattern, allFlags));\n if (matches && matches.length > 0) {\n counts.push(`${file}: ${matches.length}`);\n }\n } catch {\n continue;\n }\n }\n if (counts.length === 0) return 'No matches found';\n return counts.slice(0, maxResults).join('\\n');\n }\n\n const results: string[] = [];\n let totalMatches = 0;\n\n for (const file of files.slice(0, 500)) {\n if (totalMatches >= maxResults) break;\n\n try {\n const fullPath = path.join(baseDir, file);\n const content = await fs.readFile(fullPath, 'utf-8');\n const lines = content.split('\\n');\n\n const matchingLineIndices: number[] = [];\n lines.forEach((line, index) => {\n if (regex.test(line)) {\n matchingLineIndices.push(index);\n }\n regex.lastIndex = 0;\n });\n\n if (matchingLineIndices.length === 0) continue;\n\n for (const lineIdx of matchingLineIndices) {\n if (totalMatches >= maxResults) break;\n\n if (contextLines > 0) {\n const start = Math.max(0, lineIdx - contextLines);\n const end = Math.min(lines.length - 1, lineIdx + contextLines);\n\n results.push(`--- ${file} ---`);\n for (let i = start; i <= end; i++) {\n const prefix = i === lineIdx ? '>' : ' ';\n results.push(`${prefix} ${i + 1}: ${lines[i].trimEnd()}`);\n }\n results.push('');\n } else {\n results.push(`${file}:${lineIdx + 1}: ${lines[lineIdx].trim()}`);\n }\n totalMatches++;\n }\n } catch {\n continue;\n }\n }\n\n if (results.length === 0) {\n return 'No matches found';\n }\n\n let output = results.join('\\n');\n if (totalMatches >= maxResults) {\n output += `\\n\\n(Showing first ${maxResults} matches. Use max_results to see more or narrow your search.)`;\n }\n\n return output;\n } catch (error) {\n return `Error: ${(error as Error).message}`;\n }\n },\n {\n name: 'grep',\n description:\n 'Search for a regex pattern in files. Supports context lines, case sensitivity, and multiple output modes. Ignores node_modules, .git, dist by default.',\n schema: z.object({\n pattern: z.string().describe('Regex pattern to search'),\n search_path: z\n .string()\n .optional()\n .describe('Directory to search in (default: project root)'),\n file_pattern: z\n .string()\n .optional()\n .describe('Glob pattern for files (e.g., \"**/*.ts\")'),\n context_lines: z\n .number()\n .optional()\n .describe('Number of context lines before/after each match (like grep -C)'),\n case_sensitive: z\n .boolean()\n .optional()\n .describe('Case sensitive search (default: false)'),\n output_mode: z\n .enum(['content', 'files_with_matches', 'count'])\n .optional()\n .describe(\n 'Output mode: \"content\" (default), \"files_with_matches\" (just paths), \"count\" (match counts)',\n ),\n max_results: z\n .number()\n .optional()\n .describe('Maximum results to return (default: 100)'),\n }),\n },\n );\n }\n\n private createLsTool() {\n return tool(\n async (input) => {\n try {\n const directory =\n (input as any).directory || (input as any).path || process.cwd();\n\n const resolvedPath = path.isAbsolute(directory)\n ? directory\n : path.resolve(process.cwd(), directory);\n\n const entries = await fs.readdir(resolvedPath, { withFileTypes: true });\n\n if (entries.length === 0) {\n return `Directory \"${resolvedPath}\" is empty`;\n }\n\n const dirs = entries\n .filter((e) => e.isDirectory())\n .sort((a, b) => a.name.localeCompare(b.name));\n const files = entries\n .filter((e) => !e.isDirectory())\n .sort((a, b) => a.name.localeCompare(b.name));\n\n const lines = [\n `Directory: ${resolvedPath}`,\n `${dirs.length} directories, ${files.length} files`,\n '',\n ...dirs.map((e) => `d ${e.name}/`),\n ...files.map((e) => `f ${e.name}`),\n ];\n\n return lines.join('\\n');\n } catch (error) {\n const err = error as NodeJS.ErrnoException;\n if (err.code === 'ENOENT') {\n return `Directory not found: \"${(input as any).directory || (input as any).path}\"`;\n }\n return `Error: ${err.message}`;\n }\n },\n {\n name: 'ls',\n description:\n 'List directory contents. Shows directories first (with /), then files. Supports relative paths.',\n schema: z.object({\n directory: z\n .string()\n .optional()\n .describe('Directory path (default: working directory)'),\n path: z\n .string()\n .optional()\n .describe('Alias for directory'),\n }),\n },\n );\n }\n}\n"],"names":["FilesystemToolsService","DEFAULT_IGNORE","getTools","createReadFileTool","createWriteFileTool","createEditFileTool","createGlobTool","createGrepTool","createLsTool","tool","input","filePath","file_path","offset","limit","resolvedPath","path","isAbsolute","resolve","process","cwd","stat","fs","isDirectory","entries","readdir","withFileTypes","listing","slice","map","e","name","join","length","buffer","Buffer","alloc","fd","open","read","close","hasBinaryBytes","some","byte","i","Math","round","size","error","err","code","basename","matches","glob","ignore","m","message","content","readFile","trim","lines","split","start","end","selectedLines","formatted","line","lineNum","truncated","readFiles","add","description","schema","z","object","string","describe","number","optional","undefined","fileExists","access","has","dir","dirname","mkdir","recursive","writeFile","oldString","old_string","newString","new_string","replaceAll","replace_all","includes","trimmedOld","approxMatch","findIndex","l","occurrences","newContent","replace","replacedCount","boolean","default","pattern","searchDir","files","sorted","sort","limited","result","searchPath","search_path","filePattern","file_pattern","contextLines","context_lines","caseSensitive","case_sensitive","outputMode","output_mode","maxResults","max_results","baseDir","nodir","flags","regex","RegExp","regexError","matchingFiles","file","fullPath","test","push","lastIndex","counts","allFlags","match","results","totalMatches","matchingLineIndices","forEach","index","lineIdx","max","min","prefix","trimEnd","output","enum","directory","dirs","filter","a","b","localeCompare","Set"],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "SearchToolsService", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return SearchToolsService;
9
+ }
10
+ });
11
+ const _common = require("@nestjs/common");
12
+ const _tools = require("@langchain/core/tools");
13
+ const _zod = require("zod");
14
+ function _ts_decorate(decorators, target, key, desc) {
15
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
+ else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
18
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
19
+ }
20
+ let SearchToolsService = class SearchToolsService {
21
+ getTools() {
22
+ return [
23
+ this.createWebSearchTool(),
24
+ this.createWebFetchTool()
25
+ ];
26
+ }
27
+ createWebSearchTool() {
28
+ return (0, _tools.tool)(async ({ query })=>{
29
+ return `Web search for "${query}" - Integration pending. Configure search provider in .cast/config.md`;
30
+ }, {
31
+ name: 'web_search',
32
+ description: 'Search the web for information.',
33
+ schema: _zod.z.object({
34
+ query: _zod.z.string().describe('Search query')
35
+ })
36
+ });
37
+ }
38
+ createWebFetchTool() {
39
+ return (0, _tools.tool)(async ({ url })=>{
40
+ try {
41
+ const response = await fetch(url);
42
+ const text = await response.text();
43
+ if (text.length > 50000) {
44
+ return text.slice(0, 50000) + '\n... (truncated)';
45
+ }
46
+ return text;
47
+ } catch (error) {
48
+ return `Error fetching URL: ${error.message}`;
49
+ }
50
+ }, {
51
+ name: 'web_fetch',
52
+ description: 'Fetch content from a URL.',
53
+ schema: _zod.z.object({
54
+ url: _zod.z.string().describe('URL to fetch')
55
+ })
56
+ });
57
+ }
58
+ };
59
+ SearchToolsService = _ts_decorate([
60
+ (0, _common.Injectable)()
61
+ ], SearchToolsService);
62
+
63
+ //# sourceMappingURL=search-tools.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/modules/tools/services/search-tools.service.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\nimport { tool } from '@langchain/core/tools';\nimport { z } from 'zod';\n\n@Injectable()\nexport class SearchToolsService {\n getTools() {\n return [this.createWebSearchTool(), this.createWebFetchTool()];\n }\n\n private createWebSearchTool() {\n return tool(\n async ({ query }) => {\n return `Web search for \"${query}\" - Integration pending. Configure search provider in .cast/config.md`;\n },\n {\n name: 'web_search',\n description: 'Search the web for information.',\n schema: z.object({\n query: z.string().describe('Search query'),\n }),\n },\n );\n }\n\n private createWebFetchTool() {\n return tool(\n async ({ url }) => {\n try {\n const response = await fetch(url);\n const text = await response.text();\n\n if (text.length > 50000) {\n return text.slice(0, 50000) + '\\n... (truncated)';\n }\n\n return text;\n } catch (error) {\n return `Error fetching URL: ${(error as Error).message}`;\n }\n },\n {\n name: 'web_fetch',\n description: 'Fetch content from a URL.',\n schema: z.object({\n url: z.string().describe('URL to fetch'),\n }),\n },\n );\n }\n}\n"],"names":["SearchToolsService","getTools","createWebSearchTool","createWebFetchTool","tool","query","name","description","schema","z","object","string","describe","url","response","fetch","text","length","slice","error","message"],"mappings":";;;;+BAKaA;;;eAAAA;;;wBALc;uBACN;qBACH;;;;;;;AAGX,IAAA,AAAMA,qBAAN,MAAMA;IACXC,WAAW;QACT,OAAO;YAAC,IAAI,CAACC,mBAAmB;YAAI,IAAI,CAACC,kBAAkB;SAAG;IAChE;IAEQD,sBAAsB;QAC5B,OAAOE,IAAAA,WAAI,EACT,OAAO,EAAEC,KAAK,EAAE;YACd,OAAO,CAAC,gBAAgB,EAAEA,MAAM,qEAAqE,CAAC;QACxG,GACA;YACEC,MAAM;YACNC,aAAa;YACbC,QAAQC,MAAC,CAACC,MAAM,CAAC;gBACfL,OAAOI,MAAC,CAACE,MAAM,GAAGC,QAAQ,CAAC;YAC7B;QACF;IAEJ;IAEQT,qBAAqB;QAC3B,OAAOC,IAAAA,WAAI,EACT,OAAO,EAAES,GAAG,EAAE;YACZ,IAAI;gBACF,MAAMC,WAAW,MAAMC,MAAMF;gBAC7B,MAAMG,OAAO,MAAMF,SAASE,IAAI;gBAEhC,IAAIA,KAAKC,MAAM,GAAG,OAAO;oBACvB,OAAOD,KAAKE,KAAK,CAAC,GAAG,SAAS;gBAChC;gBAEA,OAAOF;YACT,EAAE,OAAOG,OAAO;gBACd,OAAO,CAAC,oBAAoB,EAAE,AAACA,MAAgBC,OAAO,EAAE;YAC1D;QACF,GACA;YACEd,MAAM;YACNC,aAAa;YACbC,QAAQC,MAAC,CAACC,MAAM,CAAC;gBACfG,KAAKJ,MAAC,CAACE,MAAM,GAAGC,QAAQ,CAAC;YAC3B;QACF;IAEJ;AACF"}