claude-ide-bridge 1.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 (273) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +263 -0
  3. package/dist/activityLog.d.ts +26 -0
  4. package/dist/activityLog.js +76 -0
  5. package/dist/activityLog.js.map +1 -0
  6. package/dist/bridge.d.ts +19 -0
  7. package/dist/bridge.js +277 -0
  8. package/dist/bridge.js.map +1 -0
  9. package/dist/config.d.ts +22 -0
  10. package/dist/config.js +221 -0
  11. package/dist/config.js.map +1 -0
  12. package/dist/errors.d.ts +16 -0
  13. package/dist/errors.js +20 -0
  14. package/dist/errors.js.map +1 -0
  15. package/dist/extensionClient.d.ts +193 -0
  16. package/dist/extensionClient.js +698 -0
  17. package/dist/extensionClient.js.map +1 -0
  18. package/dist/fileLock.d.ts +12 -0
  19. package/dist/fileLock.js +30 -0
  20. package/dist/fileLock.js.map +1 -0
  21. package/dist/index.d.ts +2 -0
  22. package/dist/index.js +38 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/lockfile.d.ts +12 -0
  25. package/dist/lockfile.js +127 -0
  26. package/dist/lockfile.js.map +1 -0
  27. package/dist/logger.d.ts +16 -0
  28. package/dist/logger.js +68 -0
  29. package/dist/logger.js.map +1 -0
  30. package/dist/probe.d.ts +22 -0
  31. package/dist/probe.js +45 -0
  32. package/dist/probe.js.map +1 -0
  33. package/dist/server.d.ts +25 -0
  34. package/dist/server.js +265 -0
  35. package/dist/server.js.map +1 -0
  36. package/dist/tools/activityLog.d.ts +39 -0
  37. package/dist/tools/activityLog.js +49 -0
  38. package/dist/tools/activityLog.js.map +1 -0
  39. package/dist/tools/aiComments.d.ts +26 -0
  40. package/dist/tools/aiComments.js +196 -0
  41. package/dist/tools/aiComments.js.map +1 -0
  42. package/dist/tools/bridgeStatus.d.ts +21 -0
  43. package/dist/tools/bridgeStatus.js +41 -0
  44. package/dist/tools/bridgeStatus.js.map +1 -0
  45. package/dist/tools/checkDocumentDirty.d.ts +28 -0
  46. package/dist/tools/checkDocumentDirty.js +61 -0
  47. package/dist/tools/checkDocumentDirty.js.map +1 -0
  48. package/dist/tools/clipboard.d.ts +50 -0
  49. package/dist/tools/clipboard.js +82 -0
  50. package/dist/tools/clipboard.js.map +1 -0
  51. package/dist/tools/closeTabs.d.ts +49 -0
  52. package/dist/tools/closeTabs.js +77 -0
  53. package/dist/tools/closeTabs.js.map +1 -0
  54. package/dist/tools/debug.d.ts +154 -0
  55. package/dist/tools/debug.js +248 -0
  56. package/dist/tools/debug.js.map +1 -0
  57. package/dist/tools/decorations.d.ts +92 -0
  58. package/dist/tools/decorations.js +150 -0
  59. package/dist/tools/decorations.js.map +1 -0
  60. package/dist/tools/diffDebugger.d.ts +62 -0
  61. package/dist/tools/diffDebugger.js +245 -0
  62. package/dist/tools/diffDebugger.js.map +1 -0
  63. package/dist/tools/editText.d.ts +80 -0
  64. package/dist/tools/editText.js +274 -0
  65. package/dist/tools/editText.js.map +1 -0
  66. package/dist/tools/fileOperations.d.ts +111 -0
  67. package/dist/tools/fileOperations.js +280 -0
  68. package/dist/tools/fileOperations.js.map +1 -0
  69. package/dist/tools/fileWatcher.d.ts +54 -0
  70. package/dist/tools/fileWatcher.js +100 -0
  71. package/dist/tools/fileWatcher.js.map +1 -0
  72. package/dist/tools/findFiles.d.ts +31 -0
  73. package/dist/tools/findFiles.js +119 -0
  74. package/dist/tools/findFiles.js.map +1 -0
  75. package/dist/tools/fixAllLintErrors.d.ts +29 -0
  76. package/dist/tools/fixAllLintErrors.js +114 -0
  77. package/dist/tools/fixAllLintErrors.js.map +1 -0
  78. package/dist/tools/flowGuardian.d.ts +61 -0
  79. package/dist/tools/flowGuardian.js +311 -0
  80. package/dist/tools/flowGuardian.js.map +1 -0
  81. package/dist/tools/formatDocument.d.ts +30 -0
  82. package/dist/tools/formatDocument.js +132 -0
  83. package/dist/tools/formatDocument.js.map +1 -0
  84. package/dist/tools/formatFile.d.ts +28 -0
  85. package/dist/tools/formatFile.js +110 -0
  86. package/dist/tools/formatFile.js.map +1 -0
  87. package/dist/tools/getBufferContent.d.ts +38 -0
  88. package/dist/tools/getBufferContent.js +100 -0
  89. package/dist/tools/getBufferContent.js.map +1 -0
  90. package/dist/tools/getCurrentSelection.d.ts +43 -0
  91. package/dist/tools/getCurrentSelection.js +75 -0
  92. package/dist/tools/getCurrentSelection.js.map +1 -0
  93. package/dist/tools/getDiagnostics.d.ts +38 -0
  94. package/dist/tools/getDiagnostics.js +204 -0
  95. package/dist/tools/getDiagnostics.js.map +1 -0
  96. package/dist/tools/getDocumentSymbols.d.ts +27 -0
  97. package/dist/tools/getDocumentSymbols.js +133 -0
  98. package/dist/tools/getDocumentSymbols.js.map +1 -0
  99. package/dist/tools/getFileTree.d.ts +36 -0
  100. package/dist/tools/getFileTree.js +111 -0
  101. package/dist/tools/getFileTree.js.map +1 -0
  102. package/dist/tools/getGitDiff.d.ts +34 -0
  103. package/dist/tools/getGitDiff.js +57 -0
  104. package/dist/tools/getGitDiff.js.map +1 -0
  105. package/dist/tools/getGitLog.d.ts +30 -0
  106. package/dist/tools/getGitLog.js +65 -0
  107. package/dist/tools/getGitLog.js.map +1 -0
  108. package/dist/tools/getGitStatus.d.ts +26 -0
  109. package/dist/tools/getGitStatus.js +95 -0
  110. package/dist/tools/getGitStatus.js.map +1 -0
  111. package/dist/tools/getOpenEditors.d.ts +21 -0
  112. package/dist/tools/getOpenEditors.js +84 -0
  113. package/dist/tools/getOpenEditors.js.map +1 -0
  114. package/dist/tools/getProjectInfo.d.ts +20 -0
  115. package/dist/tools/getProjectInfo.js +315 -0
  116. package/dist/tools/getProjectInfo.js.map +1 -0
  117. package/dist/tools/getToolCapabilities.d.ts +23 -0
  118. package/dist/tools/getToolCapabilities.js +249 -0
  119. package/dist/tools/getToolCapabilities.js.map +1 -0
  120. package/dist/tools/getWorkspaceFolders.d.ts +21 -0
  121. package/dist/tools/getWorkspaceFolders.js +47 -0
  122. package/dist/tools/getWorkspaceFolders.js.map +1 -0
  123. package/dist/tools/gitHistory.d.ts +78 -0
  124. package/dist/tools/gitHistory.js +151 -0
  125. package/dist/tools/gitHistory.js.map +1 -0
  126. package/dist/tools/gitWrite.d.ts +335 -0
  127. package/dist/tools/gitWrite.js +859 -0
  128. package/dist/tools/gitWrite.js.map +1 -0
  129. package/dist/tools/github/actions.d.ts +67 -0
  130. package/dist/tools/github/actions.js +155 -0
  131. package/dist/tools/github/actions.js.map +1 -0
  132. package/dist/tools/github/index.d.ts +4 -0
  133. package/dist/tools/github/index.js +5 -0
  134. package/dist/tools/github/index.js.map +1 -0
  135. package/dist/tools/github/issues.d.ts +140 -0
  136. package/dist/tools/github/issues.js +279 -0
  137. package/dist/tools/github/issues.js.map +1 -0
  138. package/dist/tools/github/pr.d.ts +101 -0
  139. package/dist/tools/github/pr.js +215 -0
  140. package/dist/tools/github/pr.js.map +1 -0
  141. package/dist/tools/github/review.d.ts +101 -0
  142. package/dist/tools/github/review.js +292 -0
  143. package/dist/tools/github/review.js.map +1 -0
  144. package/dist/tools/github/shared.d.ts +4 -0
  145. package/dist/tools/github/shared.js +12 -0
  146. package/dist/tools/github/shared.js.map +1 -0
  147. package/dist/tools/github.d.ts +308 -0
  148. package/dist/tools/github.js +656 -0
  149. package/dist/tools/github.js.map +1 -0
  150. package/dist/tools/hoverAtCursor.d.ts +22 -0
  151. package/dist/tools/hoverAtCursor.js +51 -0
  152. package/dist/tools/hoverAtCursor.js.map +1 -0
  153. package/dist/tools/httpClient.d.ts +83 -0
  154. package/dist/tools/httpClient.js +335 -0
  155. package/dist/tools/httpClient.js.map +1 -0
  156. package/dist/tools/index.d.ts +7 -0
  157. package/dist/tools/index.js +246 -0
  158. package/dist/tools/index.js.map +1 -0
  159. package/dist/tools/inlayHints.d.ts +38 -0
  160. package/dist/tools/inlayHints.js +56 -0
  161. package/dist/tools/inlayHints.js.map +1 -0
  162. package/dist/tools/linters/biome.d.ts +2 -0
  163. package/dist/tools/linters/biome.js +44 -0
  164. package/dist/tools/linters/biome.js.map +1 -0
  165. package/dist/tools/linters/cargo.d.ts +2 -0
  166. package/dist/tools/linters/cargo.js +45 -0
  167. package/dist/tools/linters/cargo.js.map +1 -0
  168. package/dist/tools/linters/eslint.d.ts +2 -0
  169. package/dist/tools/linters/eslint.js +59 -0
  170. package/dist/tools/linters/eslint.js.map +1 -0
  171. package/dist/tools/linters/govet.d.ts +2 -0
  172. package/dist/tools/linters/govet.js +37 -0
  173. package/dist/tools/linters/govet.js.map +1 -0
  174. package/dist/tools/linters/pyright.d.ts +2 -0
  175. package/dist/tools/linters/pyright.js +34 -0
  176. package/dist/tools/linters/pyright.js.map +1 -0
  177. package/dist/tools/linters/ruff.d.ts +2 -0
  178. package/dist/tools/linters/ruff.js +30 -0
  179. package/dist/tools/linters/ruff.js.map +1 -0
  180. package/dist/tools/linters/types.d.ts +16 -0
  181. package/dist/tools/linters/types.js +2 -0
  182. package/dist/tools/linters/types.js.map +1 -0
  183. package/dist/tools/linters/typescript.d.ts +2 -0
  184. package/dist/tools/linters/typescript.js +38 -0
  185. package/dist/tools/linters/typescript.js.map +1 -0
  186. package/dist/tools/lsp.d.ts +310 -0
  187. package/dist/tools/lsp.js +684 -0
  188. package/dist/tools/lsp.js.map +1 -0
  189. package/dist/tools/notebook.d.ts +95 -0
  190. package/dist/tools/notebook.js +144 -0
  191. package/dist/tools/notebook.js.map +1 -0
  192. package/dist/tools/openDiff.d.ts +41 -0
  193. package/dist/tools/openDiff.js +116 -0
  194. package/dist/tools/openDiff.js.map +1 -0
  195. package/dist/tools/openFile.d.ts +34 -0
  196. package/dist/tools/openFile.js +102 -0
  197. package/dist/tools/openFile.js.map +1 -0
  198. package/dist/tools/organizeImports.d.ts +29 -0
  199. package/dist/tools/organizeImports.js +64 -0
  200. package/dist/tools/organizeImports.js.map +1 -0
  201. package/dist/tools/planPersistence.d.ts +196 -0
  202. package/dist/tools/planPersistence.js +437 -0
  203. package/dist/tools/planPersistence.js.map +1 -0
  204. package/dist/tools/replaceBlock.d.ts +40 -0
  205. package/dist/tools/replaceBlock.js +105 -0
  206. package/dist/tools/replaceBlock.js.map +1 -0
  207. package/dist/tools/runCommand.d.ts +43 -0
  208. package/dist/tools/runCommand.js +141 -0
  209. package/dist/tools/runCommand.js.map +1 -0
  210. package/dist/tools/runTests.d.ts +32 -0
  211. package/dist/tools/runTests.js +160 -0
  212. package/dist/tools/runTests.js.map +1 -0
  213. package/dist/tools/saveDocument.d.ts +28 -0
  214. package/dist/tools/saveDocument.js +58 -0
  215. package/dist/tools/saveDocument.js.map +1 -0
  216. package/dist/tools/searchAndReplace.d.ts +50 -0
  217. package/dist/tools/searchAndReplace.js +203 -0
  218. package/dist/tools/searchAndReplace.js.map +1 -0
  219. package/dist/tools/searchWorkspace.d.ts +52 -0
  220. package/dist/tools/searchWorkspace.js +159 -0
  221. package/dist/tools/searchWorkspace.js.map +1 -0
  222. package/dist/tools/setActiveWorkspaceFolder.d.ts +28 -0
  223. package/dist/tools/setActiveWorkspaceFolder.js +32 -0
  224. package/dist/tools/setActiveWorkspaceFolder.js.map +1 -0
  225. package/dist/tools/tasks.d.ts +56 -0
  226. package/dist/tools/tasks.js +89 -0
  227. package/dist/tools/tasks.js.map +1 -0
  228. package/dist/tools/terminal.d.ts +241 -0
  229. package/dist/tools/terminal.js +539 -0
  230. package/dist/tools/terminal.js.map +1 -0
  231. package/dist/tools/testRunners/cargoTest.d.ts +2 -0
  232. package/dist/tools/testRunners/cargoTest.js +123 -0
  233. package/dist/tools/testRunners/cargoTest.js.map +1 -0
  234. package/dist/tools/testRunners/goTest.d.ts +2 -0
  235. package/dist/tools/testRunners/goTest.js +106 -0
  236. package/dist/tools/testRunners/goTest.js.map +1 -0
  237. package/dist/tools/testRunners/pytest.d.ts +2 -0
  238. package/dist/tools/testRunners/pytest.js +133 -0
  239. package/dist/tools/testRunners/pytest.js.map +1 -0
  240. package/dist/tools/testRunners/types.d.ts +18 -0
  241. package/dist/tools/testRunners/types.js +2 -0
  242. package/dist/tools/testRunners/types.js.map +1 -0
  243. package/dist/tools/testRunners/vitestJest.d.ts +3 -0
  244. package/dist/tools/testRunners/vitestJest.js +178 -0
  245. package/dist/tools/testRunners/vitestJest.js.map +1 -0
  246. package/dist/tools/typeHierarchy.d.ts +45 -0
  247. package/dist/tools/typeHierarchy.js +65 -0
  248. package/dist/tools/typeHierarchy.js.map +1 -0
  249. package/dist/tools/utils.d.ts +54 -0
  250. package/dist/tools/utils.js +267 -0
  251. package/dist/tools/utils.js.map +1 -0
  252. package/dist/tools/vscodeCommands.d.ts +59 -0
  253. package/dist/tools/vscodeCommands.js +108 -0
  254. package/dist/tools/vscodeCommands.js.map +1 -0
  255. package/dist/tools/watchDiagnostics.d.ts +32 -0
  256. package/dist/tools/watchDiagnostics.js +87 -0
  257. package/dist/tools/watchDiagnostics.js.map +1 -0
  258. package/dist/tools/workspaceSettings.d.ts +67 -0
  259. package/dist/tools/workspaceSettings.js +102 -0
  260. package/dist/tools/workspaceSettings.js.map +1 -0
  261. package/dist/tools/workspaceSnapshots.d.ts +174 -0
  262. package/dist/tools/workspaceSnapshots.js +474 -0
  263. package/dist/tools/workspaceSnapshots.js.map +1 -0
  264. package/dist/transport.d.ts +57 -0
  265. package/dist/transport.js +417 -0
  266. package/dist/transport.js.map +1 -0
  267. package/dist/version.d.ts +2 -0
  268. package/dist/version.js +3 -0
  269. package/dist/version.js.map +1 -0
  270. package/dist/wsUtils.d.ts +9 -0
  271. package/dist/wsUtils.js +54 -0
  272. package/dist/wsUtils.js.map +1 -0
  273. package/package.json +69 -0
@@ -0,0 +1,141 @@
1
+ import { INTERPRETER_COMMANDS } from "../config.js";
2
+ import { execSafe, optionalInt, optionalString, requireString, resolveFilePath, success, truncateOutput, } from "./utils.js";
3
+ const MAX_ARGS = 100;
4
+ const MAX_ARG_LENGTH = 4096;
5
+ /** Flags that allow interpreter commands to execute arbitrary code */
6
+ const DANGEROUS_INTERPRETER_FLAGS = new Set([
7
+ "-e",
8
+ "--eval",
9
+ "-c",
10
+ "--print",
11
+ "-p",
12
+ "--input-type",
13
+ "--import", // Node.js ESM loader
14
+ "--loader", // Custom ESM loader
15
+ "--experimental-loader", // Custom ESM loader (legacy)
16
+ "-m", // Python module execution
17
+ ]);
18
+ /** Flags that redirect where commands read config/manifests from */
19
+ const DANGEROUS_PATH_FLAGS = new Set([
20
+ "--prefix",
21
+ "--manifest-path",
22
+ "--config",
23
+ "--rcfile",
24
+ "--require",
25
+ "-r",
26
+ "--userconfig", // npm config redirection
27
+ "--globalconfig", // npm config redirection
28
+ "-f",
29
+ "--makefile", // make Makefile path
30
+ ]);
31
+ function validateCommand(command, allowlist) {
32
+ if (command.includes("/") ||
33
+ command.includes("\\") ||
34
+ command.includes("..") ||
35
+ command.includes(" ")) {
36
+ throw new Error(`Invalid command "${command}": must be a simple basename without /, \\, .., or spaces`);
37
+ }
38
+ if (!allowlist.some((entry) => entry.toLowerCase() === command)) {
39
+ throw new Error(`Command "${command}" is not in the allowlist. Use --allow-command ${command} to add it. Run getToolCapabilities to see allowed commands.`);
40
+ }
41
+ }
42
+ function validateArgs(args, command) {
43
+ if (args === undefined || args === null)
44
+ return [];
45
+ if (!Array.isArray(args)) {
46
+ throw new Error("args must be an array of strings");
47
+ }
48
+ if (args.length > MAX_ARGS) {
49
+ throw new Error(`args exceeds maximum length of ${MAX_ARGS}`);
50
+ }
51
+ const isInterpreter = INTERPRETER_COMMANDS.has(command);
52
+ for (let i = 0; i < args.length; i++) {
53
+ const arg = args[i];
54
+ if (typeof arg !== "string") {
55
+ throw new Error(`args[${i}] must be a string`);
56
+ }
57
+ if (arg.length > MAX_ARG_LENGTH) {
58
+ throw new Error(`args[${i}] exceeds maximum length of ${MAX_ARG_LENGTH}`);
59
+ }
60
+ // Block code-execution flags for interpreter commands
61
+ if (isInterpreter && DANGEROUS_INTERPRETER_FLAGS.has(arg)) {
62
+ throw new Error(`Flag "${arg}" is blocked for interpreter command "${command}" — it allows arbitrary code execution`);
63
+ }
64
+ // Block config/path-override flags for all commands
65
+ if (DANGEROUS_PATH_FLAGS.has(arg)) {
66
+ throw new Error(`Flag "${arg}" is blocked — it can redirect command execution outside the workspace`);
67
+ }
68
+ }
69
+ return args;
70
+ }
71
+ export function createRunCommandTool(workspace, config) {
72
+ return {
73
+ schema: {
74
+ name: "runCommand",
75
+ description: "Execute an allowlisted command in the workspace. Returns stdout, stderr, exit code, and timing information. Commands run without a shell for security.",
76
+ annotations: { destructiveHint: true },
77
+ inputSchema: {
78
+ type: "object",
79
+ properties: {
80
+ command: {
81
+ type: "string",
82
+ description: "Command basename to run (must be in the allowlist, no paths)",
83
+ },
84
+ args: {
85
+ type: "array",
86
+ items: { type: "string" },
87
+ description: "Command arguments",
88
+ },
89
+ cwd: {
90
+ type: "string",
91
+ description: "Working directory for the command (absolute or workspace-relative, default: workspace root)",
92
+ },
93
+ timeout: {
94
+ type: "integer",
95
+ description: `Timeout in milliseconds (default: ${config.commandTimeout}, max: 120000)`,
96
+ },
97
+ },
98
+ required: ["command"],
99
+ additionalProperties: false,
100
+ },
101
+ },
102
+ timeoutMs: 300_000,
103
+ handler: async (args, signal) => {
104
+ // Normalize to lowercase before all validation — prevents case-sensitivity bypass
105
+ // on case-insensitive filesystems (macOS HFS+, Windows) where "NODE" resolves to "node"
106
+ const command = requireString(args, "command", 256).toLowerCase();
107
+ validateCommand(command, config.commandAllowlist);
108
+ const cmdArgs = validateArgs(args.args, command);
109
+ const cwdRaw = optionalString(args, "cwd");
110
+ const timeout = optionalInt(args, "timeout", 1000, 120_000) ?? config.commandTimeout;
111
+ const cwd = cwdRaw ? resolveFilePath(cwdRaw, workspace) : workspace;
112
+ const maxBytes = config.maxResultSize * 1024;
113
+ const result = await execSafe(command, cmdArgs, {
114
+ cwd,
115
+ timeout,
116
+ maxBuffer: maxBytes,
117
+ signal,
118
+ });
119
+ const stdoutResult = truncateOutput(result.stdout, maxBytes);
120
+ const stderrResult = truncateOutput(result.stderr, maxBytes);
121
+ const anyTruncated = stdoutResult.truncated || stderrResult.truncated;
122
+ return success({
123
+ exitCode: result.exitCode,
124
+ stdout: stdoutResult.text,
125
+ stderr: stderrResult.text,
126
+ durationMs: result.durationMs,
127
+ timedOut: result.timedOut,
128
+ ...(anyTruncated
129
+ ? {
130
+ truncated: true,
131
+ stdoutTruncated: stdoutResult.truncated,
132
+ stderrTruncated: stderrResult.truncated,
133
+ maxBytes,
134
+ note: "Output exceeded limit. Redirect to a file (command > out.txt) to capture full output.",
135
+ }
136
+ : {}),
137
+ });
138
+ },
139
+ };
140
+ }
141
+ //# sourceMappingURL=runCommand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runCommand.js","sourceRoot":"","sources":["../../src/tools/runCommand.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type { ProbeResults } from "../probe.js";
2
+ import type { ProgressFn } from "../transport.js";
3
+ export declare function createRunTestsTool(workspace: string, probes?: ProbeResults): {
4
+ schema: {
5
+ name: string;
6
+ description: string;
7
+ inputSchema: {
8
+ type: "object";
9
+ properties: {
10
+ filter: {
11
+ type: string;
12
+ description: string;
13
+ };
14
+ runner: {
15
+ type: string;
16
+ description: string;
17
+ };
18
+ noCache: {
19
+ type: string;
20
+ description: string;
21
+ };
22
+ };
23
+ additionalProperties: false;
24
+ };
25
+ };
26
+ handler(args: Record<string, unknown>, signal?: AbortSignal, progress?: ProgressFn): Promise<{
27
+ content: Array<{
28
+ type: string;
29
+ text: string;
30
+ }>;
31
+ }>;
32
+ };
@@ -0,0 +1,160 @@
1
+ import { cargoTestRunner } from "./testRunners/cargoTest.js";
2
+ import { goTestRunner } from "./testRunners/goTest.js";
3
+ import { pytestRunner } from "./testRunners/pytest.js";
4
+ import { jestRunner, vitestRunner } from "./testRunners/vitestJest.js";
5
+ import { optionalBool, optionalString, success } from "./utils.js";
6
+ const MAX_CACHE_ENTRIES = 50;
7
+ const ALL_RUNNERS = [
8
+ vitestRunner,
9
+ jestRunner,
10
+ pytestRunner,
11
+ cargoTestRunner,
12
+ goTestRunner,
13
+ ];
14
+ export function createRunTestsTool(workspace, probes) {
15
+ const availableRunners = probes
16
+ ? ALL_RUNNERS.filter((r) => r.detect(workspace, probes))
17
+ : [];
18
+ const caches = new Map();
19
+ const runningPromises = new Map();
20
+ const runnerErrors = new Map();
21
+ async function runRunner(runner, filter, signal) {
22
+ const cacheKey = `${runner.name}:${filter ?? ""}`;
23
+ const now = Date.now();
24
+ const cached = caches.get(cacheKey);
25
+ if (cached && now - cached.timestamp < runner.cacheTtl) {
26
+ return cached.data;
27
+ }
28
+ let running = runningPromises.get(cacheKey);
29
+ if (!running) {
30
+ running = runner
31
+ .run(workspace, filter, signal)
32
+ .then((data) => {
33
+ // Evict oldest entry if cache is full
34
+ if (caches.size >= MAX_CACHE_ENTRIES) {
35
+ const oldestKey = caches.keys().next().value;
36
+ if (oldestKey)
37
+ caches.delete(oldestKey);
38
+ }
39
+ caches.set(cacheKey, { data, timestamp: Date.now() });
40
+ // Clear any previous error for this runner on success
41
+ runnerErrors.delete(runner.name);
42
+ return data;
43
+ })
44
+ .catch((err) => {
45
+ if (!(err instanceof Error) || err.name !== "AbortError") {
46
+ caches.set(cacheKey, { data: [], timestamp: Date.now() });
47
+ runnerErrors.set(runner.name, err instanceof Error ? err.message : String(err));
48
+ }
49
+ return [];
50
+ })
51
+ .finally(() => {
52
+ runningPromises.delete(cacheKey);
53
+ });
54
+ runningPromises.set(cacheKey, running);
55
+ }
56
+ return running;
57
+ }
58
+ return {
59
+ schema: {
60
+ name: "runTests",
61
+ description: "Run tests using auto-detected frameworks (Vitest, Jest, Pytest, Cargo test, Go test). Returns structured results with pass/fail status, failure messages, and file:line locations for correlation with code changes. Results are cached per runner (30s TTL) — use noCache: true after code changes to get fresh results.",
62
+ inputSchema: {
63
+ type: "object",
64
+ properties: {
65
+ filter: {
66
+ type: "string",
67
+ description: "Test name pattern or file path to filter which tests run",
68
+ },
69
+ runner: {
70
+ type: "string",
71
+ description: "Specific runner to use (e.g., 'vitest', 'jest', 'pytest', 'cargo-test', 'go-test'). Default: all detected",
72
+ },
73
+ noCache: {
74
+ type: "boolean",
75
+ description: "Skip cache and force a fresh run. Default: false",
76
+ },
77
+ },
78
+ additionalProperties: false,
79
+ },
80
+ },
81
+ async handler(args, signal, progress) {
82
+ progress?.(0, 100);
83
+ const filter = optionalString(args, "filter");
84
+ const runnerName = optionalString(args, "runner");
85
+ const noCache = optionalBool(args, "noCache") ?? false;
86
+ if (availableRunners.length === 0) {
87
+ return success({
88
+ available: false,
89
+ runners: [],
90
+ summary: {
91
+ total: 0,
92
+ passed: 0,
93
+ failed: 0,
94
+ skipped: 0,
95
+ errored: 0,
96
+ durationMs: 0,
97
+ },
98
+ results: [],
99
+ failures: [],
100
+ });
101
+ }
102
+ let runners = availableRunners;
103
+ if (runnerName) {
104
+ runners = availableRunners.filter((r) => r.name === runnerName);
105
+ if (runners.length === 0) {
106
+ return success({
107
+ available: true,
108
+ runners: availableRunners.map((r) => r.name),
109
+ error: `Runner '${runnerName}' not found. Available: ${availableRunners.map((r) => r.name).join(", ")}`,
110
+ summary: {
111
+ total: 0,
112
+ passed: 0,
113
+ failed: 0,
114
+ skipped: 0,
115
+ errored: 0,
116
+ durationMs: 0,
117
+ },
118
+ results: [],
119
+ failures: [],
120
+ });
121
+ }
122
+ }
123
+ if (noCache) {
124
+ for (const r of runners) {
125
+ const key = `${r.name}:${filter ?? ""}`;
126
+ caches.delete(key);
127
+ }
128
+ }
129
+ const startTime = Date.now();
130
+ const allResults = await Promise.all(runners.map((r) => runRunner(r, filter, signal)));
131
+ const results = allResults.flat();
132
+ const durationMs = Date.now() - startTime;
133
+ const summary = {
134
+ total: results.length,
135
+ passed: results.filter((r) => r.status === "passed").length,
136
+ failed: results.filter((r) => r.status === "failed").length,
137
+ skipped: results.filter((r) => r.status === "skipped").length,
138
+ errored: results.filter((r) => r.status === "errored").length,
139
+ durationMs,
140
+ };
141
+ // Collect any runner errors from this execution
142
+ const errors = {};
143
+ for (const r of runners) {
144
+ const err = runnerErrors.get(r.name);
145
+ if (err)
146
+ errors[r.name] = err;
147
+ }
148
+ progress?.(100, 100);
149
+ return success({
150
+ available: true,
151
+ runners: runners.map((r) => r.name),
152
+ summary,
153
+ results,
154
+ failures: results.filter((r) => r.status === "failed" || r.status === "errored"),
155
+ ...(Object.keys(errors).length > 0 && { runnerErrors: errors }),
156
+ });
157
+ },
158
+ };
159
+ }
160
+ //# sourceMappingURL=runTests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runTests.js","sourceRoot":"","sources":["../../src/tools/runTests.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { type ExtensionClient } from "../extensionClient.js";
2
+ export declare function createSaveDocumentTool(workspace: string, extensionClient?: ExtensionClient): {
3
+ schema: {
4
+ name: string;
5
+ description: string;
6
+ annotations: {
7
+ destructiveHint: boolean;
8
+ };
9
+ inputSchema: {
10
+ $schema: string;
11
+ type: string;
12
+ additionalProperties: boolean;
13
+ required: string[];
14
+ properties: {
15
+ filePath: {
16
+ type: string;
17
+ description: string;
18
+ };
19
+ };
20
+ };
21
+ };
22
+ handler(args: Record<string, unknown>): Promise<{
23
+ content: Array<{
24
+ type: string;
25
+ text: string;
26
+ }>;
27
+ }>;
28
+ };
@@ -0,0 +1,58 @@
1
+ import { ExtensionTimeoutError, } from "../extensionClient.js";
2
+ import { requireString, resolveFilePath, success } from "./utils.js";
3
+ export function createSaveDocumentTool(workspace, extensionClient) {
4
+ return {
5
+ schema: {
6
+ name: "saveDocument",
7
+ description: "Save a document with unsaved changes. Uses VS Code's real buffer save when the extension is connected (ensures editor state matches disk). Without the extension, this is a no-op — edits applied via editText are already written directly to disk.",
8
+ annotations: { destructiveHint: true },
9
+ inputSchema: {
10
+ $schema: "http://json-schema.org/draft-07/schema#",
11
+ type: "object",
12
+ additionalProperties: false,
13
+ required: ["filePath"],
14
+ properties: {
15
+ filePath: { type: "string", description: "Path to the file to save" },
16
+ },
17
+ },
18
+ },
19
+ async handler(args) {
20
+ const rawPath = requireString(args, "filePath");
21
+ const filePath = resolveFilePath(rawPath, workspace);
22
+ // Use extension for real buffer flush when available
23
+ if (extensionClient?.isConnected()) {
24
+ try {
25
+ const saved = await extensionClient.saveFile(filePath);
26
+ if (saved) {
27
+ return success({
28
+ success: true,
29
+ filePath,
30
+ saved: true,
31
+ source: "vscode-buffer",
32
+ });
33
+ }
34
+ // false — file not open in editor (already on disk from editText or never opened)
35
+ return success({
36
+ success: true,
37
+ filePath,
38
+ saved: false,
39
+ message: "File is not open in VS Code editor — content is already persisted to disk",
40
+ });
41
+ }
42
+ catch (err) {
43
+ if (!(err instanceof ExtensionTimeoutError))
44
+ throw err;
45
+ // Timeout — fall through to no-op response
46
+ }
47
+ }
48
+ // Without the extension, editText already writes directly to disk
49
+ return success({
50
+ success: true,
51
+ filePath,
52
+ saved: false,
53
+ message: "Extension not connected — edits are written directly to disk by editText; no buffer flush needed",
54
+ });
55
+ },
56
+ };
57
+ }
58
+ //# sourceMappingURL=saveDocument.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"saveDocument.js","sourceRoot":"","sources":["../../src/tools/saveDocument.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErE,MAAM,UAAU,sBAAsB,CACpC,SAAiB,EACjB,eAAiC;IAEjC,OAAO;QACL,MAAM,EAAE;YACN,IAAI,EAAE,cAAc;YACpB,WAAW,EACT,sPAAsP;YACxP,WAAW,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE;YACtC,WAAW,EAAE;gBACX,OAAO,EAAE,yCAAyC;gBAClD,IAAI,EAAE,QAAQ;gBACd,oBAAoB,EAAE,KAAK;gBAC3B,QAAQ,EAAE,CAAC,UAAU,CAAC;gBACtB,UAAU,EAAE;oBACV,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0BAA0B,EAAE;iBACtE;aACF;SACF;QAED,KAAK,CAAC,OAAO,CAAC,IAA6B;YACzC,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YAChD,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAErD,qDAAqD;YACrD,IAAI,eAAe,EAAE,WAAW,EAAE,EAAE,CAAC;gBACnC,IAAI,CAAC;oBACH,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;oBACvD,IAAI,KAAK,EAAE,CAAC;wBACV,OAAO,OAAO,CAAC;4BACb,OAAO,EAAE,IAAI;4BACb,QAAQ;4BACR,KAAK,EAAE,IAAI;4BACX,MAAM,EAAE,eAAe;yBACxB,CAAC,CAAC;oBACL,CAAC;oBACD,kFAAkF;oBAClF,OAAO,OAAO,CAAC;wBACb,OAAO,EAAE,IAAI;wBACb,QAAQ;wBACR,KAAK,EAAE,KAAK;wBACZ,OAAO,EACL,2EAA2E;qBAC9E,CAAC,CAAC;gBACL,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,IAAI,CAAC,CAAC,GAAG,YAAY,qBAAqB,CAAC;wBAAE,MAAM,GAAG,CAAC;oBACvD,2CAA2C;gBAC7C,CAAC;YACH,CAAC;YAED,kEAAkE;YAClE,OAAO,OAAO,CAAC;gBACb,OAAO,EAAE,IAAI;gBACb,QAAQ;gBACR,KAAK,EAAE,KAAK;gBACZ,OAAO,EACL,kGAAkG;aACrG,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,50 @@
1
+ export declare function createSearchAndReplaceTool(workspace: string): {
2
+ schema: {
3
+ name: string;
4
+ description: string;
5
+ annotations: {
6
+ destructiveHint: boolean;
7
+ };
8
+ inputSchema: {
9
+ type: "object";
10
+ properties: {
11
+ pattern: {
12
+ type: string;
13
+ description: string;
14
+ };
15
+ replacement: {
16
+ type: string;
17
+ description: string;
18
+ };
19
+ glob: {
20
+ type: string;
21
+ description: string;
22
+ };
23
+ isRegex: {
24
+ type: string;
25
+ description: string;
26
+ };
27
+ caseSensitive: {
28
+ type: string;
29
+ description: string;
30
+ };
31
+ dryRun: {
32
+ type: string;
33
+ description: string;
34
+ };
35
+ includeIgnored: {
36
+ type: string;
37
+ description: string;
38
+ };
39
+ };
40
+ required: string[];
41
+ additionalProperties: false;
42
+ };
43
+ };
44
+ handler: (args: Record<string, unknown>) => Promise<{
45
+ content: Array<{
46
+ type: string;
47
+ text: string;
48
+ }>;
49
+ }>;
50
+ };