brms-host 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/build/bin/install.d.ts +13 -0
  2. package/build/bin/install.js +124 -0
  3. package/build/bin/install.js.map +1 -0
  4. package/build/bridge/native-messaging.d.ts +27 -0
  5. package/build/bridge/native-messaging.js +118 -0
  6. package/build/bridge/native-messaging.js.map +1 -0
  7. package/build/browser/connection.d.ts +12 -0
  8. package/build/browser/connection.js +57 -0
  9. package/build/browser/connection.js.map +1 -0
  10. package/build/browser/console.d.ts +16 -0
  11. package/build/browser/console.js +44 -0
  12. package/build/browser/console.js.map +1 -0
  13. package/build/browser/dom.d.ts +9 -0
  14. package/build/browser/dom.js +16 -0
  15. package/build/browser/dom.js.map +1 -0
  16. package/build/browser/network.d.ts +14 -0
  17. package/build/browser/network.js +47 -0
  18. package/build/browser/network.js.map +1 -0
  19. package/build/index.d.ts +8 -0
  20. package/build/index.js +111 -0
  21. package/build/index.js.map +1 -0
  22. package/build/server.d.ts +2 -0
  23. package/build/server.js +30 -0
  24. package/build/server.js.map +1 -0
  25. package/build/tools/connection.tools.d.ts +2 -0
  26. package/build/tools/connection.tools.js +28 -0
  27. package/build/tools/connection.tools.js.map +1 -0
  28. package/build/tools/console.tools.d.ts +2 -0
  29. package/build/tools/console.tools.js +25 -0
  30. package/build/tools/console.tools.js.map +1 -0
  31. package/build/tools/debug.tools.d.ts +2 -0
  32. package/build/tools/debug.tools.js +226 -0
  33. package/build/tools/debug.tools.js.map +1 -0
  34. package/build/tools/dom.tools.d.ts +2 -0
  35. package/build/tools/dom.tools.js +26 -0
  36. package/build/tools/dom.tools.js.map +1 -0
  37. package/build/tools/events.tools.d.ts +2 -0
  38. package/build/tools/events.tools.js +18 -0
  39. package/build/tools/events.tools.js.map +1 -0
  40. package/build/tools/layout.tools.d.ts +2 -0
  41. package/build/tools/layout.tools.js +20 -0
  42. package/build/tools/layout.tools.js.map +1 -0
  43. package/build/tools/network.tools.d.ts +2 -0
  44. package/build/tools/network.tools.js +29 -0
  45. package/build/tools/network.tools.js.map +1 -0
  46. package/build/tools/screenshot.tools.d.ts +2 -0
  47. package/build/tools/screenshot.tools.js +40 -0
  48. package/build/tools/screenshot.tools.js.map +1 -0
  49. package/build/tools/styles.tools.d.ts +2 -0
  50. package/build/tools/styles.tools.js +22 -0
  51. package/build/tools/styles.tools.js.map +1 -0
  52. package/build/types/index.d.ts +130 -0
  53. package/build/types/index.js +2 -0
  54. package/build/types/index.js.map +1 -0
  55. package/build/utils/errors.d.ts +16 -0
  56. package/build/utils/errors.js +29 -0
  57. package/build/utils/errors.js.map +1 -0
  58. package/build/utils/logger.d.ts +11 -0
  59. package/build/utils/logger.js +15 -0
  60. package/build/utils/logger.js.map +1 -0
  61. package/package.json +35 -0
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * brms-host install [--extension-id=<id>]
4
+ *
5
+ * Registers the native messaging host manifest so Chrome can find it.
6
+ * Also prints the Cursor MCP config.
7
+ *
8
+ * The extension ID is required. You can find it on chrome://extensions
9
+ * after loading the unpacked extension. Pass it via:
10
+ * --extension-id=<id> CLI flag
11
+ * BRMS_EXTENSION_ID=<id> environment variable
12
+ */
13
+ export {};
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * brms-host install [--extension-id=<id>]
4
+ *
5
+ * Registers the native messaging host manifest so Chrome can find it.
6
+ * Also prints the Cursor MCP config.
7
+ *
8
+ * The extension ID is required. You can find it on chrome://extensions
9
+ * after loading the unpacked extension. Pass it via:
10
+ * --extension-id=<id> CLI flag
11
+ * BRMS_EXTENSION_ID=<id> environment variable
12
+ */
13
+ import { writeFileSync, mkdirSync, existsSync } from 'node:fs';
14
+ import { resolve, dirname } from 'node:path';
15
+ import { homedir, platform } from 'node:os';
16
+ import { fileURLToPath } from 'node:url';
17
+ const HOST_NAME = 'com.brms.host';
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const __dirname = dirname(__filename);
20
+ function parseExtensionId() {
21
+ for (const arg of process.argv) {
22
+ if (arg.startsWith('--extension-id=')) {
23
+ return arg.split('=')[1];
24
+ }
25
+ }
26
+ return process.env.BRMS_EXTENSION_ID || null;
27
+ }
28
+ function getManifestDir() {
29
+ const os = platform();
30
+ if (os === 'darwin') {
31
+ return resolve(homedir(), 'Library', 'Application Support', 'Google', 'Chrome', 'NativeMessagingHosts');
32
+ }
33
+ if (os === 'linux') {
34
+ return resolve(homedir(), '.config', 'google-chrome', 'NativeMessagingHosts');
35
+ }
36
+ if (os === 'win32') {
37
+ return resolve(homedir(), 'AppData', 'Roaming', 'brms');
38
+ }
39
+ throw new Error(`Unsupported OS: ${os}`);
40
+ }
41
+ function getHostEntrypoint() {
42
+ return resolve(__dirname, '..', 'index.js');
43
+ }
44
+ function install() {
45
+ const extensionId = parseExtensionId();
46
+ if (!extensionId) {
47
+ console.error('');
48
+ console.error(' Error: Extension ID is required.');
49
+ console.error('');
50
+ console.error(' 1. Load the BRMS extension in Chrome:');
51
+ console.error(' chrome://extensions → Enable Developer mode → Load unpacked');
52
+ console.error('');
53
+ console.error(' 2. Copy the extension ID from the extension card, then run:');
54
+ console.error('');
55
+ console.error(' npx brms-host install --extension-id=<your-extension-id>');
56
+ console.error('');
57
+ process.exit(1);
58
+ }
59
+ if (!/^[a-z]{32}$/.test(extensionId)) {
60
+ console.error(` Error: "${extensionId}" doesn't look like a valid Chrome extension ID.`);
61
+ console.error(' Extension IDs are 32 lowercase letters (e.g. llhnnmoopjffkkbbobjjkkcbhakngdek).');
62
+ process.exit(1);
63
+ }
64
+ const manifestDir = getManifestDir();
65
+ const hostPath = getHostEntrypoint();
66
+ if (!existsSync(manifestDir)) {
67
+ mkdirSync(manifestDir, { recursive: true });
68
+ }
69
+ const manifest = {
70
+ name: HOST_NAME,
71
+ description: 'BRMS Native Messaging Host — bridges Chrome Extension to MCP server',
72
+ path: hostPath,
73
+ type: 'stdio',
74
+ allowed_origins: [
75
+ `chrome-extension://${extensionId}/`,
76
+ ],
77
+ };
78
+ const os = platform();
79
+ if (os === 'darwin' || os === 'linux') {
80
+ const wrapperPath = resolve(manifestDir, 'brms-host');
81
+ const nodeExec = process.execPath;
82
+ writeFileSync(wrapperPath, `#!/bin/sh\nexec "${nodeExec}" "${hostPath}" "$@"\n`, { mode: 0o755 });
83
+ manifest.path = wrapperPath;
84
+ }
85
+ const manifestPath = resolve(manifestDir, `${HOST_NAME}.json`);
86
+ writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
87
+ if (os === 'win32') {
88
+ console.log('\n[brms] Windows detected. You may need to add a registry key:');
89
+ console.log(` HKCU\\Software\\Google\\Chrome\\NativeMessagingHosts\\${HOST_NAME}`);
90
+ console.log(` Value: ${manifestPath}\n`);
91
+ }
92
+ console.log('');
93
+ console.log(' BRMS Native Messaging Host installed successfully!');
94
+ console.log('');
95
+ console.log(` Extension ID: ${extensionId}`);
96
+ console.log(` Manifest: ${manifestPath}`);
97
+ console.log(` Host: ${manifest.path}`);
98
+ console.log('');
99
+ console.log(' Next step — add to your project\'s .cursor/mcp.json:');
100
+ console.log('');
101
+ console.log(' {');
102
+ console.log(' "mcpServers": {');
103
+ console.log(' "brms": {');
104
+ console.log(' "url": "http://localhost:3100/mcp"');
105
+ console.log(' }');
106
+ console.log(' }');
107
+ console.log(' }');
108
+ console.log('');
109
+ }
110
+ const cmd = process.argv[2];
111
+ if (cmd === 'install') {
112
+ install();
113
+ }
114
+ else {
115
+ console.log('Usage: brms-host install --extension-id=<id>');
116
+ console.log('');
117
+ console.log('Commands:');
118
+ console.log(' install Register the native messaging host for Chrome');
119
+ console.log('');
120
+ console.log('Options:');
121
+ console.log(' --extension-id=<id> Chrome extension ID (from chrome://extensions)');
122
+ process.exit(1);
123
+ }
124
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/bin/install.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Native Messaging bridge: communicates with the Chrome extension
3
+ * using Chrome's 4-byte little-endian length-prefixed JSON protocol
4
+ * over stdin/stdout.
5
+ */
6
+ type PushHandler = (payload: Record<string, unknown>) => void;
7
+ declare class NativeMessagingBridge {
8
+ private pending;
9
+ private pushHandlers;
10
+ private readBuffer;
11
+ private connected;
12
+ start(): void;
13
+ isConnected(): boolean;
14
+ /**
15
+ * Send a request to the extension and await the response.
16
+ */
17
+ sendRequest(type: string, payload?: Record<string, unknown>): Promise<Record<string, unknown>>;
18
+ /**
19
+ * Register a handler for push messages from the extension.
20
+ */
21
+ onPush(type: string, handler: PushHandler): void;
22
+ private write;
23
+ private drain;
24
+ private handleMessage;
25
+ }
26
+ export declare const bridge: NativeMessagingBridge;
27
+ export {};
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Native Messaging bridge: communicates with the Chrome extension
3
+ * using Chrome's 4-byte little-endian length-prefixed JSON protocol
4
+ * over stdin/stdout.
5
+ */
6
+ import { randomUUID } from 'node:crypto';
7
+ import { log } from '../utils/logger.js';
8
+ const REQUEST_TIMEOUT_MS = 30_000;
9
+ class NativeMessagingBridge {
10
+ pending = new Map();
11
+ pushHandlers = new Map();
12
+ readBuffer = Buffer.alloc(0);
13
+ connected = false;
14
+ start() {
15
+ if (this.connected)
16
+ return;
17
+ this.connected = true;
18
+ process.stdin.on('data', (chunk) => {
19
+ this.readBuffer = Buffer.concat([this.readBuffer, chunk]);
20
+ this.drain();
21
+ });
22
+ process.stdin.on('end', () => {
23
+ log.warn('Native messaging stdin closed');
24
+ this.connected = false;
25
+ for (const [, req] of this.pending) {
26
+ clearTimeout(req.timer);
27
+ req.reject(new Error('Extension disconnected'));
28
+ }
29
+ this.pending.clear();
30
+ });
31
+ log.info('Native messaging bridge started');
32
+ }
33
+ isConnected() {
34
+ return this.connected;
35
+ }
36
+ /**
37
+ * Send a request to the extension and await the response.
38
+ */
39
+ sendRequest(type, payload = {}) {
40
+ return new Promise((resolve, reject) => {
41
+ const id = randomUUID();
42
+ const timer = setTimeout(() => {
43
+ this.pending.delete(id);
44
+ reject(new Error(`Request ${type} timed out after ${REQUEST_TIMEOUT_MS}ms`));
45
+ }, REQUEST_TIMEOUT_MS);
46
+ this.pending.set(id, { resolve, reject, timer });
47
+ this.write({ id, kind: 'request', type, payload });
48
+ });
49
+ }
50
+ /**
51
+ * Register a handler for push messages from the extension.
52
+ */
53
+ onPush(type, handler) {
54
+ const handlers = this.pushHandlers.get(type) ?? [];
55
+ handlers.push(handler);
56
+ this.pushHandlers.set(type, handlers);
57
+ }
58
+ write(msg) {
59
+ const json = JSON.stringify(msg);
60
+ const body = Buffer.from(json, 'utf-8');
61
+ const header = Buffer.alloc(4);
62
+ header.writeUInt32LE(body.length, 0);
63
+ process.stdout.write(Buffer.concat([header, body]));
64
+ }
65
+ drain() {
66
+ while (this.readBuffer.length >= 4) {
67
+ const msgLen = this.readBuffer.readUInt32LE(0);
68
+ if (this.readBuffer.length < 4 + msgLen)
69
+ break;
70
+ const jsonBuf = this.readBuffer.subarray(4, 4 + msgLen);
71
+ this.readBuffer = this.readBuffer.subarray(4 + msgLen);
72
+ try {
73
+ const msg = JSON.parse(jsonBuf.toString('utf-8'));
74
+ this.handleMessage(msg);
75
+ }
76
+ catch (err) {
77
+ log.error('Failed to parse native message', err);
78
+ }
79
+ }
80
+ }
81
+ handleMessage(msg) {
82
+ const kind = msg.kind;
83
+ if (kind === 'response') {
84
+ const id = msg.id;
85
+ const pending = this.pending.get(id);
86
+ if (!pending)
87
+ return;
88
+ clearTimeout(pending.timer);
89
+ this.pending.delete(id);
90
+ if (msg.error) {
91
+ pending.reject(new Error(msg.error));
92
+ }
93
+ else {
94
+ pending.resolve((msg.payload ?? {}));
95
+ }
96
+ return;
97
+ }
98
+ if (kind === 'push') {
99
+ const type = msg.type;
100
+ const handlers = this.pushHandlers.get(type);
101
+ if (handlers) {
102
+ const payload = (msg.payload ?? {});
103
+ for (const h of handlers) {
104
+ try {
105
+ h(payload);
106
+ }
107
+ catch (err) {
108
+ log.error(`Push handler error (${type})`, err);
109
+ }
110
+ }
111
+ }
112
+ return;
113
+ }
114
+ log.warn('Unknown message kind:', kind);
115
+ }
116
+ }
117
+ export const bridge = new NativeMessagingBridge();
118
+ //# sourceMappingURL=native-messaging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native-messaging.js","sourceRoot":"","sources":["../../src/bridge/native-messaging.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { PageInfo } from '../types/index.js';
2
+ declare class BrowserManager {
3
+ private activeTabId;
4
+ private connected;
5
+ connect(): Promise<PageInfo[]>;
6
+ getPages(): Promise<PageInfo[]>;
7
+ selectPage(index: number): Promise<PageInfo>;
8
+ getActiveTabId(): number;
9
+ isConnected(): boolean;
10
+ }
11
+ export declare const browserManager: BrowserManager;
12
+ export {};
@@ -0,0 +1,57 @@
1
+ import { bridge } from '../bridge/native-messaging.js';
2
+ import { log } from '../utils/logger.js';
3
+ import { notConnected } from '../utils/errors.js';
4
+ class BrowserManager {
5
+ activeTabId = null;
6
+ connected = false;
7
+ async connect() {
8
+ if (!bridge.isConnected()) {
9
+ throw new Error('Native messaging bridge not connected. Ensure the BRMS Chrome Extension is running.');
10
+ }
11
+ const result = await bridge.sendRequest('list_tabs');
12
+ const tabs = (result.tabs ?? []);
13
+ if (tabs.length > 0) {
14
+ this.activeTabId = tabs[0].tabId;
15
+ await bridge.sendRequest('select_tab', { tabId: this.activeTabId });
16
+ }
17
+ this.connected = true;
18
+ log.info(`Connected via extension. Found ${tabs.length} tab(s)`);
19
+ return tabs.map((t, i) => ({
20
+ index: i,
21
+ title: t.title,
22
+ url: t.url,
23
+ }));
24
+ }
25
+ async getPages() {
26
+ if (!this.connected)
27
+ throw notConnected();
28
+ const result = await bridge.sendRequest('list_tabs');
29
+ const tabs = (result.tabs ?? []);
30
+ return tabs.map((t, i) => ({
31
+ index: i,
32
+ title: t.title,
33
+ url: t.url,
34
+ }));
35
+ }
36
+ async selectPage(index) {
37
+ if (!this.connected)
38
+ throw notConnected();
39
+ const result = await bridge.sendRequest('select_tab', { index });
40
+ this.activeTabId = result.tabId;
41
+ log.info(`Selected tab ${index}: ${result.url}`);
42
+ return { index, title: result.title, url: result.url };
43
+ }
44
+ getActiveTabId() {
45
+ if (!this.connected)
46
+ throw notConnected();
47
+ if (this.activeTabId === null) {
48
+ throw new Error('No active tab selected. Call select_page first.');
49
+ }
50
+ return this.activeTabId;
51
+ }
52
+ isConnected() {
53
+ return this.connected && bridge.isConnected();
54
+ }
55
+ }
56
+ export const browserManager = new BrowserManager();
57
+ //# sourceMappingURL=connection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/browser/connection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { ConsoleEntry } from '../types/index.js';
2
+ type ConsoleLevel = ConsoleEntry['level'];
3
+ declare class ConsoleCapture {
4
+ private entries;
5
+ private listening;
6
+ /**
7
+ * Start listening for console_entry push messages from the extension.
8
+ */
9
+ attach(): void;
10
+ getEntries(level?: ConsoleLevel, limit?: number): ConsoleEntry[];
11
+ getErrors(limit?: number): ConsoleEntry[];
12
+ clear(): void;
13
+ private push;
14
+ }
15
+ export declare const consoleCapture: ConsoleCapture;
16
+ export {};
@@ -0,0 +1,44 @@
1
+ import { bridge } from '../bridge/native-messaging.js';
2
+ import { log } from '../utils/logger.js';
3
+ const MAX_BUFFER = 200;
4
+ class ConsoleCapture {
5
+ entries = [];
6
+ listening = false;
7
+ /**
8
+ * Start listening for console_entry push messages from the extension.
9
+ */
10
+ attach() {
11
+ if (this.listening)
12
+ return;
13
+ this.listening = true;
14
+ this.entries = [];
15
+ bridge.onPush('console_entry', (payload) => {
16
+ this.push(payload);
17
+ });
18
+ log.info('Console capture attached (push-based)');
19
+ }
20
+ getEntries(level, limit) {
21
+ let results = [...this.entries];
22
+ if (level) {
23
+ results = results.filter((e) => e.level === level);
24
+ }
25
+ if (limit !== undefined) {
26
+ results = results.slice(-limit);
27
+ }
28
+ return results;
29
+ }
30
+ getErrors(limit) {
31
+ return this.getEntries('error', limit);
32
+ }
33
+ clear() {
34
+ this.entries = [];
35
+ }
36
+ push(entry) {
37
+ this.entries.push(entry);
38
+ if (this.entries.length > MAX_BUFFER) {
39
+ this.entries.shift();
40
+ }
41
+ }
42
+ }
43
+ export const consoleCapture = new ConsoleCapture();
44
+ //# sourceMappingURL=console.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.js","sourceRoot":"","sources":["../../src/browser/console.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAEzC,MAAM,UAAU,GAAG,GAAG,CAAC;AAIvB,MAAM,cAAc;IACV,OAAO,GAAmB,EAAE,CAAC;IAC7B,SAAS,GAAG,KAAK,CAAC;IAE1B;;OAEG;IACH,MAAM;QACJ,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAElB,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,OAAO,EAAE,EAAE;YACzC,IAAI,CAAC,IAAI,CAAC,OAAkC,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;IACpD,CAAC;IAED,UAAU,CAAC,KAAoB,EAAE,KAAc;QAC7C,IAAI,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;QAEhC,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;QACrD,CAAC;QAED,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;QAClC,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,SAAS,CAAC,KAAc;QACtB,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACzC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACpB,CAAC;IAEO,IAAI,CAAC,KAAmB;QAC9B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;YACrC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;IACH,CAAC;CACF;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { DOMNode } from '../types/index.js';
2
+ export declare function getSnapshot(selector?: string, maxDepth?: number, maxNodes?: number): Promise<DOMNode | DOMNode[]>;
3
+ export declare function queryDOM(selector: string): Promise<Array<{
4
+ tag: string;
5
+ id: string;
6
+ classes: string[];
7
+ text: string;
8
+ attributes: Record<string, string>;
9
+ }>>;
@@ -0,0 +1,16 @@
1
+ import { bridge } from '../bridge/native-messaging.js';
2
+ const DEFAULT_DEPTH = 10;
3
+ const DEFAULT_MAX_NODES = 1000;
4
+ export async function getSnapshot(selector, maxDepth = DEFAULT_DEPTH, maxNodes = DEFAULT_MAX_NODES) {
5
+ const result = await bridge.sendRequest('dom_snapshot', {
6
+ selector: selector ?? null,
7
+ depth: maxDepth,
8
+ maxNodes,
9
+ });
10
+ return result.tree;
11
+ }
12
+ export async function queryDOM(selector) {
13
+ const result = await bridge.sendRequest('dom_query', { selector });
14
+ return (result.elements ?? []);
15
+ }
16
+ //# sourceMappingURL=dom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/browser/dom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAGvD,MAAM,aAAa,GAAG,EAAE,CAAC;AACzB,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAE/B,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,QAAiB,EACjB,WAAmB,aAAa,EAChC,WAAmB,iBAAiB;IAEpC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,cAAc,EAAE;QACtD,QAAQ,EAAE,QAAQ,IAAI,IAAI;QAC1B,KAAK,EAAE,QAAQ;QACf,QAAQ;KACT,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,IAA2B,CAAC;AAC5C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,QAAgB;IAEhB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IACnE,OAAO,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAA4G,CAAC;AAC5I,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { NetworkEntry, NetworkFilter } from '../types/index.js';
2
+ declare class NetworkMonitor {
3
+ private entries;
4
+ private listening;
5
+ /**
6
+ * Start listening for network_entry push messages from the extension.
7
+ */
8
+ attach(): void;
9
+ getEntries(filter?: NetworkFilter): NetworkEntry[];
10
+ clear(): void;
11
+ private pushEntry;
12
+ }
13
+ export declare const networkMonitor: NetworkMonitor;
14
+ export {};
@@ -0,0 +1,47 @@
1
+ import { bridge } from '../bridge/native-messaging.js';
2
+ import { log } from '../utils/logger.js';
3
+ const MAX_BUFFER = 500;
4
+ class NetworkMonitor {
5
+ entries = [];
6
+ listening = false;
7
+ /**
8
+ * Start listening for network_entry push messages from the extension.
9
+ */
10
+ attach() {
11
+ if (this.listening)
12
+ return;
13
+ this.listening = true;
14
+ this.entries = [];
15
+ bridge.onPush('network_entry', (payload) => {
16
+ this.pushEntry(payload);
17
+ });
18
+ log.info('Network monitor attached (push-based)');
19
+ }
20
+ getEntries(filter) {
21
+ let results = [...this.entries];
22
+ if (filter?.urlPattern) {
23
+ const re = new RegExp(filter.urlPattern, 'i');
24
+ results = results.filter((e) => re.test(e.url));
25
+ }
26
+ if (filter?.statusCode !== undefined) {
27
+ results = results.filter((e) => e.status === filter.statusCode);
28
+ }
29
+ if (filter?.resourceType) {
30
+ const rt = filter.resourceType.toLowerCase();
31
+ results = results.filter((e) => e.resourceType.toLowerCase() === rt);
32
+ }
33
+ const limit = filter?.limit ?? results.length;
34
+ return results.slice(-limit);
35
+ }
36
+ clear() {
37
+ this.entries = [];
38
+ }
39
+ pushEntry(entry) {
40
+ this.entries.push(entry);
41
+ if (this.entries.length > MAX_BUFFER) {
42
+ this.entries.shift();
43
+ }
44
+ }
45
+ }
46
+ export const networkMonitor = new NetworkMonitor();
47
+ //# sourceMappingURL=network.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/browser/network.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AACvD,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAEzC,MAAM,UAAU,GAAG,GAAG,CAAC;AAEvB,MAAM,cAAc;IACV,OAAO,GAAmB,EAAE,CAAC;IAC7B,SAAS,GAAG,KAAK,CAAC;IAE1B;;OAEG;IACH,MAAM;QACJ,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAElB,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,OAAO,EAAE,EAAE;YACzC,IAAI,CAAC,SAAS,CAAC,OAAkC,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;IACpD,CAAC;IAED,UAAU,CAAC,MAAsB;QAC/B,IAAI,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;QAEhC,IAAI,MAAM,EAAE,UAAU,EAAE,CAAC;YACvB,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;YAC9C,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAClD,CAAC;QACD,IAAI,MAAM,EAAE,UAAU,KAAK,SAAS,EAAE,CAAC;YACrC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,UAAU,CAAC,CAAC;QAClE,CAAC;QACD,IAAI,MAAM,EAAE,YAAY,EAAE,CAAC;YACzB,MAAM,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC;YAC7C,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;QACvE,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,EAAE,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;QAC9C,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACpB,CAAC;IAEO,SAAS,CAAC,KAAmB;QACnC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;YACrC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;IACH,CAAC;CACF;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC"}
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * BRMS Host entry point.
4
+ *
5
+ * - Starts an HTTP server on port 3100 exposing MCP via Streamable HTTP
6
+ * - Starts the native messaging bridge to communicate with the Chrome extension
7
+ */
8
+ export {};