@opentabs-dev/browser-extension 0.0.34

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 (305) hide show
  1. package/dist/background-log-state.d.ts +10 -0
  2. package/dist/background-log-state.d.ts.map +1 -0
  3. package/dist/background-log-state.js +11 -0
  4. package/dist/background-log-state.js.map +1 -0
  5. package/dist/background-message-handlers.d.ts +41 -0
  6. package/dist/background-message-handlers.d.ts.map +1 -0
  7. package/dist/background-message-handlers.js +214 -0
  8. package/dist/background-message-handlers.js.map +1 -0
  9. package/dist/background.d.ts +2 -0
  10. package/dist/background.d.ts.map +1 -0
  11. package/dist/background.js +3780 -0
  12. package/dist/background.js.map +1 -0
  13. package/dist/bg-log-state.d.ts +10 -0
  14. package/dist/bg-log-state.d.ts.map +1 -0
  15. package/dist/bg-log-state.js +11 -0
  16. package/dist/bg-log-state.js.map +1 -0
  17. package/dist/browser-commands/content-commands.d.ts +25 -0
  18. package/dist/browser-commands/content-commands.d.ts.map +1 -0
  19. package/dist/browser-commands/content-commands.js +166 -0
  20. package/dist/browser-commands/content-commands.js.map +1 -0
  21. package/dist/browser-commands/cookie-commands.d.ts +14 -0
  22. package/dist/browser-commands/cookie-commands.d.ts.map +1 -0
  23. package/dist/browser-commands/cookie-commands.js +99 -0
  24. package/dist/browser-commands/cookie-commands.js.map +1 -0
  25. package/dist/browser-commands/extension-commands.d.ts +12 -0
  26. package/dist/browser-commands/extension-commands.d.ts.map +1 -0
  27. package/dist/browser-commands/extension-commands.js +386 -0
  28. package/dist/browser-commands/extension-commands.js.map +1 -0
  29. package/dist/browser-commands/helpers.d.ts +35 -0
  30. package/dist/browser-commands/helpers.d.ts.map +1 -0
  31. package/dist/browser-commands/helpers.js +121 -0
  32. package/dist/browser-commands/helpers.js.map +1 -0
  33. package/dist/browser-commands/index.d.ts +11 -0
  34. package/dist/browser-commands/index.d.ts.map +1 -0
  35. package/dist/browser-commands/index.js +10 -0
  36. package/dist/browser-commands/index.js.map +1 -0
  37. package/dist/browser-commands/interaction-commands.d.ts +23 -0
  38. package/dist/browser-commands/interaction-commands.d.ts.map +1 -0
  39. package/dist/browser-commands/interaction-commands.js +353 -0
  40. package/dist/browser-commands/interaction-commands.js.map +1 -0
  41. package/dist/browser-commands/key-press-command.d.ts +2 -0
  42. package/dist/browser-commands/key-press-command.d.ts.map +1 -0
  43. package/dist/browser-commands/key-press-command.js +144 -0
  44. package/dist/browser-commands/key-press-command.js.map +1 -0
  45. package/dist/browser-commands/network-commands.d.ts +6 -0
  46. package/dist/browser-commands/network-commands.d.ts.map +1 -0
  47. package/dist/browser-commands/network-commands.js +69 -0
  48. package/dist/browser-commands/network-commands.js.map +1 -0
  49. package/dist/browser-commands/resource-commands.d.ts +37 -0
  50. package/dist/browser-commands/resource-commands.d.ts.map +1 -0
  51. package/dist/browser-commands/resource-commands.js +153 -0
  52. package/dist/browser-commands/resource-commands.js.map +1 -0
  53. package/dist/browser-commands/scroll-command.d.ts +2 -0
  54. package/dist/browser-commands/scroll-command.d.ts.map +1 -0
  55. package/dist/browser-commands/scroll-command.js +133 -0
  56. package/dist/browser-commands/scroll-command.js.map +1 -0
  57. package/dist/browser-commands/tab-commands.d.ts +33 -0
  58. package/dist/browser-commands/tab-commands.d.ts.map +1 -0
  59. package/dist/browser-commands/tab-commands.js +121 -0
  60. package/dist/browser-commands/tab-commands.js.map +1 -0
  61. package/dist/browser-commands.d.ts +36 -0
  62. package/dist/browser-commands.d.ts.map +1 -0
  63. package/dist/browser-commands.js +1931 -0
  64. package/dist/browser-commands.js.map +1 -0
  65. package/dist/confirmation-badge.d.ts +17 -0
  66. package/dist/confirmation-badge.d.ts.map +1 -0
  67. package/dist/confirmation-badge.js +64 -0
  68. package/dist/confirmation-badge.js.map +1 -0
  69. package/dist/constants.d.ts +79 -0
  70. package/dist/constants.d.ts.map +1 -0
  71. package/dist/constants.js +79 -0
  72. package/dist/constants.js.map +1 -0
  73. package/dist/dispatch-helpers.d.ts +61 -0
  74. package/dist/dispatch-helpers.d.ts.map +1 -0
  75. package/dist/dispatch-helpers.js +149 -0
  76. package/dist/dispatch-helpers.js.map +1 -0
  77. package/dist/extension-messages.d.ts +146 -0
  78. package/dist/extension-messages.d.ts.map +1 -0
  79. package/dist/extension-messages.js +2 -0
  80. package/dist/extension-messages.js.map +1 -0
  81. package/dist/iife-injection.d.ts +55 -0
  82. package/dist/iife-injection.d.ts.map +1 -0
  83. package/dist/iife-injection.js +474 -0
  84. package/dist/iife-injection.js.map +1 -0
  85. package/dist/json-rpc-errors.d.ts +8 -0
  86. package/dist/json-rpc-errors.d.ts.map +1 -0
  87. package/dist/json-rpc-errors.js +8 -0
  88. package/dist/json-rpc-errors.js.map +1 -0
  89. package/dist/known-methods.d.ts +19 -0
  90. package/dist/known-methods.d.ts.map +1 -0
  91. package/dist/known-methods.js +68 -0
  92. package/dist/known-methods.js.map +1 -0
  93. package/dist/log-collector.d.ts +45 -0
  94. package/dist/log-collector.d.ts.map +1 -0
  95. package/dist/log-collector.js +99 -0
  96. package/dist/log-collector.js.map +1 -0
  97. package/dist/message-router.d.ts +28 -0
  98. package/dist/message-router.d.ts.map +1 -0
  99. package/dist/message-router.js +367 -0
  100. package/dist/message-router.js.map +1 -0
  101. package/dist/messaging.d.ts +15 -0
  102. package/dist/messaging.d.ts.map +1 -0
  103. package/dist/messaging.js +41 -0
  104. package/dist/messaging.js.map +1 -0
  105. package/dist/network-capture.d.ts +56 -0
  106. package/dist/network-capture.d.ts.map +1 -0
  107. package/dist/network-capture.js +374 -0
  108. package/dist/network-capture.js.map +1 -0
  109. package/dist/offscreen/index.d.ts +16 -0
  110. package/dist/offscreen/index.d.ts.map +1 -0
  111. package/dist/offscreen/index.js +549 -0
  112. package/dist/offscreen/index.js.map +1 -0
  113. package/dist/plugin-storage.d.ts +19 -0
  114. package/dist/plugin-storage.d.ts.map +1 -0
  115. package/dist/plugin-storage.js +100 -0
  116. package/dist/plugin-storage.js.map +1 -0
  117. package/dist/rate-limiter.d.ts +18 -0
  118. package/dist/rate-limiter.d.ts.map +1 -0
  119. package/dist/rate-limiter.js +53 -0
  120. package/dist/rate-limiter.js.map +1 -0
  121. package/dist/resource-prompt-dispatch.d.ts +14 -0
  122. package/dist/resource-prompt-dispatch.d.ts.map +1 -0
  123. package/dist/resource-prompt-dispatch.js +195 -0
  124. package/dist/resource-prompt-dispatch.js.map +1 -0
  125. package/dist/sanitize-error.d.ts +8 -0
  126. package/dist/sanitize-error.d.ts.map +1 -0
  127. package/dist/sanitize-error.js +25 -0
  128. package/dist/sanitize-error.js.map +1 -0
  129. package/dist/sanitize-svg.d.ts +20 -0
  130. package/dist/sanitize-svg.d.ts.map +1 -0
  131. package/dist/sanitize-svg.js +296 -0
  132. package/dist/sanitize-svg.js.map +1 -0
  133. package/dist/side-panel/App.d.ts +3 -0
  134. package/dist/side-panel/App.d.ts.map +1 -0
  135. package/dist/side-panel/App.js +147 -0
  136. package/dist/side-panel/App.js.map +1 -0
  137. package/dist/side-panel/bridge.d.ts +50 -0
  138. package/dist/side-panel/bridge.d.ts.map +1 -0
  139. package/dist/side-panel/bridge.js +113 -0
  140. package/dist/side-panel/bridge.js.map +1 -0
  141. package/dist/side-panel/components/ConfirmationDialog.d.ts +16 -0
  142. package/dist/side-panel/components/ConfirmationDialog.d.ts.map +1 -0
  143. package/dist/side-panel/components/ConfirmationDialog.js +39 -0
  144. package/dist/side-panel/components/ConfirmationDialog.js.map +1 -0
  145. package/dist/side-panel/components/EmptyStates.d.ts +8 -0
  146. package/dist/side-panel/components/EmptyStates.d.ts.map +1 -0
  147. package/dist/side-panel/components/EmptyStates.js +40 -0
  148. package/dist/side-panel/components/EmptyStates.js.map +1 -0
  149. package/dist/side-panel/components/ErrorBoundary.d.ts +23 -0
  150. package/dist/side-panel/components/ErrorBoundary.d.ts.map +1 -0
  151. package/dist/side-panel/components/ErrorBoundary.js +28 -0
  152. package/dist/side-panel/components/ErrorBoundary.js.map +1 -0
  153. package/dist/side-panel/components/FailedPluginCard.d.ts +6 -0
  154. package/dist/side-panel/components/FailedPluginCard.d.ts.map +1 -0
  155. package/dist/side-panel/components/FailedPluginCard.js +9 -0
  156. package/dist/side-panel/components/FailedPluginCard.js.map +1 -0
  157. package/dist/side-panel/components/Footer.d.ts +3 -0
  158. package/dist/side-panel/components/Footer.d.ts.map +1 -0
  159. package/dist/side-panel/components/Footer.js +32 -0
  160. package/dist/side-panel/components/Footer.js.map +1 -0
  161. package/dist/side-panel/components/Header.d.ts +5 -0
  162. package/dist/side-panel/components/Header.d.ts.map +1 -0
  163. package/dist/side-panel/components/Header.js +6 -0
  164. package/dist/side-panel/components/Header.js.map +1 -0
  165. package/dist/side-panel/components/PluginCard.d.ts +10 -0
  166. package/dist/side-panel/components/PluginCard.d.ts.map +1 -0
  167. package/dist/side-panel/components/PluginCard.js +50 -0
  168. package/dist/side-panel/components/PluginCard.js.map +1 -0
  169. package/dist/side-panel/components/PluginIcon.d.ts +21 -0
  170. package/dist/side-panel/components/PluginIcon.d.ts.map +1 -0
  171. package/dist/side-panel/components/PluginIcon.js +48 -0
  172. package/dist/side-panel/components/PluginIcon.js.map +1 -0
  173. package/dist/side-panel/components/PluginList.d.ts +11 -0
  174. package/dist/side-panel/components/PluginList.d.ts.map +1 -0
  175. package/dist/side-panel/components/PluginList.js +17 -0
  176. package/dist/side-panel/components/PluginList.js.map +1 -0
  177. package/dist/side-panel/components/ToolIcon.d.ts +7 -0
  178. package/dist/side-panel/components/ToolIcon.d.ts.map +1 -0
  179. package/dist/side-panel/components/ToolIcon.js +8 -0
  180. package/dist/side-panel/components/ToolIcon.js.map +1 -0
  181. package/dist/side-panel/components/ToolRow.d.ts +11 -0
  182. package/dist/side-panel/components/ToolRow.d.ts.map +1 -0
  183. package/dist/side-panel/components/ToolRow.js +8 -0
  184. package/dist/side-panel/components/ToolRow.js.map +1 -0
  185. package/dist/side-panel/components/VersionMismatchBanner.d.ts +3 -0
  186. package/dist/side-panel/components/VersionMismatchBanner.d.ts.map +1 -0
  187. package/dist/side-panel/components/VersionMismatchBanner.js +5 -0
  188. package/dist/side-panel/components/VersionMismatchBanner.js.map +1 -0
  189. package/dist/side-panel/components/retro/Accordion.d.ts +8 -0
  190. package/dist/side-panel/components/retro/Accordion.d.ts.map +1 -0
  191. package/dist/side-panel/components/retro/Accordion.js +15 -0
  192. package/dist/side-panel/components/retro/Accordion.js.map +1 -0
  193. package/dist/side-panel/components/retro/Alert.d.ts +25 -0
  194. package/dist/side-panel/components/retro/Alert.d.ts.map +1 -0
  195. package/dist/side-panel/components/retro/Alert.js +33 -0
  196. package/dist/side-panel/components/retro/Alert.js.map +1 -0
  197. package/dist/side-panel/components/retro/Badge.d.ts +15 -0
  198. package/dist/side-panel/components/retro/Badge.d.ts.map +1 -0
  199. package/dist/side-panel/components/retro/Badge.js +23 -0
  200. package/dist/side-panel/components/retro/Badge.js.map +1 -0
  201. package/dist/side-panel/components/retro/Button.d.ts +13 -0
  202. package/dist/side-panel/components/retro/Button.d.ts.map +1 -0
  203. package/dist/side-panel/components/retro/Button.js +33 -0
  204. package/dist/side-panel/components/retro/Button.js.map +1 -0
  205. package/dist/side-panel/components/retro/Empty.d.ts +31 -0
  206. package/dist/side-panel/components/retro/Empty.d.ts.map +1 -0
  207. package/dist/side-panel/components/retro/Empty.js +25 -0
  208. package/dist/side-panel/components/retro/Empty.js.map +1 -0
  209. package/dist/side-panel/components/retro/Input.d.ts +8 -0
  210. package/dist/side-panel/components/retro/Input.d.ts.map +1 -0
  211. package/dist/side-panel/components/retro/Input.js +7 -0
  212. package/dist/side-panel/components/retro/Input.js.map +1 -0
  213. package/dist/side-panel/components/retro/Loader.d.ts +14 -0
  214. package/dist/side-panel/components/retro/Loader.d.ts.map +1 -0
  215. package/dist/side-panel/components/retro/Loader.js +30 -0
  216. package/dist/side-panel/components/retro/Loader.js.map +1 -0
  217. package/dist/side-panel/components/retro/Menu.d.ts +9 -0
  218. package/dist/side-panel/components/retro/Menu.d.ts.map +1 -0
  219. package/dist/side-panel/components/retro/Menu.js +17 -0
  220. package/dist/side-panel/components/retro/Menu.js.map +1 -0
  221. package/dist/side-panel/components/retro/NumberStepper.d.ts +18 -0
  222. package/dist/side-panel/components/retro/NumberStepper.d.ts.map +1 -0
  223. package/dist/side-panel/components/retro/NumberStepper.js +38 -0
  224. package/dist/side-panel/components/retro/NumberStepper.js.map +1 -0
  225. package/dist/side-panel/components/retro/Progress.d.ts +9 -0
  226. package/dist/side-panel/components/retro/Progress.d.ts.map +1 -0
  227. package/dist/side-panel/components/retro/Progress.js +6 -0
  228. package/dist/side-panel/components/retro/Progress.js.map +1 -0
  229. package/dist/side-panel/components/retro/Switch.d.ts +4 -0
  230. package/dist/side-panel/components/retro/Switch.d.ts.map +1 -0
  231. package/dist/side-panel/components/retro/Switch.js +6 -0
  232. package/dist/side-panel/components/retro/Switch.js.map +1 -0
  233. package/dist/side-panel/components/retro/Text.d.ts +11 -0
  234. package/dist/side-panel/components/retro/Text.d.ts.map +1 -0
  235. package/dist/side-panel/components/retro/Text.js +28 -0
  236. package/dist/side-panel/components/retro/Text.js.map +1 -0
  237. package/dist/side-panel/components/retro/Tooltip.d.ts +12 -0
  238. package/dist/side-panel/components/retro/Tooltip.d.ts.map +1 -0
  239. package/dist/side-panel/components/retro/Tooltip.js +32 -0
  240. package/dist/side-panel/components/retro/Tooltip.js.map +1 -0
  241. package/dist/side-panel/constants.d.ts +5 -0
  242. package/dist/side-panel/constants.d.ts.map +1 -0
  243. package/dist/side-panel/constants.js +5 -0
  244. package/dist/side-panel/constants.js.map +1 -0
  245. package/dist/side-panel/hooks/useServerNotifications.d.ts +21 -0
  246. package/dist/side-panel/hooks/useServerNotifications.d.ts.map +1 -0
  247. package/dist/side-panel/hooks/useServerNotifications.js +93 -0
  248. package/dist/side-panel/hooks/useServerNotifications.js.map +1 -0
  249. package/dist/side-panel/hooks/useTheme.d.ts +8 -0
  250. package/dist/side-panel/hooks/useTheme.d.ts.map +1 -0
  251. package/dist/side-panel/hooks/useTheme.js +30 -0
  252. package/dist/side-panel/hooks/useTheme.js.map +1 -0
  253. package/dist/side-panel/index.d.ts +2 -0
  254. package/dist/side-panel/index.d.ts.map +1 -0
  255. package/dist/side-panel/index.js +12 -0
  256. package/dist/side-panel/index.js.map +1 -0
  257. package/dist/side-panel/lib/cn.d.ts +3 -0
  258. package/dist/side-panel/lib/cn.d.ts.map +1 -0
  259. package/dist/side-panel/lib/cn.js +4 -0
  260. package/dist/side-panel/lib/cn.js.map +1 -0
  261. package/dist/side-panel/lib/utils.d.ts +3 -0
  262. package/dist/side-panel/lib/utils.d.ts.map +1 -0
  263. package/dist/side-panel/lib/utils.js +4 -0
  264. package/dist/side-panel/lib/utils.js.map +1 -0
  265. package/dist/side-panel/side-panel.js +78034 -0
  266. package/dist/side-panel/styles.css +2 -0
  267. package/dist/side-panel-state.d.ts +11 -0
  268. package/dist/side-panel-state.d.ts.map +1 -0
  269. package/dist/side-panel-state.js +38 -0
  270. package/dist/side-panel-state.js.map +1 -0
  271. package/dist/side-panel-toggle.d.ts +3 -0
  272. package/dist/side-panel-toggle.d.ts.map +1 -0
  273. package/dist/side-panel-toggle.js +31 -0
  274. package/dist/side-panel-toggle.js.map +1 -0
  275. package/dist/tab-matching.d.ts +51 -0
  276. package/dist/tab-matching.d.ts.map +1 -0
  277. package/dist/tab-matching.js +160 -0
  278. package/dist/tab-matching.js.map +1 -0
  279. package/dist/tab-state.d.ts +56 -0
  280. package/dist/tab-state.d.ts.map +1 -0
  281. package/dist/tab-state.js +282 -0
  282. package/dist/tab-state.js.map +1 -0
  283. package/dist/tool-dispatch.d.ts +19 -0
  284. package/dist/tool-dispatch.d.ts.map +1 -0
  285. package/dist/tool-dispatch.js +336 -0
  286. package/dist/tool-dispatch.js.map +1 -0
  287. package/dist/types.d.ts +82 -0
  288. package/dist/types.d.ts.map +1 -0
  289. package/dist/types.js +2 -0
  290. package/dist/types.js.map +1 -0
  291. package/icons/icon-128.png +0 -0
  292. package/icons/icon-16.png +0 -0
  293. package/icons/icon-32.png +0 -0
  294. package/icons/icon-48.png +0 -0
  295. package/icons/icon.svg +6 -0
  296. package/manifest.json +38 -0
  297. package/offscreen/offscreen.html +10 -0
  298. package/package.json +49 -0
  299. package/side-panel/dark-mode.js +29 -0
  300. package/side-panel/fonts/archivo-black-latin.woff2 +0 -0
  301. package/side-panel/fonts/space-grotesk-latin.woff2 +0 -0
  302. package/side-panel/fonts/space-mono-400-latin.woff2 +0 -0
  303. package/side-panel/fonts/space-mono-700-latin.woff2 +0 -0
  304. package/side-panel/fonts.css +34 -0
  305. package/side-panel/side-panel.html +16 -0
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Ring-buffer log collector that intercepts console methods and captures entries
3
+ * for retrieval by debugging tools. Each extension context (background, offscreen)
4
+ * gets its own LogCollector instance since they run in separate JS contexts.
5
+ */
6
+ type LogLevel = 'log' | 'warn' | 'error' | 'info';
7
+ type LogSource = 'background' | 'offscreen' | 'side-panel';
8
+ interface LogEntry {
9
+ timestamp: number;
10
+ level: LogLevel;
11
+ source: LogSource;
12
+ message: string;
13
+ }
14
+ interface LogFilterOptions {
15
+ level?: LogLevel;
16
+ source?: LogSource;
17
+ since?: number;
18
+ limit?: number;
19
+ }
20
+ interface LogStats {
21
+ totalCaptured: number;
22
+ bufferSize: number;
23
+ oldestTimestamp: number | null;
24
+ newestTimestamp: number | null;
25
+ }
26
+ declare class LogCollector {
27
+ private readonly buffer;
28
+ private readonly maxEntries;
29
+ private readonly source;
30
+ private totalCaptured;
31
+ constructor(source: LogSource, maxEntries?: number);
32
+ capture(level: LogLevel, args: unknown[]): void;
33
+ getEntries(options?: LogFilterOptions): LogEntry[];
34
+ clear(): void;
35
+ getStats(): LogStats;
36
+ }
37
+ /**
38
+ * Install a LogCollector as console interceptors for the given context.
39
+ * Wraps console.log, console.warn, console.error, and console.info — capturing
40
+ * entries in the ring buffer while still calling the original console methods.
41
+ */
42
+ declare const installLogCollector: (source: LogSource, maxEntries?: number) => LogCollector;
43
+ export { installLogCollector, LogCollector };
44
+ export type { LogEntry, LogFilterOptions, LogLevel, LogSource, LogStats };
45
+ //# sourceMappingURL=log-collector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-collector.d.ts","sourceRoot":"","sources":["../src/log-collector.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,KAAK,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAClD,KAAK,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,YAAY,CAAC;AAE3D,UAAU,QAAQ;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,SAAS,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,QAAQ;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAoBD,cAAM,YAAY;IAChB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,aAAa,CAAK;gBAEd,MAAM,EAAE,SAAS,EAAE,UAAU,GAAE,MAA4B;IAKvE,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAc/C,UAAU,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,QAAQ,EAAE;IAyBlD,KAAK,IAAI,IAAI;IAIb,QAAQ,IAAI,QAAQ;CAUrB;AAED;;;;GAIG;AACH,QAAA,MAAM,mBAAmB,GAAI,QAAQ,SAAS,EAAE,aAAa,MAAM,KAAG,YAarE,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,CAAC;AAC7C,YAAY,EAAE,QAAQ,EAAE,gBAAgB,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Ring-buffer log collector that intercepts console methods and captures entries
3
+ * for retrieval by debugging tools. Each extension context (background, offscreen)
4
+ * gets its own LogCollector instance since they run in separate JS contexts.
5
+ */
6
+ const MAX_MESSAGE_LENGTH = 2000;
7
+ const DEFAULT_MAX_ENTRIES = 500;
8
+ const formatArg = (arg) => {
9
+ if (typeof arg === 'string')
10
+ return arg;
11
+ if (arg instanceof Error)
12
+ return `${arg.message}${arg.stack ? `\n${arg.stack}` : ''}`;
13
+ try {
14
+ return JSON.stringify(arg);
15
+ }
16
+ catch {
17
+ return String(arg);
18
+ }
19
+ };
20
+ const formatMessage = (args) => {
21
+ const raw = args.map(formatArg).join(' ');
22
+ return raw.length > MAX_MESSAGE_LENGTH ? raw.slice(0, MAX_MESSAGE_LENGTH) : raw;
23
+ };
24
+ class LogCollector {
25
+ buffer = [];
26
+ maxEntries;
27
+ source;
28
+ totalCaptured = 0;
29
+ constructor(source, maxEntries = DEFAULT_MAX_ENTRIES) {
30
+ this.source = source;
31
+ this.maxEntries = maxEntries;
32
+ }
33
+ capture(level, args) {
34
+ const entry = {
35
+ timestamp: Date.now(),
36
+ level,
37
+ source: this.source,
38
+ message: formatMessage(args),
39
+ };
40
+ if (this.buffer.length >= this.maxEntries) {
41
+ this.buffer.shift();
42
+ }
43
+ this.buffer.push(entry);
44
+ this.totalCaptured++;
45
+ }
46
+ getEntries(options) {
47
+ let entries = this.buffer;
48
+ if (options?.level) {
49
+ const level = options.level;
50
+ entries = entries.filter(e => e.level === level);
51
+ }
52
+ if (options?.source) {
53
+ const source = options.source;
54
+ entries = entries.filter(e => e.source === source);
55
+ }
56
+ if (options?.since !== undefined) {
57
+ const since = options.since;
58
+ entries = entries.filter(e => e.timestamp >= since);
59
+ }
60
+ // Return newest-first
61
+ const result = [...entries].reverse();
62
+ if (options?.limit !== undefined && options.limit > 0) {
63
+ return result.slice(0, options.limit);
64
+ }
65
+ return result;
66
+ }
67
+ clear() {
68
+ this.buffer.length = 0;
69
+ }
70
+ getStats() {
71
+ const oldest = this.buffer[0];
72
+ const newest = this.buffer[this.buffer.length - 1];
73
+ return {
74
+ totalCaptured: this.totalCaptured,
75
+ bufferSize: this.buffer.length,
76
+ oldestTimestamp: oldest?.timestamp ?? null,
77
+ newestTimestamp: newest?.timestamp ?? null,
78
+ };
79
+ }
80
+ }
81
+ /**
82
+ * Install a LogCollector as console interceptors for the given context.
83
+ * Wraps console.log, console.warn, console.error, and console.info — capturing
84
+ * entries in the ring buffer while still calling the original console methods.
85
+ */
86
+ const installLogCollector = (source, maxEntries) => {
87
+ const collector = new LogCollector(source, maxEntries);
88
+ const levels = ['log', 'warn', 'error', 'info'];
89
+ for (const level of levels) {
90
+ const original = console[level].bind(console);
91
+ console[level] = (...args) => {
92
+ collector.capture(level, args);
93
+ original(...args);
94
+ };
95
+ }
96
+ return collector;
97
+ };
98
+ export { installLogCollector, LogCollector };
99
+ //# sourceMappingURL=log-collector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-collector.js","sourceRoot":"","sources":["../src/log-collector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { TrustTier, WireToolDef } from '@opentabs-dev/shared';
2
+ /** Validated plugin payload after passing through validatePluginPayload */
3
+ interface ValidatedPluginPayload {
4
+ name: string;
5
+ version: string;
6
+ displayName: string;
7
+ urlPatterns: string[];
8
+ trustTier: TrustTier;
9
+ sourcePath?: string;
10
+ adapterHash?: string;
11
+ adapterFile?: string;
12
+ iconSvg?: string;
13
+ iconInactiveSvg?: string;
14
+ tools: WireToolDef[];
15
+ }
16
+ /**
17
+ * Validate a raw plugin payload from sync.full or plugin.update.
18
+ * Returns a validated payload or null if the payload is malformed.
19
+ * Logs a warning for each rejected payload so issues are visible in DevTools.
20
+ */
21
+ declare const validatePluginPayload: (raw: unknown) => ValidatedPluginPayload | null;
22
+ /** Handle a JSON-RPC message received from the MCP server */
23
+ declare const handleServerMessage: (message: Record<string, unknown>) => void;
24
+ /** Method names registered in the dispatch table, exported for test verification */
25
+ declare const methodHandlerNames: string[];
26
+ export { handleServerMessage, methodHandlerNames, validatePluginPayload };
27
+ export type { ValidatedPluginPayload };
28
+ //# sourceMappingURL=message-router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-router.d.ts","sourceRoot":"","sources":["../src/message-router.ts"],"names":[],"mappings":"AAgDA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAoDnE,2EAA2E;AAC3E,UAAU,sBAAsB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAiBD;;;;GAIG;AACH,QAAA,MAAM,qBAAqB,GAAI,KAAK,OAAO,KAAG,sBAAsB,GAAG,IA+DtE,CAAC;AA0OF,6DAA6D;AAC7D,QAAA,MAAM,mBAAmB,GAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IA+C/D,CAAC;AAEF,oFAAoF;AACpF,QAAA,MAAM,kBAAkB,UAAoC,CAAC;AAE7D,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,CAAC;AAC1E,YAAY,EAAE,sBAAsB,EAAE,CAAC"}
@@ -0,0 +1,367 @@
1
+ import { handleBrowserClearConsoleLogs, handleBrowserClickElement, handleBrowserCloseTab, handleBrowserDeleteCookies, handleBrowserDisableNetworkCapture, handleBrowserEnableNetworkCapture, handleBrowserExecuteScript, handleBrowserFocusTab, handleBrowserGetConsoleLogs, handleBrowserGetCookies, handleBrowserGetNetworkRequests, handleBrowserGetPageHtml, handleBrowserGetStorage, handleBrowserGetTabContent, handleBrowserGetTabInfo, handleBrowserGetResourceContent, handleBrowserHandleDialog, handleBrowserListResources, handleBrowserListTabs, handleBrowserHoverElement, handleBrowserPressKey, handleBrowserScroll, handleBrowserNavigateTab, handleBrowserOpenTab, handleBrowserQueryElements, handleBrowserScreenshotTab, handleBrowserSelectOption, handleBrowserSetCookie, handleBrowserTypeText, handleBrowserWaitForElement, handleExtensionCheckAdapter, handleExtensionForceReconnect, handleExtensionGetLogs, handleExtensionGetSidePanel, handleExtensionGetState, } from './browser-commands/index.js';
2
+ import { notifyConfirmationRequest } from './confirmation-badge.js';
3
+ import { isValidPluginName, RELOAD_FLUSH_DELAY_MS, WS_CONNECTED_KEY } from './constants.js';
4
+ import { cleanupAdaptersInMatchingTabs, injectPluginIntoMatchingTabs } from './iife-injection.js';
5
+ import { JSONRPC_INTERNAL_ERROR, JSONRPC_INVALID_PARAMS, JSONRPC_METHOD_NOT_FOUND } from './json-rpc-errors.js';
6
+ import { forwardToSidePanel, sendTabStateNotification, sendToServer } from './messaging.js';
7
+ import { getAllPluginMeta, removePlugin, removePluginsBatch, storePluginsBatch } from './plugin-storage.js';
8
+ import { checkRateLimit } from './rate-limiter.js';
9
+ import { handleResourceRead, handlePromptGet } from './resource-prompt-dispatch.js';
10
+ import { clearPluginTabState, computePluginTabState, sendTabSyncAll, updateLastKnownState } from './tab-state.js';
11
+ import { handleToolDispatch } from './tool-dispatch.js';
12
+ /** Wraps an async request handler with the id !== undefined guard and .catch logging */
13
+ const wrapAsync = (method, fn) => (params, id) => {
14
+ if (id !== undefined) {
15
+ fn(params, id).catch((err) => console.warn(`[opentabs] ${method} handler failed:`, err));
16
+ }
17
+ };
18
+ /** Wraps a sync request handler with the id !== undefined guard and try-catch error logging */
19
+ const wrapSync = (method, fn) => (params, id) => {
20
+ if (id !== undefined) {
21
+ try {
22
+ fn(params, id);
23
+ }
24
+ catch (err) {
25
+ console.warn(`[opentabs] ${method} handler failed:`, err);
26
+ }
27
+ }
28
+ };
29
+ /** Wraps an async notification handler (no id guard — always executes) with .catch logging */
30
+ const wrapNotification = (method, fn) => params => {
31
+ fn(params).catch((err) => console.warn(`[opentabs] ${method} handler failed:`, err));
32
+ };
33
+ /**
34
+ * Methods whose notifications the side panel processes. Messages with other
35
+ * methods are not forwarded — this avoids sending payloads like sync.full
36
+ * (contains all plugin metadata) and tool.dispatch (contains tool input) to
37
+ * the side panel, which only needs tab state changes and invocation animations.
38
+ */
39
+ const SIDE_PANEL_METHODS = new Set([
40
+ 'tab.stateChanged',
41
+ 'tool.invocationStart',
42
+ 'tool.invocationEnd',
43
+ 'plugins.changed',
44
+ 'confirmation.request',
45
+ ]);
46
+ /** Convert a validated plugin payload to the PluginMeta shape stored in chrome.storage */
47
+ const toPluginMeta = (p) => ({
48
+ name: p.name,
49
+ version: p.version,
50
+ displayName: p.displayName,
51
+ urlPatterns: p.urlPatterns,
52
+ trustTier: p.trustTier,
53
+ sourcePath: p.sourcePath,
54
+ adapterHash: p.adapterHash,
55
+ adapterFile: p.adapterFile,
56
+ iconSvg: p.iconSvg,
57
+ iconInactiveSvg: p.iconInactiveSvg,
58
+ tools: p.tools,
59
+ });
60
+ /**
61
+ * Validate a raw plugin payload from sync.full or plugin.update.
62
+ * Returns a validated payload or null if the payload is malformed.
63
+ * Logs a warning for each rejected payload so issues are visible in DevTools.
64
+ */
65
+ const validatePluginPayload = (raw) => {
66
+ if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
67
+ console.warn('[opentabs] Rejecting plugin payload: not an object');
68
+ return null;
69
+ }
70
+ const obj = raw;
71
+ if (typeof obj.name !== 'string' || obj.name.length === 0) {
72
+ console.warn('[opentabs] Rejecting plugin payload: missing or invalid "name"');
73
+ return null;
74
+ }
75
+ // Defense-in-depth: reject names with path traversal characters or names
76
+ // that don't match the expected plugin name format (lowercase alphanumeric
77
+ // with hyphens). This prevents a compromised MCP server from injecting
78
+ // arbitrary file paths via crafted plugin names.
79
+ if (/[/\\]|\.\./.test(obj.name) || !isValidPluginName(obj.name)) {
80
+ console.warn(`[opentabs] Rejecting plugin payload: unsafe name "${obj.name}"`);
81
+ return null;
82
+ }
83
+ const urlPatterns = Array.isArray(obj.urlPatterns)
84
+ ? obj.urlPatterns.filter((p) => typeof p === 'string')
85
+ : [];
86
+ const tools = Array.isArray(obj.tools)
87
+ ? obj.tools
88
+ .filter((t) => typeof t === 'object' &&
89
+ t !== null &&
90
+ typeof t.name === 'string' &&
91
+ typeof t.description === 'string' &&
92
+ typeof t.enabled === 'boolean')
93
+ .map((t) => ({
94
+ name: t.name,
95
+ displayName: typeof t.displayName === 'string' ? t.displayName : t.name,
96
+ description: t.description,
97
+ icon: typeof t.icon === 'string' ? t.icon : 'wrench',
98
+ enabled: t.enabled,
99
+ }))
100
+ : [];
101
+ return {
102
+ name: obj.name,
103
+ version: typeof obj.version === 'string' ? obj.version : '0.0.0',
104
+ displayName: typeof obj.displayName === 'string' ? obj.displayName : obj.name,
105
+ urlPatterns,
106
+ trustTier: obj.trustTier === 'official' || obj.trustTier === 'community' || obj.trustTier === 'local'
107
+ ? obj.trustTier
108
+ : 'local',
109
+ sourcePath: typeof obj.sourcePath === 'string' ? obj.sourcePath : undefined,
110
+ adapterHash: typeof obj.adapterHash === 'string' ? obj.adapterHash : undefined,
111
+ adapterFile: typeof obj.adapterFile === 'string' ? obj.adapterFile : undefined,
112
+ iconSvg: typeof obj.iconSvg === 'string' ? obj.iconSvg : undefined,
113
+ iconInactiveSvg: typeof obj.iconInactiveSvg === 'string' ? obj.iconInactiveSvg : undefined,
114
+ tools,
115
+ };
116
+ };
117
+ // ---------------------------------------------------------------------------
118
+ // Handlers
119
+ // ---------------------------------------------------------------------------
120
+ /** Handle extension.reload: respond if id is present, then clear ws state and reload */
121
+ const handleExtensionReload = (_params, id) => {
122
+ if (id !== undefined) {
123
+ sendToServer({ jsonrpc: '2.0', result: { reloading: true }, id });
124
+ }
125
+ // Clear wsConnected from session storage before reload so the restarted
126
+ // background script does not read a stale "true" value. Without this,
127
+ // the ws:state connected=true message from the new offscreen document
128
+ // would be treated as a no-op (wasConnected already true), skipping
129
+ // sendTabSyncAll and leaving the MCP server without tab state.
130
+ //
131
+ // The reload is scheduled after the storage write completes (with a
132
+ // small delay for the response to flush over WebSocket).
133
+ void chrome.storage.session
134
+ .set({ [WS_CONNECTED_KEY]: false })
135
+ .catch(() => { })
136
+ .then(() => {
137
+ setTimeout(() => {
138
+ chrome.runtime.reload();
139
+ }, RELOAD_FLUSH_DELAY_MS);
140
+ });
141
+ };
142
+ const handleSyncFull = async (params) => {
143
+ const rawPlugins = params.plugins;
144
+ if (!Array.isArray(rawPlugins))
145
+ return;
146
+ // Validate each payload — reject malformed entries instead of blindly casting
147
+ const validated = [];
148
+ for (const raw of rawPlugins) {
149
+ const result = validatePluginPayload(raw);
150
+ if (result)
151
+ validated.push(result);
152
+ }
153
+ // Deduplicate by plugin name (last occurrence wins, defense-in-depth)
154
+ const deduped = new Map();
155
+ for (const p of validated) {
156
+ if (deduped.has(p.name)) {
157
+ console.warn(`[opentabs] Duplicate plugin in sync.full: ${p.name} — using last occurrence`);
158
+ }
159
+ deduped.set(p.name, p);
160
+ }
161
+ const uniquePlugins = Array.from(deduped.values());
162
+ // Collect the names of plugins in this sync set
163
+ const syncedNames = new Set(uniquePlugins.map(p => p.name));
164
+ // Remove plugins that are in storage but absent from the sync set (batched)
165
+ const existingMeta = await getAllPluginMeta();
166
+ const removedNames = Object.keys(existingMeta).filter(name => !syncedNames.has(name));
167
+ if (removedNames.length > 0) {
168
+ // Clean up injected adapters from matching tabs before removing storage
169
+ // entries (need URL patterns from existingMeta to find the right tabs).
170
+ // Best-effort: errors are caught per-plugin so one failure does not block
171
+ // cleanup of other plugins or the rest of the sync.full flow.
172
+ await Promise.allSettled(removedNames.map(name => {
173
+ const meta = existingMeta[name];
174
+ if (meta)
175
+ return cleanupAdaptersInMatchingTabs(name, meta.urlPatterns);
176
+ return Promise.resolve();
177
+ }));
178
+ await removePluginsBatch(removedNames);
179
+ for (const name of removedNames)
180
+ clearPluginTabState(name);
181
+ }
182
+ // Build the full meta index in memory, then write to chrome.storage.local
183
+ // in a single batched call.
184
+ const metas = uniquePlugins.map(toPluginMeta);
185
+ await storePluginsBatch(metas);
186
+ // Inject all plugins into matching tabs in parallel — each plugin's
187
+ // injection is independent and involves cross-process IPC, so parallelizing
188
+ // avoids O(N × round-trip) latency on sync.full with many plugins.
189
+ // Using allSettled so one failed injection does not block tab state sync.
190
+ const injectionResults = await Promise.allSettled(metas.map(meta => injectPluginIntoMatchingTabs(meta.name, meta.urlPatterns, true, meta.version, meta.adapterHash, meta.adapterFile)));
191
+ for (const result of injectionResults) {
192
+ if (result.status === 'rejected') {
193
+ console.warn('[opentabs] Plugin injection failed during sync.full:', result.reason);
194
+ }
195
+ }
196
+ // Send tab.syncAll AFTER all plugins are stored and injected to avoid the
197
+ // race condition where tab.syncAll runs before plugins are in storage.
198
+ await sendTabSyncAll();
199
+ // Notify the side panel so it refreshes its plugin list without user interaction
200
+ forwardToSidePanel({
201
+ type: 'sp:serverMessage',
202
+ data: { jsonrpc: '2.0', method: 'plugins.changed' },
203
+ });
204
+ };
205
+ const handlePluginUpdate = async (params) => {
206
+ const validated = validatePluginPayload(params);
207
+ if (!validated)
208
+ return;
209
+ const meta = toPluginMeta(validated);
210
+ await storePluginsBatch([meta]);
211
+ // Force re-injection so the new IIFE overwrites the stale adapter code
212
+ // already present in matching tabs. Without this, injectPluginIntoMatchingTabs
213
+ // skips tabs where the adapter is already injected, leaving old code running.
214
+ await injectPluginIntoMatchingTabs(meta.name, meta.urlPatterns, true, meta.version, meta.adapterHash, meta.adapterFile);
215
+ // Report updated tab state to the server after re-injection so the MCP
216
+ // server's tabMapping reflects the new adapter's readiness immediately.
217
+ // updateLastKnownState goes through the plugin lock to avoid interleaving
218
+ // with concurrent checkTabChanged / checkTabRemoved for the same plugin.
219
+ const newState = await computePluginTabState(meta);
220
+ await updateLastKnownState(meta.name, newState.state);
221
+ sendTabStateNotification(meta.name, newState);
222
+ // Notify the side panel so it refreshes its plugin list without user interaction
223
+ forwardToSidePanel({
224
+ type: 'sp:serverMessage',
225
+ data: { jsonrpc: '2.0', method: 'plugins.changed' },
226
+ });
227
+ };
228
+ const handlePluginUninstall = async (params, id) => {
229
+ const pluginName = params.name;
230
+ if (typeof pluginName !== 'string' || pluginName.length === 0) {
231
+ sendToServer({
232
+ jsonrpc: '2.0',
233
+ error: { code: JSONRPC_INVALID_PARAMS, message: 'Missing plugin name' },
234
+ id,
235
+ });
236
+ return;
237
+ }
238
+ if (!isValidPluginName(pluginName)) {
239
+ sendToServer({
240
+ jsonrpc: '2.0',
241
+ error: { code: JSONRPC_INVALID_PARAMS, message: `Invalid plugin name format: "${pluginName}"` },
242
+ id,
243
+ });
244
+ return;
245
+ }
246
+ // Clean up injected adapters from matching tabs before removing storage
247
+ // (need URL patterns from meta to find the right tabs).
248
+ // Best-effort: a cleanup failure must not prevent plugin removal from
249
+ // storage and tab state, matching handleSyncFull's allSettled approach.
250
+ const meta = await getAllPluginMeta();
251
+ const pluginMeta = meta[pluginName];
252
+ if (pluginMeta) {
253
+ try {
254
+ await cleanupAdaptersInMatchingTabs(pluginName, pluginMeta.urlPatterns);
255
+ }
256
+ catch (err) {
257
+ console.warn(`[opentabs] Failed to clean up adapters for ${pluginName}:`, err);
258
+ }
259
+ }
260
+ await removePlugin(pluginName);
261
+ clearPluginTabState(pluginName);
262
+ sendToServer({
263
+ jsonrpc: '2.0',
264
+ result: { success: true },
265
+ id,
266
+ });
267
+ };
268
+ // ---------------------------------------------------------------------------
269
+ // Dispatch table
270
+ // ---------------------------------------------------------------------------
271
+ /** Dispatch table mapping JSON-RPC methods to handlers */
272
+ const methodHandlers = new Map([
273
+ ['extension.reload', handleExtensionReload],
274
+ ['sync.full', wrapNotification('sync.full', handleSyncFull)],
275
+ ['plugin.update', wrapNotification('plugin.update', handlePluginUpdate)],
276
+ ['plugin.uninstall', wrapAsync('plugin.uninstall', handlePluginUninstall)],
277
+ ['tool.dispatch', wrapAsync('tool.dispatch', handleToolDispatch)],
278
+ ['resource.read', wrapAsync('resource.read', handleResourceRead)],
279
+ ['prompt.get', wrapAsync('prompt.get', handlePromptGet)],
280
+ ['browser.listTabs', wrapAsync('browser.listTabs', (_params, id) => handleBrowserListTabs(id))],
281
+ ['browser.openTab', wrapAsync('browser.openTab', handleBrowserOpenTab)],
282
+ ['browser.closeTab', wrapAsync('browser.closeTab', handleBrowserCloseTab)],
283
+ ['browser.navigateTab', wrapAsync('browser.navigateTab', handleBrowserNavigateTab)],
284
+ ['browser.focusTab', wrapAsync('browser.focusTab', handleBrowserFocusTab)],
285
+ ['browser.getTabInfo', wrapAsync('browser.getTabInfo', handleBrowserGetTabInfo)],
286
+ ['browser.screenshotTab', wrapAsync('browser.screenshotTab', handleBrowserScreenshotTab)],
287
+ ['browser.getTabContent', wrapAsync('browser.getTabContent', handleBrowserGetTabContent)],
288
+ ['browser.getPageHtml', wrapAsync('browser.getPageHtml', handleBrowserGetPageHtml)],
289
+ ['browser.getStorage', wrapAsync('browser.getStorage', handleBrowserGetStorage)],
290
+ ['browser.clickElement', wrapAsync('browser.clickElement', handleBrowserClickElement)],
291
+ ['browser.typeText', wrapAsync('browser.typeText', handleBrowserTypeText)],
292
+ ['browser.selectOption', wrapAsync('browser.selectOption', handleBrowserSelectOption)],
293
+ ['browser.waitForElement', wrapAsync('browser.waitForElement', handleBrowserWaitForElement)],
294
+ ['browser.queryElements', wrapAsync('browser.queryElements', handleBrowserQueryElements)],
295
+ ['browser.getCookies', wrapAsync('browser.getCookies', handleBrowserGetCookies)],
296
+ ['browser.setCookie', wrapAsync('browser.setCookie', handleBrowserSetCookie)],
297
+ ['browser.deleteCookies', wrapAsync('browser.deleteCookies', handleBrowserDeleteCookies)],
298
+ ['browser.enableNetworkCapture', wrapAsync('browser.enableNetworkCapture', handleBrowserEnableNetworkCapture)],
299
+ ['browser.getNetworkRequests', wrapSync('browser.getNetworkRequests', handleBrowserGetNetworkRequests)],
300
+ ['browser.disableNetworkCapture', wrapSync('browser.disableNetworkCapture', handleBrowserDisableNetworkCapture)],
301
+ ['browser.getConsoleLogs', wrapSync('browser.getConsoleLogs', handleBrowserGetConsoleLogs)],
302
+ ['browser.clearConsoleLogs', wrapSync('browser.clearConsoleLogs', handleBrowserClearConsoleLogs)],
303
+ ['browser.executeScript', wrapAsync('browser.executeScript', handleBrowserExecuteScript)],
304
+ ['browser.listResources', wrapAsync('browser.listResources', handleBrowserListResources)],
305
+ ['browser.getResourceContent', wrapAsync('browser.getResourceContent', handleBrowserGetResourceContent)],
306
+ ['browser.pressKey', wrapAsync('browser.pressKey', handleBrowserPressKey)],
307
+ ['browser.scroll', wrapAsync('browser.scroll', handleBrowserScroll)],
308
+ ['browser.hoverElement', wrapAsync('browser.hoverElement', handleBrowserHoverElement)],
309
+ ['browser.handleDialog', wrapAsync('browser.handleDialog', handleBrowserHandleDialog)],
310
+ ['extension.getState', wrapAsync('extension.getState', (_params, id) => handleExtensionGetState(id))],
311
+ ['extension.getLogs', wrapAsync('extension.getLogs', handleExtensionGetLogs)],
312
+ ['extension.getSidePanel', wrapAsync('extension.getSidePanel', (_params, id) => handleExtensionGetSidePanel(id))],
313
+ ['extension.checkAdapter', wrapAsync('extension.checkAdapter', handleExtensionCheckAdapter)],
314
+ [
315
+ 'extension.forceReconnect',
316
+ wrapAsync('extension.forceReconnect', (_params, id) => handleExtensionForceReconnect(id)),
317
+ ],
318
+ ]);
319
+ /** Handle a JSON-RPC message received from the MCP server */
320
+ const handleServerMessage = (message) => {
321
+ const method = message.method;
322
+ const id = message.id;
323
+ const params = (message.params ?? {});
324
+ // Forward to the side panel only if useful: responses (matched by id in the
325
+ // bridge's pending-request map) and the small set of notification methods the
326
+ // side panel actually handles. This avoids sending large payloads
327
+ // (sync.full metadata, tool.dispatch input) that the side panel would ignore.
328
+ const isResponse = id !== undefined && !method;
329
+ if (isResponse || (method && SIDE_PANEL_METHODS.has(method))) {
330
+ forwardToSidePanel({ type: 'sp:serverMessage', data: message });
331
+ }
332
+ // Badge and notification for confirmation requests — alerts the user when a
333
+ // browser tool needs approval, especially when the side panel is closed.
334
+ if (method === 'confirmation.request') {
335
+ notifyConfirmationRequest(params);
336
+ }
337
+ if (!method)
338
+ return;
339
+ const handler = methodHandlers.get(method);
340
+ if (handler) {
341
+ if (!checkRateLimit(method)) {
342
+ console.warn(`[opentabs] Rate limited: ${method}`);
343
+ if (id !== undefined) {
344
+ sendToServer({
345
+ jsonrpc: '2.0',
346
+ error: { code: JSONRPC_INTERNAL_ERROR, message: `Rate limited: ${method}` },
347
+ id,
348
+ });
349
+ }
350
+ return;
351
+ }
352
+ handler(params, id);
353
+ return;
354
+ }
355
+ // Unrecognized method with an id — send JSONRPC_METHOD_NOT_FOUND
356
+ if (id !== undefined) {
357
+ sendToServer({
358
+ jsonrpc: '2.0',
359
+ error: { code: JSONRPC_METHOD_NOT_FOUND, message: `Method not found: ${method}` },
360
+ id,
361
+ });
362
+ }
363
+ };
364
+ /** Method names registered in the dispatch table, exported for test verification */
365
+ const methodHandlerNames = Array.from(methodHandlers.keys());
366
+ export { handleServerMessage, methodHandlerNames, validatePluginPayload };
367
+ //# sourceMappingURL=message-router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-router.js","sourceRoot":"","sources":["../src/message-router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { PluginTabStateInfo, SpConnectionStateMessage, SpRelayMessage } from './extension-messages.js';
2
+ /** Messages that can be forwarded to the side panel */
3
+ type SidePanelMessage = SpConnectionStateMessage | SpRelayMessage;
4
+ /** Send a JSON-RPC message to the MCP server via offscreen WebSocket */
5
+ export declare const sendToServer: (data: unknown) => void;
6
+ /** Forward a message to the side panel (fire-and-forget) */
7
+ export declare const forwardToSidePanel: (message: SidePanelMessage) => void;
8
+ /**
9
+ * Send a tab.stateChanged notification to both the MCP server and the side panel.
10
+ * Encapsulates the JSON-RPC payload construction for the tab.stateChanged method,
11
+ * eliminating duplicated payload building across tab-state.ts and message-router.ts.
12
+ */
13
+ export declare const sendTabStateNotification: (pluginName: string, stateInfo: PluginTabStateInfo) => void;
14
+ export {};
15
+ //# sourceMappingURL=messaging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messaging.d.ts","sourceRoot":"","sources":["../src/messaging.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,EACf,MAAM,yBAAyB,CAAC;AAEjC,uDAAuD;AACvD,KAAK,gBAAgB,GAAG,wBAAwB,GAAG,cAAc,CAAC;AAElE,wEAAwE;AACxE,eAAO,MAAM,YAAY,GAAI,MAAM,OAAO,KAAG,IAK5C,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,kBAAkB,GAAI,SAAS,gBAAgB,KAAG,IAK9D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,GAAI,YAAY,MAAM,EAAE,WAAW,kBAAkB,KAAG,IAsB5F,CAAC"}
@@ -0,0 +1,41 @@
1
+ /** Send a JSON-RPC message to the MCP server via offscreen WebSocket */
2
+ export const sendToServer = (data) => {
3
+ const method = data.method ?? 'unknown';
4
+ chrome.runtime.sendMessage({ type: 'ws:send', data }).catch((err) => {
5
+ console.warn(`[opentabs] sendToServer failed for "${method}":`, err);
6
+ });
7
+ };
8
+ /** Forward a message to the side panel (fire-and-forget) */
9
+ export const forwardToSidePanel = (message) => {
10
+ const type = message.type;
11
+ chrome.runtime.sendMessage(message).catch((err) => {
12
+ console.warn(`[opentabs] forwardToSidePanel failed for "${type}":`, err);
13
+ });
14
+ };
15
+ /**
16
+ * Send a tab.stateChanged notification to both the MCP server and the side panel.
17
+ * Encapsulates the JSON-RPC payload construction for the tab.stateChanged method,
18
+ * eliminating duplicated payload building across tab-state.ts and message-router.ts.
19
+ */
20
+ export const sendTabStateNotification = (pluginName, stateInfo) => {
21
+ const params = {
22
+ plugin: pluginName,
23
+ state: stateInfo.state,
24
+ tabId: stateInfo.tabId,
25
+ url: stateInfo.url,
26
+ };
27
+ sendToServer({
28
+ jsonrpc: '2.0',
29
+ method: 'tab.stateChanged',
30
+ params,
31
+ });
32
+ forwardToSidePanel({
33
+ type: 'sp:serverMessage',
34
+ data: {
35
+ jsonrpc: '2.0',
36
+ method: 'tab.stateChanged',
37
+ params,
38
+ },
39
+ });
40
+ };
41
+ //# sourceMappingURL=messaging.js.map