@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
package/dist/config.js ADDED
@@ -0,0 +1,344 @@
1
+ /**
2
+ * Config system — ~/.opentabs/config.json
3
+ *
4
+ * Single source of truth for local plugin paths and tool enabled/disabled state.
5
+ * Created automatically on first MCP server run with sensible defaults.
6
+ *
7
+ * The config directory defaults to ~/.opentabs but can be overridden via the
8
+ * OPENTABS_CONFIG_DIR environment variable. This is essential for parallel
9
+ * E2E test execution where each test worker needs its own isolated config
10
+ * to avoid clobbering shared state.
11
+ */
12
+ import { log } from './logger.js';
13
+ import { chmod, mkdir, rename, unlink } from 'node:fs/promises';
14
+ import { homedir } from 'node:os';
15
+ import { join } from 'node:path';
16
+ /** Read the config directory, checking the environment variable on each call
17
+ * so that test overrides via OPENTABS_CONFIG_DIR take effect even after
18
+ * the module has been cached. */
19
+ const getConfigDir = () => Bun.env.OPENTABS_CONFIG_DIR || join(homedir(), '.opentabs');
20
+ const getConfigPath = () => join(getConfigDir(), 'config.json');
21
+ /** Managed extension install directory (~/.opentabs/extension/) */
22
+ const getExtensionDir = () => join(getConfigDir(), 'extension');
23
+ /** @public Version marker file for the managed extension install */
24
+ const getExtensionVersionFile = () => join(getExtensionDir(), '.opentabs-version');
25
+ /** @public Directory for plugin adapter IIFEs inside the managed extension */
26
+ const getAdaptersDir = () => join(getExtensionDir(), 'adapters');
27
+ /**
28
+ * Write config atomically: write to a temp file in the same directory,
29
+ * set restrictive permissions, then rename over the target. The rename
30
+ * is atomic on POSIX filesystems, so readers never see a partially-written file.
31
+ */
32
+ const atomicWriteConfig = async (configPath, content) => {
33
+ const tmpPath = configPath + '.tmp';
34
+ try {
35
+ await Bun.write(tmpPath, content);
36
+ await chmod(tmpPath, 0o600).catch((err) => {
37
+ log.warn(`Warning: Could not set file permissions on ${tmpPath}: ${err instanceof Error ? err.message : String(err)}. The config file may be readable by other users.`);
38
+ });
39
+ await rename(tmpPath, configPath);
40
+ }
41
+ catch (err) {
42
+ await unlink(tmpPath).catch(() => { });
43
+ throw err;
44
+ }
45
+ };
46
+ /** Generate a 256-bit cryptographic random secret as a 64-character hex string. */
47
+ const generateSecret = () => {
48
+ const bytes = new Uint8Array(32);
49
+ crypto.getRandomValues(bytes);
50
+ return Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
51
+ };
52
+ /**
53
+ * Read and parse config.json with retry and exponential backoff.
54
+ *
55
+ * Handles transient file unavailability during non-atomic writes from
56
+ * external processes (CLI commands, manual edits). Retries up to 3 times
57
+ * with 100ms / 200ms / 400ms delays before giving up.
58
+ *
59
+ * Returns the raw parsed JSON or null if the file cannot be read after
60
+ * all retries. Callers decide how to handle the failure.
61
+ */
62
+ const readConfigWithRetry = async (configPath, maxRetries = 3, initialDelayMs = 100) => {
63
+ let delay = initialDelayMs;
64
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
65
+ try {
66
+ const raw = await Bun.file(configPath).text();
67
+ const parsed = JSON.parse(raw);
68
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
69
+ if (attempt === maxRetries) {
70
+ log.warn(`Config at ${configPath} is not a JSON object after ${maxRetries + 1} attempt(s)`);
71
+ return null;
72
+ }
73
+ log.debug(`Config at ${configPath} is not a JSON object — retrying (attempt ${attempt + 1})`);
74
+ await new Promise(r => setTimeout(r, delay));
75
+ delay *= 2;
76
+ continue;
77
+ }
78
+ return parsed;
79
+ }
80
+ catch (err) {
81
+ if (attempt === maxRetries) {
82
+ log.warn(`Failed to read config from ${configPath} after ${maxRetries + 1} attempt(s):`, err);
83
+ return null;
84
+ }
85
+ log.debug(`Config read attempt ${attempt + 1} failed, retrying in ${delay}ms`);
86
+ await new Promise(r => setTimeout(r, delay));
87
+ delay *= 2;
88
+ }
89
+ }
90
+ return null;
91
+ };
92
+ /** Check whether a string looks like a local filesystem path. */
93
+ const isLocalPathEntry = (s) => s.startsWith('./') ||
94
+ s.startsWith('.\\') ||
95
+ s.startsWith('../') ||
96
+ s.startsWith('..\\') ||
97
+ s.startsWith('/') ||
98
+ s.startsWith('~/') ||
99
+ /^[A-Za-z]:[/\\]/.test(s);
100
+ const VALID_TOOL_PERMISSIONS = new Set(['allow', 'ask', 'deny']);
101
+ const isToolPermission = (v) => typeof v === 'string' && VALID_TOOL_PERMISSIONS.has(v);
102
+ /** Default permissions config: trust localhost, everything else uses tier defaults */
103
+ const defaultPermissions = () => ({
104
+ trustedDomains: ['localhost', '127.0.0.1'],
105
+ sensitiveDomains: [],
106
+ toolPolicy: {},
107
+ domainToolPolicy: {},
108
+ });
109
+ /** Parse a raw permissions value from config.json into a validated PermissionsConfig */
110
+ const parsePermissionsConfig = (raw) => {
111
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
112
+ return defaultPermissions();
113
+ }
114
+ const obj = raw;
115
+ const trustedDomains = Array.isArray(obj.trustedDomains)
116
+ ? obj.trustedDomains.filter((d) => typeof d === 'string')
117
+ : ['localhost', '127.0.0.1'];
118
+ const sensitiveDomains = Array.isArray(obj.sensitiveDomains)
119
+ ? obj.sensitiveDomains.filter((d) => typeof d === 'string')
120
+ : [];
121
+ const toolPolicy = {};
122
+ if (obj.toolPolicy && typeof obj.toolPolicy === 'object' && !Array.isArray(obj.toolPolicy)) {
123
+ for (const [key, value] of Object.entries(obj.toolPolicy)) {
124
+ if (isToolPermission(value)) {
125
+ toolPolicy[key] = value;
126
+ }
127
+ }
128
+ }
129
+ const domainToolPolicy = {};
130
+ if (obj.domainToolPolicy && typeof obj.domainToolPolicy === 'object' && !Array.isArray(obj.domainToolPolicy)) {
131
+ for (const [domain, tools] of Object.entries(obj.domainToolPolicy)) {
132
+ if (tools && typeof tools === 'object' && !Array.isArray(tools)) {
133
+ const domainEntry = {};
134
+ for (const [toolName, perm] of Object.entries(tools)) {
135
+ if (isToolPermission(perm)) {
136
+ domainEntry[toolName] = perm;
137
+ }
138
+ }
139
+ if (Object.keys(domainEntry).length > 0) {
140
+ domainToolPolicy[domain] = domainEntry;
141
+ }
142
+ }
143
+ }
144
+ }
145
+ return { trustedDomains, sensitiveDomains, toolPolicy, domainToolPolicy };
146
+ };
147
+ /**
148
+ * Parse a raw config record into an OpentabsConfig.
149
+ * Validates and normalizes field types to prevent downstream errors.
150
+ */
151
+ const parseConfigRecord = (record) => {
152
+ const localPlugins = Array.isArray(record.localPlugins)
153
+ ? record.localPlugins.filter((p) => typeof p === 'string')
154
+ : [];
155
+ const tools = {};
156
+ if (record.tools && typeof record.tools === 'object' && !Array.isArray(record.tools)) {
157
+ for (const [key, value] of Object.entries(record.tools)) {
158
+ if (typeof value === 'boolean') {
159
+ tools[key] = value;
160
+ }
161
+ }
162
+ }
163
+ const browserToolPolicy = {};
164
+ if (record.browserToolPolicy &&
165
+ typeof record.browserToolPolicy === 'object' &&
166
+ !Array.isArray(record.browserToolPolicy)) {
167
+ for (const [key, value] of Object.entries(record.browserToolPolicy)) {
168
+ if (typeof value === 'boolean') {
169
+ browserToolPolicy[key] = value;
170
+ }
171
+ }
172
+ }
173
+ // Migration: if the old `plugins` array exists, extract local paths into localPlugins
174
+ // and drop npm package names (they will be auto-discovered from global node_modules).
175
+ if (Array.isArray(record.plugins)) {
176
+ const legacyPlugins = record.plugins.filter((p) => typeof p === 'string');
177
+ const localPaths = legacyPlugins.filter(isLocalPathEntry);
178
+ const npmPackages = legacyPlugins.filter(p => !isLocalPathEntry(p));
179
+ if (localPaths.length > 0) {
180
+ // Merge into localPlugins, deduplicating
181
+ const existing = new Set(localPlugins);
182
+ for (const p of localPaths) {
183
+ if (!existing.has(p)) {
184
+ localPlugins.push(p);
185
+ existing.add(p);
186
+ }
187
+ }
188
+ log.info(`Migrating ${localPaths.length} local path(s) from "plugins" to "localPlugins". ` +
189
+ 'Update your config.json to use "localPlugins" for local plugin paths.');
190
+ }
191
+ if (npmPackages.length > 0) {
192
+ log.info(`Dropping ${npmPackages.length} npm package name(s) from legacy "plugins" array. ` +
193
+ 'npm plugins are now auto-discovered from global node_modules.');
194
+ }
195
+ }
196
+ // Migration: merge legacy npmPlugins — these are npm packages that will be auto-discovered,
197
+ // so they are dropped with a notice.
198
+ if (Array.isArray(record.npmPlugins)) {
199
+ const legacyNpm = record.npmPlugins.filter((p) => typeof p === 'string');
200
+ if (legacyNpm.length > 0) {
201
+ log.info(`Dropping ${legacyNpm.length} npmPlugins entry/entries. ` +
202
+ 'npm plugins are now auto-discovered from global node_modules.');
203
+ }
204
+ }
205
+ // Parse permissions config with defensive validation
206
+ const permissions = parsePermissionsConfig(record.permissions);
207
+ const skipConfirmation = typeof record.skipConfirmation === 'boolean' ? record.skipConfirmation : undefined;
208
+ const secret = typeof record.secret === 'string' ? record.secret : undefined;
209
+ return { localPlugins, tools, browserToolPolicy, permissions, skipConfirmation, secret };
210
+ };
211
+ /**
212
+ * Load config from ~/.opentabs/config.json.
213
+ * Creates the directory and file with defaults if they don't exist.
214
+ *
215
+ * On transient read/parse errors (corrupted file, mid-write from another
216
+ * process), retries with exponential backoff. If all retries fail, throws
217
+ * an error so the caller (reloadCore) can preserve previous state instead
218
+ * of replacing it with an empty config.
219
+ */
220
+ const loadConfig = async () => {
221
+ const configDir = getConfigDir();
222
+ const configPath = getConfigPath();
223
+ await mkdir(configDir, { recursive: true, mode: 0o700 });
224
+ const configFile = Bun.file(configPath);
225
+ if (!(await configFile.exists())) {
226
+ // First run — create default config with a fresh shared secret
227
+ const config = {
228
+ localPlugins: [],
229
+ tools: {},
230
+ browserToolPolicy: {},
231
+ permissions: defaultPermissions(),
232
+ secret: generateSecret(),
233
+ };
234
+ await atomicWriteConfig(configPath, JSON.stringify(config, null, 2) + '\n');
235
+ log.info(`Created default config at ${configPath}`);
236
+ return config;
237
+ }
238
+ const record = await readConfigWithRetry(configPath);
239
+ if (!record) {
240
+ // All retries exhausted — throw so the caller can preserve previous state.
241
+ // This prevents the old behavior of returning an empty fallback config
242
+ // which would wipe all plugins from state on any transient read error.
243
+ throw new Error(`Config at ${configPath} is unreadable after retries`);
244
+ }
245
+ const config = parseConfigRecord(record);
246
+ let { secret } = config;
247
+ // Generate secret if missing (upgrade from older config)
248
+ if (!secret) {
249
+ secret = generateSecret();
250
+ const updated = { ...config, secret };
251
+ await atomicWriteConfig(configPath, JSON.stringify(updated, null, 2) + '\n');
252
+ log.info(`Generated WebSocket authentication secret in ${configPath}`);
253
+ }
254
+ return { ...config, secret };
255
+ };
256
+ /**
257
+ * Save config to ~/.opentabs/config.json.
258
+ * Serialized via state.configWriteMutex to prevent concurrent read-modify-write
259
+ * races. The mutex lives on ServerState so it survives bun --hot re-evaluations
260
+ * (module-level variables reset on hot reload, but state persists on globalThis).
261
+ */
262
+ const saveConfig = async (state, config) => {
263
+ const configDir = getConfigDir();
264
+ const configPath = getConfigPath();
265
+ const prev = state.configWriteMutex;
266
+ state.configWriteMutex = (async () => {
267
+ await prev;
268
+ await mkdir(configDir, { recursive: true, mode: 0o700 });
269
+ await atomicWriteConfig(configPath, JSON.stringify(config, null, 2) + '\n');
270
+ })().catch((err) => {
271
+ // Reset mutex so subsequent writes don't hang on a rejected promise
272
+ state.configWriteMutex = Promise.resolve();
273
+ log.warn(`Failed to save config to ${configPath}:`, err);
274
+ throw err;
275
+ });
276
+ await state.configWriteMutex;
277
+ };
278
+ /**
279
+ * Persist only the tool enabled/disabled state to config.json.
280
+ *
281
+ * Reads the current config from disk, updates only the `tools` field,
282
+ * and writes it back atomically. This prevents stale in-memory plugin
283
+ * paths from overwriting externally-added plugins — the root cause of
284
+ * the "plugin disappears during development" bug.
285
+ *
286
+ * The read-modify-write is serialized via state.configWriteMutex.
287
+ */
288
+ const saveToolConfig = async (state, tools) => {
289
+ const configDir = getConfigDir();
290
+ const configPath = getConfigPath();
291
+ const prev = state.configWriteMutex;
292
+ state.configWriteMutex = (async () => {
293
+ await prev;
294
+ await mkdir(configDir, { recursive: true, mode: 0o700 });
295
+ // Read current config from disk to preserve localPlugins and secret
296
+ const record = await readConfigWithRetry(configPath, 2, 50);
297
+ if (!record) {
298
+ log.warn('Cannot persist tool config — config file unreadable');
299
+ return;
300
+ }
301
+ const current = parseConfigRecord(record);
302
+ const updated = {
303
+ localPlugins: current.localPlugins,
304
+ tools,
305
+ browserToolPolicy: current.browserToolPolicy,
306
+ permissions: current.permissions,
307
+ skipConfirmation: current.skipConfirmation,
308
+ secret: current.secret,
309
+ };
310
+ await atomicWriteConfig(configPath, JSON.stringify(updated, null, 2) + '\n');
311
+ })().catch((err) => {
312
+ state.configWriteMutex = Promise.resolve();
313
+ log.warn(`Failed to save tool config to ${configPath}:`, err);
314
+ throw err;
315
+ });
316
+ await state.configWriteMutex;
317
+ };
318
+ /**
319
+ * Write auth.json to the managed extension directory so the Chrome extension
320
+ * can bootstrap the shared secret without an unauthenticated HTTP request.
321
+ *
322
+ * The file is written atomically (write to .tmp, chmod 0600, rename) matching
323
+ * the atomicWriteConfig pattern. Called on every reload so the port and secret
324
+ * stay in sync with the running server.
325
+ */
326
+ const writeAuthFile = async (secret, port) => {
327
+ const extensionDir = getExtensionDir();
328
+ await mkdir(extensionDir, { recursive: true });
329
+ const authPath = join(extensionDir, 'auth.json');
330
+ const tmpPath = authPath + '.tmp';
331
+ try {
332
+ await Bun.write(tmpPath, JSON.stringify({ secret, port }) + '\n');
333
+ await chmod(tmpPath, 0o600).catch((err) => {
334
+ log.warn(`Warning: Could not set file permissions on ${tmpPath}: ${err instanceof Error ? err.message : String(err)}. The auth file may be readable by other users.`);
335
+ });
336
+ await rename(tmpPath, authPath);
337
+ }
338
+ catch (err) {
339
+ await unlink(tmpPath).catch(() => { });
340
+ throw err;
341
+ }
342
+ };
343
+ export { loadConfig, saveConfig, saveToolConfig, writeAuthFile, getConfigDir, getExtensionDir, getExtensionVersionFile, getAdaptersDir, };
344
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Dev mode detection — determined once at startup and stored for the process lifetime.
3
+ *
4
+ * Dev mode is enabled by passing --dev on the command line or setting OPENTABS_DEV=1
5
+ * in the environment. Production mode is the default when neither is present.
6
+ *
7
+ * Dev mode enables: file watchers for local plugins, config.json watching, mtime
8
+ * polling fallback, and the POST /reload HTTP endpoint.
9
+ *
10
+ * Production mode: static plugin discovery at startup, restart to reload.
11
+ */
12
+ /** Whether the server is running in dev mode (file watchers, hot reload, config watching) */
13
+ export declare const isDev: () => boolean;
14
+ //# sourceMappingURL=dev-mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-mode.d.ts","sourceRoot":"","sources":["../src/dev-mode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,6FAA6F;AAC7F,eAAO,MAAM,KAAK,QAAO,OAAkB,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Dev mode detection — determined once at startup and stored for the process lifetime.
3
+ *
4
+ * Dev mode is enabled by passing --dev on the command line or setting OPENTABS_DEV=1
5
+ * in the environment. Production mode is the default when neither is present.
6
+ *
7
+ * Dev mode enables: file watchers for local plugins, config.json watching, mtime
8
+ * polling fallback, and the POST /reload HTTP endpoint.
9
+ *
10
+ * Production mode: static plugin discovery at startup, restart to reload.
11
+ */
12
+ const devMode = Bun.argv.includes('--dev') || Bun.env.OPENTABS_DEV === '1' || Bun.env.OPENTABS_DEV === 'true';
13
+ /** Whether the server is running in dev mode (file watchers, hot reload, config watching) */
14
+ export const isDev = () => devMode;
15
+ //# sourceMappingURL=dev-mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev-mode.js","sourceRoot":"","sources":["../src/dev-mode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,YAAY,KAAK,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,YAAY,KAAK,MAAM,CAAC;AAE9G,6FAA6F;AAC7F,MAAM,CAAC,MAAM,KAAK,GAAG,GAAY,EAAE,CAAC,OAAO,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Legacy plugin discovery (opentabs-plugin.json based).
3
+ *
4
+ * Provides the old discoverPlugins and loadPluginFromDir functions that read
5
+ * opentabs-plugin.json manifests. Used by reload.ts and file-watcher.ts until
6
+ * they are migrated to the new package.json-based pipeline in later stories.
7
+ *
8
+ * This file will be deleted once US-009 (reload.ts), US-012 (file-watcher.ts),
9
+ * and US-020 (cleanup) are complete.
10
+ */
11
+ import type { FailedPlugin, RegisteredPlugin } from './state.js';
12
+ import type { TrustTier } from '@opentabs-dev/shared';
13
+ /**
14
+ * Load a single plugin from a directory.
15
+ * Reads opentabs-plugin.json and dist/adapter.iife.js.
16
+ */
17
+ declare const loadPluginFromDir: (dir: string, trustTier: TrustTier, npmPkgName: string | null, sourcePath?: string) => Promise<RegisteredPlugin>;
18
+ /** Result of full plugin discovery: successfully loaded plugins and failed paths */
19
+ interface DiscoveryOutcome {
20
+ plugins: Map<string, RegisteredPlugin>;
21
+ failures: FailedPlugin[];
22
+ }
23
+ /**
24
+ * Legacy plugin discovery using opentabs-plugin.json manifests.
25
+ * Discovers from both node_modules and local filesystem paths.
26
+ *
27
+ * This function will be replaced by the new discoverPlugins in discovery.ts
28
+ * once reload.ts (US-009) and file-watcher.ts (US-012) are migrated.
29
+ */
30
+ declare const discoverPluginsLegacy: (localPaths: string[], allowedNpmPackages: string[], rootDir?: string) => Promise<DiscoveryOutcome>;
31
+ export { discoverPluginsLegacy, loadPluginFromDir };
32
+ //# sourceMappingURL=discovery-legacy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery-legacy.d.ts","sourceRoot":"","sources":["../src/discovery-legacy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAUH,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAqEtD;;;GAGG;AACH,QAAA,MAAM,iBAAiB,GACrB,KAAK,MAAM,EACX,WAAW,SAAS,EACpB,YAAY,MAAM,GAAG,IAAI,EACzB,aAAa,MAAM,KAClB,OAAO,CAAC,gBAAgB,CA+E1B,CAAC;AA4PF,oFAAoF;AACpF,UAAU,gBAAgB;IACxB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACvC,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,QAAA,MAAM,qBAAqB,GACzB,YAAY,MAAM,EAAE,EACpB,oBAAoB,MAAM,EAAE,EAC5B,UAAU,MAAM,KACf,OAAO,CAAC,gBAAgB,CAoC1B,CAAC;AAEF,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,CAAC"}