@jobshimo/browser-link 0.7.7 → 0.7.9
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/bridge/client.js +26 -18
- package/dist/bridge/client.js.map +1 -1
- package/dist/cli.js +7 -5
- package/dist/cli.js.map +1 -1
- package/dist/extension/manifest.json +1 -1
- package/dist/server.js +10 -10
- package/dist/server.js.map +1 -1
- package/dist/ui/app.js +1 -1
- package/dist/ui/app.js.map +1 -1
- package/dist/ui/screens/about.d.ts +6 -0
- package/dist/ui/screens/about.js +17 -0
- package/dist/ui/screens/about.js.map +1 -0
- package/dist/ui/screens/client-picker.d.ts +8 -0
- package/dist/ui/screens/client-picker.js +43 -0
- package/dist/ui/screens/client-picker.js.map +1 -0
- package/dist/ui/screens/doctor.d.ts +6 -0
- package/dist/ui/screens/doctor.js +43 -0
- package/dist/ui/screens/doctor.js.map +1 -0
- package/dist/ui/screens/extension.d.ts +6 -0
- package/dist/ui/screens/extension.js +32 -0
- package/dist/ui/screens/extension.js.map +1 -0
- package/dist/ui/screens/free-port.d.ts +6 -0
- package/dist/ui/screens/free-port.js +83 -0
- package/dist/ui/screens/free-port.js.map +1 -0
- package/dist/ui/screens/index.d.ts +12 -0
- package/dist/ui/screens/index.js +13 -0
- package/dist/ui/screens/index.js.map +1 -0
- package/dist/ui/screens/install-result.d.ts +8 -0
- package/dist/ui/screens/install-result.js +27 -0
- package/dist/ui/screens/install-result.js.map +1 -0
- package/dist/ui/screens/language.d.ts +8 -0
- package/dist/ui/screens/language.js +42 -0
- package/dist/ui/screens/language.js.map +1 -0
- package/dist/ui/screens/menu.d.ts +9 -0
- package/dist/ui/screens/menu.js +81 -0
- package/dist/ui/screens/menu.js.map +1 -0
- package/dist/ui/screens/multi-agent.d.ts +6 -0
- package/dist/ui/screens/multi-agent.js +131 -0
- package/dist/ui/screens/multi-agent.js.map +1 -0
- package/dist/ui/screens/permissions.d.ts +6 -0
- package/dist/ui/screens/permissions.js +135 -0
- package/dist/ui/screens/permissions.js.map +1 -0
- package/dist/ui/screens/types.d.ts +4 -0
- package/dist/ui/screens/types.js +2 -0
- package/dist/ui/screens/types.js.map +1 -0
- package/dist/ui/screens/updates.d.ts +6 -0
- package/dist/ui/screens/updates.js +113 -0
- package/dist/ui/screens/updates.js.map +1 -0
- package/dist/ui/screens/welcome.d.ts +10 -0
- package/dist/ui/screens/welcome.js +44 -0
- package/dist/ui/screens/welcome.js.map +1 -0
- package/package.json +1 -1
- package/dist/ui/screens.d.ts +0 -65
- package/dist/ui/screens.js +0 -743
- package/dist/ui/screens.js.map +0 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text, useInput } from 'ink';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { Frame, Menu } from '../components.js';
|
|
5
|
+
import { runFreePort } from '../../commands/free-port.js';
|
|
6
|
+
const FREE_PORT_I18N = {
|
|
7
|
+
en: {
|
|
8
|
+
title: 'Free port 17529',
|
|
9
|
+
intro: [
|
|
10
|
+
'If an MCP client (Claude / OpenCode / Copilot) was closed without',
|
|
11
|
+
'shutting down browser-link cleanly, the next client crashes with',
|
|
12
|
+
'"port already in use". This screen finds the process holding',
|
|
13
|
+
'127.0.0.1:17529 and stops it.',
|
|
14
|
+
'',
|
|
15
|
+
'Safety: only processes whose image starts with "node" are killed.',
|
|
16
|
+
'Anything else is left alone with an explanation.',
|
|
17
|
+
].join('\n'),
|
|
18
|
+
confirmPrompt: 'Stop the process holding port 17529?',
|
|
19
|
+
confirmYes: 'Yes — kill it',
|
|
20
|
+
confirmNo: 'No — back to menu',
|
|
21
|
+
running: 'Stopping…',
|
|
22
|
+
footer: '↑↓ navigate · ↵ select · Esc back',
|
|
23
|
+
doneFooter: '↵ / Esc back to menu',
|
|
24
|
+
},
|
|
25
|
+
es: {
|
|
26
|
+
title: 'Liberar puerto 17529',
|
|
27
|
+
intro: [
|
|
28
|
+
'Si un cliente MCP (Claude / OpenCode / Copilot) cerró sin bajar',
|
|
29
|
+
'browser-link de forma limpia, el próximo cliente crashea con',
|
|
30
|
+
'"port already in use". Esta pantalla busca el proceso que tiene',
|
|
31
|
+
'127.0.0.1:17529 y lo para.',
|
|
32
|
+
'',
|
|
33
|
+
'Seguridad: sólo se matan procesos cuyo nombre empieza con "node".',
|
|
34
|
+
'Cualquier otro se deja vivo con una explicación.',
|
|
35
|
+
].join('\n'),
|
|
36
|
+
confirmPrompt: '¿Parar el proceso que tiene el puerto 17529?',
|
|
37
|
+
confirmYes: 'Sí — matalo',
|
|
38
|
+
confirmNo: 'No — volver al menú',
|
|
39
|
+
running: 'Parando…',
|
|
40
|
+
footer: '↑↓ moverse · ↵ elegir · Esc volver',
|
|
41
|
+
doneFooter: '↵ / Esc volver al menú',
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
export function FreePortView({ language, onBack }) {
|
|
45
|
+
const t = FREE_PORT_I18N[language];
|
|
46
|
+
const [phase, setPhase] = useState('confirm');
|
|
47
|
+
const [result, setResult] = useState(null);
|
|
48
|
+
const items = [
|
|
49
|
+
{ value: 'yes', label: t.confirmYes },
|
|
50
|
+
{ value: 'no', label: t.confirmNo },
|
|
51
|
+
];
|
|
52
|
+
const [idx, setIdx] = useState(1);
|
|
53
|
+
useInput((_input, key) => {
|
|
54
|
+
if (phase === 'confirm') {
|
|
55
|
+
if (key.upArrow)
|
|
56
|
+
setIdx((i) => (i - 1 + items.length) % items.length);
|
|
57
|
+
else if (key.downArrow)
|
|
58
|
+
setIdx((i) => (i + 1) % items.length);
|
|
59
|
+
else if (key.return) {
|
|
60
|
+
const v = items[idx].value;
|
|
61
|
+
if (v === 'no')
|
|
62
|
+
onBack();
|
|
63
|
+
else {
|
|
64
|
+
setPhase('running');
|
|
65
|
+
// Defer the synchronous kill so Ink renders the "running" state.
|
|
66
|
+
setTimeout(() => {
|
|
67
|
+
const r = runFreePort(language);
|
|
68
|
+
setResult(r);
|
|
69
|
+
setPhase('done');
|
|
70
|
+
}, 0);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else if (key.escape)
|
|
74
|
+
onBack();
|
|
75
|
+
}
|
|
76
|
+
else if (phase === 'done') {
|
|
77
|
+
if (key.return || key.escape)
|
|
78
|
+
onBack();
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
return (_jsxs(Frame, { title: t.title, footer: phase === 'done' ? t.doneFooter : t.footer, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { children: t.intro }) }), phase === 'confirm' && (_jsxs(_Fragment, { children: [_jsx(Text, { color: "white", bold: true, children: t.confirmPrompt }), _jsx(Box, { marginTop: 1, children: _jsx(Menu, { items: items, selectedIndex: idx }) })] })), phase === 'running' && _jsx(Text, { color: "gray", children: t.running }), phase === 'done' && result && (_jsx(Text, { color: result.ok ? 'green' : 'yellow', children: result.message }))] }));
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=free-port.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"free-port.js","sourceRoot":"","sources":["../../../src/ui/screens/free-port.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAiB,MAAM,kBAAkB,CAAC;AAE9D,OAAO,EAAE,WAAW,EAAuB,MAAM,6BAA6B,CAAC;AAc/E,MAAM,cAAc,GAAmC;IACrD,EAAE,EAAE;QACF,KAAK,EAAE,iBAAiB;QACxB,KAAK,EAAE;YACL,mEAAmE;YACnE,kEAAkE;YAClE,8DAA8D;YAC9D,+BAA+B;YAC/B,EAAE;YACF,mEAAmE;YACnE,kDAAkD;SACnD,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,aAAa,EAAE,sCAAsC;QACrD,UAAU,EAAE,eAAe;QAC3B,SAAS,EAAE,mBAAmB;QAC9B,OAAO,EAAE,WAAW;QACpB,MAAM,EAAE,mCAAmC;QAC3C,UAAU,EAAE,sBAAsB;KACnC;IACD,EAAE,EAAE;QACF,KAAK,EAAE,sBAAsB;QAC7B,KAAK,EAAE;YACL,iEAAiE;YACjE,8DAA8D;YAC9D,iEAAiE;YACjE,4BAA4B;YAC5B,EAAE;YACF,mEAAmE;YACnE,kDAAkD;SACnD,CAAC,IAAI,CAAC,IAAI,CAAC;QACZ,aAAa,EAAE,8CAA8C;QAC7D,UAAU,EAAE,aAAa;QACzB,SAAS,EAAE,qBAAqB;QAChC,OAAO,EAAE,UAAU;QACnB,MAAM,EAAE,oCAAoC;QAC5C,UAAU,EAAE,wBAAwB;KACrC;CACF,CAAC;AAMF,MAAM,UAAU,YAAY,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAqB;IAClE,MAAM,CAAC,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAiC,SAAS,CAAC,CAAC;IAC9E,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAwB,IAAI,CAAC,CAAC;IAClE,MAAM,KAAK,GAA6B;QACtC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,UAAU,EAAE;QACrC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,SAAS,EAAE;KACpC,CAAC;IACF,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAElC,QAAQ,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;QACvB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,IAAI,GAAG,CAAC,OAAO;gBAAE,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;iBACjE,IAAI,GAAG,CAAC,SAAS;gBAAE,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;iBACzD,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;gBACpB,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;gBAC3B,IAAI,CAAC,KAAK,IAAI;oBAAE,MAAM,EAAE,CAAC;qBACpB,CAAC;oBACJ,QAAQ,CAAC,SAAS,CAAC,CAAC;oBACpB,iEAAiE;oBACjE,UAAU,CAAC,GAAG,EAAE;wBACd,MAAM,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;wBAChC,SAAS,CAAC,CAAC,CAAC,CAAC;wBACb,QAAQ,CAAC,MAAM,CAAC,CAAC;oBACnB,CAAC,EAAE,CAAC,CAAC,CAAC;gBACR,CAAC;YACH,CAAC;iBAAM,IAAI,GAAG,CAAC,MAAM;gBAAE,MAAM,EAAE,CAAC;QAClC,CAAC;aAAM,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YAC5B,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM;gBAAE,MAAM,EAAE,CAAC;QACzC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,CACL,MAAC,KAAK,IAAC,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,aACvE,KAAC,GAAG,IAAC,YAAY,EAAE,CAAC,YAClB,KAAC,IAAI,cAAE,CAAC,CAAC,KAAK,GAAQ,GAClB,EACL,KAAK,KAAK,SAAS,IAAI,CACtB,8BACE,KAAC,IAAI,IAAC,KAAK,EAAC,OAAO,EAAC,IAAI,kBACrB,CAAC,CAAC,aAAa,GACX,EACP,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,GAAI,GACtC,IACL,CACJ,EACA,KAAK,KAAK,SAAS,IAAI,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,YAAE,CAAC,CAAC,OAAO,GAAQ,EAC5D,KAAK,KAAK,MAAM,IAAI,MAAM,IAAI,CAC7B,KAAC,IAAI,IAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,YAAG,MAAM,CAAC,OAAO,GAAQ,CACrE,IACK,CACT,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { WelcomeScreen } from './welcome.js';
|
|
2
|
+
export { MainMenu, type MenuAction } from './menu.js';
|
|
3
|
+
export { ClientPicker } from './client-picker.js';
|
|
4
|
+
export { InstallResultView } from './install-result.js';
|
|
5
|
+
export { ExtensionView } from './extension.js';
|
|
6
|
+
export { DoctorView } from './doctor.js';
|
|
7
|
+
export { AboutView } from './about.js';
|
|
8
|
+
export { PermissionsView } from './permissions.js';
|
|
9
|
+
export { UpdatesView } from './updates.js';
|
|
10
|
+
export { LanguageView } from './language.js';
|
|
11
|
+
export { MultiAgentView } from './multi-agent.js';
|
|
12
|
+
export { FreePortView } from './free-port.js';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { WelcomeScreen } from './welcome.js';
|
|
2
|
+
export { MainMenu } from './menu.js';
|
|
3
|
+
export { ClientPicker } from './client-picker.js';
|
|
4
|
+
export { InstallResultView } from './install-result.js';
|
|
5
|
+
export { ExtensionView } from './extension.js';
|
|
6
|
+
export { DoctorView } from './doctor.js';
|
|
7
|
+
export { AboutView } from './about.js';
|
|
8
|
+
export { PermissionsView } from './permissions.js';
|
|
9
|
+
export { UpdatesView } from './updates.js';
|
|
10
|
+
export { LanguageView } from './language.js';
|
|
11
|
+
export { MultiAgentView } from './multi-agent.js';
|
|
12
|
+
export { FreePortView } from './free-port.js';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/ui/screens/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAmB,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type InstallReport } from '../../commands/install.js';
|
|
2
|
+
import type { CommonProps } from './types.js';
|
|
3
|
+
interface InstallResultProps extends CommonProps {
|
|
4
|
+
report: InstallReport;
|
|
5
|
+
onBack: () => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function InstallResultView({ language, report, onBack }: InstallResultProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text, useInput } from 'ink';
|
|
3
|
+
import { Frame } from '../components.js';
|
|
4
|
+
const RESULT_I18N = {
|
|
5
|
+
en: {
|
|
6
|
+
ok: 'Registered',
|
|
7
|
+
warn: 'Not registered',
|
|
8
|
+
hint: 'Restart the MCP client so it picks up the new entry.',
|
|
9
|
+
footer: '↵ / Esc back to menu',
|
|
10
|
+
},
|
|
11
|
+
es: {
|
|
12
|
+
ok: 'Registrado',
|
|
13
|
+
warn: 'No registrado',
|
|
14
|
+
hint: 'Reiniciá el cliente MCP para que tome la nueva entrada.',
|
|
15
|
+
footer: '↵ / Esc volver al menú',
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
export function InstallResultView({ language, report, onBack }) {
|
|
19
|
+
const t = RESULT_I18N[language];
|
|
20
|
+
useInput((_input, key) => {
|
|
21
|
+
if (key.return || key.escape)
|
|
22
|
+
onBack();
|
|
23
|
+
});
|
|
24
|
+
const ok = report.installedClient;
|
|
25
|
+
return (_jsxs(Frame, { title: `${report.displayName} — ${ok ? t.ok : t.warn}`, footer: t.footer, children: [_jsxs(Text, { color: ok ? 'green' : 'yellow', children: [ok ? '✓ ' : '⚠ ', report.message] }), ok && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "cyan", children: ["\u2192 ", t.hint] }) }))] }));
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=install-result.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-result.js","sourceRoot":"","sources":["../../../src/ui/screens/install-result.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAUzC,MAAM,WAAW,GAAiF;IAChG,EAAE,EAAE;QACF,EAAE,EAAE,YAAY;QAChB,IAAI,EAAE,gBAAgB;QACtB,IAAI,EAAE,sDAAsD;QAC5D,MAAM,EAAE,sBAAsB;KAC/B;IACD,EAAE,EAAE;QACF,EAAE,EAAE,YAAY;QAChB,IAAI,EAAE,eAAe;QACrB,IAAI,EAAE,yDAAyD;QAC/D,MAAM,EAAE,wBAAwB;KACjC;CACF,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAsB;IAChF,MAAM,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IAChC,QAAQ,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;QACvB,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM;YAAE,MAAM,EAAE,CAAC;IACzC,CAAC,CAAC,CAAC;IACH,MAAM,EAAE,GAAG,MAAM,CAAC,eAAe,CAAC;IAClC,OAAO,CACL,MAAC,KAAK,IAAC,KAAK,EAAE,GAAG,MAAM,CAAC,WAAW,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,aAC7E,MAAC,IAAI,IAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,aACjC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAChB,MAAM,CAAC,OAAO,IACV,EACN,EAAE,IAAI,CACL,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,MAAC,IAAI,IAAC,KAAK,EAAC,MAAM,wBAAI,CAAC,CAAC,IAAI,IAAQ,GAChC,CACP,IACK,CACT,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Language } from '../../commands/welcome.js';
|
|
2
|
+
import type { CommonProps } from './types.js';
|
|
3
|
+
interface LanguageViewProps extends CommonProps {
|
|
4
|
+
onPick: (next: Language) => void;
|
|
5
|
+
onBack: () => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function LanguageView({ language, onPick, onBack }: LanguageViewProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text, useInput } from 'ink';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { Frame, Menu } from '../components.js';
|
|
5
|
+
const LANG_I18N = {
|
|
6
|
+
en: {
|
|
7
|
+
title: 'Language — switch between English and Español',
|
|
8
|
+
prompt: 'Pick a language',
|
|
9
|
+
saved: '✓ Saved. All output will now use the selected language.',
|
|
10
|
+
footer: '↑↓ navigate · ↵ pick · Esc back',
|
|
11
|
+
},
|
|
12
|
+
es: {
|
|
13
|
+
title: 'Idioma — cambiar entre English y Español',
|
|
14
|
+
prompt: 'Elegí un idioma',
|
|
15
|
+
saved: '✓ Guardado. Todo el output va a usar el idioma elegido.',
|
|
16
|
+
footer: '↑↓ moverse · ↵ elegir · Esc volver',
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
export function LanguageView({ language, onPick, onBack }) {
|
|
20
|
+
const t = LANG_I18N[language];
|
|
21
|
+
const items = [
|
|
22
|
+
{ value: 'en', label: 'English' },
|
|
23
|
+
{ value: 'es', label: 'Español' },
|
|
24
|
+
];
|
|
25
|
+
const [idx, setIdx] = useState(language === 'es' ? 1 : 0);
|
|
26
|
+
const [saved, setSaved] = useState(false);
|
|
27
|
+
useInput((_input, key) => {
|
|
28
|
+
if (key.upArrow)
|
|
29
|
+
setIdx((i) => (i - 1 + items.length) % items.length);
|
|
30
|
+
else if (key.downArrow)
|
|
31
|
+
setIdx((i) => (i + 1) % items.length);
|
|
32
|
+
else if (key.return) {
|
|
33
|
+
const next = items[idx].value;
|
|
34
|
+
onPick(next);
|
|
35
|
+
setSaved(true);
|
|
36
|
+
}
|
|
37
|
+
else if (key.escape)
|
|
38
|
+
onBack();
|
|
39
|
+
});
|
|
40
|
+
return (_jsxs(Frame, { title: t.title, footer: t.footer, children: [_jsx(Text, { color: "white", bold: true, children: t.prompt }), _jsx(Box, { marginTop: 1, children: _jsx(Menu, { items: items, selectedIndex: idx }) }), saved && (_jsx(Box, { marginTop: 1, children: _jsx(Text, { color: "green", children: t.saved }) }))] }));
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=language.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language.js","sourceRoot":"","sources":["../../../src/ui/screens/language.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAiB,MAAM,kBAAkB,CAAC;AAI9D,MAAM,SAAS,GAGX;IACF,EAAE,EAAE;QACF,KAAK,EAAE,+CAA+C;QACtD,MAAM,EAAE,iBAAiB;QACzB,KAAK,EAAE,yDAAyD;QAChE,MAAM,EAAE,iCAAiC;KAC1C;IACD,EAAE,EAAE;QACF,KAAK,EAAE,0CAA0C;QACjD,MAAM,EAAE,iBAAiB;QACzB,KAAK,EAAE,yDAAyD;QAChE,MAAM,EAAE,oCAAoC;KAC7C;CACF,CAAC;AAOF,MAAM,UAAU,YAAY,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAqB;IAC1E,MAAM,CAAC,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC9B,MAAM,KAAK,GAAyB;QAClC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE;QACjC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE;KAClC,CAAC;IACF,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAS,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE1C,QAAQ,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;QACvB,IAAI,GAAG,CAAC,OAAO;YAAE,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;aACjE,IAAI,GAAG,CAAC,SAAS;YAAE,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;aACzD,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,CAAC;YACb,QAAQ,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;aAAM,IAAI,GAAG,CAAC,MAAM;YAAE,MAAM,EAAE,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,OAAO,CACL,MAAC,KAAK,IAAC,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,aACrC,KAAC,IAAI,IAAC,KAAK,EAAC,OAAO,EAAC,IAAI,kBACrB,CAAC,CAAC,MAAM,GACJ,EACP,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,GAAI,GACtC,EACL,KAAK,IAAI,CACR,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,YACf,KAAC,IAAI,IAAC,KAAK,EAAC,OAAO,YAAE,CAAC,CAAC,KAAK,GAAQ,GAChC,CACP,IACK,CACT,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CommonProps } from './types.js';
|
|
2
|
+
export type MenuAction = 'register' | 'permissions' | 'multiAgent' | 'extension' | 'doctor' | 'updates' | 'freePort' | 'language' | 'welcome' | 'about' | 'repo' | 'quit';
|
|
3
|
+
interface MainMenuProps extends CommonProps {
|
|
4
|
+
onSelect: (action: MenuAction) => void;
|
|
5
|
+
onSwapLang: () => void;
|
|
6
|
+
onQuit: () => void;
|
|
7
|
+
}
|
|
8
|
+
export declare function MainMenu({ language, onSelect, onSwapLang, onQuit }: MainMenuProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text, useInput } from 'ink';
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { Frame, Menu } from '../components.js';
|
|
5
|
+
const MENU_I18N = {
|
|
6
|
+
en: {
|
|
7
|
+
title: 'browser-link — setup',
|
|
8
|
+
prompt: 'Pick an action',
|
|
9
|
+
footer: '↑↓ navigate · ↵ select · l language · q quit',
|
|
10
|
+
options: {
|
|
11
|
+
register: 'Register browser-link with an MCP client',
|
|
12
|
+
permissions: 'Permissions — pick which MCP tools to expose',
|
|
13
|
+
multiAgent: 'Multi-agent — let multiple MCP clients share one bridge',
|
|
14
|
+
extension: 'Show Chrome extension install steps',
|
|
15
|
+
doctor: 'Run doctor (diagnose current setup)',
|
|
16
|
+
updates: 'Check for updates on npm',
|
|
17
|
+
freePort: 'Free port — stop a stuck browser-link holding 17529',
|
|
18
|
+
language: 'Language — switch between English and Español',
|
|
19
|
+
welcome: 'Show the welcome screen',
|
|
20
|
+
about: 'About / Help — what is this and how it works',
|
|
21
|
+
repo: 'Open the GitHub repository',
|
|
22
|
+
quit: 'Quit',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
es: {
|
|
26
|
+
title: 'browser-link — configuración',
|
|
27
|
+
prompt: 'Elegí una acción',
|
|
28
|
+
footer: '↑↓ moverse · ↵ elegir · l idioma · q salir',
|
|
29
|
+
options: {
|
|
30
|
+
register: 'Registrar browser-link en un cliente MCP',
|
|
31
|
+
permissions: 'Permisos — elegí qué tools del MCP se exponen',
|
|
32
|
+
multiAgent: 'Multi-agente — varios clientes MCP comparten el mismo puente',
|
|
33
|
+
extension: 'Ver pasos para instalar la extensión de Chrome',
|
|
34
|
+
doctor: 'Diagnóstico (estado actual de la instalación)',
|
|
35
|
+
updates: 'Buscar actualizaciones en npm',
|
|
36
|
+
freePort: 'Liberar puerto — matar el browser-link colgado en 17529',
|
|
37
|
+
language: 'Idioma — cambiar entre English y Español',
|
|
38
|
+
welcome: 'Mostrar la pantalla de bienvenida',
|
|
39
|
+
about: 'Información / ayuda — qué es esto y cómo funciona',
|
|
40
|
+
repo: 'Abrir el repositorio en GitHub',
|
|
41
|
+
quit: 'Salir',
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
export function MainMenu({ language, onSelect, onSwapLang, onQuit }) {
|
|
46
|
+
const t = MENU_I18N[language];
|
|
47
|
+
const items = [
|
|
48
|
+
'register',
|
|
49
|
+
'permissions',
|
|
50
|
+
'multiAgent',
|
|
51
|
+
'extension',
|
|
52
|
+
'doctor',
|
|
53
|
+
'updates',
|
|
54
|
+
'freePort',
|
|
55
|
+
'language',
|
|
56
|
+
'welcome',
|
|
57
|
+
'about',
|
|
58
|
+
'repo',
|
|
59
|
+
'quit',
|
|
60
|
+
].map((a) => ({ value: a, label: t.options[a] }));
|
|
61
|
+
const [idx, setIdx] = useState(0);
|
|
62
|
+
useInput((input, key) => {
|
|
63
|
+
if (key.upArrow)
|
|
64
|
+
setIdx((i) => (i - 1 + items.length) % items.length);
|
|
65
|
+
else if (key.downArrow)
|
|
66
|
+
setIdx((i) => (i + 1) % items.length);
|
|
67
|
+
else if (key.return) {
|
|
68
|
+
const v = items[idx].value;
|
|
69
|
+
if (v === 'quit')
|
|
70
|
+
onQuit();
|
|
71
|
+
else
|
|
72
|
+
onSelect(v);
|
|
73
|
+
}
|
|
74
|
+
else if (input === 'q' || key.escape)
|
|
75
|
+
onQuit();
|
|
76
|
+
else if (input === 'l')
|
|
77
|
+
onSwapLang();
|
|
78
|
+
});
|
|
79
|
+
return (_jsxs(Frame, { title: t.title, footer: t.footer, children: [_jsx(Text, { color: "white", bold: true, children: t.prompt }), _jsx(Box, { marginTop: 1, children: _jsx(Menu, { items: items, selectedIndex: idx }) })] }));
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=menu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menu.js","sourceRoot":"","sources":["../../../src/ui/screens/menu.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text, useInput } from 'ink';
|
|
3
|
+
import { useMemo, useState } from 'react';
|
|
4
|
+
import { Frame } from '../components.js';
|
|
5
|
+
import { loadConfig, saveConfig } from '../../config.js';
|
|
6
|
+
const MULTI_AGENT_I18N = {
|
|
7
|
+
en: {
|
|
8
|
+
title: 'Multi-agent — let multiple MCP clients share one browser-link',
|
|
9
|
+
multiHeader: 'Multi-agent mode',
|
|
10
|
+
multiBody: [
|
|
11
|
+
'browser-link normally binds 127.0.0.1:17529 from the first MCP',
|
|
12
|
+
'client that starts it. Other clients (Claude + Copilot + OpenCode at',
|
|
13
|
+
'the same time) crash with "port in use".',
|
|
14
|
+
'',
|
|
15
|
+
'When multi-agent is ON, the second instance becomes a proxy that',
|
|
16
|
+
'forwards MCP requests to the first one over an internal port',
|
|
17
|
+
'(127.0.0.1:17530, kernel-validated like the main one). All agents',
|
|
18
|
+
'end up sharing the same connected Chrome tabs and the same',
|
|
19
|
+
'persistent UI map.',
|
|
20
|
+
].join('\n'),
|
|
21
|
+
multiToggle: 'Enable multi-agent mode',
|
|
22
|
+
reelectHeader: 'Auto-reelect on primary close (advanced)',
|
|
23
|
+
reelectBody: [
|
|
24
|
+
'When the primary client closes, secondary clients lose the bridge.',
|
|
25
|
+
'With auto-reelect ON, one of them takes over the primary role',
|
|
26
|
+
'automatically (race on bind). With it OFF, you relaunch your MCP',
|
|
27
|
+
'client manually to reconnect.',
|
|
28
|
+
].join('\n'),
|
|
29
|
+
reelectToggle: 'Auto-reelect when primary closes',
|
|
30
|
+
reelectDisabled: '(enable multi-agent first)',
|
|
31
|
+
unsaved: '* Unsaved changes — press s to save',
|
|
32
|
+
saved: '✓ Saved.',
|
|
33
|
+
restart: 'Restart every MCP client for these changes to take effect.',
|
|
34
|
+
footer: '↑↓ navigate · Space toggle · s save · Esc back',
|
|
35
|
+
},
|
|
36
|
+
es: {
|
|
37
|
+
title: 'Multi-agente — varios clientes MCP comparten el mismo puente',
|
|
38
|
+
multiHeader: 'Modo multi-agente',
|
|
39
|
+
multiBody: [
|
|
40
|
+
'browser-link normalmente bindea 127.0.0.1:17529 desde el primer',
|
|
41
|
+
'cliente MCP que lo arranca. Otros clientes (Claude + Copilot +',
|
|
42
|
+
'OpenCode al mismo tiempo) caen con "port in use".',
|
|
43
|
+
'',
|
|
44
|
+
'Con multi-agente activado, el segundo proceso se vuelve un proxy',
|
|
45
|
+
'que reenvía los pedidos MCP al primero por un puerto interno',
|
|
46
|
+
'(127.0.0.1:17530, validado por kernel igual que el principal).',
|
|
47
|
+
'Todos los agentes terminan viendo las mismas pestañas conectadas',
|
|
48
|
+
'y el mismo mapa persistente.',
|
|
49
|
+
].join('\n'),
|
|
50
|
+
multiToggle: 'Activar modo multi-agente',
|
|
51
|
+
reelectHeader: 'Re-elección automática al cerrar el primary (avanzado)',
|
|
52
|
+
reelectBody: [
|
|
53
|
+
'Cuando el cliente primary cierra, los secundarios pierden el',
|
|
54
|
+
'puente. Con re-elección automática activada, uno de ellos toma el',
|
|
55
|
+
'rol de primary automáticamente (race en el bind). Con ella',
|
|
56
|
+
'desactivada, tenés que relanzar el cliente MCP a mano para',
|
|
57
|
+
'reconectar.',
|
|
58
|
+
].join('\n'),
|
|
59
|
+
reelectToggle: 'Re-elegir automáticamente al cerrar el primary',
|
|
60
|
+
reelectDisabled: '(activá primero multi-agente)',
|
|
61
|
+
unsaved: '* Cambios sin guardar — apretá s para guardar',
|
|
62
|
+
saved: '✓ Guardado.',
|
|
63
|
+
restart: 'Reiniciá cada cliente MCP para que los cambios tengan efecto.',
|
|
64
|
+
footer: '↑↓ moverse · Espacio cambiar · s guardar · Esc volver',
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
export function MultiAgentView({ language, onBack }) {
|
|
68
|
+
const t = MULTI_AGENT_I18N[language];
|
|
69
|
+
const initialCfg = useMemo(() => loadConfig(), []);
|
|
70
|
+
const [savedMulti, setSavedMulti] = useState(initialCfg.multiAgent === true);
|
|
71
|
+
const [savedReelect, setSavedReelect] = useState(initialCfg.autoReelect === true);
|
|
72
|
+
const [multi, setMulti] = useState(savedMulti);
|
|
73
|
+
const [reelect, setReelect] = useState(savedReelect);
|
|
74
|
+
const [justSaved, setJustSaved] = useState(false);
|
|
75
|
+
// Only the two toggles are navigable.
|
|
76
|
+
const [cursor, setCursor] = useState('multi');
|
|
77
|
+
const move = (dir) => {
|
|
78
|
+
setCursor((c) => {
|
|
79
|
+
if (dir === 1)
|
|
80
|
+
return c === 'multi' ? 'reelect' : 'multi';
|
|
81
|
+
return c === 'reelect' ? 'multi' : 'reelect';
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
const toggle = () => {
|
|
85
|
+
if (cursor === 'multi') {
|
|
86
|
+
setMulti((m) => {
|
|
87
|
+
const next = !m;
|
|
88
|
+
// Turning multi off also clears the working reelect state, matching
|
|
89
|
+
// the config normalisation rule (autoReelect implies multiAgent).
|
|
90
|
+
if (!next)
|
|
91
|
+
setReelect(false);
|
|
92
|
+
return next;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
// Auto-reelect can only be turned on when multi is on.
|
|
97
|
+
if (!multi)
|
|
98
|
+
return;
|
|
99
|
+
setReelect((r) => !r);
|
|
100
|
+
}
|
|
101
|
+
setJustSaved(false);
|
|
102
|
+
};
|
|
103
|
+
const save = () => {
|
|
104
|
+
saveConfig({ multiAgent: multi, autoReelect: multi ? reelect : false });
|
|
105
|
+
setSavedMulti(multi);
|
|
106
|
+
setSavedReelect(multi ? reelect : false);
|
|
107
|
+
setJustSaved(true);
|
|
108
|
+
};
|
|
109
|
+
useInput((input, key) => {
|
|
110
|
+
if (key.upArrow)
|
|
111
|
+
move(-1);
|
|
112
|
+
else if (key.downArrow)
|
|
113
|
+
move(1);
|
|
114
|
+
else if (input === ' ')
|
|
115
|
+
toggle();
|
|
116
|
+
else if (input === 's' || input === 'S')
|
|
117
|
+
save();
|
|
118
|
+
else if (input === 'q' || key.escape)
|
|
119
|
+
onBack();
|
|
120
|
+
});
|
|
121
|
+
const unsaved = multi !== savedMulti || reelect !== savedReelect;
|
|
122
|
+
const checkbox = (on, dim) => {
|
|
123
|
+
if (dim)
|
|
124
|
+
return { mark: '[ ]', color: 'gray' };
|
|
125
|
+
return on ? { mark: '[x]', color: 'green' } : { mark: '[ ]', color: 'red' };
|
|
126
|
+
};
|
|
127
|
+
const multiBox = checkbox(multi, false);
|
|
128
|
+
const reelectBox = checkbox(multi ? reelect : false, !multi);
|
|
129
|
+
return (_jsxs(Frame, { title: t.title, footer: t.footer, children: [_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { color: "cyan", bold: true, children: t.multiHeader }), _jsx(Text, { children: t.multiBody })] }), _jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { color: cursor === 'multi' ? 'cyan' : 'gray', children: cursor === 'multi' ? '❯ ' : ' ' }), _jsxs(Text, { color: multiBox.color, children: [multiBox.mark, " "] }), _jsx(Text, { color: cursor === 'multi' ? 'white' : 'gray', bold: cursor === 'multi', children: t.multiToggle })] }), _jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { color: "cyan", bold: true, children: t.reelectHeader }), _jsx(Text, { children: t.reelectBody })] }), _jsxs(Box, { marginBottom: 1, children: [_jsx(Text, { color: cursor === 'reelect' ? 'cyan' : 'gray', children: cursor === 'reelect' ? '❯ ' : ' ' }), _jsxs(Text, { color: reelectBox.color, children: [reelectBox.mark, " "] }), _jsxs(Text, { color: !multi ? 'gray' : cursor === 'reelect' ? 'white' : 'gray', bold: cursor === 'reelect' && multi, children: [t.reelectToggle, !multi && (_jsxs(Text, { color: "gray", dimColor: true, children: [' ', t.reelectDisabled] }))] })] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [unsaved ? (_jsx(Text, { color: "yellow", children: t.unsaved })) : justSaved ? (_jsx(Text, { color: "green", children: t.saved })) : null, _jsx(Text, { color: "gray", italic: true, children: t.restart })] })] }));
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=multi-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multi-agent.js","sourceRoot":"","sources":["../../../src/ui/screens/multi-agent.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text, useInput } from 'ink';
|
|
3
|
+
import { useMemo, useState } from 'react';
|
|
4
|
+
import { Frame } from '../components.js';
|
|
5
|
+
import { loadConfig, saveConfig } from '../../config.js';
|
|
6
|
+
import { PRESETS, TOOL_CATALOGUE, sanitizeDisabledTools, } from '../../permissions.js';
|
|
7
|
+
const PERM_I18N = {
|
|
8
|
+
en: {
|
|
9
|
+
title: 'Permissions — pick which MCP tools to expose',
|
|
10
|
+
intro: 'Apply a preset (↵) or toggle individual tools (Space). Press s to save.',
|
|
11
|
+
presetsHeader: 'Presets',
|
|
12
|
+
bridgeHeader: 'Browser bridge',
|
|
13
|
+
mapHeader: 'Persistent UI map',
|
|
14
|
+
applyPrefix: 'Apply: ',
|
|
15
|
+
unsaved: '* Unsaved changes — press s to save',
|
|
16
|
+
saved: '✓ Saved.',
|
|
17
|
+
restart: 'Changes take effect the next time your MCP client starts the server.',
|
|
18
|
+
footer: '↑↓ navigate · Space toggle · ↵ apply preset · s save · Esc back',
|
|
19
|
+
},
|
|
20
|
+
es: {
|
|
21
|
+
title: 'Permisos — elegí qué tools del MCP se exponen',
|
|
22
|
+
intro: 'Aplicá un preset (↵) o cambiá tools individuales (Espacio). Apretá s para guardar.',
|
|
23
|
+
presetsHeader: 'Presets',
|
|
24
|
+
bridgeHeader: 'Bridge del browser',
|
|
25
|
+
mapHeader: 'Mapa persistente',
|
|
26
|
+
applyPrefix: 'Aplicar: ',
|
|
27
|
+
unsaved: '* Cambios sin guardar — apretá s para guardar',
|
|
28
|
+
saved: '✓ Guardado.',
|
|
29
|
+
restart: 'Los cambios tienen efecto la próxima vez que el cliente MCP arranque el servidor.',
|
|
30
|
+
footer: '↑↓ moverse · Espacio cambiar · ↵ aplicar preset · s guardar · Esc volver',
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
function setsDiffer(a, b) {
|
|
34
|
+
if (a.size !== b.size)
|
|
35
|
+
return true;
|
|
36
|
+
for (const x of a)
|
|
37
|
+
if (!b.has(x))
|
|
38
|
+
return true;
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
export function PermissionsView({ language, onBack }) {
|
|
42
|
+
const t = PERM_I18N[language];
|
|
43
|
+
const rows = useMemo(() => {
|
|
44
|
+
const r = [];
|
|
45
|
+
for (const preset of PRESETS)
|
|
46
|
+
r.push({ kind: 'preset', preset });
|
|
47
|
+
r.push({ kind: 'header', family: 'bridge' });
|
|
48
|
+
for (const tool of TOOL_CATALOGUE) {
|
|
49
|
+
if (tool.family === 'bridge')
|
|
50
|
+
r.push({ kind: 'tool', tool });
|
|
51
|
+
}
|
|
52
|
+
r.push({ kind: 'header', family: 'map' });
|
|
53
|
+
for (const tool of TOOL_CATALOGUE) {
|
|
54
|
+
if (tool.family === 'map')
|
|
55
|
+
r.push({ kind: 'tool', tool });
|
|
56
|
+
}
|
|
57
|
+
return r;
|
|
58
|
+
}, []);
|
|
59
|
+
const initial = useMemo(() => new Set(loadConfig().disabledTools ?? []), []);
|
|
60
|
+
const [savedDisabled, setSavedDisabled] = useState(initial);
|
|
61
|
+
const [disabled, setDisabled] = useState(initial);
|
|
62
|
+
const firstNonHeader = rows.findIndex((r) => r.kind !== 'header');
|
|
63
|
+
const [cursor, setCursor] = useState(firstNonHeader);
|
|
64
|
+
const [justSaved, setJustSaved] = useState(false);
|
|
65
|
+
const move = (dir) => {
|
|
66
|
+
setCursor((idx) => {
|
|
67
|
+
let i = idx;
|
|
68
|
+
for (let n = 0; n < rows.length; n++) {
|
|
69
|
+
i = (i + dir + rows.length) % rows.length;
|
|
70
|
+
if (rows[i].kind !== 'header')
|
|
71
|
+
return i;
|
|
72
|
+
}
|
|
73
|
+
return idx;
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
const toggleTool = (name) => {
|
|
77
|
+
setDisabled((prev) => {
|
|
78
|
+
const next = new Set(prev);
|
|
79
|
+
if (next.has(name))
|
|
80
|
+
next.delete(name);
|
|
81
|
+
else
|
|
82
|
+
next.add(name);
|
|
83
|
+
return next;
|
|
84
|
+
});
|
|
85
|
+
setJustSaved(false);
|
|
86
|
+
};
|
|
87
|
+
const applyPreset = (preset) => {
|
|
88
|
+
setDisabled(new Set(preset.disabled));
|
|
89
|
+
setJustSaved(false);
|
|
90
|
+
};
|
|
91
|
+
const save = () => {
|
|
92
|
+
const list = sanitizeDisabledTools([...disabled]);
|
|
93
|
+
saveConfig({ disabledTools: list });
|
|
94
|
+
setSavedDisabled(new Set(list));
|
|
95
|
+
setJustSaved(true);
|
|
96
|
+
};
|
|
97
|
+
useInput((input, key) => {
|
|
98
|
+
if (key.upArrow)
|
|
99
|
+
move(-1);
|
|
100
|
+
else if (key.downArrow)
|
|
101
|
+
move(1);
|
|
102
|
+
else if (input === ' ') {
|
|
103
|
+
const row = rows[cursor];
|
|
104
|
+
if (row.kind === 'tool')
|
|
105
|
+
toggleTool(row.tool.name);
|
|
106
|
+
}
|
|
107
|
+
else if (key.return) {
|
|
108
|
+
const row = rows[cursor];
|
|
109
|
+
if (row.kind === 'preset')
|
|
110
|
+
applyPreset(row.preset);
|
|
111
|
+
}
|
|
112
|
+
else if (input === 's' || input === 'S') {
|
|
113
|
+
save();
|
|
114
|
+
}
|
|
115
|
+
else if (input === 'q' || key.escape)
|
|
116
|
+
onBack();
|
|
117
|
+
});
|
|
118
|
+
const unsaved = setsDiffer(disabled, savedDisabled);
|
|
119
|
+
return (_jsxs(Frame, { title: t.title, footer: t.footer, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { color: "white", children: t.intro }) }), _jsx(Box, { flexDirection: "column", children: rows.map((row, i) => {
|
|
120
|
+
if (row.kind === 'header') {
|
|
121
|
+
const label = row.family === 'bridge' ? t.bridgeHeader : t.mapHeader;
|
|
122
|
+
return (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "cyan", bold: true, children: [label, ":"] }) }, `h-${i}`));
|
|
123
|
+
}
|
|
124
|
+
const isCursor = i === cursor;
|
|
125
|
+
const cursorMark = isCursor ? '❯' : ' ';
|
|
126
|
+
if (row.kind === 'preset') {
|
|
127
|
+
return (_jsxs(Box, { children: [_jsxs(Text, { color: isCursor ? 'cyan' : 'gray', children: [cursorMark, " "] }), _jsxs(Text, { color: isCursor ? 'white' : 'gray', bold: isCursor, children: [t.applyPrefix, row.preset.label] })] }, `p-${row.preset.id}`));
|
|
128
|
+
}
|
|
129
|
+
const isDisabled = disabled.has(row.tool.name);
|
|
130
|
+
const checkbox = isDisabled ? '[ ]' : '[x]';
|
|
131
|
+
const checkboxColor = isDisabled ? 'red' : 'green';
|
|
132
|
+
return (_jsxs(Box, { children: [_jsxs(Text, { color: isCursor ? 'cyan' : 'gray', children: [cursorMark, " "] }), _jsxs(Text, { color: checkboxColor, children: [checkbox, " "] }), _jsx(Text, { color: isCursor ? 'white' : isDisabled ? 'gray' : 'white', bold: isCursor, children: row.tool.name.padEnd(28) }), _jsxs(Text, { color: "gray", dimColor: true, children: [' ', row.tool.summary] })] }, `t-${row.tool.name}`));
|
|
133
|
+
}) }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [unsaved ? (_jsx(Text, { color: "yellow", children: t.unsaved })) : justSaved ? (_jsx(Text, { color: "green", children: t.saved })) : null, _jsx(Text, { color: "gray", italic: true, children: t.restart })] })] }));
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=permissions.js.map
|