@4onstudios/iris-agent 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 (216) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +690 -0
  3. package/dist/api/acp/acpServer.d.ts +23 -0
  4. package/dist/api/acp/acpServer.js +814 -0
  5. package/dist/api/acp/index.d.ts +2 -0
  6. package/dist/api/acp/index.js +2 -0
  7. package/dist/api/acp/irisClient.d.ts +58 -0
  8. package/dist/api/acp/irisClient.js +214 -0
  9. package/dist/api/agent.d.ts +14 -0
  10. package/dist/api/agent.js +4171 -0
  11. package/dist/api/backendService.d.ts +4 -0
  12. package/dist/api/backendService.js +14 -0
  13. package/dist/api/core/agent/host/AgentContract.d.ts +82 -0
  14. package/dist/api/core/agent/host/AgentContract.js +1 -0
  15. package/dist/api/core/agent/host/AgentRegistry.d.ts +24 -0
  16. package/dist/api/core/agent/host/AgentRegistry.js +125 -0
  17. package/dist/api/core/agent/host/defaultRegistry.d.ts +15 -0
  18. package/dist/api/core/agent/host/defaultRegistry.js +46 -0
  19. package/dist/api/core/agent/host/externalAgentLifecycle.d.ts +65 -0
  20. package/dist/api/core/agent/host/externalAgentLifecycle.js +117 -0
  21. package/dist/api/core/agent/host/hostSessionManager.d.ts +111 -0
  22. package/dist/api/core/agent/host/hostSessionManager.js +352 -0
  23. package/dist/api/core/agent/host/index.d.ts +5 -0
  24. package/dist/api/core/agent/host/index.js +5 -0
  25. package/dist/api/core/agent/index.d.ts +87 -0
  26. package/dist/api/core/agent/index.js +1024 -0
  27. package/dist/api/core/agent/publicContracts.d.ts +35 -0
  28. package/dist/api/core/agent/publicContracts.js +103 -0
  29. package/dist/api/core/agent/tools/applyDiff.d.ts +51 -0
  30. package/dist/api/core/agent/tools/applyDiff.js +131 -0
  31. package/dist/api/core/agent/tools/backgroundTasks.d.ts +240 -0
  32. package/dist/api/core/agent/tools/backgroundTasks.js +313 -0
  33. package/dist/api/core/agent/tools/createDirectory.d.ts +43 -0
  34. package/dist/api/core/agent/tools/createDirectory.js +77 -0
  35. package/dist/api/core/agent/tools/deleteFile.d.ts +37 -0
  36. package/dist/api/core/agent/tools/deleteFile.js +66 -0
  37. package/dist/api/core/agent/tools/editFile.d.ts +73 -0
  38. package/dist/api/core/agent/tools/editFile.js +173 -0
  39. package/dist/api/core/agent/tools/executeCommand.d.ts +59 -0
  40. package/dist/api/core/agent/tools/executeCommand.js +250 -0
  41. package/dist/api/core/agent/tools/fileContent.d.ts +54 -0
  42. package/dist/api/core/agent/tools/fileContent.js +227 -0
  43. package/dist/api/core/agent/tools/findDefinition.d.ts +72 -0
  44. package/dist/api/core/agent/tools/findDefinition.js +109 -0
  45. package/dist/api/core/agent/tools/findReferences.d.ts +86 -0
  46. package/dist/api/core/agent/tools/findReferences.js +135 -0
  47. package/dist/api/core/agent/tools/formatDocument.d.ts +67 -0
  48. package/dist/api/core/agent/tools/formatDocument.js +90 -0
  49. package/dist/api/core/agent/tools/getCodeActions.d.ts +77 -0
  50. package/dist/api/core/agent/tools/getCodeActions.js +97 -0
  51. package/dist/api/core/agent/tools/getCodeCompletion.d.ts +77 -0
  52. package/dist/api/core/agent/tools/getCodeCompletion.js +174 -0
  53. package/dist/api/core/agent/tools/getCodeContext.d.ts +14 -0
  54. package/dist/api/core/agent/tools/getCodeContext.js +282 -0
  55. package/dist/api/core/agent/tools/getSignatureHelp.d.ts +61 -0
  56. package/dist/api/core/agent/tools/getSignatureHelp.js +85 -0
  57. package/dist/api/core/agent/tools/getSymbols.d.ts +50 -0
  58. package/dist/api/core/agent/tools/getSymbols.js +164 -0
  59. package/dist/api/core/agent/tools/getSymbolsLSP.d.ts +58 -0
  60. package/dist/api/core/agent/tools/getSymbolsLSP.js +147 -0
  61. package/dist/api/core/agent/tools/getTypeInfo.d.ts +70 -0
  62. package/dist/api/core/agent/tools/getTypeInfo.js +84 -0
  63. package/dist/api/core/agent/tools/getWorkspaceInfo.d.ts +80 -0
  64. package/dist/api/core/agent/tools/getWorkspaceInfo.js +281 -0
  65. package/dist/api/core/agent/tools/getWorkspaceSymbols.d.ts +53 -0
  66. package/dist/api/core/agent/tools/getWorkspaceSymbols.js +97 -0
  67. package/dist/api/core/agent/tools/grepSearch.d.ts +100 -0
  68. package/dist/api/core/agent/tools/grepSearch.js +211 -0
  69. package/dist/api/core/agent/tools/languageModelToolsIntegration.d.ts +13 -0
  70. package/dist/api/core/agent/tools/languageModelToolsIntegration.js +22 -0
  71. package/dist/api/core/agent/tools/listDirectory.d.ts +66 -0
  72. package/dist/api/core/agent/tools/listDirectory.js +161 -0
  73. package/dist/api/core/agent/tools/mcpTools.d.ts +48 -0
  74. package/dist/api/core/agent/tools/mcpTools.js +442 -0
  75. package/dist/api/core/agent/tools/queryKnowledgeGraph.d.ts +120 -0
  76. package/dist/api/core/agent/tools/queryKnowledgeGraph.js +306 -0
  77. package/dist/api/core/agent/tools/readFile.d.ts +92 -0
  78. package/dist/api/core/agent/tools/readFile.js +337 -0
  79. package/dist/api/core/agent/tools/renameFile.d.ts +49 -0
  80. package/dist/api/core/agent/tools/renameFile.js +86 -0
  81. package/dist/api/core/agent/tools/renameSymbol.d.ts +70 -0
  82. package/dist/api/core/agent/tools/renameSymbol.js +106 -0
  83. package/dist/api/core/agent/tools/runTerminalCommand.d.ts +72 -0
  84. package/dist/api/core/agent/tools/runTerminalCommand.js +69 -0
  85. package/dist/api/core/agent/tools/searchFiles.d.ts +82 -0
  86. package/dist/api/core/agent/tools/searchFiles.js +280 -0
  87. package/dist/api/core/agent/tools/terminalAutoApprove.d.ts +3 -0
  88. package/dist/api/core/agent/tools/terminalAutoApprove.js +676 -0
  89. package/dist/api/core/agent/tools/treeTraversal.d.ts +60 -0
  90. package/dist/api/core/agent/tools/treeTraversal.js +217 -0
  91. package/dist/api/core/agent/tools/webSearch.d.ts +37 -0
  92. package/dist/api/core/agent/tools/webSearch.js +80 -0
  93. package/dist/api/core/agent/tools/writeFile.d.ts +59 -0
  94. package/dist/api/core/agent/tools/writeFile.js +97 -0
  95. package/dist/api/core/agent/utils/capturedWorkspaceMutationBridge.d.ts +12 -0
  96. package/dist/api/core/agent/utils/capturedWorkspaceMutationBridge.js +67 -0
  97. package/dist/api/core/agent/utils/diffUtils.d.ts +14 -0
  98. package/dist/api/core/agent/utils/diffUtils.js +39 -0
  99. package/dist/api/core/agent/utils/environmentSnapshot.d.ts +42 -0
  100. package/dist/api/core/agent/utils/environmentSnapshot.js +213 -0
  101. package/dist/api/core/agent/utils/errorRecovery.d.ts +49 -0
  102. package/dist/api/core/agent/utils/errorRecovery.js +229 -0
  103. package/dist/api/core/agent/utils/multimodalTokenLimiter.d.ts +8 -0
  104. package/dist/api/core/agent/utils/multimodalTokenLimiter.js +238 -0
  105. package/dist/api/core/agent/utils/openRouterModelSettings.d.ts +12 -0
  106. package/dist/api/core/agent/utils/openRouterModelSettings.js +34 -0
  107. package/dist/api/core/agent/utils/pathRecovery.d.ts +1 -0
  108. package/dist/api/core/agent/utils/pathRecovery.js +29 -0
  109. package/dist/api/core/agent/utils/repoMapIndex.d.ts +3 -0
  110. package/dist/api/core/agent/utils/repoMapIndex.js +197 -0
  111. package/dist/api/core/agent/utils/skillsDiscovery.d.ts +10 -0
  112. package/dist/api/core/agent/utils/skillsDiscovery.js +50 -0
  113. package/dist/api/core/agent/utils/toolCallBudget.d.ts +9 -0
  114. package/dist/api/core/agent/utils/toolCallBudget.js +55 -0
  115. package/dist/api/core/agent/utils/toolLifecycle.d.ts +30 -0
  116. package/dist/api/core/agent/utils/toolLifecycle.js +361 -0
  117. package/dist/api/core/agent/utils/toolResultSafetyProcessor.d.ts +12 -0
  118. package/dist/api/core/agent/utils/toolResultSafetyProcessor.js +57 -0
  119. package/dist/api/core/agent/utils/workspaceMutationBridge.d.ts +13 -0
  120. package/dist/api/core/agent/utils/workspaceMutationBridge.js +149 -0
  121. package/dist/api/core/agent/utils/workspacePathGuard.d.ts +7 -0
  122. package/dist/api/core/agent/utils/workspacePathGuard.js +79 -0
  123. package/dist/api/core/containers/chat/toolResultSerialization.d.ts +8 -0
  124. package/dist/api/core/containers/chat/toolResultSerialization.js +71 -0
  125. package/dist/api/core/library/BrowserManager.d.ts +11 -0
  126. package/dist/api/core/library/BrowserManager.js +66 -0
  127. package/dist/api/core/library/desktopWorkspace.d.ts +1 -0
  128. package/dist/api/core/library/desktopWorkspace.js +3 -0
  129. package/dist/api/core/library/extensionManager.d.ts +10 -0
  130. package/dist/api/core/library/extensionManager.js +27 -0
  131. package/dist/api/core/library/knowledgeGraph.d.ts +268 -0
  132. package/dist/api/core/library/knowledgeGraph.js +989 -0
  133. package/dist/api/core/library/languageModelTools.d.ts +141 -0
  134. package/dist/api/core/library/languageModelTools.js +207 -0
  135. package/dist/api/core/library/localRuntime.d.ts +23 -0
  136. package/dist/api/core/library/localRuntime.js +144 -0
  137. package/dist/api/core/library/lsp/coreLsp.d.ts +367 -0
  138. package/dist/api/core/library/lsp/coreLsp.js +2076 -0
  139. package/dist/api/core/library/lsp/protocol.d.ts +25 -0
  140. package/dist/api/core/library/lsp/protocol.js +1 -0
  141. package/dist/api/core/library/lsp/serverManager.d.ts +37 -0
  142. package/dist/api/core/library/lsp/serverManager.js +427 -0
  143. package/dist/api/core/library/mcpServerProvider.d.ts +69 -0
  144. package/dist/api/core/library/mcpServerProvider.js +152 -0
  145. package/dist/api/core/library/mcpSettings.d.ts +20 -0
  146. package/dist/api/core/library/mcpSettings.js +131 -0
  147. package/dist/api/core/library/patternMatcher.d.ts +66 -0
  148. package/dist/api/core/library/patternMatcher.js +284 -0
  149. package/dist/api/core/library/regexEscape.d.ts +4 -0
  150. package/dist/api/core/library/regexEscape.js +4 -0
  151. package/dist/api/core/library/runtimeEventBus.d.ts +27 -0
  152. package/dist/api/core/library/runtimeEventBus.js +78 -0
  153. package/dist/api/core/library/safetyMiddleware.d.ts +98 -0
  154. package/dist/api/core/library/safetyMiddleware.js +215 -0
  155. package/dist/api/core/library/tauri.d.ts +71 -0
  156. package/dist/api/core/library/tauri.js +222 -0
  157. package/dist/api/core/library/tauriImport.d.ts +5 -0
  158. package/dist/api/core/library/tauriImport.js +7 -0
  159. package/dist/api/core/library/terminalAutoApproveSettings.d.ts +32 -0
  160. package/dist/api/core/library/terminalAutoApproveSettings.js +529 -0
  161. package/dist/api/core/library/workspaceIdentity.d.ts +10 -0
  162. package/dist/api/core/library/workspaceIdentity.js +49 -0
  163. package/dist/api/core/library/workspaceSummary.d.ts +19 -0
  164. package/dist/api/core/library/workspaceSummary.js +35 -0
  165. package/dist/api/core/skills/agent-customization/SKILL.md +27 -0
  166. package/dist/api/core/skills/bug-fix/SKILL.md +21 -0
  167. package/dist/api/core/skills/create-pr/SKILL.md +32 -0
  168. package/dist/api/core/skills/dev-server/SKILL.md +20 -0
  169. package/dist/api/core/skills/fix-suggestions/SKILL.md +21 -0
  170. package/dist/api/core/skills/github-search/SKILL.md +21 -0
  171. package/dist/api/core/skills/github-summary/SKILL.md +25 -0
  172. package/dist/api/core/skills/integration-tests/SKILL.md +29 -0
  173. package/dist/api/core/skills/pr-comments/SKILL.md +23 -0
  174. package/dist/api/core/skills/project-setup/SKILL.md +20 -0
  175. package/dist/api/core/skills/search-integration/SKILL.md +19 -0
  176. package/dist/api/core/skills/search-results/SKILL.md +19 -0
  177. package/dist/api/core/skills/typescript-upgrade/SKILL.md +21 -0
  178. package/dist/api/data/runStore.d.ts +46 -0
  179. package/dist/api/data/runStore.js +244 -0
  180. package/dist/api/helpers/agentUtils.d.ts +11 -0
  181. package/dist/api/helpers/agentUtils.js +23 -0
  182. package/dist/api/helpers/modelTokenLimits.d.ts +2 -0
  183. package/dist/api/helpers/modelTokenLimits.js +158 -0
  184. package/dist/api/helpers/observationalMemory.d.ts +10 -0
  185. package/dist/api/helpers/observationalMemory.js +36 -0
  186. package/dist/api/helpers/promptBudget.d.ts +30 -0
  187. package/dist/api/helpers/promptBudget.js +216 -0
  188. package/dist/api/helpers/resolveImageMessageParts.d.ts +9 -0
  189. package/dist/api/helpers/resolveImageMessageParts.js +140 -0
  190. package/dist/api/helpers/slashCommands.d.ts +31 -0
  191. package/dist/api/helpers/slashCommands.js +129 -0
  192. package/dist/api/helpers/tokenUsage.d.ts +19 -0
  193. package/dist/api/helpers/tokenUsage.js +81 -0
  194. package/dist/api/routes/fileRoutes.d.ts +2 -0
  195. package/dist/api/routes/fileRoutes.js +108 -0
  196. package/dist/api/routes/lspDocumentRoutes.d.ts +4 -0
  197. package/dist/api/routes/lspDocumentRoutes.js +84 -0
  198. package/dist/api/routes/lspHierarchyRoutes.d.ts +4 -0
  199. package/dist/api/routes/lspHierarchyRoutes.js +122 -0
  200. package/dist/api/routes/lspPositionRoutes.d.ts +4 -0
  201. package/dist/api/routes/lspPositionRoutes.js +263 -0
  202. package/dist/api/routes/lspQueryRoutes.d.ts +4 -0
  203. package/dist/api/routes/lspQueryRoutes.js +679 -0
  204. package/dist/api/routes/lspResolveRoutes.d.ts +4 -0
  205. package/dist/api/routes/lspResolveRoutes.js +143 -0
  206. package/dist/api/routes/lspSemanticDocumentRoutes.d.ts +4 -0
  207. package/dist/api/routes/lspSemanticDocumentRoutes.js +98 -0
  208. package/dist/api/routes/semanticRoutes.d.ts +2 -0
  209. package/dist/api/routes/semanticRoutes.js +126 -0
  210. package/dist/cli.d.ts +8 -0
  211. package/dist/cli.js +160 -0
  212. package/dist/index.d.ts +1 -0
  213. package/dist/index.js +1 -0
  214. package/dist/server.d.ts +2 -0
  215. package/dist/server.js +38 -0
  216. package/package.json +100 -0
@@ -0,0 +1,72 @@
1
+ import { z } from "zod";
2
+ import type { TerminalAutoApproveRules } from "../../library/terminalAutoApproveSettings.js";
3
+ type RunTerminalCommandParams = {
4
+ command: string;
5
+ cwd?: string;
6
+ workspaceRoot?: string;
7
+ timeout?: number;
8
+ env?: NodeJS.ProcessEnv;
9
+ runInBackground?: boolean;
10
+ description?: string;
11
+ skipConfirmation?: boolean;
12
+ autoApproveRules?: TerminalAutoApproveRules;
13
+ };
14
+ type CommandResult = Record<string, unknown> & {
15
+ success?: boolean;
16
+ error?: string;
17
+ };
18
+ /**
19
+ * Tool for running terminal commands
20
+ *
21
+ * Safe readonly commands can be auto-approved using wrapper-aware parsing.
22
+ * Commands that do not match the allow-list still return pending_confirmation,
23
+ * which triggers the existing user approval dialog in the UI.
24
+ *
25
+ * @param {Object} params - The parameters for running a command
26
+ * @param {string} params.command - The command to execute
27
+ * @param {string} [params.cwd] - Current working directory for the command
28
+ * @param {number} [params.timeout=30000] - Timeout in milliseconds
29
+ * @param {Object} [params.env] - Environment variables
30
+ * @param {boolean} [params.skipConfirmation=false] - Skip user confirmation (used internally after user approves)
31
+ * @returns {Promise<Object>} Object containing success status and command output or error
32
+ */
33
+ export declare function runTerminalCommand({ command, cwd, workspaceRoot, timeout, env, runInBackground, description, skipConfirmation, autoApproveRules, }: RunTerminalCommandParams): Promise<CommandResult>;
34
+ /**
35
+ * Tool metadata for agent system
36
+ */
37
+ export declare const runTerminalCommandTool: {
38
+ description: string;
39
+ parameters: z.ZodObject<{
40
+ command: z.ZodString;
41
+ cwd: z.ZodDefault<z.ZodString>;
42
+ workspaceRoot: z.ZodOptional<z.ZodString>;
43
+ timeout: z.ZodDefault<z.ZodNumber>;
44
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
45
+ runInBackground: z.ZodDefault<z.ZodBoolean>;
46
+ description: z.ZodOptional<z.ZodString>;
47
+ skipConfirmation: z.ZodDefault<z.ZodBoolean>;
48
+ autoApproveRules: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
49
+ }, "strip", z.ZodTypeAny, {
50
+ command?: string;
51
+ cwd?: string;
52
+ env?: Record<string, string>;
53
+ description?: string;
54
+ timeout?: number;
55
+ workspaceRoot?: string;
56
+ runInBackground?: boolean;
57
+ skipConfirmation?: boolean;
58
+ autoApproveRules?: Record<string, any>;
59
+ }, {
60
+ command?: string;
61
+ cwd?: string;
62
+ env?: Record<string, string>;
63
+ description?: string;
64
+ timeout?: number;
65
+ workspaceRoot?: string;
66
+ runInBackground?: boolean;
67
+ skipConfirmation?: boolean;
68
+ autoApproveRules?: Record<string, any>;
69
+ }>;
70
+ execute: typeof runTerminalCommand;
71
+ };
72
+ export default runTerminalCommandTool;
@@ -0,0 +1,69 @@
1
+ import { z } from "zod";
2
+ import { executeCommand } from "./executeCommand.js";
3
+ /**
4
+ * Tool for running terminal commands
5
+ *
6
+ * Safe readonly commands can be auto-approved using wrapper-aware parsing.
7
+ * Commands that do not match the allow-list still return pending_confirmation,
8
+ * which triggers the existing user approval dialog in the UI.
9
+ *
10
+ * @param {Object} params - The parameters for running a command
11
+ * @param {string} params.command - The command to execute
12
+ * @param {string} [params.cwd] - Current working directory for the command
13
+ * @param {number} [params.timeout=30000] - Timeout in milliseconds
14
+ * @param {Object} [params.env] - Environment variables
15
+ * @param {boolean} [params.skipConfirmation=false] - Skip user confirmation (used internally after user approves)
16
+ * @returns {Promise<Object>} Object containing success status and command output or error
17
+ */
18
+ export async function runTerminalCommand({ command, cwd = process.cwd(), workspaceRoot, timeout = 30000, env = {}, runInBackground = false, description, skipConfirmation = false, autoApproveRules, }) {
19
+ // Route through executeCommand for consistent confirmation flow
20
+ return executeCommand({
21
+ command,
22
+ cwd,
23
+ workspaceRoot,
24
+ timeout,
25
+ env,
26
+ runInBackground,
27
+ description,
28
+ skipConfirmation,
29
+ approvalPolicy: "auto_approve_safe",
30
+ autoApproveRules,
31
+ });
32
+ }
33
+ /**
34
+ * Tool metadata for agent system
35
+ */
36
+ export const runTerminalCommandTool = {
37
+ description: "Execute a terminal command and return its output. Safe readonly commands may auto-run; other commands require confirmation.",
38
+ parameters: z.object({
39
+ command: z.string().describe("The command to execute"),
40
+ cwd: z
41
+ .string()
42
+ .default(process.cwd())
43
+ .describe("Current working directory for the command"),
44
+ workspaceRoot: z
45
+ .string()
46
+ .optional()
47
+ .describe("Workspace root path for security validation - defaults to inferred repo root"),
48
+ timeout: z.number().default(30000).describe("Timeout in milliseconds"),
49
+ env: z.record(z.string()).optional().describe("Environment variables"),
50
+ runInBackground: z
51
+ .boolean()
52
+ .default(false)
53
+ .describe("Run command as managed background task"),
54
+ description: z
55
+ .string()
56
+ .optional()
57
+ .describe("Optional short task description for background execution"),
58
+ skipConfirmation: z
59
+ .boolean()
60
+ .default(false)
61
+ .describe("Skip user confirmation - only used internally after user approves the command"),
62
+ autoApproveRules: z
63
+ .record(z.any())
64
+ .optional()
65
+ .describe("Optional auto-approve rule map for internal runtime configuration."),
66
+ }),
67
+ execute: runTerminalCommand,
68
+ };
69
+ export default runTerminalCommandTool;
@@ -0,0 +1,82 @@
1
+ import { z } from "zod";
2
+ type SearchFilesParams = {
3
+ pattern?: string;
4
+ filePath?: string;
5
+ startLine?: number;
6
+ endLine?: number;
7
+ cwd?: string;
8
+ encoding?: BufferEncoding;
9
+ };
10
+ type FileSearchResult = {
11
+ path: string;
12
+ relativePath: string;
13
+ size: number;
14
+ lastModified: Date;
15
+ };
16
+ type SearchFilesReadSuccessResult = {
17
+ success: true;
18
+ filePath: string;
19
+ resolvedBy: "direct" | "repo_map" | "terminal_find";
20
+ startLine?: number;
21
+ endLine?: number;
22
+ totalLines: number;
23
+ content: string;
24
+ lines: string[];
25
+ size: number;
26
+ lastModified: Date;
27
+ };
28
+ type SearchFilesPatternSuccessResult = {
29
+ success: true;
30
+ message?: string;
31
+ pattern: string;
32
+ resolvedBy?: "glob" | "repo_map" | "terminal_find" | "repo_map_ranked";
33
+ count?: number;
34
+ files: FileSearchResult[];
35
+ };
36
+ type SearchFilesErrorResult = {
37
+ success: false;
38
+ error: string;
39
+ };
40
+ type SearchFilesResult = SearchFilesReadSuccessResult | SearchFilesPatternSuccessResult | SearchFilesErrorResult;
41
+ /**
42
+ * Tool for searching files and reading specific line ranges
43
+ * @param {Object} params - The parameters for searching files
44
+ * @param {string} [params.pattern] - Glob pattern to search for files
45
+ * @param {string} [params.filePath] - Specific file path to read (alternative to pattern)
46
+ * @param {number} [params.startLine] - Starting line number (1-indexed)
47
+ * @param {number} [params.endLine] - Ending line number (1-indexed)
48
+ * @param {string} [params.cwd] - Current working directory for search
49
+ * @param {string} [params.encoding='utf8'] - The encoding to use when reading the file
50
+ * @returns {Promise<Object>} Object containing success status and search results or file content
51
+ */
52
+ export declare function searchFiles({ pattern, filePath, startLine, endLine, cwd, encoding, }: SearchFilesParams): Promise<SearchFilesResult>;
53
+ /**
54
+ * Tool metadata for agent system
55
+ */
56
+ export declare const searchFilesTool: {
57
+ description: string;
58
+ parameters: z.ZodObject<{
59
+ pattern: z.ZodOptional<z.ZodString>;
60
+ filePath: z.ZodOptional<z.ZodString>;
61
+ startLine: z.ZodOptional<z.ZodNumber>;
62
+ endLine: z.ZodOptional<z.ZodNumber>;
63
+ cwd: z.ZodDefault<z.ZodString>;
64
+ encoding: z.ZodDefault<z.ZodEnum<["utf8", "ascii", "base64", "binary", "hex"]>>;
65
+ }, "strip", z.ZodTypeAny, {
66
+ cwd?: string;
67
+ pattern?: string;
68
+ encoding?: "ascii" | "utf8" | "base64" | "binary" | "hex";
69
+ filePath?: string;
70
+ startLine?: number;
71
+ endLine?: number;
72
+ }, {
73
+ cwd?: string;
74
+ pattern?: string;
75
+ encoding?: "ascii" | "utf8" | "base64" | "binary" | "hex";
76
+ filePath?: string;
77
+ startLine?: number;
78
+ endLine?: number;
79
+ }>;
80
+ execute: typeof searchFiles;
81
+ };
82
+ export default searchFilesTool;
@@ -0,0 +1,280 @@
1
+ import fs from "fs/promises";
2
+ import path from "path";
3
+ import { glob } from "glob";
4
+ import { execFile } from "child_process";
5
+ import { promisify } from "util";
6
+ import { z } from "zod";
7
+ import { findFilesViaRepoMap, rankFileCandidates, } from "../utils/repoMapIndex.js";
8
+ import { buildRecoveryQueries } from "../utils/pathRecovery.js";
9
+ const execFileAsync = promisify(execFile);
10
+ const normalizeRelativeInputPath = (value) => value.replace(/\\/g, "/").replace(/^\.\//, "").replace(/^\//, "");
11
+ const hasGlobMeta = (value) => /[*?[\]{}]/.test(value);
12
+ const isNumber = (value) => typeof value === "number";
13
+ const isPathInsideBase = (basePath, targetPath) => {
14
+ const relative = path.relative(basePath, targetPath);
15
+ return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
16
+ };
17
+ const normalizeGlobPattern = (inputPattern) => {
18
+ const normalized = inputPattern.replace(/\\/g, "/");
19
+ const anchoredToRoot = normalized.startsWith("/");
20
+ const primary = anchoredToRoot ? normalized.slice(1) : normalized;
21
+ const patterns = [primary];
22
+ if (primary.startsWith("**/")) {
23
+ patterns.push(primary.slice(3));
24
+ }
25
+ return {
26
+ patterns: Array.from(new Set(patterns.filter(Boolean))),
27
+ anchoredToRoot,
28
+ };
29
+ };
30
+ const findFilesViaTerminal = async (cwd, query) => {
31
+ const normalizedQuery = normalizeRelativeInputPath(query);
32
+ const baseName = path.basename(normalizedQuery);
33
+ const attempts = [];
34
+ // Exact relative path match first (most deterministic).
35
+ if (normalizedQuery && normalizedQuery !== baseName) {
36
+ attempts.push([
37
+ ".",
38
+ "-type",
39
+ "f",
40
+ "-path",
41
+ `./${normalizedQuery}`,
42
+ ]);
43
+ }
44
+ // Then basename match to recover from partial/incorrect relative paths.
45
+ if (baseName) {
46
+ attempts.push([".", "-type", "f", "-name", baseName]);
47
+ }
48
+ for (const args of attempts) {
49
+ try {
50
+ const { stdout } = await execFileAsync("find", args, {
51
+ cwd,
52
+ maxBuffer: 1024 * 1024 * 4,
53
+ });
54
+ const matches = stdout
55
+ .split(/\r?\n/)
56
+ .map((line) => line.trim())
57
+ .filter(Boolean)
58
+ .map((line) => path.resolve(cwd, line));
59
+ if (matches.length > 0) {
60
+ return rankFileCandidates(cwd, query, matches);
61
+ }
62
+ }
63
+ catch {
64
+ // Ignore and continue to next fallback strategy.
65
+ }
66
+ }
67
+ return [];
68
+ };
69
+ /**
70
+ * Tool for searching files and reading specific line ranges
71
+ * @param {Object} params - The parameters for searching files
72
+ * @param {string} [params.pattern] - Glob pattern to search for files
73
+ * @param {string} [params.filePath] - Specific file path to read (alternative to pattern)
74
+ * @param {number} [params.startLine] - Starting line number (1-indexed)
75
+ * @param {number} [params.endLine] - Ending line number (1-indexed)
76
+ * @param {string} [params.cwd] - Current working directory for search
77
+ * @param {string} [params.encoding='utf8'] - The encoding to use when reading the file
78
+ * @returns {Promise<Object>} Object containing success status and search results or file content
79
+ */
80
+ export async function searchFiles({ pattern, filePath, startLine, endLine, cwd = process.cwd(), encoding = "utf8", }) {
81
+ try {
82
+ const requestedStartLine = startLine;
83
+ const requestedEndLine = endLine;
84
+ if (isNumber(requestedStartLine) || isNumber(requestedEndLine)) {
85
+ if (!isNumber(requestedStartLine) || !isNumber(requestedEndLine)) {
86
+ return {
87
+ success: false,
88
+ error: "Both startLine and endLine must be provided together",
89
+ };
90
+ }
91
+ if (!Number.isInteger(requestedStartLine)
92
+ || !Number.isInteger(requestedEndLine)
93
+ || requestedStartLine < 1
94
+ || requestedEndLine < 1) {
95
+ return {
96
+ success: false,
97
+ error: "startLine and endLine must be positive integers",
98
+ };
99
+ }
100
+ if (requestedStartLine > requestedEndLine) {
101
+ return {
102
+ success: false,
103
+ error: "startLine cannot be greater than endLine",
104
+ };
105
+ }
106
+ }
107
+ const absoluteCwd = path.resolve(cwd);
108
+ // If filePath is provided, read that specific file
109
+ if (filePath) {
110
+ const absolutePath = path.isAbsolute(filePath)
111
+ ? path.resolve(filePath)
112
+ : path.resolve(absoluteCwd, filePath);
113
+ // Reads are allowed outside the workspace root when the resolved path is
114
+ // directly readable, so callers can inspect sibling repos and shared files.
115
+ let readablePath = absolutePath;
116
+ let resolvedBy = "direct";
117
+ // Check if file exists
118
+ try {
119
+ await fs.access(readablePath, fs.constants.R_OK);
120
+ }
121
+ catch {
122
+ const recoveryQueries = buildRecoveryQueries(filePath, absoluteCwd);
123
+ const safeRecoveredMatches = [];
124
+ let foundByRepoMap = false;
125
+ for (const query of recoveryQueries) {
126
+ const repoMapMatches = await findFilesViaRepoMap(cwd, query, 5);
127
+ const recoveredMatches = repoMapMatches.length > 0
128
+ ? repoMapMatches
129
+ : await findFilesViaTerminal(cwd, query);
130
+ const safeMatches = recoveredMatches.filter((candidate) => isPathInsideBase(absoluteCwd, path.resolve(candidate)));
131
+ if (safeMatches.length > 0) {
132
+ safeRecoveredMatches.push(...safeMatches);
133
+ foundByRepoMap = repoMapMatches.length > 0;
134
+ break;
135
+ }
136
+ }
137
+ if (safeRecoveredMatches.length === 0) {
138
+ return {
139
+ success: false,
140
+ error: `File not found or not readable: ${filePath}`,
141
+ };
142
+ }
143
+ readablePath = safeRecoveredMatches[0];
144
+ resolvedBy = foundByRepoMap ? "repo_map" : "terminal_find";
145
+ }
146
+ // Read file content
147
+ const content = await fs.readFile(readablePath, encoding);
148
+ const lines = content.split("\n");
149
+ // Get stats
150
+ const stats = await fs.stat(readablePath);
151
+ // If line range is specified, extract those lines
152
+ if (startLine !== undefined && endLine !== undefined) {
153
+ const start = startLine - 1; // Convert to 0-indexed
154
+ const end = endLine;
155
+ if (start >= lines.length) {
156
+ return {
157
+ success: false,
158
+ error: `Start line ${startLine} exceeds file length (${lines.length} lines)`,
159
+ };
160
+ }
161
+ const selectedLines = lines.slice(start, end);
162
+ return {
163
+ success: true,
164
+ filePath: readablePath,
165
+ resolvedBy,
166
+ startLine: start + 1,
167
+ endLine: Math.min(end, lines.length),
168
+ totalLines: lines.length,
169
+ content: selectedLines.join("\n"),
170
+ lines: selectedLines,
171
+ size: stats.size,
172
+ lastModified: stats.mtime,
173
+ };
174
+ }
175
+ // Return entire file if no line range specified
176
+ return {
177
+ success: true,
178
+ filePath: readablePath,
179
+ resolvedBy,
180
+ totalLines: lines.length,
181
+ content,
182
+ lines,
183
+ size: stats.size,
184
+ lastModified: stats.mtime,
185
+ };
186
+ }
187
+ // If pattern is provided, search for matching files
188
+ if (pattern) {
189
+ let resolvedBy = "glob";
190
+ const { patterns, anchoredToRoot } = normalizeGlobPattern(pattern);
191
+ const fileSets = await Promise.all(patterns.map((singlePattern) => glob(singlePattern, {
192
+ cwd: absoluteCwd,
193
+ absolute: true,
194
+ nodir: true,
195
+ dot: true,
196
+ matchBase: !anchoredToRoot,
197
+ ignore: [
198
+ "**/node_modules/**",
199
+ "**/dist/**",
200
+ "**/build/**",
201
+ "**/.git/**",
202
+ ],
203
+ })));
204
+ const files = Array.from(new Set(fileSets.flat().filter((candidate) => isPathInsideBase(absoluteCwd, path.resolve(candidate)))));
205
+ let resolvedFiles = files;
206
+ // Fallback to terminal file search for plain names/paths when glob misses.
207
+ if (resolvedFiles.length === 0 && !hasGlobMeta(pattern)) {
208
+ const repoMapMatches = await findFilesViaRepoMap(cwd, pattern, 50);
209
+ const fallbackFiles = repoMapMatches.length > 0
210
+ ? repoMapMatches
211
+ : await findFilesViaTerminal(cwd, pattern);
212
+ resolvedFiles = fallbackFiles.filter((candidate) => isPathInsideBase(absoluteCwd, path.resolve(candidate)));
213
+ resolvedBy = repoMapMatches.length > 0 ? "repo_map" : "terminal_find";
214
+ }
215
+ else if (resolvedFiles.length > 1 && !hasGlobMeta(pattern)) {
216
+ resolvedFiles = await rankFileCandidates(cwd, pattern, resolvedFiles);
217
+ resolvedBy = "repo_map_ranked";
218
+ }
219
+ if (resolvedFiles.length === 0) {
220
+ return {
221
+ success: true,
222
+ message: "No files found matching the pattern",
223
+ pattern,
224
+ resolvedBy,
225
+ files: [],
226
+ };
227
+ }
228
+ // Get file details
229
+ const fileDetails = await Promise.all(resolvedFiles.map(async (file) => {
230
+ try {
231
+ const stats = await fs.stat(file);
232
+ return {
233
+ path: file,
234
+ relativePath: path.relative(absoluteCwd, file),
235
+ size: stats.size,
236
+ lastModified: stats.mtime,
237
+ };
238
+ }
239
+ catch (err) {
240
+ return null;
241
+ }
242
+ }));
243
+ const validFiles = fileDetails.filter((file) => file !== null);
244
+ return {
245
+ success: true,
246
+ pattern,
247
+ resolvedBy,
248
+ count: resolvedFiles.length,
249
+ files: validFiles,
250
+ };
251
+ }
252
+ return {
253
+ success: false,
254
+ error: "Either pattern or filePath must be provided",
255
+ };
256
+ }
257
+ catch (error) {
258
+ const err = error;
259
+ return {
260
+ success: false,
261
+ error: err.message,
262
+ };
263
+ }
264
+ }
265
+ /**
266
+ * Tool metadata for agent system
267
+ */
268
+ export const searchFilesTool = {
269
+ description: "Search for files using glob patterns or read specific line ranges from a file",
270
+ parameters: z.object({
271
+ pattern: z.string().optional().describe("Glob pattern to search for files (e.g., \"**/*.js\", \"src/**/*.json\")"),
272
+ filePath: z.string().optional().describe("Specific file path to read (alternative to pattern)"),
273
+ startLine: z.number().optional().describe("Starting line number to read (1-indexed, inclusive)"),
274
+ endLine: z.number().optional().describe("Ending line number to read (1-indexed, inclusive)"),
275
+ cwd: z.string().default(process.cwd()).describe("Current working directory for search"),
276
+ encoding: z.enum(["utf8", "ascii", "base64", "binary", "hex"]).default("utf8").describe("The encoding to use when reading the file"),
277
+ }),
278
+ execute: searchFiles,
279
+ };
280
+ export default searchFilesTool;
@@ -0,0 +1,3 @@
1
+ import type { TerminalAutoApproveRules } from "../../library/terminalAutoApproveSettings.js";
2
+ export type TerminalApprovalPolicy = "always_prompt" | "auto_approve_safe";
3
+ export declare function shouldAutoApproveTerminalCommand(commandLine: string | undefined, customRuleConfig?: TerminalAutoApproveRules): boolean;