@timetotest/cli 0.2.3 → 0.3.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 (200) hide show
  1. package/README.md +49 -40
  2. package/dist/bin/ttt.js +0 -2
  3. package/dist/bin/ttt.js.map +1 -1
  4. package/dist/package.json +13 -6
  5. package/dist/src/commands/chat/ChatApp.js +270 -100
  6. package/dist/src/commands/chat/ChatApp.js.map +1 -1
  7. package/dist/src/commands/chat/components/Banner.js +1 -1
  8. package/dist/src/commands/chat/components/ChatInput.js +97 -36
  9. package/dist/src/commands/chat/components/ChatInput.js.map +1 -1
  10. package/dist/src/commands/chat/components/ChatMessage.js +102 -0
  11. package/dist/src/commands/chat/components/ChatMessage.js.map +1 -0
  12. package/dist/src/commands/chat/components/MessageBubble.js +2 -1
  13. package/dist/src/commands/chat/components/MessageBubble.js.map +1 -1
  14. package/dist/src/commands/chat/components/PermissionPrompt.js +92 -0
  15. package/dist/src/commands/chat/components/PermissionPrompt.js.map +1 -0
  16. package/dist/src/commands/chat/components/StatusIndicator.js +21 -5
  17. package/dist/src/commands/chat/components/StatusIndicator.js.map +1 -1
  18. package/dist/src/commands/chat/components/ToolCallDisplay.js +141 -0
  19. package/dist/src/commands/chat/components/ToolCallDisplay.js.map +1 -0
  20. package/dist/src/commands/chat-ink.js +389 -61
  21. package/dist/src/commands/chat-ink.js.map +1 -1
  22. package/dist/src/commands/login.js +5 -5
  23. package/dist/src/commands/login.js.map +1 -1
  24. package/dist/src/commands/test.js +14 -194
  25. package/dist/src/commands/test.js.map +1 -1
  26. package/dist/src/lib/__tests__/code-mode-integration.test.js +381 -0
  27. package/dist/src/lib/__tests__/code-mode-integration.test.js.map +1 -0
  28. package/dist/src/lib/__tests__/config-manager.test.js +81 -0
  29. package/dist/src/lib/__tests__/config-manager.test.js.map +1 -0
  30. package/dist/src/lib/__tests__/mode-persistence-integration.test.js +75 -0
  31. package/dist/src/lib/__tests__/mode-persistence-integration.test.js.map +1 -0
  32. package/dist/src/lib/__tests__/permission-flow-integration.test.js +145 -0
  33. package/dist/src/lib/__tests__/permission-flow-integration.test.js.map +1 -0
  34. package/dist/src/lib/__tests__/permissions.test.js +132 -0
  35. package/dist/src/lib/__tests__/permissions.test.js.map +1 -0
  36. package/dist/src/lib/agent-orchestrator.js +263 -4
  37. package/dist/src/lib/agent-orchestrator.js.map +1 -1
  38. package/dist/src/lib/config.js +40 -0
  39. package/dist/src/lib/config.js.map +1 -1
  40. package/dist/src/lib/context-compactor.js +310 -0
  41. package/dist/src/lib/context-compactor.js.map +1 -0
  42. package/dist/src/lib/http.js +8 -0
  43. package/dist/src/lib/http.js.map +1 -1
  44. package/dist/src/lib/local-tools/code/__tests__/grep-search.test.js +146 -0
  45. package/dist/src/lib/local-tools/code/__tests__/grep-search.test.js.map +1 -0
  46. package/dist/src/lib/local-tools/code/__tests__/list-directory.test.js +192 -0
  47. package/dist/src/lib/local-tools/code/__tests__/list-directory.test.js.map +1 -0
  48. package/dist/src/lib/local-tools/code/__tests__/read-file.test.js +169 -0
  49. package/dist/src/lib/local-tools/code/__tests__/read-file.test.js.map +1 -0
  50. package/dist/src/lib/local-tools/code/__tests__/run-command.test.js +101 -0
  51. package/dist/src/lib/local-tools/code/__tests__/run-command.test.js.map +1 -0
  52. package/dist/src/lib/local-tools/code/__tests__/search-files.test.js +191 -0
  53. package/dist/src/lib/local-tools/code/__tests__/search-files.test.js.map +1 -0
  54. package/dist/src/lib/local-tools/code/grep-search.js +404 -0
  55. package/dist/src/lib/local-tools/code/grep-search.js.map +1 -0
  56. package/dist/src/lib/local-tools/code/index.js +11 -0
  57. package/dist/src/lib/local-tools/code/index.js.map +1 -0
  58. package/dist/src/lib/local-tools/code/list-directory.js +276 -0
  59. package/dist/src/lib/local-tools/code/list-directory.js.map +1 -0
  60. package/dist/src/lib/local-tools/code/read-file.js +301 -0
  61. package/dist/src/lib/local-tools/code/read-file.js.map +1 -0
  62. package/dist/src/lib/local-tools/code/run-command.js +235 -0
  63. package/dist/src/lib/local-tools/code/run-command.js.map +1 -0
  64. package/dist/src/lib/local-tools/code/search-files.js +297 -0
  65. package/dist/src/lib/local-tools/code/search-files.js.map +1 -0
  66. package/dist/src/lib/local-tools/code/types.js +6 -0
  67. package/dist/src/lib/local-tools/code/types.js.map +1 -0
  68. package/dist/src/lib/local-tools/ui/playwright-mcp.js +1 -1
  69. package/dist/src/lib/permissions.js +94 -0
  70. package/dist/src/lib/permissions.js.map +1 -0
  71. package/dist/src/lib/prompts/builder.js +13 -10
  72. package/dist/src/lib/prompts/builder.js.map +1 -1
  73. package/dist/src/lib/prompts/templates.js +78 -0
  74. package/dist/src/lib/prompts/templates.js.map +1 -1
  75. package/dist/src/lib/session-manager.js.map +1 -1
  76. package/dist/src/lib/testing-mode.js +2 -2
  77. package/dist/src/lib/testing-mode.js.map +1 -1
  78. package/dist/src/lib/tool-executor.js +131 -2
  79. package/dist/src/lib/tool-executor.js.map +1 -1
  80. package/dist/src/lib/tool-registry.js +171 -3
  81. package/dist/src/lib/tool-registry.js.map +1 -1
  82. package/dist/src/lib/tool-result-pruner.js +4 -4
  83. package/dist/src/lib/tool-result-pruner.js.map +1 -1
  84. package/dist/src/lib/tui/ink/components/AppFrame.js +17 -0
  85. package/dist/src/lib/tui/ink/components/AppFrame.js.map +1 -0
  86. package/dist/src/lib/tui/ink/components/CommandPalette.js +24 -0
  87. package/dist/src/lib/tui/ink/components/CommandPalette.js.map +1 -0
  88. package/dist/src/lib/tui/ink/components/Pill.js +19 -0
  89. package/dist/src/lib/tui/ink/components/Pill.js.map +1 -0
  90. package/dist/src/lib/tui/ink/components/TimetoTestLogo.js +30 -0
  91. package/dist/src/lib/tui/ink/components/TimetoTestLogo.js.map +1 -0
  92. package/dist/src/lib/tui/ink/theme.js +28 -0
  93. package/dist/src/lib/tui/ink/theme.js.map +1 -0
  94. package/dist/src/lib/tui/interactive-chat.js +35 -35
  95. package/dist/src/lib/tui/interactive-chat.js.map +1 -1
  96. package/dist/src/lib/tui/print.js +18 -18
  97. package/dist/src/lib/tui/print.js.map +1 -1
  98. package/dist/src/lib/tui/prompt.js +3 -3
  99. package/dist/src/lib/tui/prompt.js.map +1 -1
  100. package/dist/src/lib/tui/status.js +1 -1
  101. package/dist/src/lib/tui/status.js.map +1 -1
  102. package/dist/src/lib/update.js +10 -10
  103. package/dist/src/lib/update.js.map +1 -1
  104. package/package.json +13 -6
  105. package/dist/src/commands/ask/AskApp.js +0 -121
  106. package/dist/src/commands/ask/AskApp.js.map +0 -1
  107. package/dist/src/commands/ask/components/AssistantResponse.js +0 -31
  108. package/dist/src/commands/ask/components/AssistantResponse.js.map +0 -1
  109. package/dist/src/commands/ask/components/Banner.js +0 -15
  110. package/dist/src/commands/ask/components/Banner.js.map +0 -1
  111. package/dist/src/commands/ask/components/ChatInput.js +0 -93
  112. package/dist/src/commands/ask/components/ChatInput.js.map +0 -1
  113. package/dist/src/commands/ask/components/Divider.js +0 -17
  114. package/dist/src/commands/ask/components/Divider.js.map +0 -1
  115. package/dist/src/commands/ask/components/IntroTips.js +0 -19
  116. package/dist/src/commands/ask/components/IntroTips.js.map +0 -1
  117. package/dist/src/commands/ask/components/MessageBubble.js +0 -47
  118. package/dist/src/commands/ask/components/MessageBubble.js.map +0 -1
  119. package/dist/src/commands/ask/components/SessionInfo.js +0 -20
  120. package/dist/src/commands/ask/components/SessionInfo.js.map +0 -1
  121. package/dist/src/commands/ask/components/StatusIndicator.js +0 -67
  122. package/dist/src/commands/ask/components/StatusIndicator.js.map +0 -1
  123. package/dist/src/commands/ask-ink.js +0 -380
  124. package/dist/src/commands/ask-ink.js.map +0 -1
  125. package/dist/src/commands/ask.js +0 -991
  126. package/dist/src/commands/ask.js.map +0 -1
  127. package/dist/src/commands/chat/components/Divider.js +0 -7
  128. package/dist/src/commands/chat/components/Divider.js.map +0 -1
  129. package/dist/src/commands/chat/components/SessionInfo.js +0 -11
  130. package/dist/src/commands/chat/components/SessionInfo.js.map +0 -1
  131. package/dist/src/commands/chat.js +0 -82
  132. package/dist/src/commands/chat.js.map +0 -1
  133. package/dist/src/commands/start-test.js +0 -119
  134. package/dist/src/commands/start-test.js.map +0 -1
  135. package/dist/src/commands/stream.js +0 -17
  136. package/dist/src/commands/stream.js.map +0 -1
  137. package/dist/src/lib/legacy-chat-runner.js +0 -37
  138. package/dist/src/lib/legacy-chat-runner.js.map +0 -1
  139. package/dist/src/lib/local-tools/ui/click-element.js +0 -105
  140. package/dist/src/lib/local-tools/ui/click-element.js.map +0 -1
  141. package/dist/src/lib/local-tools/ui/dom-rag.js +0 -201
  142. package/dist/src/lib/local-tools/ui/dom-rag.js.map +0 -1
  143. package/dist/src/lib/local-tools/ui/find-element.js +0 -31
  144. package/dist/src/lib/local-tools/ui/find-element.js.map +0 -1
  145. package/dist/src/lib/local-tools/ui/hover-element.js +0 -94
  146. package/dist/src/lib/local-tools/ui/hover-element.js.map +0 -1
  147. package/dist/src/lib/local-tools/ui/manage-tab.js +0 -65
  148. package/dist/src/lib/local-tools/ui/manage-tab.js.map +0 -1
  149. package/dist/src/lib/local-tools/ui/navigate.js +0 -35
  150. package/dist/src/lib/local-tools/ui/navigate.js.map +0 -1
  151. package/dist/src/lib/local-tools/ui/page-discovery.js +0 -32
  152. package/dist/src/lib/local-tools/ui/page-discovery.js.map +0 -1
  153. package/dist/src/lib/local-tools/ui/screenshot.js +0 -19
  154. package/dist/src/lib/local-tools/ui/screenshot.js.map +0 -1
  155. package/dist/src/lib/local-tools/ui/search-interactive-elements.js +0 -18
  156. package/dist/src/lib/local-tools/ui/search-interactive-elements.js.map +0 -1
  157. package/dist/src/lib/local-tools/ui/selector-resolver.js +0 -153
  158. package/dist/src/lib/local-tools/ui/selector-resolver.js.map +0 -1
  159. package/dist/src/lib/local-tools/ui/type-text.js +0 -40
  160. package/dist/src/lib/local-tools/ui/type-text.js.map +0 -1
  161. package/dist/src/lib/tui/components/AskIntro.js +0 -6
  162. package/dist/src/lib/tui/components/AskIntro.js.map +0 -1
  163. package/dist/src/lib/tui/components/Banner.js +0 -15
  164. package/dist/src/lib/tui/components/Banner.js.map +0 -1
  165. package/dist/src/lib/tui/components/Divider.js +0 -17
  166. package/dist/src/lib/tui/components/Divider.js.map +0 -1
  167. package/dist/src/lib/tui/components/EventLine.js +0 -110
  168. package/dist/src/lib/tui/components/EventLine.js.map +0 -1
  169. package/dist/src/lib/tui/components/Header.js +0 -15
  170. package/dist/src/lib/tui/components/Header.js.map +0 -1
  171. package/dist/src/lib/tui/components/InputBox.js +0 -9
  172. package/dist/src/lib/tui/components/InputBox.js.map +0 -1
  173. package/dist/src/lib/tui/components/Mapping.js +0 -8
  174. package/dist/src/lib/tui/components/Mapping.js.map +0 -1
  175. package/dist/src/lib/tui/components/ProjectList.js +0 -6
  176. package/dist/src/lib/tui/components/ProjectList.js.map +0 -1
  177. package/dist/src/lib/tui/components/Spinner.js +0 -20
  178. package/dist/src/lib/tui/components/Spinner.js.map +0 -1
  179. package/dist/src/lib/tui/components/StatusBanner.js +0 -12
  180. package/dist/src/lib/tui/components/StatusBanner.js.map +0 -1
  181. package/dist/src/lib/tui/components/StatusBar.js +0 -11
  182. package/dist/src/lib/tui/components/StatusBar.js.map +0 -1
  183. package/dist/src/lib/tui/components/UserBubble.js +0 -6
  184. package/dist/src/lib/tui/components/UserBubble.js.map +0 -1
  185. package/dist/src/lib/tui/components/index.js +0 -16
  186. package/dist/src/lib/tui/components/index.js.map +0 -1
  187. package/dist/src/lib/tui/ink-print.js +0 -41
  188. package/dist/src/lib/tui/ink-print.js.map +0 -1
  189. package/dist/src/test-agent-flow.js +0 -148
  190. package/dist/src/test-agent-flow.js.map +0 -1
  191. package/dist/src/test-browser-session.js +0 -152
  192. package/dist/src/test-browser-session.js.map +0 -1
  193. package/dist/src/test-browser-snapshot.js +0 -187
  194. package/dist/src/test-browser-snapshot.js.map +0 -1
  195. package/dist/src/test-snapshot-detailed.js +0 -219
  196. package/dist/src/test-snapshot-detailed.js.map +0 -1
  197. package/dist/src/test-snapshot-simple.js +0 -85
  198. package/dist/src/test-snapshot-simple.js.map +0 -1
  199. package/dist/src/test-snapshot-tabs.js +0 -110
  200. package/dist/src/test-snapshot-tabs.js.map +0 -1
@@ -0,0 +1,276 @@
1
+ /**
2
+ * list_directory tool - List directory contents with filtering options.
3
+ * Supports glob pattern filtering, recursive listing, and hidden file filtering.
4
+ *
5
+ * Security: Implements path validation to prevent directory traversal (TR-5).
6
+ */
7
+ import * as fs from "fs/promises";
8
+ import * as path from "path";
9
+ // Default max depth for recursive listing to prevent excessive traversal
10
+ const DEFAULT_MAX_DEPTH = 10;
11
+ // Maximum number of entries to return to prevent memory issues
12
+ const MAX_ENTRIES = 1000;
13
+ /**
14
+ * Validate and resolve a directory path to prevent directory traversal.
15
+ * Returns the resolved absolute path if valid, or an error.
16
+ *
17
+ * Security (TR-5):
18
+ * - All paths normalized and validated against project root
19
+ * - Reject paths containing `..` that escape root
20
+ * - Use `path.resolve()` and check prefix
21
+ */
22
+ function validatePath(dirPath, workingDirectory) {
23
+ // Normalize the working directory to absolute path
24
+ const rootDir = path.resolve(workingDirectory);
25
+ // Resolve the requested path relative to working directory
26
+ const resolvedPath = path.resolve(rootDir, dirPath);
27
+ // Security check: ensure resolved path is within root directory
28
+ // Use path.sep to ensure we're checking directory boundaries properly
29
+ const normalizedRoot = rootDir.endsWith(path.sep)
30
+ ? rootDir
31
+ : rootDir + path.sep;
32
+ const normalizedResolved = resolvedPath + path.sep;
33
+ if (!normalizedResolved.startsWith(normalizedRoot) &&
34
+ resolvedPath !== rootDir) {
35
+ return {
36
+ valid: false,
37
+ error: "Path validation failed: access denied",
38
+ };
39
+ }
40
+ return { valid: true, resolvedPath };
41
+ }
42
+ /**
43
+ * Check if a filename matches a glob pattern.
44
+ * Supports basic glob patterns: *, ?, and character classes [abc].
45
+ */
46
+ function matchesGlobPattern(filename, pattern) {
47
+ // Convert glob pattern to regex
48
+ let regexPattern = pattern
49
+ // Escape special regex characters except glob wildcards
50
+ .replace(/[.+^${}()|[\]\\]/g, "\\$&")
51
+ // Convert glob * to regex .*
52
+ .replace(/\*/g, ".*")
53
+ // Convert glob ? to regex .
54
+ .replace(/\?/g, ".");
55
+ // Create regex with case-insensitive matching for cross-platform compatibility
56
+ const regex = new RegExp(`^${regexPattern}$`, "i");
57
+ return regex.test(filename);
58
+ }
59
+ /**
60
+ * Check if a file/directory name is hidden (starts with .).
61
+ */
62
+ function isHidden(name) {
63
+ return name.startsWith(".");
64
+ }
65
+ /**
66
+ * Get file/directory stats and create a DirectoryEntry.
67
+ */
68
+ async function createDirectoryEntry(entryPath, name) {
69
+ try {
70
+ const stats = await fs.stat(entryPath);
71
+ const entry = {
72
+ name,
73
+ type: stats.isDirectory() ? "directory" : "file",
74
+ };
75
+ // Add size for files
76
+ if (!stats.isDirectory()) {
77
+ entry.size = stats.size;
78
+ }
79
+ // Add modification time
80
+ entry.modified = stats.mtime.toISOString();
81
+ return entry;
82
+ }
83
+ catch {
84
+ // Skip entries we can't stat (permission issues, etc.)
85
+ return null;
86
+ }
87
+ }
88
+ /**
89
+ * Recursively list directory contents.
90
+ */
91
+ async function listDirectoryRecursive(dirPath, rootDir, options) {
92
+ // Check depth limit
93
+ if (options.currentDepth > options.maxDepth) {
94
+ return;
95
+ }
96
+ // Check entry limit
97
+ if (options.entries.length >= MAX_ENTRIES) {
98
+ return;
99
+ }
100
+ try {
101
+ const items = await fs.readdir(dirPath);
102
+ for (const item of items) {
103
+ // Check entry limit
104
+ if (options.entries.length >= MAX_ENTRIES) {
105
+ return;
106
+ }
107
+ // Skip hidden files if not included
108
+ if (!options.includeHidden && isHidden(item)) {
109
+ continue;
110
+ }
111
+ const fullPath = path.join(dirPath, item);
112
+ // Calculate relative path from base for display
113
+ const relativePath = options.basePath === "."
114
+ ? item
115
+ : path.join(path.relative(path.resolve(rootDir, options.basePath), dirPath), item);
116
+ // Apply pattern filter if specified
117
+ if (options.pattern && !matchesGlobPattern(item, options.pattern)) {
118
+ // For directories, still recurse even if name doesn't match pattern
119
+ // (files inside might match)
120
+ try {
121
+ const stats = await fs.stat(fullPath);
122
+ if (stats.isDirectory()) {
123
+ await listDirectoryRecursive(fullPath, rootDir, {
124
+ ...options,
125
+ currentDepth: options.currentDepth + 1,
126
+ });
127
+ }
128
+ }
129
+ catch {
130
+ // Skip on error
131
+ }
132
+ continue;
133
+ }
134
+ const entry = await createDirectoryEntry(fullPath, relativePath);
135
+ if (entry) {
136
+ options.entries.push(entry);
137
+ // Recurse into directories
138
+ if (entry.type === "directory") {
139
+ await listDirectoryRecursive(fullPath, rootDir, {
140
+ ...options,
141
+ currentDepth: options.currentDepth + 1,
142
+ });
143
+ }
144
+ }
145
+ }
146
+ }
147
+ catch {
148
+ // Skip directories we can't read
149
+ }
150
+ }
151
+ /**
152
+ * List directory contents with filtering options.
153
+ *
154
+ * @param args - ListDirectoryArgs containing path and filtering options
155
+ * @param context - CodeContext with working directory
156
+ * @returns ListDirectoryResult with directory entries
157
+ */
158
+ export async function listDirectory(args, context) {
159
+ const { path: dirPath = ".", pattern, recursive = false, include_hidden = false, max_depth, } = args;
160
+ // Validate path to prevent directory traversal
161
+ const pathValidation = validatePath(dirPath, context.workingDirectory);
162
+ if (!pathValidation.valid) {
163
+ return {
164
+ success: false,
165
+ path: dirPath,
166
+ entries: [],
167
+ total_count: 0,
168
+ error: pathValidation.error,
169
+ };
170
+ }
171
+ const resolvedPath = pathValidation.resolvedPath;
172
+ try {
173
+ // Check if path exists and is a directory
174
+ const stats = await fs.stat(resolvedPath);
175
+ if (!stats.isDirectory()) {
176
+ return {
177
+ success: false,
178
+ path: dirPath,
179
+ entries: [],
180
+ total_count: 0,
181
+ error: "Path is not a directory",
182
+ };
183
+ }
184
+ const entries = [];
185
+ if (recursive) {
186
+ // Recursive listing
187
+ const effectiveMaxDepth = max_depth ?? DEFAULT_MAX_DEPTH;
188
+ await listDirectoryRecursive(resolvedPath, context.workingDirectory, {
189
+ pattern,
190
+ includeHidden: include_hidden,
191
+ maxDepth: effectiveMaxDepth,
192
+ currentDepth: 0,
193
+ entries,
194
+ basePath: dirPath,
195
+ });
196
+ }
197
+ else {
198
+ // Non-recursive listing
199
+ const items = await fs.readdir(resolvedPath);
200
+ for (const item of items) {
201
+ // Check entry limit
202
+ if (entries.length >= MAX_ENTRIES) {
203
+ break;
204
+ }
205
+ // Skip hidden files if not included
206
+ if (!include_hidden && isHidden(item)) {
207
+ continue;
208
+ }
209
+ // Apply pattern filter if specified
210
+ if (pattern && !matchesGlobPattern(item, pattern)) {
211
+ continue;
212
+ }
213
+ const fullPath = path.join(resolvedPath, item);
214
+ const entry = await createDirectoryEntry(fullPath, item);
215
+ if (entry) {
216
+ entries.push(entry);
217
+ }
218
+ }
219
+ }
220
+ // Sort entries: directories first, then alphabetically
221
+ entries.sort((a, b) => {
222
+ if (a.type !== b.type) {
223
+ return a.type === "directory" ? -1 : 1;
224
+ }
225
+ return a.name.localeCompare(b.name);
226
+ });
227
+ return {
228
+ success: true,
229
+ path: dirPath,
230
+ entries,
231
+ total_count: entries.length,
232
+ };
233
+ }
234
+ catch (error) {
235
+ // Handle specific error types without exposing sensitive info (TR-5)
236
+ if (error instanceof Error) {
237
+ const nodeError = error;
238
+ if (nodeError.code === "ENOENT") {
239
+ return {
240
+ success: false,
241
+ path: dirPath,
242
+ entries: [],
243
+ total_count: 0,
244
+ error: "Directory not found",
245
+ };
246
+ }
247
+ if (nodeError.code === "EACCES") {
248
+ return {
249
+ success: false,
250
+ path: dirPath,
251
+ entries: [],
252
+ total_count: 0,
253
+ error: "Permission denied",
254
+ };
255
+ }
256
+ if (nodeError.code === "ENOTDIR") {
257
+ return {
258
+ success: false,
259
+ path: dirPath,
260
+ entries: [],
261
+ total_count: 0,
262
+ error: "Path is not a directory",
263
+ };
264
+ }
265
+ }
266
+ // Generic error without exposing details (TR-5)
267
+ return {
268
+ success: false,
269
+ path: dirPath,
270
+ entries: [],
271
+ total_count: 0,
272
+ error: "Failed to list directory",
273
+ };
274
+ }
275
+ }
276
+ //# sourceMappingURL=list-directory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-directory.js","sourceRoot":"","sources":["../../../../../src/lib/local-tools/code/list-directory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,301 @@
1
+ /**
2
+ * read_file tool - Read file contents with optional line range.
3
+ * Returns content with line numbers and language detection.
4
+ *
5
+ * Security: Implements path validation to prevent directory traversal (TR-5).
6
+ */
7
+ import * as fs from "fs/promises";
8
+ import * as path from "path";
9
+ // Maximum file size to read (1MB default as per TR-5)
10
+ const MAX_FILE_SIZE = 1024 * 1024;
11
+ // Language detection map based on file extensions
12
+ const EXTENSION_TO_LANGUAGE = {
13
+ // JavaScript/TypeScript
14
+ ".js": "javascript",
15
+ ".jsx": "javascript",
16
+ ".ts": "typescript",
17
+ ".tsx": "typescript",
18
+ ".mjs": "javascript",
19
+ ".cjs": "javascript",
20
+ ".mts": "typescript",
21
+ ".cts": "typescript",
22
+ // Python
23
+ ".py": "python",
24
+ ".pyw": "python",
25
+ ".pyi": "python",
26
+ // Web
27
+ ".html": "html",
28
+ ".htm": "html",
29
+ ".css": "css",
30
+ ".scss": "scss",
31
+ ".sass": "sass",
32
+ ".less": "less",
33
+ // Data formats
34
+ ".json": "json",
35
+ ".yaml": "yaml",
36
+ ".yml": "yaml",
37
+ ".xml": "xml",
38
+ ".toml": "toml",
39
+ // Shell
40
+ ".sh": "bash",
41
+ ".bash": "bash",
42
+ ".zsh": "zsh",
43
+ ".fish": "fish",
44
+ ".ps1": "powershell",
45
+ ".bat": "batch",
46
+ ".cmd": "batch",
47
+ // Other languages
48
+ ".go": "go",
49
+ ".rs": "rust",
50
+ ".rb": "ruby",
51
+ ".php": "php",
52
+ ".java": "java",
53
+ ".kt": "kotlin",
54
+ ".kts": "kotlin",
55
+ ".scala": "scala",
56
+ ".c": "c",
57
+ ".h": "c",
58
+ ".cpp": "cpp",
59
+ ".hpp": "cpp",
60
+ ".cc": "cpp",
61
+ ".cxx": "cpp",
62
+ ".cs": "csharp",
63
+ ".swift": "swift",
64
+ ".r": "r",
65
+ ".R": "r",
66
+ ".lua": "lua",
67
+ ".pl": "perl",
68
+ ".pm": "perl",
69
+ ".ex": "elixir",
70
+ ".exs": "elixir",
71
+ ".erl": "erlang",
72
+ ".hrl": "erlang",
73
+ ".clj": "clojure",
74
+ ".cljs": "clojure",
75
+ ".hs": "haskell",
76
+ ".ml": "ocaml",
77
+ ".mli": "ocaml",
78
+ ".fs": "fsharp",
79
+ ".fsx": "fsharp",
80
+ ".dart": "dart",
81
+ ".vue": "vue",
82
+ ".svelte": "svelte",
83
+ // Config/Docs
84
+ ".md": "markdown",
85
+ ".mdx": "markdown",
86
+ ".rst": "restructuredtext",
87
+ ".txt": "text",
88
+ ".ini": "ini",
89
+ ".cfg": "ini",
90
+ ".conf": "ini",
91
+ ".env": "dotenv",
92
+ ".gitignore": "gitignore",
93
+ ".dockerignore": "dockerignore",
94
+ ".editorconfig": "editorconfig",
95
+ // SQL
96
+ ".sql": "sql",
97
+ // GraphQL
98
+ ".graphql": "graphql",
99
+ ".gql": "graphql",
100
+ // Makefile
101
+ Makefile: "makefile",
102
+ makefile: "makefile",
103
+ // Dockerfile
104
+ Dockerfile: "dockerfile",
105
+ dockerfile: "dockerfile",
106
+ };
107
+ /**
108
+ * Detect language from file extension.
109
+ */
110
+ function detectLanguage(filePath) {
111
+ const ext = path.extname(filePath).toLowerCase();
112
+ const basename = path.basename(filePath);
113
+ // Check for special filenames first (Makefile, Dockerfile)
114
+ if (EXTENSION_TO_LANGUAGE[basename]) {
115
+ return EXTENSION_TO_LANGUAGE[basename];
116
+ }
117
+ return EXTENSION_TO_LANGUAGE[ext];
118
+ }
119
+ /**
120
+ * Validate and resolve a file path to prevent directory traversal.
121
+ * Returns the resolved absolute path if valid, or throws an error.
122
+ *
123
+ * Security (TR-5):
124
+ * - All paths normalized and validated against project root
125
+ * - Reject paths containing `..` that escape root
126
+ * - Use `path.resolve()` and check prefix
127
+ */
128
+ function validatePath(filePath, workingDirectory) {
129
+ // Normalize the working directory to absolute path
130
+ const rootDir = path.resolve(workingDirectory);
131
+ // Resolve the requested path relative to working directory
132
+ const resolvedPath = path.resolve(rootDir, filePath);
133
+ // Security check: ensure resolved path is within root directory
134
+ // Use path.sep to ensure we're checking directory boundaries properly
135
+ const normalizedRoot = rootDir.endsWith(path.sep)
136
+ ? rootDir
137
+ : rootDir + path.sep;
138
+ const normalizedResolved = resolvedPath + path.sep;
139
+ if (!normalizedResolved.startsWith(normalizedRoot) &&
140
+ resolvedPath !== rootDir) {
141
+ return {
142
+ valid: false,
143
+ error: "Path validation failed: access denied",
144
+ };
145
+ }
146
+ return { valid: true, resolvedPath };
147
+ }
148
+ /**
149
+ * Format content with line numbers.
150
+ */
151
+ function formatWithLineNumbers(lines, startLine, showLineNumbers) {
152
+ if (!showLineNumbers) {
153
+ return lines.join("\n");
154
+ }
155
+ const endLine = startLine + lines.length - 1;
156
+ const maxLineNumWidth = String(endLine).length;
157
+ return lines
158
+ .map((line, index) => {
159
+ const lineNum = startLine + index;
160
+ const paddedLineNum = String(lineNum).padStart(maxLineNumWidth, " ");
161
+ return `${paddedLineNum} | ${line}`;
162
+ })
163
+ .join("\n");
164
+ }
165
+ /**
166
+ * Read file contents with optional line range.
167
+ *
168
+ * @param args - ReadFileArgs containing path and optional line range
169
+ * @param context - CodeContext with working directory
170
+ * @returns ReadFileResult with file content and metadata
171
+ */
172
+ export async function readFile(args, context) {
173
+ const { path: filePath, start_line, end_line, show_line_numbers = true } = args;
174
+ // Validate path to prevent directory traversal
175
+ const pathValidation = validatePath(filePath, context.workingDirectory);
176
+ if (!pathValidation.valid) {
177
+ return {
178
+ success: false,
179
+ path: filePath,
180
+ content: "",
181
+ total_lines: 0,
182
+ start_line: 0,
183
+ end_line: 0,
184
+ error: pathValidation.error,
185
+ };
186
+ }
187
+ const resolvedPath = pathValidation.resolvedPath;
188
+ try {
189
+ // Check if file exists and get stats
190
+ const stats = await fs.stat(resolvedPath);
191
+ // Ensure it's a file, not a directory
192
+ if (stats.isDirectory()) {
193
+ return {
194
+ success: false,
195
+ path: filePath,
196
+ content: "",
197
+ total_lines: 0,
198
+ start_line: 0,
199
+ end_line: 0,
200
+ error: "Path is a directory, not a file",
201
+ };
202
+ }
203
+ // Check file size limit (TR-5: Max file size limit for reading - 1MB default)
204
+ if (stats.size > MAX_FILE_SIZE) {
205
+ return {
206
+ success: false,
207
+ path: filePath,
208
+ content: "",
209
+ total_lines: 0,
210
+ start_line: 0,
211
+ end_line: 0,
212
+ error: `File exceeds maximum size limit of ${MAX_FILE_SIZE / 1024 / 1024}MB`,
213
+ };
214
+ }
215
+ // Read file content
216
+ const content = await fs.readFile(resolvedPath, "utf-8");
217
+ const allLines = content.split("\n");
218
+ const totalLines = allLines.length;
219
+ // Detect language from extension
220
+ const language = detectLanguage(filePath);
221
+ // Calculate line range (1-indexed, inclusive)
222
+ let effectiveStartLine = start_line ?? 1;
223
+ let effectiveEndLine = end_line ?? totalLines;
224
+ // Validate and clamp line numbers
225
+ if (effectiveStartLine < 1) {
226
+ effectiveStartLine = 1;
227
+ }
228
+ if (effectiveEndLine > totalLines) {
229
+ effectiveEndLine = totalLines;
230
+ }
231
+ if (effectiveStartLine > totalLines) {
232
+ effectiveStartLine = totalLines;
233
+ }
234
+ if (effectiveEndLine < effectiveStartLine) {
235
+ effectiveEndLine = effectiveStartLine;
236
+ }
237
+ // Extract requested lines (convert to 0-indexed for array slice)
238
+ const selectedLines = allLines.slice(effectiveStartLine - 1, effectiveEndLine);
239
+ // Format content with optional line numbers
240
+ const formattedContent = formatWithLineNumbers(selectedLines, effectiveStartLine, show_line_numbers);
241
+ return {
242
+ success: true,
243
+ path: filePath,
244
+ content: formattedContent,
245
+ total_lines: totalLines,
246
+ start_line: effectiveStartLine,
247
+ end_line: effectiveEndLine,
248
+ language,
249
+ };
250
+ }
251
+ catch (error) {
252
+ // Handle specific error types without exposing file contents (TR-5)
253
+ if (error instanceof Error) {
254
+ const nodeError = error;
255
+ if (nodeError.code === "ENOENT") {
256
+ return {
257
+ success: false,
258
+ path: filePath,
259
+ content: "",
260
+ total_lines: 0,
261
+ start_line: 0,
262
+ end_line: 0,
263
+ error: "File not found",
264
+ };
265
+ }
266
+ if (nodeError.code === "EACCES") {
267
+ return {
268
+ success: false,
269
+ path: filePath,
270
+ content: "",
271
+ total_lines: 0,
272
+ start_line: 0,
273
+ end_line: 0,
274
+ error: "Permission denied",
275
+ };
276
+ }
277
+ if (nodeError.code === "EISDIR") {
278
+ return {
279
+ success: false,
280
+ path: filePath,
281
+ content: "",
282
+ total_lines: 0,
283
+ start_line: 0,
284
+ end_line: 0,
285
+ error: "Path is a directory, not a file",
286
+ };
287
+ }
288
+ }
289
+ // Generic error without exposing details (TR-5: Never include file contents in error messages)
290
+ return {
291
+ success: false,
292
+ path: filePath,
293
+ content: "",
294
+ total_lines: 0,
295
+ start_line: 0,
296
+ end_line: 0,
297
+ error: "Failed to read file",
298
+ };
299
+ }
300
+ }
301
+ //# sourceMappingURL=read-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-file.js","sourceRoot":"","sources":["../../../../../src/lib/local-tools/code/read-file.ts"],"names":[],"mappings":"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"}