@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.
@@ -1,5 +1,5 @@
1
- import { stdout } from 'node:process';
2
- import { claudeInstaller } from '../installers/claude.js';
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
- prompt: '↑/↓ to move, Enter to select, q to quit',
15
- pressEnter: 'Press Enter to return to the menu…',
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 in Claude Code',
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 (view code, report issues, contribute)',
21
+ repo: 'Open the GitHub repository',
23
22
  quit: 'Quit',
24
23
  },
25
- statusRegistered: 'already registered',
24
+ statusRegistered: 'registered',
26
25
  statusNotRegistered: 'not registered',
27
- statusClientMissing: 'Claude config not found',
28
- registerSuccessHint: 'Restart Claude Code so it picks up the new MCP entry.',
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
- prompt: '↑/↓ para moverte, Enter para elegir, q para salir',
35
- pressEnter: 'Pulsá Enter para volver al menú…',
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 Claude Code',
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 (ver código, reportar bugs, contribuir)',
42
+ repo: 'Abrir el repositorio en GitHub',
43
43
  quit: 'Salir',
44
44
  },
45
- statusRegistered: 'ya registrado',
45
+ statusRegistered: 'registrado',
46
46
  statusNotRegistered: 'no registrado',
47
- statusClientMissing: 'config de Claude no encontrada',
48
- registerSuccessHint: 'Reiniciá Claude Code para que tome el nuevo MCP.',
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
- export function claudeStatus(t) {
54
- const d = claudeInstaller.detect();
55
- if (!d.installed)
56
- return t.statusClientMissing;
57
- return d.registered ? t.statusRegistered : t.statusNotRegistered;
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
- export function renderMenuScreen(t, selectedIndex, options) {
60
- const lines = [];
61
- lines.push(`${ansi.bold}${ansi.cyan}${t.title}${ansi.reset}`);
62
- lines.push('');
63
- options.forEach((label, i) => {
64
- const isSel = i === selectedIndex;
65
- const cursor = isSel ? `${ansi.cyan}❯${ansi.reset}` : ' ';
66
- const body = isSel ? `${ansi.bold}${label}${ansi.reset}` : `${ansi.gray}${label}${ansi.reset}`;
67
- lines.push(` ${cursor} ${body}`);
68
- });
69
- lines.push('');
70
- lines.push(`${ansi.dim}${t.prompt}${ansi.reset}`);
71
- return renderBox(lines, { borderColor: ansi.gray });
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 pressEnter(t) {
74
- stdout.write('\n' + ansi.dim + t.pressEnter + ansi.reset + ' ');
75
- while (true) {
76
- const k = classifyKey(await readKey());
77
- if (k === 'enter' || k === 'ctrl-c' || k === 'esc' || k === 'q')
78
- break;
79
- }
80
- }
81
- async function runOption(t, index, language) {
82
- let lang = language;
83
- switch (index) {
84
- case 0: {
85
- clearScreen();
86
- const report = installFor('claude');
87
- const mark = report.installedClient
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 1: {
97
- clearScreen();
101
+ case 'extension': {
98
102
  printExtensionInstructions();
99
- await pressEnter(t);
100
- return { keep: true, language: lang };
103
+ return { keep: true, language };
101
104
  }
102
- case 2: {
103
- clearScreen();
104
- const r = await runDoctor();
105
- console.log(formatDoctor(r));
106
- await pressEnter(t);
107
- return { keep: true, language: lang };
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 3: {
110
- // Show welcome again (forced; hides "Don't show again" because the
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: lang };
115
- lang = result.language;
116
- return { keep: true, language: lang };
116
+ return { keep: false, language };
117
+ return { keep: true, language: result.language };
117
118
  }
118
- case 4: {
119
- await runAbout(lang);
120
- return { keep: true, language: lang };
119
+ case 'about': {
120
+ await runAbout(language);
121
+ return { keep: true, language };
121
122
  }
122
- case 5: {
123
- clearScreen();
123
+ case 'repo': {
124
124
  const ok = openUrl(REPO_URL);
125
125
  if (ok) {
126
- console.log(`${ansi.cyan}→${ansi.reset} ${t.repoOpened}`);
127
- console.log(` ${ansi.dim}${REPO_URL}${ansi.reset}`);
126
+ p.log.info(`${t.repoOpened}\n ${REPO_URL}`);
128
127
  }
129
128
  else {
130
- console.log(`${ansi.yellow}!${ansi.reset} ${t.repoFallback}`);
131
- console.log(` ${ansi.cyan}${REPO_URL}${ansi.reset}`);
129
+ p.log.warn(`${t.repoFallback}\n ${REPO_URL}`);
132
130
  }
133
- await pressEnter(t);
134
- return { keep: true, language: lang };
131
+ return { keep: true, language };
135
132
  }
136
- case 6:
137
- return { keep: false, language: lang };
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
- let selected = 0;
145
- hideCursor();
146
- try {
147
- while (true) {
148
- const t = I18N_MENU[language];
149
- const opts = [
150
- `${t.options.register} ${ansi.dim}(${claudeStatus(t)})${ansi.reset}`,
151
- t.options.extension,
152
- t.options.doctor,
153
- t.options.welcome,
154
- t.options.about,
155
- t.options.repo,
156
- t.options.quit,
157
- ];
158
- clearScreen();
159
- stdout.write(renderMenuScreen(t, selected, opts));
160
- stdout.write('\n');
161
- const key = classifyKey(await readKey());
162
- if (key === 'ctrl-c' || key === 'esc' || key === 'q')
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
- finally {
183
- showCursor();
184
- stdout.write('\n');
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":"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"}
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
- intro: string[];
17
- capabilities: string[];
18
- warning: string[];
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
- actions: {
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 {};
@@ -1,32 +1,29 @@
1
- import { stdout } from 'node:process';
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
- intro: [
8
- 'An MCP server that opens a small WebSocket bridge between Claude Code',
9
- 'and the Google Chrome tabs you explicitly grant access to through a',
10
- 'custom companion extension you load locally.',
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
- 'On every tab where you press "Conectar" in the extension popup, the',
14
- 'agent can:',
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',
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. You can connect',
21
- 'as many tabs as you want — each one is enabled one by one, by hand.',
22
- '',
23
- 'And the server remembers what it learns about each app across sessions',
24
- 'in a local SQLite map (selectors, flows, gotchas — never uploaded',
25
- 'anywhere).',
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
- 'you explicitly enable. The extension stays inert on any tab where ' +
44
- 'you have not pressed "Conectar" yourself.',
45
- extensionNote: 'The Chrome extension is custom and ships inside this package. ' +
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
- intro: [
60
- 'Un servidor MCP que abre un puente WebSocket entre Claude Code y las',
61
- 'pestañas de Google Chrome a las que vos le des acceso explícito a',
62
- 'través de una extensión que cargás vos manualmente.',
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
- 'En cada pestaña donde pulsás "Conectar" en el popup de la extensión,',
66
- 'el agente puede:',
67
- ' Navegar esa pestaña a cualquier URL',
68
- ' Leer su DOM, su consola y su tráfico de red',
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
- 'Además el servidor guarda lo que aprende de cada app entre sesiones en',
77
- 'un mapa SQLite local (selectores, flujos, gotchas nunca se sube a',
78
- 'ningún lado).',
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
- 'habilitás explícitamente. La extensión se mantiene inerte en cualquier ' +
99
- 'pestaña donde no hayas apretado "Conectar" vos mismo.',
100
- extensionNote: 'La extensión de Chrome es custom y viene incluida en este paquete. ' +
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
- hideCursor();
148
- try {
149
- while (true) {
150
- const t = I18N_WELCOME[lang];
151
- clearScreen();
152
- stdout.write(buildWelcomeScreen(t, hideDismiss));
153
- stdout.write('\n\n');
154
- stdout.write(`${ansi.dim}${hideDismiss ? t.promptNoDismiss : t.prompt}${ansi.reset} `);
155
- const key = classifyKey(await readKey());
156
- if (key === 'a')
157
- return { action: 'continue', language: lang, persisted: false };
158
- if (key === 'd' && !hideDismiss) {
159
- saveConfig({ skipWelcome: true, language: lang });
160
- return { action: 'continue', language: lang, persisted: true };
161
- }
162
- if (key === 'l') {
163
- lang = lang === 'en' ? 'es' : 'en';
164
- continue;
165
- }
166
- if (key === 'q' || key === 'esc' || key === 'ctrl-c') {
167
- return { action: 'quit', language: lang, persisted: false };
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
- finally {
173
- showCursor();
174
- stdout.write('\n');
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