@opentabs-dev/mcp-server 0.0.19

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 (309) hide show
  1. package/dist/audit-disk.d.ts +23 -0
  2. package/dist/audit-disk.d.ts.map +1 -0
  3. package/dist/audit-disk.js +74 -0
  4. package/dist/audit-disk.js.map +1 -0
  5. package/dist/browser-tools/analyze-site/detect-apis.d.ts +36 -0
  6. package/dist/browser-tools/analyze-site/detect-apis.d.ts.map +1 -0
  7. package/dist/browser-tools/analyze-site/detect-apis.js +383 -0
  8. package/dist/browser-tools/analyze-site/detect-apis.js.map +1 -0
  9. package/dist/browser-tools/analyze-site/detect-auth.d.ts +72 -0
  10. package/dist/browser-tools/analyze-site/detect-auth.d.ts.map +1 -0
  11. package/dist/browser-tools/analyze-site/detect-auth.js +384 -0
  12. package/dist/browser-tools/analyze-site/detect-auth.js.map +1 -0
  13. package/dist/browser-tools/analyze-site/detect-dom.d.ts +65 -0
  14. package/dist/browser-tools/analyze-site/detect-dom.d.ts.map +1 -0
  15. package/dist/browser-tools/analyze-site/detect-dom.js +45 -0
  16. package/dist/browser-tools/analyze-site/detect-dom.js.map +1 -0
  17. package/dist/browser-tools/analyze-site/detect-framework.d.ts +48 -0
  18. package/dist/browser-tools/analyze-site/detect-framework.d.ts.map +1 -0
  19. package/dist/browser-tools/analyze-site/detect-framework.js +31 -0
  20. package/dist/browser-tools/analyze-site/detect-framework.js.map +1 -0
  21. package/dist/browser-tools/analyze-site/detect-globals.d.ts +41 -0
  22. package/dist/browser-tools/analyze-site/detect-globals.d.ts.map +1 -0
  23. package/dist/browser-tools/analyze-site/detect-globals.js +42 -0
  24. package/dist/browser-tools/analyze-site/detect-globals.js.map +1 -0
  25. package/dist/browser-tools/analyze-site/detect-storage.d.ts +39 -0
  26. package/dist/browser-tools/analyze-site/detect-storage.d.ts.map +1 -0
  27. package/dist/browser-tools/analyze-site/detect-storage.js +34 -0
  28. package/dist/browser-tools/analyze-site/detect-storage.js.map +1 -0
  29. package/dist/browser-tools/analyze-site/index.d.ts +52 -0
  30. package/dist/browser-tools/analyze-site/index.d.ts.map +1 -0
  31. package/dist/browser-tools/analyze-site/index.js +827 -0
  32. package/dist/browser-tools/analyze-site/index.js.map +1 -0
  33. package/dist/browser-tools/analyze-site.d.ts +17 -0
  34. package/dist/browser-tools/analyze-site.d.ts.map +1 -0
  35. package/dist/browser-tools/analyze-site.js +41 -0
  36. package/dist/browser-tools/analyze-site.js.map +1 -0
  37. package/dist/browser-tools/clear-console-logs.d.ts +9 -0
  38. package/dist/browser-tools/clear-console-logs.d.ts.map +1 -0
  39. package/dist/browser-tools/clear-console-logs.js +16 -0
  40. package/dist/browser-tools/clear-console-logs.js.map +1 -0
  41. package/dist/browser-tools/click-element.d.ts +10 -0
  42. package/dist/browser-tools/click-element.d.ts.map +1 -0
  43. package/dist/browser-tools/click-element.js +22 -0
  44. package/dist/browser-tools/click-element.js.map +1 -0
  45. package/dist/browser-tools/close-tab.d.ts +9 -0
  46. package/dist/browser-tools/close-tab.d.ts.map +1 -0
  47. package/dist/browser-tools/close-tab.js +16 -0
  48. package/dist/browser-tools/close-tab.js.map +1 -0
  49. package/dist/browser-tools/definition.d.ts +26 -0
  50. package/dist/browser-tools/definition.d.ts.map +1 -0
  51. package/dist/browser-tools/definition.js +16 -0
  52. package/dist/browser-tools/definition.js.map +1 -0
  53. package/dist/browser-tools/delete-cookies.d.ts +10 -0
  54. package/dist/browser-tools/delete-cookies.d.ts.map +1 -0
  55. package/dist/browser-tools/delete-cookies.js +19 -0
  56. package/dist/browser-tools/delete-cookies.js.map +1 -0
  57. package/dist/browser-tools/disable-network-capture.d.ts +9 -0
  58. package/dist/browser-tools/disable-network-capture.d.ts.map +1 -0
  59. package/dist/browser-tools/disable-network-capture.js +16 -0
  60. package/dist/browser-tools/disable-network-capture.js.map +1 -0
  61. package/dist/browser-tools/enable-network-capture.d.ts +12 -0
  62. package/dist/browser-tools/enable-network-capture.d.ts.map +1 -0
  63. package/dist/browser-tools/enable-network-capture.js +42 -0
  64. package/dist/browser-tools/enable-network-capture.js.map +1 -0
  65. package/dist/browser-tools/execute-script.d.ts +19 -0
  66. package/dist/browser-tools/execute-script.d.ts.map +1 -0
  67. package/dist/browser-tools/execute-script.js +51 -0
  68. package/dist/browser-tools/execute-script.js.map +1 -0
  69. package/dist/browser-tools/extension-check-adapter.d.ts +11 -0
  70. package/dist/browser-tools/extension-check-adapter.d.ts.map +1 -0
  71. package/dist/browser-tools/extension-check-adapter.js +22 -0
  72. package/dist/browser-tools/extension-check-adapter.js.map +1 -0
  73. package/dist/browser-tools/extension-force-reconnect.d.ts +9 -0
  74. package/dist/browser-tools/extension-force-reconnect.d.ts.map +1 -0
  75. package/dist/browser-tools/extension-force-reconnect.js +19 -0
  76. package/dist/browser-tools/extension-force-reconnect.js.map +1 -0
  77. package/dist/browser-tools/extension-get-logs.d.ts +24 -0
  78. package/dist/browser-tools/extension-get-logs.d.ts.map +1 -0
  79. package/dist/browser-tools/extension-get-logs.js +34 -0
  80. package/dist/browser-tools/extension-get-logs.js.map +1 -0
  81. package/dist/browser-tools/extension-get-side-panel.d.ts +8 -0
  82. package/dist/browser-tools/extension-get-side-panel.d.ts.map +1 -0
  83. package/dist/browser-tools/extension-get-side-panel.js +17 -0
  84. package/dist/browser-tools/extension-get-side-panel.js.map +1 -0
  85. package/dist/browser-tools/extension-get-state.d.ts +9 -0
  86. package/dist/browser-tools/extension-get-state.d.ts.map +1 -0
  87. package/dist/browser-tools/extension-get-state.js +19 -0
  88. package/dist/browser-tools/extension-get-state.js.map +1 -0
  89. package/dist/browser-tools/focus-tab.d.ts +9 -0
  90. package/dist/browser-tools/focus-tab.d.ts.map +1 -0
  91. package/dist/browser-tools/focus-tab.js +17 -0
  92. package/dist/browser-tools/focus-tab.js.map +1 -0
  93. package/dist/browser-tools/get-console-logs.d.ts +18 -0
  94. package/dist/browser-tools/get-console-logs.d.ts.map +1 -0
  95. package/dist/browser-tools/get-console-logs.js +30 -0
  96. package/dist/browser-tools/get-console-logs.js.map +1 -0
  97. package/dist/browser-tools/get-cookies.d.ts +10 -0
  98. package/dist/browser-tools/get-cookies.d.ts.map +1 -0
  99. package/dist/browser-tools/get-cookies.js +23 -0
  100. package/dist/browser-tools/get-cookies.js.map +1 -0
  101. package/dist/browser-tools/get-network-requests.d.ts +10 -0
  102. package/dist/browser-tools/get-network-requests.d.ts.map +1 -0
  103. package/dist/browser-tools/get-network-requests.js +27 -0
  104. package/dist/browser-tools/get-network-requests.js.map +1 -0
  105. package/dist/browser-tools/get-page-html.d.ts +11 -0
  106. package/dist/browser-tools/get-page-html.d.ts.map +1 -0
  107. package/dist/browser-tools/get-page-html.js +32 -0
  108. package/dist/browser-tools/get-page-html.js.map +1 -0
  109. package/dist/browser-tools/get-resource-content.d.ts +11 -0
  110. package/dist/browser-tools/get-resource-content.d.ts.map +1 -0
  111. package/dist/browser-tools/get-resource-content.js +31 -0
  112. package/dist/browser-tools/get-resource-content.js.map +1 -0
  113. package/dist/browser-tools/get-storage.d.ts +14 -0
  114. package/dist/browser-tools/get-storage.d.ts.map +1 -0
  115. package/dist/browser-tools/get-storage.js +28 -0
  116. package/dist/browser-tools/get-storage.js.map +1 -0
  117. package/dist/browser-tools/get-tab-content.d.ts +11 -0
  118. package/dist/browser-tools/get-tab-content.d.ts.map +1 -0
  119. package/dist/browser-tools/get-tab-content.js +29 -0
  120. package/dist/browser-tools/get-tab-content.js.map +1 -0
  121. package/dist/browser-tools/get-tab-info.d.ts +9 -0
  122. package/dist/browser-tools/get-tab-info.d.ts.map +1 -0
  123. package/dist/browser-tools/get-tab-info.js +17 -0
  124. package/dist/browser-tools/get-tab-info.js.map +1 -0
  125. package/dist/browser-tools/handle-dialog.d.ts +14 -0
  126. package/dist/browser-tools/handle-dialog.d.ts.map +1 -0
  127. package/dist/browser-tools/handle-dialog.js +30 -0
  128. package/dist/browser-tools/handle-dialog.js.map +1 -0
  129. package/dist/browser-tools/hover-element.d.ts +11 -0
  130. package/dist/browser-tools/hover-element.d.ts.map +1 -0
  131. package/dist/browser-tools/hover-element.js +24 -0
  132. package/dist/browser-tools/hover-element.js.map +1 -0
  133. package/dist/browser-tools/index.d.ts +7 -0
  134. package/dist/browser-tools/index.d.ts.map +1 -0
  135. package/dist/browser-tools/index.js +81 -0
  136. package/dist/browser-tools/index.js.map +1 -0
  137. package/dist/browser-tools/list-resources.d.ts +10 -0
  138. package/dist/browser-tools/list-resources.d.ts.map +1 -0
  139. package/dist/browser-tools/list-resources.js +29 -0
  140. package/dist/browser-tools/list-resources.js.map +1 -0
  141. package/dist/browser-tools/list-tabs.d.ts +7 -0
  142. package/dist/browser-tools/list-tabs.d.ts.map +1 -0
  143. package/dist/browser-tools/list-tabs.js +16 -0
  144. package/dist/browser-tools/list-tabs.js.map +1 -0
  145. package/dist/browser-tools/navigate-tab.d.ts +10 -0
  146. package/dist/browser-tools/navigate-tab.d.ts.map +1 -0
  147. package/dist/browser-tools/navigate-tab.js +18 -0
  148. package/dist/browser-tools/navigate-tab.js.map +1 -0
  149. package/dist/browser-tools/open-tab.d.ts +9 -0
  150. package/dist/browser-tools/open-tab.d.ts.map +1 -0
  151. package/dist/browser-tools/open-tab.js +18 -0
  152. package/dist/browser-tools/open-tab.js.map +1 -0
  153. package/dist/browser-tools/press-key.d.ts +17 -0
  154. package/dist/browser-tools/press-key.d.ts.map +1 -0
  155. package/dist/browser-tools/press-key.js +43 -0
  156. package/dist/browser-tools/press-key.js.map +1 -0
  157. package/dist/browser-tools/query-elements.d.ts +12 -0
  158. package/dist/browser-tools/query-elements.d.ts.map +1 -0
  159. package/dist/browser-tools/query-elements.js +30 -0
  160. package/dist/browser-tools/query-elements.js.map +1 -0
  161. package/dist/browser-tools/reload-extension.d.ts +13 -0
  162. package/dist/browser-tools/reload-extension.d.ts.map +1 -0
  163. package/dist/browser-tools/reload-extension.js +35 -0
  164. package/dist/browser-tools/reload-extension.js.map +1 -0
  165. package/dist/browser-tools/screenshot-tab.d.ts +9 -0
  166. package/dist/browser-tools/screenshot-tab.d.ts.map +1 -0
  167. package/dist/browser-tools/screenshot-tab.js +22 -0
  168. package/dist/browser-tools/screenshot-tab.js.map +1 -0
  169. package/dist/browser-tools/scroll.d.ts +23 -0
  170. package/dist/browser-tools/scroll.d.ts.map +1 -0
  171. package/dist/browser-tools/scroll.js +56 -0
  172. package/dist/browser-tools/scroll.js.map +1 -0
  173. package/dist/browser-tools/select-option.d.ts +12 -0
  174. package/dist/browser-tools/select-option.d.ts.map +1 -0
  175. package/dist/browser-tools/select-option.js +25 -0
  176. package/dist/browser-tools/select-option.js.map +1 -0
  177. package/dist/browser-tools/set-cookie.d.ts +16 -0
  178. package/dist/browser-tools/set-cookie.d.ts.map +1 -0
  179. package/dist/browser-tools/set-cookie.js +42 -0
  180. package/dist/browser-tools/set-cookie.js.map +1 -0
  181. package/dist/browser-tools/type-text.d.ts +12 -0
  182. package/dist/browser-tools/type-text.d.ts.map +1 -0
  183. package/dist/browser-tools/type-text.js +25 -0
  184. package/dist/browser-tools/type-text.js.map +1 -0
  185. package/dist/browser-tools/url-validation.d.ts +13 -0
  186. package/dist/browser-tools/url-validation.d.ts.map +1 -0
  187. package/dist/browser-tools/url-validation.js +23 -0
  188. package/dist/browser-tools/url-validation.js.map +1 -0
  189. package/dist/browser-tools/wait-for-element.d.ts +12 -0
  190. package/dist/browser-tools/wait-for-element.d.ts.map +1 -0
  191. package/dist/browser-tools/wait-for-element.js +29 -0
  192. package/dist/browser-tools/wait-for-element.js.map +1 -0
  193. package/dist/config.d.ts +99 -0
  194. package/dist/config.d.ts.map +1 -0
  195. package/dist/config.js +344 -0
  196. package/dist/config.js.map +1 -0
  197. package/dist/dev-mode.d.ts +14 -0
  198. package/dist/dev-mode.d.ts.map +1 -0
  199. package/dist/dev-mode.js +15 -0
  200. package/dist/dev-mode.js.map +1 -0
  201. package/dist/discovery-legacy.d.ts +32 -0
  202. package/dist/discovery-legacy.d.ts.map +1 -0
  203. package/dist/discovery-legacy.js +415 -0
  204. package/dist/discovery-legacy.js.map +1 -0
  205. package/dist/discovery.d.ts +28 -0
  206. package/dist/discovery.d.ts.map +1 -0
  207. package/dist/discovery.js +97 -0
  208. package/dist/discovery.js.map +1 -0
  209. package/dist/extension-install.d.ts +27 -0
  210. package/dist/extension-install.d.ts.map +1 -0
  211. package/dist/extension-install.js +75 -0
  212. package/dist/extension-install.js.map +1 -0
  213. package/dist/extension-protocol.d.ts +130 -0
  214. package/dist/extension-protocol.d.ts.map +1 -0
  215. package/dist/extension-protocol.js +869 -0
  216. package/dist/extension-protocol.js.map +1 -0
  217. package/dist/file-watcher.d.ts +75 -0
  218. package/dist/file-watcher.d.ts.map +1 -0
  219. package/dist/file-watcher.js +616 -0
  220. package/dist/file-watcher.js.map +1 -0
  221. package/dist/http-routes.d.ts +88 -0
  222. package/dist/http-routes.d.ts.map +1 -0
  223. package/dist/http-routes.js +545 -0
  224. package/dist/http-routes.js.map +1 -0
  225. package/dist/index.d.ts +45 -0
  226. package/dist/index.d.ts.map +1 -0
  227. package/dist/index.js +187 -0
  228. package/dist/index.js.map +1 -0
  229. package/dist/loader.d.ts +100 -0
  230. package/dist/loader.d.ts.map +1 -0
  231. package/dist/loader.js +402 -0
  232. package/dist/loader.js.map +1 -0
  233. package/dist/log-buffer.d.ts +33 -0
  234. package/dist/log-buffer.d.ts.map +1 -0
  235. package/dist/log-buffer.js +64 -0
  236. package/dist/log-buffer.js.map +1 -0
  237. package/dist/logger.d.ts +34 -0
  238. package/dist/logger.d.ts.map +1 -0
  239. package/dist/logger.js +81 -0
  240. package/dist/logger.js.map +1 -0
  241. package/dist/manifest-schema.d.ts +14 -0
  242. package/dist/manifest-schema.d.ts.map +1 -0
  243. package/dist/manifest-schema.js +51 -0
  244. package/dist/manifest-schema.js.map +1 -0
  245. package/dist/mcp-setup.d.ts +131 -0
  246. package/dist/mcp-setup.d.ts.map +1 -0
  247. package/dist/mcp-setup.js +673 -0
  248. package/dist/mcp-setup.js.map +1 -0
  249. package/dist/permissions.d.ts +59 -0
  250. package/dist/permissions.d.ts.map +1 -0
  251. package/dist/permissions.js +141 -0
  252. package/dist/permissions.js.map +1 -0
  253. package/dist/registry.d.ts +78 -0
  254. package/dist/registry.d.ts.map +1 -0
  255. package/dist/registry.js +187 -0
  256. package/dist/registry.js.map +1 -0
  257. package/dist/reload.d.ts +52 -0
  258. package/dist/reload.d.ts.map +1 -0
  259. package/dist/reload.js +326 -0
  260. package/dist/reload.js.map +1 -0
  261. package/dist/resolver.d.ts +53 -0
  262. package/dist/resolver.d.ts.map +1 -0
  263. package/dist/resolver.js +272 -0
  264. package/dist/resolver.js.map +1 -0
  265. package/dist/sanitize-error.d.ts +8 -0
  266. package/dist/sanitize-error.d.ts.map +1 -0
  267. package/dist/sanitize-error.js +25 -0
  268. package/dist/sanitize-error.js.map +1 -0
  269. package/dist/sanitize-tool-output.d.ts +20 -0
  270. package/dist/sanitize-tool-output.d.ts.map +1 -0
  271. package/dist/sanitize-tool-output.js +52 -0
  272. package/dist/sanitize-tool-output.js.map +1 -0
  273. package/dist/sdk-version.d.ts +11 -0
  274. package/dist/sdk-version.d.ts.map +1 -0
  275. package/dist/sdk-version.js +23 -0
  276. package/dist/sdk-version.js.map +1 -0
  277. package/dist/shutdown.d.ts +28 -0
  278. package/dist/shutdown.d.ts.map +1 -0
  279. package/dist/shutdown.js +68 -0
  280. package/dist/shutdown.js.map +1 -0
  281. package/dist/skip-confirmation.d.ts +15 -0
  282. package/dist/skip-confirmation.d.ts.map +1 -0
  283. package/dist/skip-confirmation.js +16 -0
  284. package/dist/skip-confirmation.js.map +1 -0
  285. package/dist/skip-sanitization.d.ts +17 -0
  286. package/dist/skip-sanitization.d.ts.map +1 -0
  287. package/dist/skip-sanitization.js +18 -0
  288. package/dist/skip-sanitization.js.map +1 -0
  289. package/dist/skip-verification.d.ts +11 -0
  290. package/dist/skip-verification.d.ts.map +1 -0
  291. package/dist/skip-verification.js +12 -0
  292. package/dist/skip-verification.js.map +1 -0
  293. package/dist/state.d.ts +290 -0
  294. package/dist/state.d.ts.map +1 -0
  295. package/dist/state.js +111 -0
  296. package/dist/state.js.map +1 -0
  297. package/dist/verify-plugin.d.ts +53 -0
  298. package/dist/verify-plugin.d.ts.map +1 -0
  299. package/dist/verify-plugin.js +123 -0
  300. package/dist/verify-plugin.js.map +1 -0
  301. package/dist/version-check.d.ts +35 -0
  302. package/dist/version-check.d.ts.map +1 -0
  303. package/dist/version-check.js +111 -0
  304. package/dist/version-check.js.map +1 -0
  305. package/dist/version.d.ts +10 -0
  306. package/dist/version.d.ts.map +1 -0
  307. package/dist/version.js +22 -0
  308. package/dist/version.js.map +1 -0
  309. package/package.json +28 -0
@@ -0,0 +1,616 @@
1
+ /**
2
+ * File watcher for local plugins.
3
+ *
4
+ * Watches local plugin directories (from config.json plugins array) for changes
5
+ * to dist/tools.json and dist/adapter.iife.js. On change:
6
+ * - IIFE change → re-read, send plugin.update to extension
7
+ * - tools.json change → re-read tools AND IIFE, re-register MCP tools, notify MCP clients.
8
+ * Both files are re-read on tools.json change because `bun run build` typically produces
9
+ * both new tools and a new IIFE simultaneously. Re-reading the IIFE here avoids
10
+ * a brief race where the extension has new tool definitions pointing at old adapter code.
11
+ *
12
+ * Only watches local plugins — not npm-installed packages.
13
+ * File change events are debounced at ~200ms.
14
+ *
15
+ * Hot reload safety:
16
+ * Watcher handles and debounce timers are stored on ServerState (not module-level
17
+ * variables) so that stopFileWatching() — called from the NEW module after
18
+ * bun --hot re-evaluates — can always reach and close the PREVIOUS iteration's
19
+ * FSWatcher instances. Module-level variables reset to empty on each reload,
20
+ * which would orphan the old handles.
21
+ */
22
+ import { getConfigDir } from './config.js';
23
+ import { loadPlugin } from './loader.js';
24
+ import { log } from './logger.js';
25
+ import { buildRegistry } from './registry.js';
26
+ import { isOk } from '@opentabs-dev/shared';
27
+ import { statSync, watch } from 'node:fs';
28
+ import { join } from 'node:path';
29
+ /** Polling interval for mtime-based fallback detection (ms) */
30
+ const MTIME_POLL_INTERVAL_MS = 30_000;
31
+ /** Number of polling detections within the window that triggers a stale-watcher warning */
32
+ const STALE_WATCHER_THRESHOLD = 3;
33
+ /** Time window (ms) for counting polling detections toward a stale-watcher warning */
34
+ const STALE_WATCHER_WINDOW_MS = 5 * 60 * 1000;
35
+ /** Maximum number of detection timestamps to keep (prevents unbounded growth) */
36
+ const MAX_DETECTION_TIMESTAMPS = 20;
37
+ /**
38
+ * Read a file with retries and exponential backoff.
39
+ * Handles the case where the file is briefly unavailable during a write.
40
+ */
41
+ const readFileWithRetry = async (path, maxRetries = 3, initialDelayMs = 100) => {
42
+ let delay = initialDelayMs;
43
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
44
+ try {
45
+ return await Bun.file(path).text();
46
+ }
47
+ catch (err) {
48
+ if (attempt === maxRetries)
49
+ throw err;
50
+ await new Promise(r => setTimeout(r, delay));
51
+ delay *= 2;
52
+ }
53
+ }
54
+ throw new Error('readFileWithRetry: unreachable');
55
+ };
56
+ /**
57
+ * Check if a file exists.
58
+ */
59
+ const fileExists = async (path) => Bun.file(path).exists();
60
+ /**
61
+ * Get the mtimeMs for a file, or null if the file does not exist or stat fails.
62
+ */
63
+ const getFileMtimeMs = (path) => {
64
+ try {
65
+ const stat = statSync(path, { throwIfNoEntry: false });
66
+ return stat ? stat.mtimeMs : null;
67
+ }
68
+ catch {
69
+ return null;
70
+ }
71
+ };
72
+ /**
73
+ * Find the FileWatcherEntry for a given plugin directory.
74
+ */
75
+ const findEntry = (state, pluginDir) => state.fileWatcherEntries.find(e => e.pluginDir === pluginDir);
76
+ /**
77
+ * Record the current mtime for a file on a FileWatcherEntry's lastSeenMtimes map.
78
+ */
79
+ const recordMtime = (entry, filePath) => {
80
+ const mtime = getFileMtimeMs(filePath);
81
+ if (mtime !== null) {
82
+ entry.lastSeenMtimes.set(filePath, mtime);
83
+ }
84
+ };
85
+ /**
86
+ * Record a mtime poll detection and emit a warning if detections exceed the
87
+ * threshold within the rolling window. Keeps the timestamps array bounded.
88
+ */
89
+ const recordPollDetection = (state) => {
90
+ const now = Date.now();
91
+ state.mtimePollDetections++;
92
+ state.mtimePollDetectionTimestamps.push(now);
93
+ // Trim to bounded size
94
+ if (state.mtimePollDetectionTimestamps.length > MAX_DETECTION_TIMESTAMPS) {
95
+ state.mtimePollDetectionTimestamps = state.mtimePollDetectionTimestamps.slice(-MAX_DETECTION_TIMESTAMPS);
96
+ }
97
+ // Count detections within the window
98
+ const windowStart = now - STALE_WATCHER_WINDOW_MS;
99
+ const recentDetections = state.mtimePollDetectionTimestamps.filter(ts => ts >= windowStart);
100
+ // Emit warning exactly when crossing the threshold (not on every subsequent detection)
101
+ if (recentDetections.length === STALE_WATCHER_THRESHOLD) {
102
+ log.warn(`File watchers may be stale — detected ${STALE_WATCHER_THRESHOLD} changes via polling that fs.watch missed. Consider restarting the MCP server.`);
103
+ }
104
+ };
105
+ /**
106
+ * Extract the adapter hash embedded by the CLI's hash-setter snippet.
107
+ *
108
+ * The `opentabs-plugin build` CLI appends a self-contained hash-setter IIFE to every
109
+ * adapter bundle: `a.__adapterHash="<sha256-of-core-content>";`. The embedded
110
+ * hash is computed from the core IIFE content BEFORE the hash-setter is
111
+ * appended, so it matches what the injected adapter reports at runtime.
112
+ *
113
+ * Computing SHA-256 of the full file (including the hash-setter) produces a
114
+ * different value and causes spurious hash-mismatch errors in the extension.
115
+ * Reading the embedded hash directly is always correct.
116
+ *
117
+ * Returns undefined for old adapters built without the hash-setter.
118
+ */
119
+ const extractEmbeddedAdapterHash = (iife) => {
120
+ const match = iife.match(/\.__adapterHash="([0-9a-f]{64})"/);
121
+ return match?.[1];
122
+ };
123
+ /**
124
+ * Handle an IIFE file change for a local plugin.
125
+ */
126
+ const handleIifeChange = async (state, pluginName, pluginDir, callbacks) => {
127
+ const iifePath = join(pluginDir, 'dist', 'adapter.iife.js');
128
+ if (!(await fileExists(iifePath))) {
129
+ log.warn(`File watcher: IIFE not found at ${iifePath} — skipping`);
130
+ return;
131
+ }
132
+ try {
133
+ const iife = await readFileWithRetry(iifePath);
134
+ const plugin = state.registry.plugins.get(pluginName);
135
+ if (!plugin) {
136
+ log.warn(`File watcher: Plugin "${pluginName}" not found in state — skipping IIFE update`);
137
+ return;
138
+ }
139
+ // Update in-memory plugin state
140
+ plugin.iife = iife;
141
+ // Use the hash embedded in the IIFE by the CLI's hash-setter snippet. The
142
+ // embedded hash is SHA-256 of the core content (before the hash-setter was
143
+ // appended), which is what the adapter reports at runtime via __adapterHash.
144
+ // Computing SHA-256 of the full file would include the hash-setter and
145
+ // produce a value that never matches the runtime adapter hash.
146
+ const embeddedHash = extractEmbeddedAdapterHash(iife);
147
+ if (embeddedHash) {
148
+ plugin.adapterHash = embeddedHash;
149
+ }
150
+ // Read source map if available
151
+ const sourceMapPath = join(pluginDir, 'dist', 'adapter.iife.js.map');
152
+ let sourceMap;
153
+ try {
154
+ if (await fileExists(sourceMapPath)) {
155
+ sourceMap = await readFileWithRetry(sourceMapPath);
156
+ plugin.iifeSourceMap = sourceMap;
157
+ }
158
+ }
159
+ catch {
160
+ // Source map read failed — proceed without it
161
+ }
162
+ // Update mtime for polling fallback
163
+ const entry = findEntry(state, pluginDir);
164
+ if (entry)
165
+ recordMtime(entry, iifePath);
166
+ log.info(`File watcher: IIFE updated for "${pluginName}" — sending plugin.update`);
167
+ callbacks.onIifeChanged(pluginName, iife, sourceMap);
168
+ }
169
+ catch (err) {
170
+ log.error(`File watcher: Failed to read IIFE for "${pluginName}":`, err);
171
+ }
172
+ };
173
+ /**
174
+ * Parse a tools.json file contents into validated ManifestTool[].
175
+ * Supports both legacy array format and current { tools: [...] } format.
176
+ * Returns null if parsing fails.
177
+ */
178
+ const parseToolsJson = (raw, filePath) => {
179
+ let parsed;
180
+ try {
181
+ parsed = JSON.parse(raw);
182
+ }
183
+ catch {
184
+ log.error(`File watcher: Invalid JSON in ${filePath}`);
185
+ return null;
186
+ }
187
+ // Extract the tools array from either format
188
+ let toolsArray;
189
+ if (Array.isArray(parsed)) {
190
+ toolsArray = parsed;
191
+ }
192
+ else if (typeof parsed === 'object' && parsed !== null && 'tools' in parsed) {
193
+ const candidate = parsed.tools;
194
+ if (!Array.isArray(candidate)) {
195
+ log.error(`File watcher: ${filePath} .tools is not an array`);
196
+ return null;
197
+ }
198
+ toolsArray = candidate;
199
+ }
200
+ else {
201
+ log.error(`File watcher: ${filePath} is not a valid manifest`);
202
+ return null;
203
+ }
204
+ const tools = [];
205
+ for (const t of toolsArray) {
206
+ if (typeof t !== 'object' || t === null)
207
+ continue;
208
+ const obj = t;
209
+ if (typeof obj.name !== 'string' || typeof obj.description !== 'string')
210
+ continue;
211
+ const displayName = typeof obj.displayName === 'string' ? obj.displayName : obj.name;
212
+ const icon = typeof obj.icon === 'string' ? obj.icon : 'wrench';
213
+ const inputSchema = typeof obj.input_schema === 'object' && obj.input_schema !== null
214
+ ? obj.input_schema
215
+ : { type: 'object', properties: {} };
216
+ const outputSchema = typeof obj.output_schema === 'object' && obj.output_schema !== null
217
+ ? obj.output_schema
218
+ : { type: 'object', properties: {} };
219
+ tools.push({
220
+ name: obj.name,
221
+ displayName,
222
+ description: obj.description,
223
+ icon,
224
+ input_schema: inputSchema,
225
+ output_schema: outputSchema,
226
+ });
227
+ }
228
+ return tools;
229
+ };
230
+ /**
231
+ * Handle a dist/tools.json file change for a local plugin.
232
+ *
233
+ * Also re-reads the IIFE from disk because `bun run build` typically updates
234
+ * both tools.json and IIFE simultaneously. Without this, the tools.json watcher
235
+ * would send a plugin.update with the old IIFE, and the extension would
236
+ * briefly have new tool definitions pointing at stale adapter code until
237
+ * the IIFE watcher fires separately.
238
+ */
239
+ const handleToolsJsonChange = async (state, pluginName, pluginDir, callbacks) => {
240
+ const toolsJsonPath = join(pluginDir, 'dist', 'tools.json');
241
+ if (!(await fileExists(toolsJsonPath))) {
242
+ log.warn(`File watcher: tools.json not found at ${toolsJsonPath} — skipping`);
243
+ return;
244
+ }
245
+ try {
246
+ const raw = await readFileWithRetry(toolsJsonPath);
247
+ const tools = parseToolsJson(raw, toolsJsonPath);
248
+ if (!tools)
249
+ return;
250
+ const plugin = state.registry.plugins.get(pluginName);
251
+ if (!plugin) {
252
+ log.warn(`File watcher: Plugin "${pluginName}" not found in state — skipping tools.json update`);
253
+ return;
254
+ }
255
+ // Update tool definitions
256
+ plugin.tools = tools;
257
+ // Re-read IIFE from disk so the extension has the latest adapter code.
258
+ // Use the hash embedded in the IIFE rather than recomputing from the full
259
+ // file. The full file includes the hash-setter snippet, so SHA-256(full
260
+ // file) differs from SHA-256(core content) = the value the runtime adapter
261
+ // reports. The embedded hash is always authoritative.
262
+ const iifePath = join(pluginDir, 'dist', 'adapter.iife.js');
263
+ if (await fileExists(iifePath)) {
264
+ try {
265
+ const iife = await readFileWithRetry(iifePath);
266
+ plugin.iife = iife;
267
+ const embeddedHash = extractEmbeddedAdapterHash(iife);
268
+ if (embeddedHash) {
269
+ plugin.adapterHash = embeddedHash;
270
+ }
271
+ }
272
+ catch {
273
+ // IIFE read failed — the IIFE watcher will handle it separately
274
+ }
275
+ // Read source map if available
276
+ const sourceMapPath = join(pluginDir, 'dist', 'adapter.iife.js.map');
277
+ try {
278
+ if (await fileExists(sourceMapPath)) {
279
+ plugin.iifeSourceMap = await readFileWithRetry(sourceMapPath);
280
+ }
281
+ }
282
+ catch {
283
+ // Source map read failed — proceed without it
284
+ }
285
+ }
286
+ // Update mtimes for polling fallback (both tools.json and IIFE were re-read)
287
+ const entry = findEntry(state, pluginDir);
288
+ if (entry) {
289
+ recordMtime(entry, toolsJsonPath);
290
+ recordMtime(entry, iifePath);
291
+ }
292
+ log.info(`File watcher: tools.json updated for "${pluginName}" — re-registering MCP tools`);
293
+ callbacks.onManifestChanged(pluginName);
294
+ }
295
+ catch (err) {
296
+ log.error(`File watcher: Failed to read tools.json for "${pluginName}":`, err);
297
+ }
298
+ };
299
+ /**
300
+ * Handle a file change in a pending plugin directory (one that failed initial
301
+ * discovery). Attempts full discovery via loadPlugin; on success, adds
302
+ * the plugin to state and invokes onPluginDiscovered so MCP tools are
303
+ * re-registered and the extension is synced.
304
+ */
305
+ const handlePendingPluginChange = async (state, pluginDir, callbacks) => {
306
+ const result = await loadPlugin(pluginDir, 'local', 'local');
307
+ if (!isOk(result))
308
+ return; // Discovery still failing — keep watching silently
309
+ const plugin = result.value;
310
+ // Plugin loaded successfully — add to registry
311
+ if (state.registry.plugins.has(plugin.name)) {
312
+ log.warn(`File watcher: Pending plugin "${plugin.name}" at ${pluginDir} conflicts with existing plugin — skipping`);
313
+ return;
314
+ }
315
+ // Build a new registry that includes the newly discovered plugin
316
+ const updatedPlugins = [...state.registry.plugins.values(), plugin];
317
+ state.registry = buildRegistry(updatedPlugins, [...state.registry.failures]);
318
+ // Update mtimes for polling fallback
319
+ const entry = findEntry(state, pluginDir);
320
+ if (entry) {
321
+ recordMtime(entry, join(pluginDir, 'dist', 'tools.json'));
322
+ recordMtime(entry, join(pluginDir, 'dist', 'adapter.iife.js'));
323
+ }
324
+ log.info(`File watcher: Discovered pending plugin "${plugin.name}" at ${pluginDir}`);
325
+ callbacks.onPluginDiscovered(plugin.name);
326
+ };
327
+ /**
328
+ * Set up file watching for a pending plugin directory (one that failed initial
329
+ * discovery). Watches for tools.json and IIFE changes in dist/, and attempts
330
+ * full discovery on each change.
331
+ */
332
+ const watchPendingPlugin = (state, pluginDir, callbacks) => {
333
+ const watchers = [];
334
+ const distDir = join(pluginDir, 'dist');
335
+ const gen = state.fileWatcherGeneration;
336
+ // Watch dist directory for tools.json and IIFE creation/changes
337
+ try {
338
+ const distWatcher = watch(distDir, (_eventType, filename) => {
339
+ if (filename !== 'tools.json' && filename !== 'adapter.iife.js')
340
+ return;
341
+ const key = `${pluginDir}:pending`;
342
+ const existing = state.fileWatcherTimers.get(key);
343
+ if (existing)
344
+ clearTimeout(existing);
345
+ state.fileWatcherTimers.set(key, setTimeout(() => {
346
+ state.fileWatcherTimers.delete(key);
347
+ if (state.fileWatcherGeneration !== gen)
348
+ return;
349
+ void handlePendingPluginChange(state, pluginDir, callbacks);
350
+ }, 200));
351
+ });
352
+ watchers.push(distWatcher);
353
+ }
354
+ catch {
355
+ // dist/ may not exist yet — will be watched once plugin is rebuilt
356
+ }
357
+ return { pluginDir, pluginName: `(pending:${pluginDir})`, watchers, lastSeenMtimes: new Map() };
358
+ };
359
+ /**
360
+ * Set up file watching for a single local plugin directory.
361
+ *
362
+ * Watches the dist/ subdirectory for tools.json and adapter.iife.js changes.
363
+ * Uses directory-level watching (not file-level) because on macOS, file-level
364
+ * fs.watch() via kqueue fails to deliver events after a close + recreate cycle
365
+ * (which happens on every hot reload). Directory-level watching uses FSEvents
366
+ * on macOS and reliably delivers events across watcher restarts.
367
+ */
368
+ const watchPlugin = (state, pluginDir, pluginName, callbacks) => {
369
+ const watchers = [];
370
+ const distDir = join(pluginDir, 'dist');
371
+ const gen = state.fileWatcherGeneration;
372
+ // Watch dist directory for tools.json and IIFE changes
373
+ try {
374
+ const distWatcher = watch(distDir, (_eventType, filename) => {
375
+ if (filename === 'tools.json') {
376
+ const key = `${pluginDir}:tools`;
377
+ const existing = state.fileWatcherTimers.get(key);
378
+ if (existing)
379
+ clearTimeout(existing);
380
+ state.fileWatcherTimers.set(key, setTimeout(() => {
381
+ state.fileWatcherTimers.delete(key);
382
+ if (state.fileWatcherGeneration !== gen)
383
+ return;
384
+ void handleToolsJsonChange(state, pluginName, pluginDir, callbacks);
385
+ }, 200));
386
+ }
387
+ else if (filename === 'adapter.iife.js') {
388
+ const key = `${pluginDir}:iife`;
389
+ const existing = state.fileWatcherTimers.get(key);
390
+ if (existing)
391
+ clearTimeout(existing);
392
+ state.fileWatcherTimers.set(key, setTimeout(() => {
393
+ state.fileWatcherTimers.delete(key);
394
+ if (state.fileWatcherGeneration !== gen)
395
+ return;
396
+ void handleIifeChange(state, pluginName, pluginDir, callbacks);
397
+ }, 200));
398
+ }
399
+ });
400
+ watchers.push(distWatcher);
401
+ }
402
+ catch (err) {
403
+ log.warn(`File watcher: Could not watch dist dir at ${distDir}:`, err);
404
+ }
405
+ return { pluginDir, pluginName, watchers, lastSeenMtimes: new Map() };
406
+ };
407
+ /**
408
+ * Start watching the config directory for changes to config.json.
409
+ * Uses directory-level watching (not file-level) because on macOS, file-level
410
+ * fs.watch() via kqueue fails to deliver events after a close + recreate cycle.
411
+ * The debounce pattern matches plugin file watchers — uses fileWatcherTimers
412
+ * with a 'config' key and checks fileWatcherGeneration to discard stale callbacks.
413
+ */
414
+ const startConfigWatching = (state, callbacks) => {
415
+ // Close any existing config watcher
416
+ if (state.configWatcher) {
417
+ state.configWatcher.close();
418
+ state.configWatcher = null;
419
+ }
420
+ const configDir = getConfigDir();
421
+ const gen = state.fileWatcherGeneration;
422
+ // Record initial config.json mtime for mtime polling fallback
423
+ const configPath = join(configDir, 'config.json');
424
+ state.configLastSeenMtime = getFileMtimeMs(configPath);
425
+ try {
426
+ state.configWatcher = watch(configDir, (_eventType, filename) => {
427
+ if (filename !== 'config.json')
428
+ return;
429
+ const key = 'config';
430
+ const existing = state.fileWatcherTimers.get(key);
431
+ if (existing)
432
+ clearTimeout(existing);
433
+ state.fileWatcherTimers.set(key, setTimeout(() => {
434
+ state.fileWatcherTimers.delete(key);
435
+ if (state.fileWatcherGeneration !== gen)
436
+ return;
437
+ log.info('Config watcher: config.json changed — triggering reload');
438
+ // Update config mtime for polling fallback
439
+ state.configLastSeenMtime = getFileMtimeMs(configPath);
440
+ callbacks.onConfigChanged();
441
+ }, 200));
442
+ });
443
+ log.info(`Config watcher: Watching ${configDir} for config.json changes`);
444
+ }
445
+ catch (err) {
446
+ log.warn(`Config watcher: Could not watch config dir at ${configDir}:`, err);
447
+ }
448
+ };
449
+ /**
450
+ * Start periodic mtime polling as a fallback for stale fs.watch() watchers.
451
+ *
452
+ * fs.watch() can go stale on macOS (FSEvents bug in long-running Bun processes)
453
+ * and Linux (inotify limits). This polling loop stats every watched file and
454
+ * config.json on a fixed interval. If a file's mtime is newer than what was
455
+ * last recorded, the appropriate handler is invoked — the same handler that
456
+ * fs.watch() would have called. Because handlers already debounce and check
457
+ * fileWatcherGeneration, duplicate invocations from both fs.watch() and
458
+ * polling are safely deduplicated.
459
+ */
460
+ const startMtimePolling = (state, callbacks) => {
461
+ // Clean up any existing poll timer (defensive — stopFileWatching should clear this)
462
+ if (state.mtimePollTimerId !== null) {
463
+ clearInterval(state.mtimePollTimerId);
464
+ state.mtimePollTimerId = null;
465
+ }
466
+ const gen = state.fileWatcherGeneration;
467
+ state.mtimePollTimerId = setInterval(() => {
468
+ // Bail out if a new generation started (hot reload happened)
469
+ if (state.fileWatcherGeneration !== gen) {
470
+ if (state.mtimePollTimerId !== null) {
471
+ clearInterval(state.mtimePollTimerId);
472
+ state.mtimePollTimerId = null;
473
+ }
474
+ return;
475
+ }
476
+ state.mtimeLastPollAt = Date.now();
477
+ // Poll plugin files (tools.json + IIFE)
478
+ for (const entry of state.fileWatcherEntries) {
479
+ const toolsJsonPath = join(entry.pluginDir, 'dist', 'tools.json');
480
+ const iifePath = join(entry.pluginDir, 'dist', 'adapter.iife.js');
481
+ const isPending = entry.pluginName.startsWith('(pending:');
482
+ // Check tools.json mtime
483
+ const toolsMtime = getFileMtimeMs(toolsJsonPath);
484
+ const lastToolsMtime = entry.lastSeenMtimes.get(toolsJsonPath);
485
+ if (toolsMtime !== null && lastToolsMtime !== undefined && toolsMtime > lastToolsMtime) {
486
+ log.info(`Mtime poll: Detected change to ${toolsJsonPath} (old=${lastToolsMtime}, new=${toolsMtime}) — fs.watch may be stale`);
487
+ recordPollDetection(state);
488
+ entry.lastSeenMtimes.set(toolsJsonPath, toolsMtime);
489
+ if (isPending) {
490
+ void handlePendingPluginChange(state, entry.pluginDir, callbacks);
491
+ }
492
+ else {
493
+ void handleToolsJsonChange(state, entry.pluginName, entry.pluginDir, callbacks);
494
+ }
495
+ }
496
+ // Check IIFE mtime
497
+ const iifeMtime = getFileMtimeMs(iifePath);
498
+ const lastIifeMtime = entry.lastSeenMtimes.get(iifePath);
499
+ if (iifeMtime !== null && lastIifeMtime !== undefined && iifeMtime > lastIifeMtime) {
500
+ log.info(`Mtime poll: Detected change to ${iifePath} (old=${lastIifeMtime}, new=${iifeMtime}) — fs.watch may be stale`);
501
+ recordPollDetection(state);
502
+ entry.lastSeenMtimes.set(iifePath, iifeMtime);
503
+ if (isPending) {
504
+ void handlePendingPluginChange(state, entry.pluginDir, callbacks);
505
+ }
506
+ else {
507
+ void handleIifeChange(state, entry.pluginName, entry.pluginDir, callbacks);
508
+ }
509
+ }
510
+ }
511
+ // Poll config.json mtime
512
+ const configPath = join(getConfigDir(), 'config.json');
513
+ const configMtime = getFileMtimeMs(configPath);
514
+ if (configMtime !== null && state.configLastSeenMtime !== null && configMtime > state.configLastSeenMtime) {
515
+ log.info(`Mtime poll: Detected change to ${configPath} (old=${state.configLastSeenMtime}, new=${configMtime}) — fs.watch may be stale`);
516
+ recordPollDetection(state);
517
+ state.configLastSeenMtime = configMtime;
518
+ callbacks.onConfigChanged();
519
+ }
520
+ }, MTIME_POLL_INTERVAL_MS);
521
+ log.info(`Mtime polling started (interval=${MTIME_POLL_INTERVAL_MS}ms)`);
522
+ };
523
+ /**
524
+ * Start file watching for all local plugins and pending plugin paths.
525
+ *
526
+ * Watches two categories:
527
+ * 1. Successfully loaded local plugins (from state.plugins) — watches for
528
+ * manifest and IIFE updates using the existing per-event handlers.
529
+ * 2. Pending plugin paths (configured in config.json but failed initial
530
+ * discovery) — watches for any file changes and reattempts full discovery
531
+ * via loadPluginFromDir.
532
+ *
533
+ * @param resolvedPluginPaths - Absolute paths to all configured local plugin
534
+ * directories (from config.json, resolved against the config dir). Paths
535
+ * that exist on disk but are not in state.plugins are watched as pending.
536
+ */
537
+ const startFileWatching = (state, callbacks, resolvedPluginPaths = []) => {
538
+ // Clean up any existing watchers first
539
+ stopFileWatching(state);
540
+ state.fileWatcherGeneration++;
541
+ // Build set of paths already successfully loaded
542
+ const loadedPaths = new Set();
543
+ // Watch successfully loaded local plugins
544
+ const localPlugins = Array.from(state.registry.plugins.values()).filter(p => p.trustTier === 'local' && p.sourcePath);
545
+ for (const plugin of localPlugins) {
546
+ const srcPath = plugin.sourcePath;
547
+ if (!srcPath)
548
+ continue;
549
+ loadedPaths.add(srcPath);
550
+ const entry = watchPlugin(state, srcPath, plugin.name, callbacks);
551
+ state.fileWatcherEntries.push(entry);
552
+ // Record initial mtimes for mtime polling fallback
553
+ recordMtime(entry, join(srcPath, 'dist', 'tools.json'));
554
+ recordMtime(entry, join(srcPath, 'dist', 'adapter.iife.js'));
555
+ log.info(`File watcher: Watching "${plugin.name}" at ${srcPath}`);
556
+ }
557
+ // Watch pending plugin paths that failed initial discovery
558
+ let pendingCount = 0;
559
+ for (const pluginPath of resolvedPluginPaths) {
560
+ if (loadedPaths.has(pluginPath))
561
+ continue;
562
+ // Skip paths that don't exist on disk
563
+ try {
564
+ if (!statSync(pluginPath, { throwIfNoEntry: false })?.isDirectory())
565
+ continue;
566
+ }
567
+ catch {
568
+ continue;
569
+ }
570
+ const entry = watchPendingPlugin(state, pluginPath, callbacks);
571
+ state.fileWatcherEntries.push(entry);
572
+ // Record initial mtimes for mtime polling fallback
573
+ recordMtime(entry, join(pluginPath, 'dist', 'tools.json'));
574
+ recordMtime(entry, join(pluginPath, 'dist', 'adapter.iife.js'));
575
+ pendingCount++;
576
+ log.info(`File watcher: Watching pending plugin path at ${pluginPath}`);
577
+ }
578
+ const loadedCount = state.fileWatcherEntries.length - pendingCount;
579
+ if (loadedCount === 0 && pendingCount === 0) {
580
+ log.info('File watcher: No local plugins to watch');
581
+ }
582
+ else {
583
+ log.info(`File watcher: Watching ${loadedCount} loaded + ${pendingCount} pending plugin path(s)`);
584
+ }
585
+ // Start mtime polling as a fallback for stale fs.watch() watchers
586
+ startMtimePolling(state, callbacks);
587
+ };
588
+ /**
589
+ * Stop all file watchers and clean up.
590
+ * Reads watcher handles and timers from state (not module-level variables)
591
+ * so that the new module after hot reload can close the old module's watchers.
592
+ */
593
+ const stopFileWatching = (state) => {
594
+ for (const entry of state.fileWatcherEntries) {
595
+ for (const watcher of entry.watchers) {
596
+ watcher.close();
597
+ }
598
+ }
599
+ state.fileWatcherEntries.length = 0;
600
+ // Close config watcher
601
+ if (state.configWatcher) {
602
+ state.configWatcher.close();
603
+ state.configWatcher = null;
604
+ }
605
+ // Stop mtime polling
606
+ if (state.mtimePollTimerId !== null) {
607
+ clearInterval(state.mtimePollTimerId);
608
+ state.mtimePollTimerId = null;
609
+ }
610
+ for (const timer of state.fileWatcherTimers.values()) {
611
+ clearTimeout(timer);
612
+ }
613
+ state.fileWatcherTimers.clear();
614
+ };
615
+ export { handleToolsJsonChange, startConfigWatching, startFileWatching, stopFileWatching };
616
+ //# sourceMappingURL=file-watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-watcher.js","sourceRoot":"","sources":["../src/file-watcher.ts"],"names":[],"mappings":"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"}