@jobshimo/browser-link 0.0.1 → 0.1.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/LICENSE +21 -21
- package/README.md +102 -83
- package/dist/cli.js +19 -19
- package/dist/commands/about.d.ts +17 -15
- package/dist/commands/about.js +161 -186
- package/dist/commands/about.js.map +1 -1
- package/dist/commands/menu.d.ts +2 -3
- package/dist/commands/menu.js +111 -131
- package/dist/commands/menu.js.map +1 -1
- package/dist/commands/welcome.d.ts +8 -7
- package/dist/commands/welcome.js +78 -121
- package/dist/commands/welcome.js.map +1 -1
- package/dist/extension/background.js +90 -90
- package/dist/extension/icons/icon.svg +14 -14
- package/dist/extension/manifest.json +28 -28
- package/dist/extension/popup.html +88 -88
- package/dist/installers/index.d.ts +2 -3
- package/dist/installers/index.js +4 -4
- package/dist/installers/index.js.map +1 -1
- package/dist/installers/opencode.js +49 -21
- package/dist/installers/opencode.js.map +1 -1
- package/dist/map/db.js +28 -28
- package/dist/map/queries.js +4 -4
- package/dist/tools/server-instructions.js +46 -46
- package/package.json +64 -61
- package/dist/commands/tty.d.ts +0 -51
- package/dist/commands/tty.js +0 -148
- package/dist/commands/tty.js.map +0 -1
package/dist/commands/menu.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
|
+
import { INSTALLERS } from '../installers/index.js';
|
|
3
3
|
import { installFor } from './install.js';
|
|
4
4
|
import { formatDoctor, runDoctor } from './doctor.js';
|
|
5
5
|
import { printExtensionInstructions } from './extension.js';
|
|
@@ -7,181 +7,161 @@ import { runWelcome } from './welcome.js';
|
|
|
7
7
|
import { runAbout } from './about.js';
|
|
8
8
|
import { openUrl } from '../utils/open-url.js';
|
|
9
9
|
const REPO_URL = 'https://github.com/jobshimo/browser-link';
|
|
10
|
-
import { ansi, classifyKey, clearScreen, hideCursor, readKey, renderBox, showCursor, } from './tty.js';
|
|
11
10
|
export const I18N_MENU = {
|
|
12
11
|
en: {
|
|
13
12
|
title: 'browser-link — setup',
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
outro: 'See you around. Run `browser-link` any time to come back.',
|
|
14
|
+
prompt: 'Pick an action',
|
|
16
15
|
options: {
|
|
17
|
-
register: 'Register browser-link
|
|
16
|
+
register: 'Register browser-link with an MCP client',
|
|
18
17
|
extension: 'Show Chrome extension install steps',
|
|
19
18
|
doctor: 'Run doctor (diagnose current setup)',
|
|
20
|
-
welcome: 'Show welcome screen',
|
|
19
|
+
welcome: 'Show the welcome screen',
|
|
21
20
|
about: 'About / Help — what is this and how it works',
|
|
22
|
-
repo: 'Open the GitHub repository
|
|
21
|
+
repo: 'Open the GitHub repository',
|
|
23
22
|
quit: 'Quit',
|
|
24
23
|
},
|
|
25
|
-
statusRegistered: '
|
|
24
|
+
statusRegistered: 'registered',
|
|
26
25
|
statusNotRegistered: 'not registered',
|
|
27
|
-
statusClientMissing: '
|
|
28
|
-
registerSuccessHint: 'Restart
|
|
26
|
+
statusClientMissing: 'not detected',
|
|
27
|
+
registerSuccessHint: 'Restart the MCP client so it picks up the new entry.',
|
|
29
28
|
repoOpened: 'Opening the repository in your browser…',
|
|
30
29
|
repoFallback: 'Could not open a browser automatically. Visit:',
|
|
30
|
+
pickClient: 'Which MCP client do you want to register?',
|
|
31
31
|
},
|
|
32
32
|
es: {
|
|
33
33
|
title: 'browser-link — configuración',
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
outro: 'Hasta luego. Ejecutá `browser-link` cuando quieras volver.',
|
|
35
|
+
prompt: 'Elegí una acción',
|
|
36
36
|
options: {
|
|
37
|
-
register: 'Registrar browser-link en
|
|
37
|
+
register: 'Registrar browser-link en un cliente MCP',
|
|
38
38
|
extension: 'Ver pasos para instalar la extensión de Chrome',
|
|
39
39
|
doctor: 'Diagnóstico (estado actual de la instalación)',
|
|
40
|
-
welcome: 'Mostrar pantalla de bienvenida',
|
|
40
|
+
welcome: 'Mostrar la pantalla de bienvenida',
|
|
41
41
|
about: 'Información / ayuda — qué es esto y cómo funciona',
|
|
42
|
-
repo: 'Abrir el repositorio en GitHub
|
|
42
|
+
repo: 'Abrir el repositorio en GitHub',
|
|
43
43
|
quit: 'Salir',
|
|
44
44
|
},
|
|
45
|
-
statusRegistered: '
|
|
45
|
+
statusRegistered: 'registrado',
|
|
46
46
|
statusNotRegistered: 'no registrado',
|
|
47
|
-
statusClientMissing: '
|
|
48
|
-
registerSuccessHint: 'Reiniciá
|
|
47
|
+
statusClientMissing: 'no detectado',
|
|
48
|
+
registerSuccessHint: 'Reiniciá el cliente MCP para que tome la nueva entrada.',
|
|
49
49
|
repoOpened: 'Abriendo el repositorio en tu navegador…',
|
|
50
50
|
repoFallback: 'No se pudo abrir el navegador automáticamente. Visitá:',
|
|
51
|
+
pickClient: '¿En qué cliente MCP querés registrar browser-link?',
|
|
51
52
|
},
|
|
52
53
|
};
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
function clientStatusLine(t) {
|
|
55
|
+
return INSTALLERS.map((inst) => {
|
|
56
|
+
const d = inst.detect();
|
|
57
|
+
const status = !d.installed
|
|
58
|
+
? t.statusClientMissing
|
|
59
|
+
: d.registered
|
|
60
|
+
? t.statusRegistered
|
|
61
|
+
: t.statusNotRegistered;
|
|
62
|
+
return `${inst.displayName.padEnd(10)} ${status}`;
|
|
63
|
+
}).join('\n');
|
|
58
64
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
65
|
+
async function pickClient(t) {
|
|
66
|
+
// When only one installer is wired, skip the picker.
|
|
67
|
+
if (INSTALLERS.length === 1)
|
|
68
|
+
return INSTALLERS[0].id;
|
|
69
|
+
const choice = (await p.select({
|
|
70
|
+
message: t.pickClient,
|
|
71
|
+
options: INSTALLERS.map((inst) => {
|
|
72
|
+
const d = inst.detect();
|
|
73
|
+
const hint = !d.installed
|
|
74
|
+
? t.statusClientMissing
|
|
75
|
+
: d.registered
|
|
76
|
+
? t.statusRegistered
|
|
77
|
+
: t.statusNotRegistered;
|
|
78
|
+
return { value: inst.id, label: inst.displayName, hint };
|
|
79
|
+
}),
|
|
80
|
+
}));
|
|
81
|
+
if (p.isCancel(choice))
|
|
82
|
+
return null;
|
|
83
|
+
return choice;
|
|
72
84
|
}
|
|
73
|
-
async function
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
? `${ansi.green}✓${ansi.reset}`
|
|
89
|
-
: `${ansi.gray}·${ansi.reset}`;
|
|
90
|
-
console.log(`${mark} ${ansi.bold}${report.displayName}${ansi.reset}: ${report.message}`);
|
|
91
|
-
if (report.installedClient)
|
|
92
|
-
console.log(` ${ansi.cyan}→${ansi.reset} ${t.registerSuccessHint}`);
|
|
93
|
-
await pressEnter(t);
|
|
94
|
-
return { keep: true, language: lang };
|
|
85
|
+
async function runAction(t, action, language) {
|
|
86
|
+
switch (action) {
|
|
87
|
+
case 'register': {
|
|
88
|
+
const client = await pickClient(t);
|
|
89
|
+
if (!client)
|
|
90
|
+
return { keep: true, language };
|
|
91
|
+
const report = installFor(client);
|
|
92
|
+
if (report.installedClient) {
|
|
93
|
+
p.log.success(`${report.displayName}: ${report.message}`);
|
|
94
|
+
p.log.info(t.registerSuccessHint);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
p.log.warn(`${report.displayName}: ${report.message}`);
|
|
98
|
+
}
|
|
99
|
+
return { keep: true, language };
|
|
95
100
|
}
|
|
96
|
-
case
|
|
97
|
-
clearScreen();
|
|
101
|
+
case 'extension': {
|
|
98
102
|
printExtensionInstructions();
|
|
99
|
-
|
|
100
|
-
return { keep: true, language: lang };
|
|
103
|
+
return { keep: true, language };
|
|
101
104
|
}
|
|
102
|
-
case
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
console.log(
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
case 'doctor': {
|
|
106
|
+
const report = await runDoctor();
|
|
107
|
+
// Plain print — the doctor output has its own structure and is wide.
|
|
108
|
+
console.log('');
|
|
109
|
+
console.log(formatDoctor(report));
|
|
110
|
+
console.log('');
|
|
111
|
+
return { keep: true, language };
|
|
108
112
|
}
|
|
109
|
-
case
|
|
110
|
-
|
|
111
|
-
// user explicitly asked to see it).
|
|
112
|
-
const result = await runWelcome({ initial: lang, hideDismiss: true });
|
|
113
|
+
case 'welcome': {
|
|
114
|
+
const result = await runWelcome({ initial: language, hideDismiss: true });
|
|
113
115
|
if (result.action === 'quit')
|
|
114
|
-
return { keep: false, language
|
|
115
|
-
|
|
116
|
-
return { keep: true, language: lang };
|
|
116
|
+
return { keep: false, language };
|
|
117
|
+
return { keep: true, language: result.language };
|
|
117
118
|
}
|
|
118
|
-
case
|
|
119
|
-
await runAbout(
|
|
120
|
-
return { keep: true, language
|
|
119
|
+
case 'about': {
|
|
120
|
+
await runAbout(language);
|
|
121
|
+
return { keep: true, language };
|
|
121
122
|
}
|
|
122
|
-
case
|
|
123
|
-
clearScreen();
|
|
123
|
+
case 'repo': {
|
|
124
124
|
const ok = openUrl(REPO_URL);
|
|
125
125
|
if (ok) {
|
|
126
|
-
|
|
127
|
-
console.log(` ${ansi.dim}${REPO_URL}${ansi.reset}`);
|
|
126
|
+
p.log.info(`${t.repoOpened}\n ${REPO_URL}`);
|
|
128
127
|
}
|
|
129
128
|
else {
|
|
130
|
-
|
|
131
|
-
console.log(` ${ansi.cyan}${REPO_URL}${ansi.reset}`);
|
|
129
|
+
p.log.warn(`${t.repoFallback}\n ${REPO_URL}`);
|
|
132
130
|
}
|
|
133
|
-
|
|
134
|
-
return { keep: true, language: lang };
|
|
131
|
+
return { keep: true, language };
|
|
135
132
|
}
|
|
136
|
-
case
|
|
137
|
-
return { keep: false, language
|
|
138
|
-
default:
|
|
139
|
-
return { keep: true, language: lang };
|
|
133
|
+
case 'quit':
|
|
134
|
+
return { keep: false, language };
|
|
140
135
|
}
|
|
141
136
|
}
|
|
142
137
|
export async function runMenu(initialLanguage = 'en') {
|
|
143
138
|
let language = initialLanguage;
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
t.options.
|
|
152
|
-
t.options.
|
|
153
|
-
t.options.
|
|
154
|
-
t.options.
|
|
155
|
-
t.options.
|
|
156
|
-
t.options.
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
return;
|
|
164
|
-
if (key === 'up') {
|
|
165
|
-
selected = (selected - 1 + opts.length) % opts.length;
|
|
166
|
-
continue;
|
|
167
|
-
}
|
|
168
|
-
if (key === 'down') {
|
|
169
|
-
selected = (selected + 1) % opts.length;
|
|
170
|
-
continue;
|
|
171
|
-
}
|
|
172
|
-
if (key === 'enter') {
|
|
173
|
-
showCursor();
|
|
174
|
-
const result = await runOption(t, selected, language);
|
|
175
|
-
if (!result.keep)
|
|
176
|
-
return;
|
|
177
|
-
language = result.language;
|
|
178
|
-
hideCursor();
|
|
179
|
-
}
|
|
139
|
+
p.intro(I18N_MENU[language].title);
|
|
140
|
+
while (true) {
|
|
141
|
+
const t = I18N_MENU[language];
|
|
142
|
+
p.note(clientStatusLine(t), 'MCP clients');
|
|
143
|
+
const action = (await p.select({
|
|
144
|
+
message: t.prompt,
|
|
145
|
+
options: [
|
|
146
|
+
{ value: 'register', label: t.options.register },
|
|
147
|
+
{ value: 'extension', label: t.options.extension },
|
|
148
|
+
{ value: 'doctor', label: t.options.doctor },
|
|
149
|
+
{ value: 'welcome', label: t.options.welcome },
|
|
150
|
+
{ value: 'about', label: t.options.about },
|
|
151
|
+
{ value: 'repo', label: t.options.repo },
|
|
152
|
+
{ value: 'quit', label: t.options.quit },
|
|
153
|
+
],
|
|
154
|
+
}));
|
|
155
|
+
if (p.isCancel(action)) {
|
|
156
|
+
p.outro(t.outro);
|
|
157
|
+
return;
|
|
180
158
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
159
|
+
const result = await runAction(t, action, language);
|
|
160
|
+
if (!result.keep) {
|
|
161
|
+
p.outro(I18N_MENU[result.language].outro);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
language = result.language;
|
|
185
165
|
}
|
|
186
166
|
}
|
|
187
167
|
//# sourceMappingURL=menu.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu.js","sourceRoot":"","sources":["../../src/commands/menu.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"menu.js","sourceRoot":"","sources":["../../src/commands/menu.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,21 +13,22 @@ export interface WelcomeOptions {
|
|
|
13
13
|
}
|
|
14
14
|
interface I18n {
|
|
15
15
|
title: string;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
aboutTitle: string;
|
|
17
|
+
about: string;
|
|
18
|
+
capabilitiesTitle: string;
|
|
19
|
+
capabilities: string;
|
|
20
|
+
warningTitle: string;
|
|
21
|
+
warning: string;
|
|
19
22
|
responsibility: string;
|
|
20
23
|
extensionNote: string;
|
|
21
|
-
|
|
24
|
+
prompt: string;
|
|
25
|
+
options: {
|
|
22
26
|
accept: string;
|
|
23
27
|
dismiss: string;
|
|
24
28
|
swap: string;
|
|
25
29
|
quit: string;
|
|
26
30
|
};
|
|
27
|
-
prompt: string;
|
|
28
|
-
promptNoDismiss: string;
|
|
29
31
|
}
|
|
30
32
|
export declare const I18N_WELCOME: Record<Language, I18n>;
|
|
31
|
-
export declare function buildWelcomeScreen(t: I18n, hideDismiss: boolean): string;
|
|
32
33
|
export declare function runWelcome(opts?: WelcomeOptions): Promise<WelcomeResult>;
|
|
33
34
|
export {};
|
package/dist/commands/welcome.js
CHANGED
|
@@ -1,32 +1,29 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
2
|
import { saveConfig } from '../config.js';
|
|
3
|
-
import { ansi, classifyKey, clearScreen, hideCursor, readKey, renderBox, showCursor, } from './tty.js';
|
|
4
3
|
export const I18N_WELCOME = {
|
|
5
4
|
en: {
|
|
6
5
|
title: 'browser-link',
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
'
|
|
10
|
-
'
|
|
11
|
-
|
|
6
|
+
aboutTitle: 'What this is',
|
|
7
|
+
about: [
|
|
8
|
+
'An MCP server that opens a small WebSocket bridge between an MCP',
|
|
9
|
+
'client (Claude Code, OpenCode, …) and the Google Chrome tabs you',
|
|
10
|
+
'explicitly grant access to through a custom companion extension you',
|
|
11
|
+
'load locally.',
|
|
12
|
+
].join('\n'),
|
|
13
|
+
capabilitiesTitle: 'What the agent can do on a connected tab',
|
|
12
14
|
capabilities: [
|
|
13
|
-
'
|
|
14
|
-
'
|
|
15
|
-
'
|
|
16
|
-
'
|
|
17
|
-
' • Click and type into its elements',
|
|
18
|
-
' • Execute arbitrary JavaScript in the page context',
|
|
15
|
+
'• Navigate that tab to any URL',
|
|
16
|
+
'• Read its DOM, console and network traffic',
|
|
17
|
+
'• Click and type into its elements',
|
|
18
|
+
'• Execute arbitrary JavaScript in the page context',
|
|
19
19
|
'',
|
|
20
|
-
'Tabs you do not connect remain invisible to the agent.
|
|
21
|
-
'
|
|
22
|
-
'',
|
|
23
|
-
'
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
],
|
|
20
|
+
'Tabs you do not connect remain invisible to the agent. Each one is',
|
|
21
|
+
'enabled one by one, by hand. The server also remembers what it learns',
|
|
22
|
+
'about each app across sessions in a local SQLite map (selectors,',
|
|
23
|
+
'flows, gotchas — never uploaded anywhere).',
|
|
24
|
+
].join('\n'),
|
|
25
|
+
warningTitle: '⚠ Read this before you continue',
|
|
27
26
|
warning: [
|
|
28
|
-
`${ansi.bold}${ansi.yellow}⚠ Read this before you continue${ansi.reset}`,
|
|
29
|
-
'',
|
|
30
27
|
'Connecting a tab gives the agent access to whatever is on it — any',
|
|
31
28
|
'logged-in session, saved card, wallet, banking page, work console or',
|
|
32
29
|
'admin panel the browser is currently showing on that tab.',
|
|
@@ -38,48 +35,40 @@ export const I18N_WELCOME = {
|
|
|
38
35
|
'Only connect tabs where you would be comfortable letting an automated',
|
|
39
36
|
'process act on your behalf. Disconnect a tab from the extension popup',
|
|
40
37
|
'when you are done with it.',
|
|
41
|
-
],
|
|
42
|
-
responsibility: 'You are responsible for every action the agent performs on the tabs '
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
'The setup menu after this screen will tell you where it lives so ' +
|
|
47
|
-
'you can load it via chrome://extensions → Load unpacked.',
|
|
48
|
-
actions: {
|
|
38
|
+
].join('\n'),
|
|
39
|
+
responsibility: 'You are responsible for every action the agent performs on the tabs you explicitly enable. The extension stays inert on any tab where you have not pressed "Conectar" yourself.',
|
|
40
|
+
extensionNote: 'The Chrome extension is custom and ships inside this package. The setup menu after this screen will tell you where it lives so you can load it via chrome://extensions → Load unpacked.',
|
|
41
|
+
prompt: 'How do you want to proceed?',
|
|
42
|
+
options: {
|
|
49
43
|
accept: 'I understand, continue',
|
|
50
44
|
dismiss: "Accept and don't show again",
|
|
51
45
|
swap: 'Switch to español',
|
|
52
46
|
quit: 'Quit',
|
|
53
47
|
},
|
|
54
|
-
prompt: 'Press [A] to accept, [D] to accept & hide next time, [L] for español, [Q] to quit.',
|
|
55
|
-
promptNoDismiss: 'Press [A] to continue, [L] for español, [Q] to quit.',
|
|
56
48
|
},
|
|
57
49
|
es: {
|
|
58
50
|
title: 'browser-link',
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
'
|
|
62
|
-
'
|
|
63
|
-
|
|
51
|
+
aboutTitle: 'Qué es esto',
|
|
52
|
+
about: [
|
|
53
|
+
'Un servidor MCP que abre un puente WebSocket entre un cliente MCP',
|
|
54
|
+
'(Claude Code, OpenCode, …) y las pestañas de Google Chrome a las que',
|
|
55
|
+
'vos le des acceso explícito a través de una extensión que cargás vos',
|
|
56
|
+
'manualmente.',
|
|
57
|
+
].join('\n'),
|
|
58
|
+
capabilitiesTitle: 'Qué puede hacer el agente en una pestaña conectada',
|
|
64
59
|
capabilities: [
|
|
65
|
-
'
|
|
66
|
-
'
|
|
67
|
-
'
|
|
68
|
-
'
|
|
69
|
-
' • Hacer click y escribir en sus elementos',
|
|
70
|
-
' • Ejecutar JavaScript arbitrario en el contexto de la página',
|
|
71
|
-
'',
|
|
72
|
-
'Las pestañas que NO conectes siguen invisibles para el agente. Podés',
|
|
73
|
-
'conectar todas las pestañas que quieras — cada una se habilita una por',
|
|
74
|
-
'una, a mano.',
|
|
60
|
+
'• Navegar esa pestaña a cualquier URL',
|
|
61
|
+
'• Leer su DOM, su consola y su tráfico de red',
|
|
62
|
+
'• Hacer click y escribir en sus elementos',
|
|
63
|
+
'• Ejecutar JavaScript arbitrario en el contexto de la página',
|
|
75
64
|
'',
|
|
76
|
-
'
|
|
77
|
-
'
|
|
78
|
-
'
|
|
79
|
-
|
|
65
|
+
'Las pestañas que NO conectes siguen invisibles para el agente. Cada',
|
|
66
|
+
'una se habilita una por una, a mano. El servidor además guarda lo que',
|
|
67
|
+
'aprende de cada app entre sesiones en un mapa SQLite local (selectores,',
|
|
68
|
+
'flujos, gotchas — nunca se sube a ningún lado).',
|
|
69
|
+
].join('\n'),
|
|
70
|
+
warningTitle: '⚠ Leelo antes de continuar',
|
|
80
71
|
warning: [
|
|
81
|
-
`${ansi.bold}${ansi.yellow}⚠ Leelo antes de continuar${ansi.reset}`,
|
|
82
|
-
'',
|
|
83
72
|
'Conectar una pestaña le da al agente acceso a todo lo que esté en esa',
|
|
84
73
|
'pestaña: sesiones iniciadas, tarjetas guardadas, wallets, banca,',
|
|
85
74
|
'consolas de trabajo, paneles de administración… lo que el navegador',
|
|
@@ -93,85 +82,53 @@ export const I18N_WELCOME = {
|
|
|
93
82
|
'Solo conectá pestañas donde estarías cómodo dejando que un proceso',
|
|
94
83
|
'automatizado actúe en tu nombre. Desconectá la pestaña desde el popup',
|
|
95
84
|
'cuando termines de usarla.',
|
|
96
|
-
],
|
|
97
|
-
responsibility: 'Sos responsable de cada acción que el agente haga en las pestañas que '
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
'El menú que aparece después de esta pantalla te dice exactamente dónde ' +
|
|
102
|
-
'está para que la cargues vía chrome://extensions → Cargar sin empaquetar.',
|
|
103
|
-
actions: {
|
|
85
|
+
].join('\n'),
|
|
86
|
+
responsibility: 'Sos responsable de cada acción que el agente haga en las pestañas que habilitás explícitamente. La extensión se mantiene inerte en cualquier pestaña donde no hayas apretado "Conectar" vos mismo.',
|
|
87
|
+
extensionNote: 'La extensión de Chrome es custom y viene incluida en este paquete. El menú que aparece después de esta pantalla te dice exactamente dónde está para que la cargues vía chrome://extensions → Cargar sin empaquetar.',
|
|
88
|
+
prompt: '¿Cómo querés seguir?',
|
|
89
|
+
options: {
|
|
104
90
|
accept: 'Entendido, continuar',
|
|
105
91
|
dismiss: 'Aceptar y no volver a mostrar',
|
|
106
92
|
swap: 'Cambiar a English',
|
|
107
93
|
quit: 'Salir',
|
|
108
94
|
},
|
|
109
|
-
prompt: 'Pulsá [A] para aceptar, [D] para aceptar y ocultar la próxima vez, [L] para English, [Q] para salir.',
|
|
110
|
-
promptNoDismiss: 'Pulsá [A] para continuar, [L] para English, [Q] para salir.',
|
|
111
95
|
},
|
|
112
96
|
};
|
|
113
|
-
export function buildWelcomeScreen(t, hideDismiss) {
|
|
114
|
-
const lines = [];
|
|
115
|
-
lines.push(`${ansi.bold}${ansi.cyan}${t.title}${ansi.reset}`);
|
|
116
|
-
lines.push('');
|
|
117
|
-
for (const l of t.intro)
|
|
118
|
-
lines.push(l);
|
|
119
|
-
lines.push('');
|
|
120
|
-
for (const l of t.capabilities)
|
|
121
|
-
lines.push(l);
|
|
122
|
-
lines.push('');
|
|
123
|
-
for (const l of t.warning)
|
|
124
|
-
lines.push(l);
|
|
125
|
-
lines.push('');
|
|
126
|
-
lines.push(`${ansi.dim}${t.responsibility}${ansi.reset}`);
|
|
127
|
-
lines.push('');
|
|
128
|
-
lines.push(`${ansi.dim}${t.extensionNote}${ansi.reset}`);
|
|
129
|
-
lines.push('');
|
|
130
|
-
const acceptLine = ` ${ansi.green}[A]${ansi.reset} ${t.actions.accept}`;
|
|
131
|
-
const dismissLine = hideDismiss ? '' : ` ${ansi.green}[D]${ansi.reset} ${t.actions.dismiss}`;
|
|
132
|
-
const langLine = ` ${ansi.cyan}[L]${ansi.reset} ${t.actions.swap}`;
|
|
133
|
-
const quitLine = ` ${ansi.red}[Q]${ansi.reset} ${t.actions.quit}`;
|
|
134
|
-
if (hideDismiss) {
|
|
135
|
-
lines.push(`${acceptLine} ${langLine} ${quitLine}`);
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
lines.push(acceptLine);
|
|
139
|
-
lines.push(dismissLine);
|
|
140
|
-
lines.push(`${langLine} ${quitLine}`);
|
|
141
|
-
}
|
|
142
|
-
return renderBox(lines, { borderColor: ansi.gray });
|
|
143
|
-
}
|
|
144
97
|
export async function runWelcome(opts = {}) {
|
|
145
98
|
let lang = opts.initial ?? 'en';
|
|
146
99
|
const hideDismiss = opts.hideDismiss === true;
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
// ignore other keys
|
|
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 };
|
|
170
121
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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 };
|
|
175
132
|
}
|
|
176
133
|
}
|
|
177
134
|
//# sourceMappingURL=welcome.js.map
|