@jobshimo/browser-link 0.1.0 → 0.4.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.
- package/README.md +58 -21
- package/dist/bridge/client.d.ts +101 -0
- package/dist/bridge/client.js +435 -0
- package/dist/bridge/client.js.map +1 -0
- package/dist/bridge/dispatch.d.ts +29 -0
- package/dist/bridge/dispatch.js +39 -0
- package/dist/bridge/dispatch.js.map +1 -0
- package/dist/bridge/events.d.ts +39 -0
- package/dist/bridge/events.js +47 -0
- package/dist/bridge/events.js.map +1 -0
- package/dist/bridge/protocol.d.ts +80 -0
- package/dist/bridge/protocol.js +79 -0
- package/dist/bridge/protocol.js.map +1 -0
- package/dist/bridge/server.d.ts +42 -0
- package/dist/bridge/server.js +336 -0
- package/dist/bridge/server.js.map +1 -0
- package/dist/bridge/token.d.ts +17 -0
- package/dist/bridge/token.js +79 -0
- package/dist/bridge/token.js.map +1 -0
- package/dist/cli.js +132 -39
- package/dist/cli.js.map +1 -1
- package/dist/commands/about.d.ts +3 -6
- package/dist/commands/about.js +2 -18
- package/dist/commands/about.js.map +1 -1
- package/dist/commands/doctor.d.ts +12 -1
- package/dist/commands/doctor.js +90 -20
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/extension.d.ts +3 -2
- package/dist/commands/extension.js +53 -28
- package/dist/commands/extension.js.map +1 -1
- package/dist/commands/multi-agent.d.ts +7 -0
- package/dist/commands/multi-agent.js +109 -0
- package/dist/commands/multi-agent.js.map +1 -0
- package/dist/commands/tools.d.ts +11 -0
- package/dist/commands/tools.js +168 -0
- package/dist/commands/tools.js.map +1 -0
- package/dist/commands/updates.d.ts +20 -0
- package/dist/commands/updates.js +100 -0
- package/dist/commands/updates.js.map +1 -0
- package/dist/commands/welcome.d.ts +2 -1
- package/dist/commands/welcome.js +11 -47
- package/dist/commands/welcome.js.map +1 -1
- package/dist/config.d.ts +25 -3
- package/dist/config.js +35 -2
- package/dist/config.js.map +1 -1
- package/dist/installers/copilot.d.ts +2 -0
- package/dist/installers/copilot.js +72 -0
- package/dist/installers/copilot.js.map +1 -0
- package/dist/installers/index.js +2 -1
- package/dist/installers/index.js.map +1 -1
- package/dist/installers/types.d.ts +1 -1
- package/dist/messages.d.ts +7 -0
- package/dist/permissions.d.ts +37 -0
- package/dist/permissions.js +156 -0
- package/dist/permissions.js.map +1 -0
- package/dist/server.d.ts +7 -3
- package/dist/server.js +160 -32
- package/dist/server.js.map +1 -1
- package/dist/tools/browser-definitions.js +18 -0
- package/dist/tools/browser-definitions.js.map +1 -1
- package/dist/tools/browser-dispatch.d.ts +7 -0
- package/dist/tools/browser-dispatch.js +11 -0
- package/dist/tools/browser-dispatch.js.map +1 -1
- package/dist/tools/server-instructions.d.ts +1 -1
- package/dist/tools/server-instructions.js +4 -0
- package/dist/tools/server-instructions.js.map +1 -1
- package/dist/ui/app.d.ts +7 -0
- package/dist/ui/app.js +77 -0
- package/dist/ui/app.js.map +1 -0
- package/dist/ui/components.d.ts +18 -0
- package/dist/ui/components.js +27 -0
- package/dist/ui/components.js.map +1 -0
- package/dist/ui/screens.d.ts +61 -0
- package/dist/ui/screens.js +603 -0
- package/dist/ui/screens.js.map +1 -0
- package/dist/ui/start.d.ts +6 -0
- package/dist/ui/start.js +19 -0
- package/dist/ui/start.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +15 -0
- package/dist/version.js.map +1 -0
- package/package.json +10 -4
- package/dist/commands/menu.d.ts +0 -25
- package/dist/commands/menu.js +0 -167
- package/dist/commands/menu.js.map +0 -1
package/dist/commands/welcome.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/* Welcome screen strings (English / Spanish) shared by the interactive Ink
|
|
2
|
+
* Welcome view and any future non-interactive caller. No runtime logic here
|
|
3
|
+
* — every screen consumes this as a pure data module. */
|
|
3
4
|
export const I18N_WELCOME = {
|
|
4
5
|
en: {
|
|
5
6
|
title: 'browser-link',
|
|
6
7
|
aboutTitle: 'What this is',
|
|
7
8
|
about: [
|
|
8
9
|
'An MCP server that opens a small WebSocket bridge between an MCP',
|
|
9
|
-
'client (Claude Code, OpenCode, …) and the Google
|
|
10
|
-
'explicitly grant access to through a custom companion
|
|
11
|
-
'load locally.',
|
|
10
|
+
'client (Claude Code, OpenCode, GitHub Copilot CLI…) and the Google',
|
|
11
|
+
'Chrome tabs you explicitly grant access to through a custom companion',
|
|
12
|
+
'extension you load locally.',
|
|
12
13
|
].join('\n'),
|
|
13
14
|
capabilitiesTitle: 'What the agent can do on a connected tab',
|
|
14
15
|
capabilities: [
|
|
@@ -22,7 +23,7 @@ export const I18N_WELCOME = {
|
|
|
22
23
|
'about each app across sessions in a local SQLite map (selectors,',
|
|
23
24
|
'flows, gotchas — never uploaded anywhere).',
|
|
24
25
|
].join('\n'),
|
|
25
|
-
warningTitle: '
|
|
26
|
+
warningTitle: 'Read this before you continue',
|
|
26
27
|
warning: [
|
|
27
28
|
'Connecting a tab gives the agent access to whatever is on it — any',
|
|
28
29
|
'logged-in session, saved card, wallet, banking page, work console or',
|
|
@@ -51,9 +52,9 @@ export const I18N_WELCOME = {
|
|
|
51
52
|
aboutTitle: 'Qué es esto',
|
|
52
53
|
about: [
|
|
53
54
|
'Un servidor MCP que abre un puente WebSocket entre un cliente MCP',
|
|
54
|
-
'(Claude Code, OpenCode, …) y las pestañas de Google
|
|
55
|
-
'vos le des acceso explícito a través de una extensión
|
|
56
|
-
'manualmente.',
|
|
55
|
+
'(Claude Code, OpenCode, GitHub Copilot CLI…) y las pestañas de Google',
|
|
56
|
+
'Chrome a las que vos le des acceso explícito a través de una extensión',
|
|
57
|
+
'que cargás vos manualmente.',
|
|
57
58
|
].join('\n'),
|
|
58
59
|
capabilitiesTitle: 'Qué puede hacer el agente en una pestaña conectada',
|
|
59
60
|
capabilities: [
|
|
@@ -67,7 +68,7 @@ export const I18N_WELCOME = {
|
|
|
67
68
|
'aprende de cada app entre sesiones en un mapa SQLite local (selectores,',
|
|
68
69
|
'flujos, gotchas — nunca se sube a ningún lado).',
|
|
69
70
|
].join('\n'),
|
|
70
|
-
warningTitle: '
|
|
71
|
+
warningTitle: 'Leelo antes de continuar',
|
|
71
72
|
warning: [
|
|
72
73
|
'Conectar una pestaña le da al agente acceso a todo lo que esté en esa',
|
|
73
74
|
'pestaña: sesiones iniciadas, tarjetas guardadas, wallets, banca,',
|
|
@@ -94,41 +95,4 @@ export const I18N_WELCOME = {
|
|
|
94
95
|
},
|
|
95
96
|
},
|
|
96
97
|
};
|
|
97
|
-
export async function runWelcome(opts = {}) {
|
|
98
|
-
let lang = opts.initial ?? 'en';
|
|
99
|
-
const hideDismiss = opts.hideDismiss === true;
|
|
100
|
-
while (true) {
|
|
101
|
-
const t = I18N_WELCOME[lang];
|
|
102
|
-
p.intro(t.title);
|
|
103
|
-
p.note(t.about, t.aboutTitle);
|
|
104
|
-
p.note(t.capabilities, t.capabilitiesTitle);
|
|
105
|
-
p.note(t.warning, t.warningTitle);
|
|
106
|
-
p.note(`${t.responsibility}\n\n${t.extensionNote}`);
|
|
107
|
-
const options = [
|
|
108
|
-
{ value: 'accept', label: t.options.accept },
|
|
109
|
-
];
|
|
110
|
-
if (!hideDismiss)
|
|
111
|
-
options.push({ value: 'dismiss', label: t.options.dismiss });
|
|
112
|
-
options.push({ value: 'swap', label: t.options.swap }, { value: 'quit', label: t.options.quit });
|
|
113
|
-
const choice = (await p.select({
|
|
114
|
-
message: t.prompt,
|
|
115
|
-
options,
|
|
116
|
-
initialValue: 'accept',
|
|
117
|
-
}));
|
|
118
|
-
if (p.isCancel(choice) || choice === 'quit') {
|
|
119
|
-
p.cancel(lang === 'es' ? 'Cancelado.' : 'Cancelled.');
|
|
120
|
-
return { action: 'quit', language: lang, persisted: false };
|
|
121
|
-
}
|
|
122
|
-
if (choice === 'swap') {
|
|
123
|
-
lang = lang === 'en' ? 'es' : 'en';
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
if (choice === 'dismiss') {
|
|
127
|
-
saveConfig({ skipWelcome: true, language: lang });
|
|
128
|
-
return { action: 'continue', language: lang, persisted: true };
|
|
129
|
-
}
|
|
130
|
-
// accept
|
|
131
|
-
return { action: 'continue', language: lang, persisted: false };
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
98
|
//# sourceMappingURL=welcome.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"welcome.js","sourceRoot":"","sources":["../../src/commands/welcome.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"welcome.js","sourceRoot":"","sources":["../../src/commands/welcome.ts"],"names":[],"mappings":"AAAA;;yDAEyD;AAkCzD,MAAM,CAAC,MAAM,YAAY,GAA2B;IAClD,EAAE,EAAE;QACF,KAAK,EAAE,cAAc;QACrB,UAAU,EAAE,cAAc;QAC1B,KAAK,EAAE;YACL,kEAAkE;YAClE,oEAAoE;YACpE,uEAAuE;YACvE,6BAA6B;SAC9B,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,iBAAiB,EAAE,0CAA0C;QAC7D,YAAY,EAAE;YACZ,gCAAgC;YAChC,6CAA6C;YAC7C,oCAAoC;YACpC,oDAAoD;YACpD,EAAE;YACF,oEAAoE;YACpE,uEAAuE;YACvE,kEAAkE;YAClE,4CAA4C;SAC7C,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,YAAY,EAAE,+BAA+B;QAC7C,OAAO,EAAE;YACP,oEAAoE;YACpE,sEAAsE;YACtE,2DAA2D;YAC3D,EAAE;YACF,uEAAuE;YACvE,wEAAwE;YACxE,qEAAqE;YACrE,EAAE;YACF,uEAAuE;YACvE,uEAAuE;YACvE,4BAA4B;SAC7B,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,cAAc,EACZ,iLAAiL;QACnL,aAAa,EACX,yLAAyL;QAC3L,MAAM,EAAE,6BAA6B;QACrC,OAAO,EAAE;YACP,MAAM,EAAE,wBAAwB;YAChC,OAAO,EAAE,6BAA6B;YACtC,IAAI,EAAE,mBAAmB;YACzB,IAAI,EAAE,MAAM;SACb;KACF;IACD,EAAE,EAAE;QACF,KAAK,EAAE,cAAc;QACrB,UAAU,EAAE,aAAa;QACzB,KAAK,EAAE;YACL,mEAAmE;YACnE,uEAAuE;YACvE,wEAAwE;YACxE,6BAA6B;SAC9B,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,iBAAiB,EAAE,oDAAoD;QACvE,YAAY,EAAE;YACZ,uCAAuC;YACvC,+CAA+C;YAC/C,2CAA2C;YAC3C,8DAA8D;YAC9D,EAAE;YACF,qEAAqE;YACrE,uEAAuE;YACvE,yEAAyE;YACzE,iDAAiD;SAClD,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,YAAY,EAAE,0BAA0B;QACxC,OAAO,EAAE;YACP,uEAAuE;YACvE,kEAAkE;YAClE,qEAAqE;YACrE,wCAAwC;YACxC,EAAE;YACF,iEAAiE;YACjE,4DAA4D;YAC5D,qEAAqE;YACrE,oCAAoC;YACpC,EAAE;YACF,oEAAoE;YACpE,uEAAuE;YACvE,4BAA4B;SAC7B,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,cAAc,EACZ,oMAAoM;QACtM,aAAa,EACX,qNAAqN;QACvN,MAAM,EAAE,sBAAsB;QAC9B,OAAO,EAAE;YACP,MAAM,EAAE,sBAAsB;YAC9B,OAAO,EAAE,+BAA+B;YACxC,IAAI,EAAE,mBAAmB;YACzB,IAAI,EAAE,OAAO;SACd;KACF;CACF,CAAC"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,11 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Small per-user config persisted next to the map DB.
|
|
3
|
-
*
|
|
4
|
-
* No domain data ever lives here.
|
|
2
|
+
* Small per-user config persisted next to the map DB. UX preferences and
|
|
3
|
+
* the tool-access deny list — never any domain data.
|
|
5
4
|
*/
|
|
6
5
|
export interface BrowserLinkConfig {
|
|
7
6
|
skipWelcome?: boolean;
|
|
8
7
|
language?: 'en' | 'es';
|
|
8
|
+
/**
|
|
9
|
+
* Tool names the MCP server must not expose. Empty / undefined means
|
|
10
|
+
* "everything enabled" (default, backwards-compatible). Unknown names
|
|
11
|
+
* are dropped silently by sanitizeDisabledTools so old configs survive
|
|
12
|
+
* tool renames or removals.
|
|
13
|
+
*/
|
|
14
|
+
disabledTools?: string[];
|
|
15
|
+
/**
|
|
16
|
+
* Multi-agent mode. When false (default), only one MCP client can have
|
|
17
|
+
* browser-link active at a time; a second client trying to spawn the
|
|
18
|
+
* server crashes with EADDRINUSE. When true, the second instance becomes
|
|
19
|
+
* a proxy that forwards MCP requests to the first one over an internal
|
|
20
|
+
* IPC port (127.0.0.1:17530). All agents end up sharing the same Chrome
|
|
21
|
+
* tabs and the same persistent UI map.
|
|
22
|
+
*/
|
|
23
|
+
multiAgent?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Only honoured when multiAgent === true. When false (default), if the
|
|
26
|
+
* primary's MCP client closes, secondary clients lose the bridge and
|
|
27
|
+
* have to be relaunched manually. When true, one of the secondaries
|
|
28
|
+
* takes over the primary role automatically (race on bind(17529)).
|
|
29
|
+
*/
|
|
30
|
+
autoReelect?: boolean;
|
|
9
31
|
}
|
|
10
32
|
export declare function loadConfig(): BrowserLinkConfig;
|
|
11
33
|
export declare function saveConfig(patch: Partial<BrowserLinkConfig>): BrowserLinkConfig;
|
package/dist/config.js
CHANGED
|
@@ -1,9 +1,42 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { dirname, join } from 'node:path';
|
|
3
3
|
import { getDataDir } from './map/paths.js';
|
|
4
|
+
import { sanitizeDisabledTools } from './permissions.js';
|
|
4
5
|
function configFile() {
|
|
5
6
|
return join(getDataDir(), 'config.json');
|
|
6
7
|
}
|
|
8
|
+
function normalise(cfg) {
|
|
9
|
+
// Always run the disabled-tools list through the sanitizer — both on read
|
|
10
|
+
// and on write — so unknown names from a downgraded build, a typo, or a
|
|
11
|
+
// manual edit never reach the server filter.
|
|
12
|
+
const sanitized = sanitizeDisabledTools(cfg.disabledTools);
|
|
13
|
+
let next;
|
|
14
|
+
if (sanitized.length === 0) {
|
|
15
|
+
const { disabledTools: _omit, ...rest } = cfg;
|
|
16
|
+
next = rest;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
next = { ...cfg, disabledTools: sanitized };
|
|
20
|
+
}
|
|
21
|
+
// autoReelect only makes sense when multiAgent is on. Drop a stray
|
|
22
|
+
// autoReelect:true if multiAgent is off, so the config file never has
|
|
23
|
+
// an inert flag advertising a behaviour it does not produce.
|
|
24
|
+
if (next.autoReelect && !next.multiAgent) {
|
|
25
|
+
const { autoReelect: _omit2, ...rest2 } = next;
|
|
26
|
+
next = rest2;
|
|
27
|
+
}
|
|
28
|
+
// Drop explicit `false` for the two new flags too — the default is false,
|
|
29
|
+
// so storing it just adds noise.
|
|
30
|
+
if (next.multiAgent === false) {
|
|
31
|
+
const { multiAgent: _omit3, ...rest3 } = next;
|
|
32
|
+
next = rest3;
|
|
33
|
+
}
|
|
34
|
+
if (next.autoReelect === false) {
|
|
35
|
+
const { autoReelect: _omit4, ...rest4 } = next;
|
|
36
|
+
next = rest4;
|
|
37
|
+
}
|
|
38
|
+
return next;
|
|
39
|
+
}
|
|
7
40
|
export function loadConfig() {
|
|
8
41
|
const path = configFile();
|
|
9
42
|
if (!existsSync(path))
|
|
@@ -12,7 +45,7 @@ export function loadConfig() {
|
|
|
12
45
|
const raw = readFileSync(path, 'utf8');
|
|
13
46
|
const parsed = JSON.parse(raw);
|
|
14
47
|
if (parsed && typeof parsed === 'object')
|
|
15
|
-
return parsed;
|
|
48
|
+
return normalise(parsed);
|
|
16
49
|
return {};
|
|
17
50
|
}
|
|
18
51
|
catch (err) {
|
|
@@ -28,7 +61,7 @@ export function saveConfig(patch) {
|
|
|
28
61
|
const path = configFile();
|
|
29
62
|
mkdirSync(dirname(path), { recursive: true });
|
|
30
63
|
const current = loadConfig();
|
|
31
|
-
const next = { ...current, ...patch };
|
|
64
|
+
const next = normalise({ ...current, ...patch });
|
|
32
65
|
writeFileSync(path, JSON.stringify(next, null, 2) + '\n', 'utf8');
|
|
33
66
|
return next;
|
|
34
67
|
}
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
const SERVER_NAME = 'browser-link';
|
|
5
|
+
function configFile() {
|
|
6
|
+
// GitHub Copilot CLI reads from ~/.copilot/mcp-config.json by default.
|
|
7
|
+
// COPILOT_HOME overrides the directory (the same env var the CLI honours).
|
|
8
|
+
const root = process.env.COPILOT_HOME ?? join(homedir(), '.copilot');
|
|
9
|
+
return join(root, 'mcp-config.json');
|
|
10
|
+
}
|
|
11
|
+
function readConfig(path) {
|
|
12
|
+
if (!existsSync(path))
|
|
13
|
+
return {};
|
|
14
|
+
try {
|
|
15
|
+
return JSON.parse(readFileSync(path, 'utf8'));
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
throw new Error(`Could not parse Copilot config at ${path}. Fix the file or delete it.`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function writeConfig(path, cfg) {
|
|
22
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
23
|
+
writeFileSync(path, JSON.stringify(cfg, null, 2) + '\n', 'utf8');
|
|
24
|
+
}
|
|
25
|
+
function isRegistered(cfg) {
|
|
26
|
+
return !!cfg.mcpServers?.[SERVER_NAME];
|
|
27
|
+
}
|
|
28
|
+
export const copilotInstaller = {
|
|
29
|
+
id: 'copilot',
|
|
30
|
+
displayName: 'GitHub Copilot CLI',
|
|
31
|
+
configPath() {
|
|
32
|
+
return configFile();
|
|
33
|
+
},
|
|
34
|
+
detect() {
|
|
35
|
+
const path = configFile();
|
|
36
|
+
if (!existsSync(path)) {
|
|
37
|
+
return { installed: false, registered: false, configPath: path };
|
|
38
|
+
}
|
|
39
|
+
const cfg = readConfig(path);
|
|
40
|
+
return { installed: true, registered: isRegistered(cfg), configPath: path };
|
|
41
|
+
},
|
|
42
|
+
install(command, args) {
|
|
43
|
+
const path = configFile();
|
|
44
|
+
const cfg = readConfig(path);
|
|
45
|
+
cfg.mcpServers = cfg.mcpServers ?? {};
|
|
46
|
+
const existing = cfg.mcpServers[SERVER_NAME];
|
|
47
|
+
// Copilot requires `env` and `tools` even when empty/wildcard.
|
|
48
|
+
cfg.mcpServers[SERVER_NAME] = {
|
|
49
|
+
type: 'local',
|
|
50
|
+
command,
|
|
51
|
+
args,
|
|
52
|
+
env: {},
|
|
53
|
+
tools: ['*'],
|
|
54
|
+
};
|
|
55
|
+
writeConfig(path, cfg);
|
|
56
|
+
return existing
|
|
57
|
+
? `Updated ${SERVER_NAME} entry in ${path}.`
|
|
58
|
+
: `Added ${SERVER_NAME} entry to ${path}.`;
|
|
59
|
+
},
|
|
60
|
+
uninstall() {
|
|
61
|
+
const path = configFile();
|
|
62
|
+
if (!existsSync(path))
|
|
63
|
+
return `No Copilot CLI config at ${path}; nothing to remove.`;
|
|
64
|
+
const cfg = readConfig(path);
|
|
65
|
+
if (!cfg.mcpServers?.[SERVER_NAME])
|
|
66
|
+
return `${SERVER_NAME} was not registered in ${path}.`;
|
|
67
|
+
delete cfg.mcpServers[SERVER_NAME];
|
|
68
|
+
writeConfig(path, cfg);
|
|
69
|
+
return `Removed ${SERVER_NAME} entry from ${path}.`;
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=copilot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilot.js","sourceRoot":"","sources":["../../src/installers/copilot.ts"],"names":[],"mappings":"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"}
|
package/dist/installers/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { claudeInstaller } from './claude.js';
|
|
2
|
+
import { copilotInstaller } from './copilot.js';
|
|
2
3
|
import { opencodeInstaller } from './opencode.js';
|
|
3
4
|
/**
|
|
4
5
|
* Installers wired into the CLI surface (`install`, `install --client X`,
|
|
5
6
|
* the interactive menu, and `doctor`). Order here is the display order.
|
|
6
7
|
*/
|
|
7
|
-
export const INSTALLERS = [claudeInstaller, opencodeInstaller];
|
|
8
|
+
export const INSTALLERS = [claudeInstaller, opencodeInstaller, copilotInstaller];
|
|
8
9
|
export function getInstaller(id) {
|
|
9
10
|
const found = INSTALLERS.find((i) => i.id === id);
|
|
10
11
|
if (!found)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/installers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGlD;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAgB,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/installers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGlD;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAgB,CAAC,eAAe,EAAE,iBAAiB,EAAE,gBAAgB,CAAC,CAAC;AAE9F,MAAM,UAAU,YAAY,CAAC,EAAY;IACvC,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAClD,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,EAAE,EAAE,CAAC,CAAC;IACpE,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/dist/messages.d.ts
CHANGED
|
@@ -9,6 +9,13 @@ export type TabId = string;
|
|
|
9
9
|
export interface TabRegisterPayload {
|
|
10
10
|
url: string;
|
|
11
11
|
title: string;
|
|
12
|
+
/**
|
|
13
|
+
* Optional. The browser-link tab_id this Chrome tab last had, as
|
|
14
|
+
* remembered by the extension across primary swaps. The primary honours
|
|
15
|
+
* it if free; otherwise it assigns a new id and emits a `tab-renamed`
|
|
16
|
+
* event the agent can pick up via the `browser.events` tool.
|
|
17
|
+
*/
|
|
18
|
+
previousTabId?: TabId;
|
|
12
19
|
}
|
|
13
20
|
export interface TabRegisteredPayload {
|
|
14
21
|
tabId: TabId;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool access control — single source of truth for which MCP tools
|
|
3
|
+
* browser-link exposes and how the user can narrow that down.
|
|
4
|
+
*
|
|
5
|
+
* The runtime answer to "is this tool allowed?" is computed from the
|
|
6
|
+
* `disabledTools` list in `config.json` (default: empty = everything
|
|
7
|
+
* allowed). The catalogue below adds human-readable metadata used by
|
|
8
|
+
* the UI and the CLI subcommand — it never affects what the MCP server
|
|
9
|
+
* returns by itself.
|
|
10
|
+
*/
|
|
11
|
+
export type ToolFamily = 'bridge' | 'map';
|
|
12
|
+
/** Coarse-grained behaviour bucket — used by presets, not by the runtime
|
|
13
|
+
* filter. The runtime only cares about the exact tool name. */
|
|
14
|
+
export type ToolCategory = 'read' | 'action' | 'eval' | 'map-read' | 'map-write';
|
|
15
|
+
export interface ToolMeta {
|
|
16
|
+
name: string;
|
|
17
|
+
family: ToolFamily;
|
|
18
|
+
category: ToolCategory;
|
|
19
|
+
summary: string;
|
|
20
|
+
}
|
|
21
|
+
export declare const TOOL_CATALOGUE: readonly ToolMeta[];
|
|
22
|
+
export type PresetId = 'all' | 'readonly' | 'no-eval' | 'no-map';
|
|
23
|
+
export interface PresetDef {
|
|
24
|
+
id: PresetId;
|
|
25
|
+
label: string;
|
|
26
|
+
/** Which tool names this preset disables. */
|
|
27
|
+
disabled: readonly string[];
|
|
28
|
+
}
|
|
29
|
+
export declare const PRESETS: readonly PresetDef[];
|
|
30
|
+
/** True when the tool should be exposed in tools/list and accepted in tools/call. */
|
|
31
|
+
export declare function isToolEnabled(name: string, disabled: readonly string[] | undefined): boolean;
|
|
32
|
+
/** Drop entries that don't match any current tool, dedupe, and sort. Used
|
|
33
|
+
* before writing the list to disk and after reading it back, so unknown
|
|
34
|
+
* names from older or newer versions never poison the runtime. */
|
|
35
|
+
export declare function sanitizeDisabledTools(input: readonly string[] | undefined): string[];
|
|
36
|
+
export declare function getPreset(id: PresetId): PresetDef;
|
|
37
|
+
export declare function isKnownTool(name: string): boolean;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool access control — single source of truth for which MCP tools
|
|
3
|
+
* browser-link exposes and how the user can narrow that down.
|
|
4
|
+
*
|
|
5
|
+
* The runtime answer to "is this tool allowed?" is computed from the
|
|
6
|
+
* `disabledTools` list in `config.json` (default: empty = everything
|
|
7
|
+
* allowed). The catalogue below adds human-readable metadata used by
|
|
8
|
+
* the UI and the CLI subcommand — it never affects what the MCP server
|
|
9
|
+
* returns by itself.
|
|
10
|
+
*/
|
|
11
|
+
export const TOOL_CATALOGUE = [
|
|
12
|
+
// Browser bridge — read-only
|
|
13
|
+
{ name: 'browser.list_tabs', family: 'bridge', category: 'read', summary: 'List connected tabs' },
|
|
14
|
+
{
|
|
15
|
+
name: 'browser.ping',
|
|
16
|
+
family: 'bridge',
|
|
17
|
+
category: 'read',
|
|
18
|
+
summary: 'Verify the bridge to a tab',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: 'browser.snapshot',
|
|
22
|
+
family: 'bridge',
|
|
23
|
+
category: 'read',
|
|
24
|
+
summary: 'Dump DOM, text and interactive elements',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'browser.console',
|
|
28
|
+
family: 'bridge',
|
|
29
|
+
category: 'read',
|
|
30
|
+
summary: 'Read recent console messages',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'browser.network',
|
|
34
|
+
family: 'bridge',
|
|
35
|
+
category: 'read',
|
|
36
|
+
summary: 'Read recent network requests',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'browser.network_body',
|
|
40
|
+
family: 'bridge',
|
|
41
|
+
category: 'read',
|
|
42
|
+
summary: 'Fetch the body of a specific request',
|
|
43
|
+
},
|
|
44
|
+
// Browser bridge — actions
|
|
45
|
+
{
|
|
46
|
+
name: 'browser.navigate',
|
|
47
|
+
family: 'bridge',
|
|
48
|
+
category: 'action',
|
|
49
|
+
summary: 'Navigate the tab to a URL',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'browser.click',
|
|
53
|
+
family: 'bridge',
|
|
54
|
+
category: 'action',
|
|
55
|
+
summary: 'Click an element by CSS selector',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'browser.type',
|
|
59
|
+
family: 'bridge',
|
|
60
|
+
category: 'action',
|
|
61
|
+
summary: 'Type text into an input',
|
|
62
|
+
},
|
|
63
|
+
// Browser bridge — arbitrary code
|
|
64
|
+
{
|
|
65
|
+
name: 'browser.evaluate',
|
|
66
|
+
family: 'bridge',
|
|
67
|
+
category: 'eval',
|
|
68
|
+
summary: 'Run arbitrary JavaScript in the page',
|
|
69
|
+
},
|
|
70
|
+
// Persistent map — reads
|
|
71
|
+
{
|
|
72
|
+
name: 'browser.map.recall',
|
|
73
|
+
family: 'map',
|
|
74
|
+
category: 'map-read',
|
|
75
|
+
summary: 'Recall selectors / flows / gotchas for an app',
|
|
76
|
+
},
|
|
77
|
+
{ name: 'browser.map.apps', family: 'map', category: 'map-read', summary: 'List known apps' },
|
|
78
|
+
// Persistent map — writes
|
|
79
|
+
{
|
|
80
|
+
name: 'browser.map.save',
|
|
81
|
+
family: 'map',
|
|
82
|
+
category: 'map-write',
|
|
83
|
+
summary: 'Persist a selector / flow / gotcha',
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'browser.map.record_use',
|
|
87
|
+
family: 'map',
|
|
88
|
+
category: 'map-write',
|
|
89
|
+
summary: 'Mark an entry verified or failed',
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: 'browser.map.forget',
|
|
93
|
+
family: 'map',
|
|
94
|
+
category: 'map-write',
|
|
95
|
+
summary: 'Delete an entry or a whole app',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: 'browser.map.rename_app',
|
|
99
|
+
family: 'map',
|
|
100
|
+
category: 'map-write',
|
|
101
|
+
summary: 'Rename an app_key',
|
|
102
|
+
},
|
|
103
|
+
];
|
|
104
|
+
function namesWhere(predicate) {
|
|
105
|
+
return TOOL_CATALOGUE.filter(predicate)
|
|
106
|
+
.map((m) => m.name)
|
|
107
|
+
.sort();
|
|
108
|
+
}
|
|
109
|
+
export const PRESETS = [
|
|
110
|
+
{ id: 'all', label: 'All enabled', disabled: [] },
|
|
111
|
+
{
|
|
112
|
+
id: 'readonly',
|
|
113
|
+
label: 'Read-only (no actions, no JS, no map writes)',
|
|
114
|
+
disabled: namesWhere((m) => m.category === 'action' || m.category === 'eval' || m.category === 'map-write'),
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
id: 'no-eval',
|
|
118
|
+
label: 'No evaluate (everything except arbitrary JS)',
|
|
119
|
+
disabled: ['browser.evaluate'],
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: 'no-map',
|
|
123
|
+
label: 'No persistent map (all bridge tools on)',
|
|
124
|
+
disabled: namesWhere((m) => m.family === 'map'),
|
|
125
|
+
},
|
|
126
|
+
];
|
|
127
|
+
const KNOWN_NAMES = new Set(TOOL_CATALOGUE.map((m) => m.name));
|
|
128
|
+
/** True when the tool should be exposed in tools/list and accepted in tools/call. */
|
|
129
|
+
export function isToolEnabled(name, disabled) {
|
|
130
|
+
if (!disabled || disabled.length === 0)
|
|
131
|
+
return true;
|
|
132
|
+
return !disabled.includes(name);
|
|
133
|
+
}
|
|
134
|
+
/** Drop entries that don't match any current tool, dedupe, and sort. Used
|
|
135
|
+
* before writing the list to disk and after reading it back, so unknown
|
|
136
|
+
* names from older or newer versions never poison the runtime. */
|
|
137
|
+
export function sanitizeDisabledTools(input) {
|
|
138
|
+
if (!input || input.length === 0)
|
|
139
|
+
return [];
|
|
140
|
+
const out = new Set();
|
|
141
|
+
for (const name of input) {
|
|
142
|
+
if (typeof name === 'string' && KNOWN_NAMES.has(name))
|
|
143
|
+
out.add(name);
|
|
144
|
+
}
|
|
145
|
+
return [...out].sort();
|
|
146
|
+
}
|
|
147
|
+
export function getPreset(id) {
|
|
148
|
+
const found = PRESETS.find((p) => p.id === id);
|
|
149
|
+
if (!found)
|
|
150
|
+
throw new Error(`Unknown preset: ${id}`);
|
|
151
|
+
return found;
|
|
152
|
+
}
|
|
153
|
+
export function isKnownTool(name) {
|
|
154
|
+
return KNOWN_NAMES.has(name);
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export declare const WS_HOST = "127.0.0.1";
|
|
2
2
|
export declare const WS_PORT = 17529;
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
/**
|
|
4
|
+
* Entry point used by the MCP client over stdio. Decides whether THIS
|
|
5
|
+
* process becomes the primary (binds 17529, runs the WS bridge + MCP
|
|
6
|
+
* server + optional IPC server) or — when multi-agent mode is enabled
|
|
7
|
+
* and another primary is already running — becomes a thin proxy that
|
|
8
|
+
* forwards MCP stdio frames to the primary over IPC.
|
|
9
|
+
*/
|
|
6
10
|
export declare function runServer(): Promise<void>;
|