@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.
- package/dist/background-log-state.d.ts +10 -0
- package/dist/background-log-state.d.ts.map +1 -0
- package/dist/background-log-state.js +11 -0
- package/dist/background-log-state.js.map +1 -0
- package/dist/background-message-handlers.d.ts +41 -0
- package/dist/background-message-handlers.d.ts.map +1 -0
- package/dist/background-message-handlers.js +214 -0
- package/dist/background-message-handlers.js.map +1 -0
- package/dist/background.d.ts +2 -0
- package/dist/background.d.ts.map +1 -0
- package/dist/background.js +3780 -0
- package/dist/background.js.map +1 -0
- package/dist/bg-log-state.d.ts +10 -0
- package/dist/bg-log-state.d.ts.map +1 -0
- package/dist/bg-log-state.js +11 -0
- package/dist/bg-log-state.js.map +1 -0
- package/dist/browser-commands/content-commands.d.ts +25 -0
- package/dist/browser-commands/content-commands.d.ts.map +1 -0
- package/dist/browser-commands/content-commands.js +166 -0
- package/dist/browser-commands/content-commands.js.map +1 -0
- package/dist/browser-commands/cookie-commands.d.ts +14 -0
- package/dist/browser-commands/cookie-commands.d.ts.map +1 -0
- package/dist/browser-commands/cookie-commands.js +99 -0
- package/dist/browser-commands/cookie-commands.js.map +1 -0
- package/dist/browser-commands/extension-commands.d.ts +12 -0
- package/dist/browser-commands/extension-commands.d.ts.map +1 -0
- package/dist/browser-commands/extension-commands.js +386 -0
- package/dist/browser-commands/extension-commands.js.map +1 -0
- package/dist/browser-commands/helpers.d.ts +35 -0
- package/dist/browser-commands/helpers.d.ts.map +1 -0
- package/dist/browser-commands/helpers.js +121 -0
- package/dist/browser-commands/helpers.js.map +1 -0
- package/dist/browser-commands/index.d.ts +11 -0
- package/dist/browser-commands/index.d.ts.map +1 -0
- package/dist/browser-commands/index.js +10 -0
- package/dist/browser-commands/index.js.map +1 -0
- package/dist/browser-commands/interaction-commands.d.ts +23 -0
- package/dist/browser-commands/interaction-commands.d.ts.map +1 -0
- package/dist/browser-commands/interaction-commands.js +353 -0
- package/dist/browser-commands/interaction-commands.js.map +1 -0
- package/dist/browser-commands/key-press-command.d.ts +2 -0
- package/dist/browser-commands/key-press-command.d.ts.map +1 -0
- package/dist/browser-commands/key-press-command.js +144 -0
- package/dist/browser-commands/key-press-command.js.map +1 -0
- package/dist/browser-commands/network-commands.d.ts +6 -0
- package/dist/browser-commands/network-commands.d.ts.map +1 -0
- package/dist/browser-commands/network-commands.js +69 -0
- package/dist/browser-commands/network-commands.js.map +1 -0
- package/dist/browser-commands/resource-commands.d.ts +37 -0
- package/dist/browser-commands/resource-commands.d.ts.map +1 -0
- package/dist/browser-commands/resource-commands.js +153 -0
- package/dist/browser-commands/resource-commands.js.map +1 -0
- package/dist/browser-commands/scroll-command.d.ts +2 -0
- package/dist/browser-commands/scroll-command.d.ts.map +1 -0
- package/dist/browser-commands/scroll-command.js +133 -0
- package/dist/browser-commands/scroll-command.js.map +1 -0
- package/dist/browser-commands/tab-commands.d.ts +33 -0
- package/dist/browser-commands/tab-commands.d.ts.map +1 -0
- package/dist/browser-commands/tab-commands.js +121 -0
- package/dist/browser-commands/tab-commands.js.map +1 -0
- package/dist/browser-commands.d.ts +36 -0
- package/dist/browser-commands.d.ts.map +1 -0
- package/dist/browser-commands.js +1931 -0
- package/dist/browser-commands.js.map +1 -0
- package/dist/confirmation-badge.d.ts +17 -0
- package/dist/confirmation-badge.d.ts.map +1 -0
- package/dist/confirmation-badge.js +64 -0
- package/dist/confirmation-badge.js.map +1 -0
- package/dist/constants.d.ts +79 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +79 -0
- package/dist/constants.js.map +1 -0
- package/dist/dispatch-helpers.d.ts +61 -0
- package/dist/dispatch-helpers.d.ts.map +1 -0
- package/dist/dispatch-helpers.js +149 -0
- package/dist/dispatch-helpers.js.map +1 -0
- package/dist/extension-messages.d.ts +146 -0
- package/dist/extension-messages.d.ts.map +1 -0
- package/dist/extension-messages.js +2 -0
- package/dist/extension-messages.js.map +1 -0
- package/dist/iife-injection.d.ts +55 -0
- package/dist/iife-injection.d.ts.map +1 -0
- package/dist/iife-injection.js +474 -0
- package/dist/iife-injection.js.map +1 -0
- package/dist/json-rpc-errors.d.ts +8 -0
- package/dist/json-rpc-errors.d.ts.map +1 -0
- package/dist/json-rpc-errors.js +8 -0
- package/dist/json-rpc-errors.js.map +1 -0
- package/dist/known-methods.d.ts +19 -0
- package/dist/known-methods.d.ts.map +1 -0
- package/dist/known-methods.js +68 -0
- package/dist/known-methods.js.map +1 -0
- package/dist/log-collector.d.ts +45 -0
- package/dist/log-collector.d.ts.map +1 -0
- package/dist/log-collector.js +99 -0
- package/dist/log-collector.js.map +1 -0
- package/dist/message-router.d.ts +28 -0
- package/dist/message-router.d.ts.map +1 -0
- package/dist/message-router.js +367 -0
- package/dist/message-router.js.map +1 -0
- package/dist/messaging.d.ts +15 -0
- package/dist/messaging.d.ts.map +1 -0
- package/dist/messaging.js +41 -0
- package/dist/messaging.js.map +1 -0
- package/dist/network-capture.d.ts +56 -0
- package/dist/network-capture.d.ts.map +1 -0
- package/dist/network-capture.js +374 -0
- package/dist/network-capture.js.map +1 -0
- package/dist/offscreen/index.d.ts +16 -0
- package/dist/offscreen/index.d.ts.map +1 -0
- package/dist/offscreen/index.js +549 -0
- package/dist/offscreen/index.js.map +1 -0
- package/dist/plugin-storage.d.ts +19 -0
- package/dist/plugin-storage.d.ts.map +1 -0
- package/dist/plugin-storage.js +100 -0
- package/dist/plugin-storage.js.map +1 -0
- package/dist/rate-limiter.d.ts +18 -0
- package/dist/rate-limiter.d.ts.map +1 -0
- package/dist/rate-limiter.js +53 -0
- package/dist/rate-limiter.js.map +1 -0
- package/dist/resource-prompt-dispatch.d.ts +14 -0
- package/dist/resource-prompt-dispatch.d.ts.map +1 -0
- package/dist/resource-prompt-dispatch.js +195 -0
- package/dist/resource-prompt-dispatch.js.map +1 -0
- package/dist/sanitize-error.d.ts +8 -0
- package/dist/sanitize-error.d.ts.map +1 -0
- package/dist/sanitize-error.js +25 -0
- package/dist/sanitize-error.js.map +1 -0
- package/dist/sanitize-svg.d.ts +20 -0
- package/dist/sanitize-svg.d.ts.map +1 -0
- package/dist/sanitize-svg.js +296 -0
- package/dist/sanitize-svg.js.map +1 -0
- package/dist/side-panel/App.d.ts +3 -0
- package/dist/side-panel/App.d.ts.map +1 -0
- package/dist/side-panel/App.js +147 -0
- package/dist/side-panel/App.js.map +1 -0
- package/dist/side-panel/bridge.d.ts +50 -0
- package/dist/side-panel/bridge.d.ts.map +1 -0
- package/dist/side-panel/bridge.js +113 -0
- package/dist/side-panel/bridge.js.map +1 -0
- package/dist/side-panel/components/ConfirmationDialog.d.ts +16 -0
- package/dist/side-panel/components/ConfirmationDialog.d.ts.map +1 -0
- package/dist/side-panel/components/ConfirmationDialog.js +39 -0
- package/dist/side-panel/components/ConfirmationDialog.js.map +1 -0
- package/dist/side-panel/components/EmptyStates.d.ts +8 -0
- package/dist/side-panel/components/EmptyStates.d.ts.map +1 -0
- package/dist/side-panel/components/EmptyStates.js +40 -0
- package/dist/side-panel/components/EmptyStates.js.map +1 -0
- package/dist/side-panel/components/ErrorBoundary.d.ts +23 -0
- package/dist/side-panel/components/ErrorBoundary.d.ts.map +1 -0
- package/dist/side-panel/components/ErrorBoundary.js +28 -0
- package/dist/side-panel/components/ErrorBoundary.js.map +1 -0
- package/dist/side-panel/components/FailedPluginCard.d.ts +6 -0
- package/dist/side-panel/components/FailedPluginCard.d.ts.map +1 -0
- package/dist/side-panel/components/FailedPluginCard.js +9 -0
- package/dist/side-panel/components/FailedPluginCard.js.map +1 -0
- package/dist/side-panel/components/Footer.d.ts +3 -0
- package/dist/side-panel/components/Footer.d.ts.map +1 -0
- package/dist/side-panel/components/Footer.js +32 -0
- package/dist/side-panel/components/Footer.js.map +1 -0
- package/dist/side-panel/components/Header.d.ts +5 -0
- package/dist/side-panel/components/Header.d.ts.map +1 -0
- package/dist/side-panel/components/Header.js +6 -0
- package/dist/side-panel/components/Header.js.map +1 -0
- package/dist/side-panel/components/PluginCard.d.ts +10 -0
- package/dist/side-panel/components/PluginCard.d.ts.map +1 -0
- package/dist/side-panel/components/PluginCard.js +50 -0
- package/dist/side-panel/components/PluginCard.js.map +1 -0
- package/dist/side-panel/components/PluginIcon.d.ts +21 -0
- package/dist/side-panel/components/PluginIcon.d.ts.map +1 -0
- package/dist/side-panel/components/PluginIcon.js +48 -0
- package/dist/side-panel/components/PluginIcon.js.map +1 -0
- package/dist/side-panel/components/PluginList.d.ts +11 -0
- package/dist/side-panel/components/PluginList.d.ts.map +1 -0
- package/dist/side-panel/components/PluginList.js +17 -0
- package/dist/side-panel/components/PluginList.js.map +1 -0
- package/dist/side-panel/components/ToolIcon.d.ts +7 -0
- package/dist/side-panel/components/ToolIcon.d.ts.map +1 -0
- package/dist/side-panel/components/ToolIcon.js +8 -0
- package/dist/side-panel/components/ToolIcon.js.map +1 -0
- package/dist/side-panel/components/ToolRow.d.ts +11 -0
- package/dist/side-panel/components/ToolRow.d.ts.map +1 -0
- package/dist/side-panel/components/ToolRow.js +8 -0
- package/dist/side-panel/components/ToolRow.js.map +1 -0
- package/dist/side-panel/components/VersionMismatchBanner.d.ts +3 -0
- package/dist/side-panel/components/VersionMismatchBanner.d.ts.map +1 -0
- package/dist/side-panel/components/VersionMismatchBanner.js +5 -0
- package/dist/side-panel/components/VersionMismatchBanner.js.map +1 -0
- package/dist/side-panel/components/retro/Accordion.d.ts +8 -0
- package/dist/side-panel/components/retro/Accordion.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Accordion.js +15 -0
- package/dist/side-panel/components/retro/Accordion.js.map +1 -0
- package/dist/side-panel/components/retro/Alert.d.ts +25 -0
- package/dist/side-panel/components/retro/Alert.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Alert.js +33 -0
- package/dist/side-panel/components/retro/Alert.js.map +1 -0
- package/dist/side-panel/components/retro/Badge.d.ts +15 -0
- package/dist/side-panel/components/retro/Badge.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Badge.js +23 -0
- package/dist/side-panel/components/retro/Badge.js.map +1 -0
- package/dist/side-panel/components/retro/Button.d.ts +13 -0
- package/dist/side-panel/components/retro/Button.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Button.js +33 -0
- package/dist/side-panel/components/retro/Button.js.map +1 -0
- package/dist/side-panel/components/retro/Empty.d.ts +31 -0
- package/dist/side-panel/components/retro/Empty.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Empty.js +25 -0
- package/dist/side-panel/components/retro/Empty.js.map +1 -0
- package/dist/side-panel/components/retro/Input.d.ts +8 -0
- package/dist/side-panel/components/retro/Input.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Input.js +7 -0
- package/dist/side-panel/components/retro/Input.js.map +1 -0
- package/dist/side-panel/components/retro/Loader.d.ts +14 -0
- package/dist/side-panel/components/retro/Loader.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Loader.js +30 -0
- package/dist/side-panel/components/retro/Loader.js.map +1 -0
- package/dist/side-panel/components/retro/Menu.d.ts +9 -0
- package/dist/side-panel/components/retro/Menu.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Menu.js +17 -0
- package/dist/side-panel/components/retro/Menu.js.map +1 -0
- package/dist/side-panel/components/retro/NumberStepper.d.ts +18 -0
- package/dist/side-panel/components/retro/NumberStepper.d.ts.map +1 -0
- package/dist/side-panel/components/retro/NumberStepper.js +38 -0
- package/dist/side-panel/components/retro/NumberStepper.js.map +1 -0
- package/dist/side-panel/components/retro/Progress.d.ts +9 -0
- package/dist/side-panel/components/retro/Progress.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Progress.js +6 -0
- package/dist/side-panel/components/retro/Progress.js.map +1 -0
- package/dist/side-panel/components/retro/Switch.d.ts +4 -0
- package/dist/side-panel/components/retro/Switch.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Switch.js +6 -0
- package/dist/side-panel/components/retro/Switch.js.map +1 -0
- package/dist/side-panel/components/retro/Text.d.ts +11 -0
- package/dist/side-panel/components/retro/Text.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Text.js +28 -0
- package/dist/side-panel/components/retro/Text.js.map +1 -0
- package/dist/side-panel/components/retro/Tooltip.d.ts +12 -0
- package/dist/side-panel/components/retro/Tooltip.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Tooltip.js +32 -0
- package/dist/side-panel/components/retro/Tooltip.js.map +1 -0
- package/dist/side-panel/constants.d.ts +5 -0
- package/dist/side-panel/constants.d.ts.map +1 -0
- package/dist/side-panel/constants.js +5 -0
- package/dist/side-panel/constants.js.map +1 -0
- package/dist/side-panel/hooks/useServerNotifications.d.ts +21 -0
- package/dist/side-panel/hooks/useServerNotifications.d.ts.map +1 -0
- package/dist/side-panel/hooks/useServerNotifications.js +93 -0
- package/dist/side-panel/hooks/useServerNotifications.js.map +1 -0
- package/dist/side-panel/hooks/useTheme.d.ts +8 -0
- package/dist/side-panel/hooks/useTheme.d.ts.map +1 -0
- package/dist/side-panel/hooks/useTheme.js +30 -0
- package/dist/side-panel/hooks/useTheme.js.map +1 -0
- package/dist/side-panel/index.d.ts +2 -0
- package/dist/side-panel/index.d.ts.map +1 -0
- package/dist/side-panel/index.js +12 -0
- package/dist/side-panel/index.js.map +1 -0
- package/dist/side-panel/lib/cn.d.ts +3 -0
- package/dist/side-panel/lib/cn.d.ts.map +1 -0
- package/dist/side-panel/lib/cn.js +4 -0
- package/dist/side-panel/lib/cn.js.map +1 -0
- package/dist/side-panel/lib/utils.d.ts +3 -0
- package/dist/side-panel/lib/utils.d.ts.map +1 -0
- package/dist/side-panel/lib/utils.js +4 -0
- package/dist/side-panel/lib/utils.js.map +1 -0
- package/dist/side-panel/side-panel.js +78034 -0
- package/dist/side-panel/styles.css +2 -0
- package/dist/side-panel-state.d.ts +11 -0
- package/dist/side-panel-state.d.ts.map +1 -0
- package/dist/side-panel-state.js +38 -0
- package/dist/side-panel-state.js.map +1 -0
- package/dist/side-panel-toggle.d.ts +3 -0
- package/dist/side-panel-toggle.d.ts.map +1 -0
- package/dist/side-panel-toggle.js +31 -0
- package/dist/side-panel-toggle.js.map +1 -0
- package/dist/tab-matching.d.ts +51 -0
- package/dist/tab-matching.d.ts.map +1 -0
- package/dist/tab-matching.js +160 -0
- package/dist/tab-matching.js.map +1 -0
- package/dist/tab-state.d.ts +56 -0
- package/dist/tab-state.d.ts.map +1 -0
- package/dist/tab-state.js +282 -0
- package/dist/tab-state.js.map +1 -0
- package/dist/tool-dispatch.d.ts +19 -0
- package/dist/tool-dispatch.d.ts.map +1 -0
- package/dist/tool-dispatch.js +336 -0
- package/dist/tool-dispatch.js.map +1 -0
- package/dist/types.d.ts +82 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/icons/icon-128.png +0 -0
- package/icons/icon-16.png +0 -0
- package/icons/icon-32.png +0 -0
- package/icons/icon-48.png +0 -0
- package/icons/icon.svg +6 -0
- package/manifest.json +38 -0
- package/offscreen/offscreen.html +10 -0
- package/package.json +49 -0
- package/side-panel/dark-mode.js +29 -0
- package/side-panel/fonts/archivo-black-latin.woff2 +0 -0
- package/side-panel/fonts/space-grotesk-latin.woff2 +0 -0
- package/side-panel/fonts/space-mono-400-latin.woff2 +0 -0
- package/side-panel/fonts/space-mono-700-latin.woff2 +0 -0
- package/side-panel/fonts.css +34 -0
- 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
|