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
package/dist/server.js ADDED
@@ -0,0 +1,265 @@
1
+ import crypto from "node:crypto";
2
+ import { EventEmitter } from "node:events";
3
+ import http from "node:http";
4
+ import { WebSocket, WebSocketServer as WsServer } from "ws";
5
+ const ALLOWED_HOSTS = new Set(["localhost", "127.0.0.1"]);
6
+ function enableTcpKeepalive(ws) {
7
+ const rawSocket = ws
8
+ ._socket;
9
+ if (rawSocket?.setKeepAlive) {
10
+ rawSocket.setKeepAlive(true, 60_000); // 60s TCP keepalive as defense-in-depth
11
+ }
12
+ }
13
+ function timingSafeTokenCompare(a, b) {
14
+ const bA = Buffer.from(a);
15
+ const bB = Buffer.from(b);
16
+ const len = Math.max(bA.length, bB.length);
17
+ const padA = Buffer.alloc(len);
18
+ const padB = Buffer.alloc(len);
19
+ bA.copy(padA);
20
+ bB.copy(padB);
21
+ return crypto.timingSafeEqual(padA, padB) && bA.length === bB.length;
22
+ }
23
+ function setupPongHandler(ws) {
24
+ ws.on("pong", (data) => {
25
+ ws.isAlive = true;
26
+ ws.missedPongs = 0;
27
+ const sentAt = Number.parseInt(data.toString(), 10);
28
+ ws.lastPongTime = Number.isNaN(sentAt) ? Date.now() : sentAt;
29
+ });
30
+ }
31
+ const MIN_CONNECTION_INTERVAL_MS = 50; // Allow multiple agents to connect within same second
32
+ export class Server extends EventEmitter {
33
+ authToken;
34
+ logger;
35
+ httpServer;
36
+ wss;
37
+ pingInterval = null;
38
+ lastClaudeConnectionTime = 0;
39
+ lastExtensionConnectionTime = 0;
40
+ startTime = Date.now();
41
+ /** Set by bridge to provide health data */
42
+ healthDataFn = null;
43
+ /** Set by bridge to provide Prometheus metrics */
44
+ metricsFn = null;
45
+ constructor(authToken, logger) {
46
+ super();
47
+ this.authToken = authToken;
48
+ this.logger = logger;
49
+ this.httpServer = http.createServer((req, res) => {
50
+ if (req.url === "/metrics" && req.method === "GET") {
51
+ try {
52
+ const body = this.metricsFn?.() ?? "";
53
+ res.writeHead(200, {
54
+ "Content-Type": "text/plain; version=0.0.4; charset=utf-8",
55
+ });
56
+ res.end(body);
57
+ }
58
+ catch (err) {
59
+ res.writeHead(500, { "Content-Type": "application/json" });
60
+ res.end(JSON.stringify({
61
+ error: err instanceof Error ? err.message : String(err),
62
+ }));
63
+ }
64
+ return;
65
+ }
66
+ if (req.url === "/health" && req.method === "GET") {
67
+ try {
68
+ const data = {
69
+ status: "ok",
70
+ uptimeMs: Date.now() - this.startTime,
71
+ connections: this.wss.clients.size,
72
+ ...(this.healthDataFn?.() ?? {}),
73
+ };
74
+ res.writeHead(200, { "Content-Type": "application/json" });
75
+ res.end(JSON.stringify(data));
76
+ }
77
+ catch (err) {
78
+ res.writeHead(500, { "Content-Type": "application/json" });
79
+ res.end(JSON.stringify({
80
+ error: err instanceof Error ? err.message : String(err),
81
+ }));
82
+ }
83
+ return;
84
+ }
85
+ res.writeHead(404, { "Content-Type": "text/plain" });
86
+ res.end("Not found");
87
+ });
88
+ // Do NOT pass server — we handle upgrade manually for pre-handshake auth
89
+ this.wss = new WsServer({
90
+ noServer: true,
91
+ maxPayload: 4 * 1024 * 1024,
92
+ perMessageDeflate: false,
93
+ });
94
+ // Authenticate on upgrade BEFORE completing the WebSocket handshake
95
+ this.httpServer.on("upgrade", (request, socket, head) => {
96
+ // Prevent unhandled error events on the raw socket during upgrade
97
+ socket.on("error", () => socket.destroy());
98
+ // Validate Host header to defend against DNS rebinding
99
+ const host = request.headers.host?.replace(/:\d+$/, "");
100
+ if (!host || !ALLOWED_HOSTS.has(host)) {
101
+ this.logger.warn(`Rejected connection with invalid Host header: ${host}`);
102
+ socket.write("HTTP/1.1 403 Forbidden\r\n\r\n");
103
+ socket.destroy();
104
+ return;
105
+ }
106
+ const now = Date.now();
107
+ // Check for extension connection (distinct header)
108
+ const extensionToken = request.headers["x-claude-ide-extension"];
109
+ if (typeof extensionToken === "string" &&
110
+ timingSafeTokenCompare(extensionToken, this.authToken)) {
111
+ // Rate limit per client type to prevent connection-storm DoS
112
+ if (now - this.lastExtensionConnectionTime <
113
+ MIN_CONNECTION_INTERVAL_MS) {
114
+ socket.write("HTTP/1.1 429 Too Many Requests\r\n\r\n");
115
+ socket.destroy();
116
+ return;
117
+ }
118
+ this.lastExtensionConnectionTime = now;
119
+ this.wss.handleUpgrade(request, socket, head, (ws) => {
120
+ const alive = ws;
121
+ alive.isAlive = true;
122
+ alive.missedPongs = 0;
123
+ alive.lastPongTime = Date.now();
124
+ enableTcpKeepalive(ws);
125
+ setupPongHandler(alive);
126
+ this.emit("extension", ws);
127
+ ws.once("close", () => {
128
+ this.lastExtensionConnectionTime = 0;
129
+ });
130
+ });
131
+ return;
132
+ }
133
+ // Check for Claude Code connection
134
+ const token = request.headers["x-claude-code-ide-authorization"];
135
+ if (typeof token !== "string" ||
136
+ !timingSafeTokenCompare(token, this.authToken)) {
137
+ this.logger.warn("Rejected unauthorized WebSocket upgrade");
138
+ socket.write("HTTP/1.1 401 Unauthorized\r\n\r\n");
139
+ socket.destroy();
140
+ return;
141
+ }
142
+ // Rate limit per client type to prevent connection-storm DoS
143
+ if (now - this.lastClaudeConnectionTime < MIN_CONNECTION_INTERVAL_MS) {
144
+ socket.write("HTTP/1.1 429 Too Many Requests\r\n\r\n");
145
+ socket.destroy();
146
+ return;
147
+ }
148
+ this.lastClaudeConnectionTime = now;
149
+ this.wss.handleUpgrade(request, socket, head, (ws) => {
150
+ this.wss.emit("connection", ws, request);
151
+ });
152
+ });
153
+ this.wss.on("connection", (raw) => {
154
+ const ws = raw;
155
+ this.logger.info("Claude Code connected");
156
+ ws.isAlive = true;
157
+ ws.missedPongs = 0;
158
+ ws.lastPongTime = Date.now();
159
+ enableTcpKeepalive(raw);
160
+ setupPongHandler(ws);
161
+ ws.on("error", (err) => {
162
+ this.logger.error(`WebSocket client error: ${err.message}`);
163
+ });
164
+ this.emit("connection", ws);
165
+ });
166
+ }
167
+ async listen(port, bindAddress = "127.0.0.1") {
168
+ return new Promise((resolve, reject) => {
169
+ this.httpServer
170
+ .listen(port, bindAddress, () => {
171
+ const addr = this.httpServer.address();
172
+ if (!addr || typeof addr === "string") {
173
+ if (this.pingInterval) {
174
+ clearInterval(this.pingInterval);
175
+ this.pingInterval = null;
176
+ }
177
+ reject(new Error("Unexpected server address"));
178
+ return;
179
+ }
180
+ // Ping clients every 30s; terminate after 3 missed pongs (90s tolerance)
181
+ this.pingInterval = setInterval(() => {
182
+ const now = Date.now();
183
+ for (const raw of this.wss.clients) {
184
+ const client = raw;
185
+ // Sleep/wake detection: if timer fired much later than expected,
186
+ // the system likely slept. Reset and probe instead of killing.
187
+ if (client.lastPingTime && now - client.lastPingTime > 45_000) {
188
+ client.missedPongs = 0;
189
+ client.isAlive = false;
190
+ client.lastPingTime = now;
191
+ if (client.readyState === WebSocket.OPEN) {
192
+ client.ping(Buffer.from(now.toString()));
193
+ }
194
+ continue;
195
+ }
196
+ if (!client.isAlive) {
197
+ client.missedPongs = (client.missedPongs ?? 0) + 1;
198
+ if (client.missedPongs >= 3) {
199
+ this.logger.warn("Terminating unresponsive client (3 missed pongs)");
200
+ client.terminate();
201
+ continue;
202
+ }
203
+ }
204
+ client.isAlive = false;
205
+ client.lastPingTime = now;
206
+ if (client.readyState === WebSocket.OPEN) {
207
+ client.ping(Buffer.from(now.toString()));
208
+ }
209
+ }
210
+ }, 30_000);
211
+ resolve(addr.port);
212
+ })
213
+ .on("error", reject);
214
+ });
215
+ }
216
+ async findAndListen(preferredPort, bindAddress = "127.0.0.1") {
217
+ if (preferredPort) {
218
+ if (preferredPort < 1 || preferredPort > 65535) {
219
+ this.logger.warn(`Invalid port ${preferredPort} (must be 1-65535), falling back to OS-assigned port`);
220
+ preferredPort = null;
221
+ }
222
+ else {
223
+ return this.listen(preferredPort, bindAddress);
224
+ }
225
+ }
226
+ // Port 0 lets the OS kernel assign a free port atomically
227
+ return this.listen(0, bindAddress);
228
+ }
229
+ async close() {
230
+ if (this.pingInterval)
231
+ clearInterval(this.pingInterval);
232
+ for (const client of this.wss.clients) {
233
+ client.close(1001, "Server shutting down");
234
+ }
235
+ // Wait up to 2s for graceful disconnect, then force-terminate
236
+ await new Promise((resolve) => {
237
+ const forceTimer = setTimeout(() => {
238
+ for (const client of this.wss.clients) {
239
+ client.terminate();
240
+ }
241
+ resolve();
242
+ }, 2000);
243
+ this.wss.close(() => {
244
+ clearTimeout(forceTimer);
245
+ resolve();
246
+ });
247
+ });
248
+ // Drain idle keep-alive HTTP connections (Node 20+ native)
249
+ this.httpServer.closeIdleConnections();
250
+ await new Promise((resolve) => {
251
+ // Hard failsafe: force-close any remaining HTTP connections after 10s
252
+ const hardTimer = setTimeout(() => {
253
+ this.httpServer.closeAllConnections();
254
+ resolve();
255
+ }, 10_000);
256
+ this.httpServer.close((err) => {
257
+ clearTimeout(hardTimer);
258
+ if (err)
259
+ this.logger.error(`HTTP server close error: ${err.message}`);
260
+ resolve();
261
+ });
262
+ });
263
+ }
264
+ }
265
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import type { ActivityLog } from "../activityLog.js";
2
+ export declare function createGetActivityLogTool(activityLog: ActivityLog): {
3
+ schema: {
4
+ name: string;
5
+ description: string;
6
+ annotations: {
7
+ readOnlyHint: boolean;
8
+ };
9
+ inputSchema: {
10
+ type: "object";
11
+ properties: {
12
+ tool: {
13
+ type: "string";
14
+ description: string;
15
+ };
16
+ status: {
17
+ type: "string";
18
+ enum: string[];
19
+ description: string;
20
+ };
21
+ last: {
22
+ type: "number";
23
+ description: string;
24
+ };
25
+ showStats: {
26
+ type: "boolean";
27
+ description: string;
28
+ };
29
+ };
30
+ additionalProperties: false;
31
+ };
32
+ };
33
+ handler: (args: Record<string, unknown>) => Promise<{
34
+ content: Array<{
35
+ type: string;
36
+ text: string;
37
+ }>;
38
+ }>;
39
+ };
@@ -0,0 +1,49 @@
1
+ import { optionalBool, optionalInt, optionalString, success } from "./utils.js";
2
+ export function createGetActivityLogTool(activityLog) {
3
+ return {
4
+ schema: {
5
+ name: "getActivityLog",
6
+ description: "Query the log of recent tool calls. Shows what tools were called, their timing, and status. Useful for reviewing what actions have been taken in this session.",
7
+ annotations: { readOnlyHint: true },
8
+ inputSchema: {
9
+ type: "object",
10
+ properties: {
11
+ tool: {
12
+ type: "string",
13
+ description: "Filter by tool name",
14
+ },
15
+ status: {
16
+ type: "string",
17
+ enum: ["success", "error"],
18
+ description: "Filter by status",
19
+ },
20
+ last: {
21
+ type: "number",
22
+ description: "Number of recent entries to return (default: 50, max: 200)",
23
+ },
24
+ showStats: {
25
+ type: "boolean",
26
+ description: "If true, include per-tool statistics (call count, avg duration, error count). Default: false",
27
+ },
28
+ },
29
+ additionalProperties: false,
30
+ },
31
+ },
32
+ handler: async (args) => {
33
+ const tool = optionalString(args, "tool");
34
+ const status = optionalString(args, "status");
35
+ const last = optionalInt(args, "last", 1, 200) ?? 50;
36
+ const showStats = optionalBool(args, "showStats") ?? false;
37
+ const entries = activityLog.query({ tool, status, last });
38
+ const result = {
39
+ entries,
40
+ count: entries.length,
41
+ };
42
+ if (showStats) {
43
+ result.stats = activityLog.stats();
44
+ }
45
+ return success(result);
46
+ },
47
+ };
48
+ }
49
+ //# sourceMappingURL=activityLog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activityLog.js","sourceRoot":"","sources":["../../src/tools/activityLog.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEhF,MAAM,UAAU,wBAAwB,CAAC,WAAwB;IAC/D,OAAO;QACL,MAAM,EAAE;YACN,IAAI,EAAE,gBAAgB;YACtB,WAAW,EACT,gKAAgK;YAClK,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;YACnC,WAAW,EAAE;gBACX,IAAI,EAAE,QAAiB;gBACvB,UAAU,EAAE;oBACV,IAAI,EAAE;wBACJ,IAAI,EAAE,QAAiB;wBACvB,WAAW,EAAE,qBAAqB;qBACnC;oBACD,MAAM,EAAE;wBACN,IAAI,EAAE,QAAiB;wBACvB,IAAI,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC;wBAC1B,WAAW,EAAE,kBAAkB;qBAChC;oBACD,IAAI,EAAE;wBACJ,IAAI,EAAE,QAAiB;wBACvB,WAAW,EACT,4DAA4D;qBAC/D;oBACD,SAAS,EAAE;wBACT,IAAI,EAAE,SAAkB;wBACxB,WAAW,EACT,8FAA8F;qBACjG;iBACF;gBACD,oBAAoB,EAAE,KAAc;aACrC;SACF;QACD,OAAO,EAAE,KAAK,EAAE,IAA6B,EAAE,EAAE;YAC/C,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC1C,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YAC9C,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;YACrD,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,KAAK,CAAC;YAE3D,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1D,MAAM,MAAM,GAA4B;gBACtC,OAAO;gBACP,KAAK,EAAE,OAAO,CAAC,MAAM;aACtB,CAAC;YACF,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,CAAC,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,CAAC;YACrC,CAAC;YACD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;QACzB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { ExtensionClient } from "../extensionClient.js";
2
+ export declare function createGetAICommentsTool(workspace: string, extensionClient: ExtensionClient): {
3
+ schema: {
4
+ name: string;
5
+ description: string;
6
+ annotations: {
7
+ readOnlyHint: boolean;
8
+ };
9
+ inputSchema: {
10
+ type: "object";
11
+ properties: {
12
+ file: {
13
+ type: string;
14
+ description: string;
15
+ };
16
+ };
17
+ additionalProperties: false;
18
+ };
19
+ };
20
+ handler: (args: Record<string, unknown>, signal?: AbortSignal) => Promise<{
21
+ content: Array<{
22
+ type: string;
23
+ text: string;
24
+ }>;
25
+ }>;
26
+ };
@@ -0,0 +1,196 @@
1
+ import path from "node:path";
2
+ import { execSafe, optionalString, resolveFilePath, success } from "./utils.js";
3
+ const SEVERITY_PREFIXES = {
4
+ fix: "fix",
5
+ todo: "todo",
6
+ question: "question",
7
+ warn: "warn",
8
+ task: "task",
9
+ };
10
+ function parseSeverityFromComment(comment) {
11
+ const match = comment.match(/^(FIX|TODO|QUESTION|WARN|TASK)\s*:?\s*/i);
12
+ if (match) {
13
+ const key = match[1].toLowerCase();
14
+ return {
15
+ severity: SEVERITY_PREFIXES[key] ?? "task",
16
+ text: comment.slice(match[0].length).trim(),
17
+ };
18
+ }
19
+ return { severity: "task", text: comment };
20
+ }
21
+ // Grep pattern covering all supported AI comment syntaxes:
22
+ // // AI:, # AI:, /* AI:, <!-- AI:, -- AI:, %% AI:, ' AI:
23
+ const GREP_PATTERN = "(\\/\\/|#|/\\*|<!--|--|%%|')\\s*AI:\\s*";
24
+ const GREP_INCLUDE_GLOBS = [
25
+ "*.ts",
26
+ "*.tsx",
27
+ "*.js",
28
+ "*.jsx",
29
+ "*.py",
30
+ "*.rb",
31
+ "*.go",
32
+ "*.rs",
33
+ "*.java",
34
+ "*.kt",
35
+ "*.swift",
36
+ "*.c",
37
+ "*.cpp",
38
+ "*.h",
39
+ "*.cs",
40
+ "*.php",
41
+ "*.lua",
42
+ "*.sql",
43
+ "*.hs",
44
+ "*.erl",
45
+ "*.ex",
46
+ "*.exs",
47
+ "*.ml",
48
+ "*.vb",
49
+ "*.m",
50
+ "*.html",
51
+ "*.vue",
52
+ "*.svelte",
53
+ "*.css",
54
+ "*.scss",
55
+ "*.yaml",
56
+ "*.yml",
57
+ "*.toml",
58
+ "*.sh",
59
+ ];
60
+ export function createGetAICommentsTool(workspace, extensionClient) {
61
+ return {
62
+ schema: {
63
+ name: "getAIComments",
64
+ description: "Get pending AI comment directives (// AI: ..., # AI: ..., /* AI: */, <!-- AI: -->, -- AI:, %% AI:, ' AI:) found in workspace source files. These are inline instructions from developers for Claude to act on. Supports severity prefixes: AI:FIX, AI:TODO, AI:QUESTION, AI:WARN.",
65
+ annotations: { readOnlyHint: true },
66
+ inputSchema: {
67
+ type: "object",
68
+ properties: {
69
+ file: {
70
+ type: "string",
71
+ description: "Optional file path to filter comments for a specific file",
72
+ },
73
+ },
74
+ additionalProperties: false,
75
+ },
76
+ },
77
+ handler: async (args, signal) => {
78
+ const rawFile = optionalString(args, "file");
79
+ // If extension is connected, use it
80
+ if (extensionClient.isConnected()) {
81
+ const allComments = [];
82
+ for (const [, comments] of extensionClient.latestAIComments) {
83
+ for (const c of comments) {
84
+ const { severity, text } = parseSeverityFromComment(c.comment);
85
+ allComments.push({
86
+ ...c,
87
+ comment: text,
88
+ severity: c.severity ?? severity,
89
+ });
90
+ }
91
+ }
92
+ // If no cached comments, try on-demand request
93
+ if (allComments.length === 0) {
94
+ try {
95
+ const result = await extensionClient.getAIComments();
96
+ if (Array.isArray(result)) {
97
+ for (const c of result) {
98
+ const { severity, text } = parseSeverityFromComment(c.comment);
99
+ allComments.push({
100
+ file: c.file,
101
+ line: c.line,
102
+ comment: text,
103
+ syntax: c.syntax,
104
+ fullLine: c.fullLine,
105
+ severity: c.severity ?? severity,
106
+ });
107
+ }
108
+ }
109
+ }
110
+ catch {
111
+ // Extension may not support on-demand scan yet
112
+ }
113
+ }
114
+ let filtered = allComments;
115
+ if (rawFile) {
116
+ const resolved = resolveFilePath(rawFile, workspace);
117
+ filtered = allComments.filter((c) => c.file === resolved);
118
+ }
119
+ return success({
120
+ available: true,
121
+ source: "extension",
122
+ comments: filtered,
123
+ count: filtered.length,
124
+ });
125
+ }
126
+ // Grep fallback when extension is not connected
127
+ const grepArgs = ["-rn", "-E", "-m", "500", GREP_PATTERN];
128
+ for (const glob of GREP_INCLUDE_GLOBS) {
129
+ grepArgs.push("--include", glob);
130
+ }
131
+ if (rawFile) {
132
+ grepArgs.push(resolveFilePath(rawFile, workspace));
133
+ }
134
+ else {
135
+ grepArgs.push(workspace);
136
+ }
137
+ const result = await execSafe("grep", grepArgs, {
138
+ cwd: workspace,
139
+ signal,
140
+ timeout: 10000,
141
+ });
142
+ const comments = [];
143
+ if (result.stdout) {
144
+ for (const line of result.stdout.split("\n")) {
145
+ if (!line.trim())
146
+ continue;
147
+ // Parse grep output: file:line:content
148
+ const match = line.match(/^(.+?):(\d+):(.+)$/);
149
+ if (!match)
150
+ continue;
151
+ const file = match[1];
152
+ const lineNum = Number.parseInt(match[2], 10);
153
+ const fullLine = match[3].trim();
154
+ // Extract AI comment text
155
+ const commentMatch = fullLine.match(/(?:\/\/|#|\/\*|<!--|--|%%|')\s*AI:\s*(.+)/i);
156
+ if (!commentMatch)
157
+ continue;
158
+ const rawComment = commentMatch[1]
159
+ .replace(/\s*\*\/\s*$/, "")
160
+ .replace(/\s*-->\s*$/, "")
161
+ .trim();
162
+ // Detect syntax
163
+ let syntax = "//";
164
+ if (fullLine.includes("/* AI:"))
165
+ syntax = "/*";
166
+ else if (fullLine.includes("<!-- AI:"))
167
+ syntax = "<!--";
168
+ else if (fullLine.includes("# AI:"))
169
+ syntax = "#";
170
+ else if (fullLine.includes("-- AI:"))
171
+ syntax = "--";
172
+ else if (fullLine.includes("%% AI:"))
173
+ syntax = "%%";
174
+ else if (fullLine.includes("' AI:"))
175
+ syntax = "'";
176
+ const { severity, text } = parseSeverityFromComment(rawComment);
177
+ comments.push({
178
+ file: path.isAbsolute(file) ? file : path.resolve(workspace, file),
179
+ line: lineNum,
180
+ comment: text,
181
+ syntax,
182
+ fullLine,
183
+ severity,
184
+ });
185
+ }
186
+ }
187
+ return success({
188
+ available: true,
189
+ source: "grep-fallback",
190
+ comments,
191
+ count: comments.length,
192
+ });
193
+ },
194
+ };
195
+ }
196
+ //# sourceMappingURL=aiComments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aiComments.js","sourceRoot":"","sources":["../../src/tools/aiComments.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAEhF,MAAM,iBAAiB,GAA2B;IAChD,GAAG,EAAE,KAAK;IACV,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,UAAU;IACpB,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;CACb,CAAC;AAEF,SAAS,wBAAwB,CAAC,OAAe;IAI/C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;IACvE,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC,WAAW,EAAE,CAAC;QACpC,OAAO;YACL,QAAQ,EAAE,iBAAiB,CAAC,GAAG,CAAC,IAAI,MAAM;YAC1C,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE;SAC5C,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC7C,CAAC;AAED,2DAA2D;AAC3D,yDAAyD;AACzD,MAAM,YAAY,GAAG,yCAAyC,CAAC;AAE/D,MAAM,kBAAkB,GAAG;IACzB,MAAM;IACN,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,QAAQ;IACR,MAAM;IACN,SAAS;IACT,KAAK;IACL,OAAO;IACP,KAAK;IACL,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,KAAK;IACL,QAAQ;IACR,OAAO;IACP,UAAU;IACV,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,MAAM;CACP,CAAC;AAEF,MAAM,UAAU,uBAAuB,CACrC,SAAiB,EACjB,eAAgC;IAEhC,OAAO;QACL,MAAM,EAAE;YACN,IAAI,EAAE,eAAe;YACrB,WAAW,EACT,mRAAmR;YACrR,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;YACnC,WAAW,EAAE;gBACX,IAAI,EAAE,QAAiB;gBACvB,UAAU,EAAE;oBACV,IAAI,EAAE;wBACJ,IAAI,EAAE,QAAQ;wBACd,WAAW,EACT,2DAA2D;qBAC9D;iBACF;gBACD,oBAAoB,EAAE,KAAc;aACrC;SACF;QACD,OAAO,EAAE,KAAK,EAAE,IAA6B,EAAE,MAAoB,EAAE,EAAE;YACrE,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAE7C,oCAAoC;YACpC,IAAI,eAAe,CAAC,WAAW,EAAE,EAAE,CAAC;gBAClC,MAAM,WAAW,GAOZ,EAAE,CAAC;gBAER,KAAK,MAAM,CAAC,EAAE,QAAQ,CAAC,IAAI,eAAe,CAAC,gBAAgB,EAAE,CAAC;oBAC5D,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;wBACzB,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,wBAAwB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;wBAC/D,WAAW,CAAC,IAAI,CAAC;4BACf,GAAG,CAAC;4BACJ,OAAO,EAAE,IAAI;4BACb,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,QAAQ;yBACjC,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;gBAED,+CAA+C;gBAC/C,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC7B,IAAI,CAAC;wBACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,aAAa,EAAE,CAAC;wBACrD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;4BAC1B,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;gCACvB,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,wBAAwB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;gCAC/D,WAAW,CAAC,IAAI,CAAC;oCACf,IAAI,EAAE,CAAC,CAAC,IAAI;oCACZ,IAAI,EAAE,CAAC,CAAC,IAAI;oCACZ,OAAO,EAAE,IAAI;oCACb,MAAM,EAAE,CAAC,CAAC,MAAM;oCAChB,QAAQ,EAAE,CAAC,CAAC,QAAQ;oCACpB,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,QAAQ;iCACjC,CAAC,CAAC;4BACL,CAAC;wBACH,CAAC;oBACH,CAAC;oBAAC,MAAM,CAAC;wBACP,+CAA+C;oBACjD,CAAC;gBACH,CAAC;gBAED,IAAI,QAAQ,GAAG,WAAW,CAAC;gBAC3B,IAAI,OAAO,EAAE,CAAC;oBACZ,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;oBACrD,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;gBAC5D,CAAC;gBAED,OAAO,OAAO,CAAC;oBACb,SAAS,EAAE,IAAI;oBACf,MAAM,EAAE,WAAW;oBACnB,QAAQ,EAAE,QAAQ;oBAClB,KAAK,EAAE,QAAQ,CAAC,MAAM;iBACvB,CAAC,CAAC;YACL,CAAC;YAED,gDAAgD;YAChD,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;YAC1D,KAAK,MAAM,IAAI,IAAI,kBAAkB,EAAE,CAAC;gBACtC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;YACnC,CAAC;YAED,IAAI,OAAO,EAAE,CAAC;gBACZ,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;YACrD,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC3B,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE;gBAC9C,GAAG,EAAE,SAAS;gBACd,MAAM;gBACN,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;YAEH,MAAM,QAAQ,GAOT,EAAE,CAAC;YAER,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC7C,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;wBAAE,SAAS;oBAC3B,uCAAuC;oBACvC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;oBAC/C,IAAI,CAAC,KAAK;wBAAE,SAAS;oBAErB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;oBACvB,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;oBAC/C,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;oBAElC,0BAA0B;oBAC1B,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CACjC,4CAA4C,CAC7C,CAAC;oBACF,IAAI,CAAC,YAAY;wBAAE,SAAS;oBAE5B,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,CAAE;yBAChC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;yBAC1B,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC;yBACzB,IAAI,EAAE,CAAC;oBAEV,gBAAgB;oBAChB,IAAI,MAAM,GAAG,IAAI,CAAC;oBAClB,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;wBAAE,MAAM,GAAG,IAAI,CAAC;yBAC1C,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;wBAAE,MAAM,GAAG,MAAM,CAAC;yBACnD,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;wBAAE,MAAM,GAAG,GAAG,CAAC;yBAC7C,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;wBAAE,MAAM,GAAG,IAAI,CAAC;yBAC/C,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;wBAAE,MAAM,GAAG,IAAI,CAAC;yBAC/C,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;wBAAE,MAAM,GAAG,GAAG,CAAC;oBAElD,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,wBAAwB,CAAC,UAAU,CAAC,CAAC;oBAEhE,QAAQ,CAAC,IAAI,CAAC;wBACZ,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC;wBAClE,IAAI,EAAE,OAAO;wBACb,OAAO,EAAE,IAAI;wBACb,MAAM;wBACN,QAAQ;wBACR,QAAQ;qBACT,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAED,OAAO,OAAO,CAAC;gBACb,SAAS,EAAE,IAAI;gBACf,MAAM,EAAE,eAAe;gBACvB,QAAQ;gBACR,KAAK,EAAE,QAAQ,CAAC,MAAM;aACvB,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { ExtensionClient } from "../extensionClient.js";
2
+ export declare function createBridgeStatusTool(extensionClient: ExtensionClient, sessions?: Map<string, unknown>): {
3
+ schema: {
4
+ name: string;
5
+ description: string;
6
+ annotations: {
7
+ readOnlyHint: boolean;
8
+ };
9
+ inputSchema: {
10
+ type: "object";
11
+ properties: {};
12
+ additionalProperties: false;
13
+ };
14
+ };
15
+ handler: () => Promise<{
16
+ content: Array<{
17
+ type: string;
18
+ text: string;
19
+ }>;
20
+ }>;
21
+ };