@jobshimo/browser-link 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +102 -83
  3. package/dist/cli.js +50 -36
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/about.d.ts +17 -18
  6. package/dist/commands/about.js +149 -190
  7. package/dist/commands/about.js.map +1 -1
  8. package/dist/commands/updates.d.ts +19 -0
  9. package/dist/commands/updates.js +83 -0
  10. package/dist/commands/updates.js.map +1 -0
  11. package/dist/commands/welcome.d.ts +10 -8
  12. package/dist/commands/welcome.js +49 -128
  13. package/dist/commands/welcome.js.map +1 -1
  14. package/dist/extension/background.js +90 -90
  15. package/dist/extension/icons/icon.svg +14 -14
  16. package/dist/extension/manifest.json +28 -28
  17. package/dist/extension/popup.html +88 -88
  18. package/dist/installers/copilot.d.ts +2 -0
  19. package/dist/installers/copilot.js +72 -0
  20. package/dist/installers/copilot.js.map +1 -0
  21. package/dist/installers/index.d.ts +2 -3
  22. package/dist/installers/index.js +5 -4
  23. package/dist/installers/index.js.map +1 -1
  24. package/dist/installers/opencode.js +49 -21
  25. package/dist/installers/opencode.js.map +1 -1
  26. package/dist/installers/types.d.ts +1 -1
  27. package/dist/map/db.js +28 -28
  28. package/dist/map/queries.js +4 -4
  29. package/dist/tools/server-instructions.js +46 -46
  30. package/dist/ui/app.d.ts +7 -0
  31. package/dist/ui/app.js +62 -0
  32. package/dist/ui/app.js.map +1 -0
  33. package/dist/ui/components.d.ts +18 -0
  34. package/dist/ui/components.js +27 -0
  35. package/dist/ui/components.js.map +1 -0
  36. package/dist/ui/screens.d.ts +48 -0
  37. package/dist/ui/screens.js +291 -0
  38. package/dist/ui/screens.js.map +1 -0
  39. package/dist/ui/start.d.ts +6 -0
  40. package/dist/ui/start.js +19 -0
  41. package/dist/ui/start.js.map +1 -0
  42. package/dist/version.d.ts +2 -0
  43. package/dist/version.js +15 -0
  44. package/dist/version.js.map +1 -0
  45. package/package.json +69 -61
  46. package/dist/commands/menu.d.ts +0 -26
  47. package/dist/commands/menu.js +0 -187
  48. package/dist/commands/menu.js.map +0 -1
  49. package/dist/commands/tty.d.ts +0 -51
  50. package/dist/commands/tty.js +0 -148
  51. package/dist/commands/tty.js.map +0 -1
package/package.json CHANGED
@@ -1,61 +1,69 @@
1
- {
2
- "name": "@jobshimo/browser-link",
3
- "version": "0.0.1",
4
- "description": "MCP server that bridges Claude (and other MCP clients) to a Chrome tab, with a persistent UI map of selectors, flows and gotchas across sessions.",
5
- "keywords": [
6
- "mcp",
7
- "model-context-protocol",
8
- "claude",
9
- "chrome",
10
- "browser-automation",
11
- "ai-tools"
12
- ],
13
- "homepage": "https://github.com/jobshimo/browser-link#readme",
14
- "bugs": {
15
- "url": "https://github.com/jobshimo/browser-link/issues"
16
- },
17
- "repository": {
18
- "type": "git",
19
- "url": "git+https://github.com/jobshimo/browser-link.git",
20
- "directory": "packages/server"
21
- },
22
- "license": "MIT",
23
- "author": "Martín Miguel Bernal",
24
- "type": "module",
25
- "main": "./dist/index.js",
26
- "bin": {
27
- "browser-link": "./dist/cli.js"
28
- },
29
- "files": [
30
- "dist",
31
- "README.md",
32
- "LICENSE"
33
- ],
34
- "publishConfig": {
35
- "access": "public"
36
- },
37
- "scripts": {
38
- "build": "tsc",
39
- "dev": "tsx watch src/cli.ts",
40
- "start": "node dist/cli.js",
41
- "typecheck": "tsc --noEmit",
42
- "clean": "rm -rf dist",
43
- "test": "vitest run",
44
- "test:watch": "vitest",
45
- "prepublishOnly": "npm run clean && npm run build && node ./scripts/prepare-publish.mjs"
46
- },
47
- "dependencies": {
48
- "@modelcontextprotocol/sdk": "^1.0.0",
49
- "better-sqlite3": "^11.5.0",
50
- "env-paths": "^3.0.0",
51
- "ws": "^8.18.0"
52
- },
53
- "devDependencies": {
54
- "@types/better-sqlite3": "^7.6.11",
55
- "@types/node": "^22.0.0",
56
- "@types/ws": "^8.5.13",
57
- "tsx": "^4.19.0",
58
- "typescript": "^5.6.0",
59
- "vitest": "^3.1.4"
60
- }
61
- }
1
+ {
2
+ "name": "@jobshimo/browser-link",
3
+ "version": "0.2.0",
4
+ "description": "MCP server that bridges Claude Code, OpenCode, GitHub Copilot CLI and other MCP clients to a Chrome tab, with a persistent UI map of selectors, flows and gotchas across sessions.",
5
+ "keywords": [
6
+ "mcp",
7
+ "model-context-protocol",
8
+ "claude",
9
+ "claude-code",
10
+ "opencode",
11
+ "github-copilot",
12
+ "copilot-cli",
13
+ "chrome",
14
+ "browser-automation",
15
+ "ai-tools"
16
+ ],
17
+ "homepage": "https://github.com/jobshimo/browser-link#readme",
18
+ "bugs": {
19
+ "url": "https://github.com/jobshimo/browser-link/issues"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/jobshimo/browser-link.git",
24
+ "directory": "packages/server"
25
+ },
26
+ "license": "MIT",
27
+ "author": "Martín Miguel Bernal",
28
+ "type": "module",
29
+ "main": "./dist/index.js",
30
+ "bin": {
31
+ "browser-link": "./dist/cli.js"
32
+ },
33
+ "files": [
34
+ "dist",
35
+ "README.md",
36
+ "LICENSE"
37
+ ],
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "scripts": {
42
+ "build": "tsc",
43
+ "dev": "tsx watch src/cli.ts",
44
+ "try": "tsx src/cli.ts",
45
+ "start": "node dist/cli.js",
46
+ "typecheck": "tsc --noEmit",
47
+ "clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
48
+ "test": "vitest run",
49
+ "test:watch": "vitest",
50
+ "prepublishOnly": "npm run clean && npm run build && node ./scripts/prepare-publish.mjs"
51
+ },
52
+ "dependencies": {
53
+ "@modelcontextprotocol/sdk": "^1.0.0",
54
+ "better-sqlite3": "^11.5.0",
55
+ "env-paths": "^3.0.0",
56
+ "ink": "^5.2.1",
57
+ "react": "^18.3.1",
58
+ "ws": "^8.18.0"
59
+ },
60
+ "devDependencies": {
61
+ "@types/better-sqlite3": "^7.6.11",
62
+ "@types/node": "^22.0.0",
63
+ "@types/react": "^18.3.28",
64
+ "@types/ws": "^8.5.13",
65
+ "tsx": "^4.19.0",
66
+ "typescript": "^5.6.0",
67
+ "vitest": "^3.1.4"
68
+ }
69
+ }
@@ -1,26 +0,0 @@
1
- import { type Language } from './welcome.js';
2
- interface MenuI18n {
3
- title: string;
4
- prompt: string;
5
- pressEnter: string;
6
- options: {
7
- register: string;
8
- extension: string;
9
- doctor: string;
10
- welcome: string;
11
- about: string;
12
- repo: string;
13
- quit: string;
14
- };
15
- statusRegistered: string;
16
- statusNotRegistered: string;
17
- statusClientMissing: string;
18
- registerSuccessHint: string;
19
- repoOpened: string;
20
- repoFallback: string;
21
- }
22
- export declare const I18N_MENU: Record<Language, MenuI18n>;
23
- export declare function claudeStatus(t: MenuI18n): string;
24
- export declare function renderMenuScreen(t: MenuI18n, selectedIndex: number, options: string[]): string;
25
- export declare function runMenu(initialLanguage?: Language): Promise<void>;
26
- export {};
@@ -1,187 +0,0 @@
1
- import { stdout } from 'node:process';
2
- import { claudeInstaller } from '../installers/claude.js';
3
- import { installFor } from './install.js';
4
- import { formatDoctor, runDoctor } from './doctor.js';
5
- import { printExtensionInstructions } from './extension.js';
6
- import { runWelcome } from './welcome.js';
7
- import { runAbout } from './about.js';
8
- import { openUrl } from '../utils/open-url.js';
9
- const REPO_URL = 'https://github.com/jobshimo/browser-link';
10
- import { ansi, classifyKey, clearScreen, hideCursor, readKey, renderBox, showCursor, } from './tty.js';
11
- export const I18N_MENU = {
12
- en: {
13
- title: 'browser-link — setup',
14
- prompt: '↑/↓ to move, Enter to select, q to quit',
15
- pressEnter: 'Press Enter to return to the menu…',
16
- options: {
17
- register: 'Register browser-link in Claude Code',
18
- extension: 'Show Chrome extension install steps',
19
- doctor: 'Run doctor (diagnose current setup)',
20
- welcome: 'Show welcome screen',
21
- about: 'About / Help — what is this and how it works',
22
- repo: 'Open the GitHub repository (view code, report issues, contribute)',
23
- quit: 'Quit',
24
- },
25
- statusRegistered: 'already registered',
26
- statusNotRegistered: 'not registered',
27
- statusClientMissing: 'Claude config not found',
28
- registerSuccessHint: 'Restart Claude Code so it picks up the new MCP entry.',
29
- repoOpened: 'Opening the repository in your browser…',
30
- repoFallback: 'Could not open a browser automatically. Visit:',
31
- },
32
- es: {
33
- title: 'browser-link — configuración',
34
- prompt: '↑/↓ para moverte, Enter para elegir, q para salir',
35
- pressEnter: 'Pulsá Enter para volver al menú…',
36
- options: {
37
- register: 'Registrar browser-link en Claude Code',
38
- extension: 'Ver pasos para instalar la extensión de Chrome',
39
- doctor: 'Diagnóstico (estado actual de la instalación)',
40
- welcome: 'Mostrar pantalla de bienvenida',
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)',
43
- quit: 'Salir',
44
- },
45
- statusRegistered: 'ya registrado',
46
- statusNotRegistered: 'no registrado',
47
- statusClientMissing: 'config de Claude no encontrada',
48
- registerSuccessHint: 'Reiniciá Claude Code para que tome el nuevo MCP.',
49
- repoOpened: 'Abriendo el repositorio en tu navegador…',
50
- repoFallback: 'No se pudo abrir el navegador automáticamente. Visitá:',
51
- },
52
- };
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;
58
- }
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 });
72
- }
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 };
95
- }
96
- case 1: {
97
- clearScreen();
98
- printExtensionInstructions();
99
- await pressEnter(t);
100
- return { keep: true, language: lang };
101
- }
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 };
108
- }
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
- if (result.action === 'quit')
114
- return { keep: false, language: lang };
115
- lang = result.language;
116
- return { keep: true, language: lang };
117
- }
118
- case 4: {
119
- await runAbout(lang);
120
- return { keep: true, language: lang };
121
- }
122
- case 5: {
123
- clearScreen();
124
- const ok = openUrl(REPO_URL);
125
- if (ok) {
126
- console.log(`${ansi.cyan}→${ansi.reset} ${t.repoOpened}`);
127
- console.log(` ${ansi.dim}${REPO_URL}${ansi.reset}`);
128
- }
129
- else {
130
- console.log(`${ansi.yellow}!${ansi.reset} ${t.repoFallback}`);
131
- console.log(` ${ansi.cyan}${REPO_URL}${ansi.reset}`);
132
- }
133
- await pressEnter(t);
134
- return { keep: true, language: lang };
135
- }
136
- case 6:
137
- return { keep: false, language: lang };
138
- default:
139
- return { keep: true, language: lang };
140
- }
141
- }
142
- export async function runMenu(initialLanguage = 'en') {
143
- 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
- }
180
- }
181
- }
182
- finally {
183
- showCursor();
184
- stdout.write('\n');
185
- }
186
- }
187
- //# sourceMappingURL=menu.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"menu.js","sourceRoot":"","sources":["../../src/commands/menu.ts"],"names":[],"mappings":"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"}
@@ -1,51 +0,0 @@
1
- export declare const ansi: {
2
- reset: string;
3
- bold: string;
4
- dim: string;
5
- italic: string;
6
- underline: string;
7
- black: string;
8
- red: string;
9
- green: string;
10
- yellow: string;
11
- blue: string;
12
- magenta: string;
13
- cyan: string;
14
- white: string;
15
- gray: string;
16
- bgYellow: string;
17
- bgRed: string;
18
- clearScreen: string;
19
- hideCursor: string;
20
- showCursor: string;
21
- };
22
- export declare const KEY: {
23
- CTRL_C: string;
24
- ESC: string;
25
- ENTER_CR: string;
26
- ENTER_LF: string;
27
- UP: string;
28
- DOWN: string;
29
- RIGHT: string;
30
- LEFT: string;
31
- };
32
- /** Visible width of a string (ignores ANSI escape sequences). Treats every
33
- * other code point as 1 column — fine for ASCII + the Latin range we use. */
34
- export declare function visibleWidth(s: string): number;
35
- export declare function padRight(s: string, width: number): string;
36
- /** Wrap a line at the given width, preserving simple ANSI runs. */
37
- export declare function wrap(text: string, width: number): string[];
38
- export interface BoxOptions {
39
- width?: number;
40
- borderColor?: string;
41
- }
42
- /** Render an array of lines inside a rounded Unicode box. */
43
- export declare function renderBox(lines: string[], opts?: BoxOptions): string;
44
- /** Read a single keypress from stdin without echoing. Returns the raw key
45
- * (a control sequence for arrows, '\r' for enter, etc.). */
46
- export declare function readKey(): Promise<string>;
47
- /** Classify a raw key into a logical name. */
48
- export declare function classifyKey(raw: string): string;
49
- export declare function clearScreen(): void;
50
- export declare function hideCursor(): void;
51
- export declare function showCursor(): void;
@@ -1,148 +0,0 @@
1
- import { stdin, stdout } from 'node:process';
2
- /* ANSI helpers — no dependencies. Modern terminals (macOS Terminal, iTerm,
3
- * Windows Terminal, PowerShell 7+, every Linux TTY) understand these.
4
- * Old cmd.exe may render the box characters poorly but the flow still works. */
5
- const ESC = '\x1b';
6
- export const ansi = {
7
- reset: `${ESC}[0m`,
8
- bold: `${ESC}[1m`,
9
- dim: `${ESC}[2m`,
10
- italic: `${ESC}[3m`,
11
- underline: `${ESC}[4m`,
12
- black: `${ESC}[30m`,
13
- red: `${ESC}[31m`,
14
- green: `${ESC}[32m`,
15
- yellow: `${ESC}[33m`,
16
- blue: `${ESC}[34m`,
17
- magenta: `${ESC}[35m`,
18
- cyan: `${ESC}[36m`,
19
- white: `${ESC}[37m`,
20
- gray: `${ESC}[90m`,
21
- bgYellow: `${ESC}[43m`,
22
- bgRed: `${ESC}[41m`,
23
- clearScreen: `${ESC}[2J${ESC}[H`,
24
- hideCursor: `${ESC}[?25l`,
25
- showCursor: `${ESC}[?25h`,
26
- };
27
- export const KEY = {
28
- CTRL_C: '\x03',
29
- ESC: '\x1b',
30
- ENTER_CR: '\r',
31
- ENTER_LF: '\n',
32
- UP: '\x1b[A',
33
- DOWN: '\x1b[B',
34
- RIGHT: '\x1b[C',
35
- LEFT: '\x1b[D',
36
- };
37
- /** Visible width of a string (ignores ANSI escape sequences). Treats every
38
- * other code point as 1 column — fine for ASCII + the Latin range we use. */
39
- export function visibleWidth(s) {
40
- // eslint-disable-next-line no-control-regex
41
- return s.replace(/\x1b\[[0-9;?]*[a-zA-Z]/g, '').length;
42
- }
43
- export function padRight(s, width) {
44
- const diff = width - visibleWidth(s);
45
- return diff > 0 ? s + ' '.repeat(diff) : s;
46
- }
47
- /** Wrap a line at the given width, preserving simple ANSI runs. */
48
- export function wrap(text, width) {
49
- if (width <= 0)
50
- return [text];
51
- const lines = [];
52
- for (const paragraph of text.split('\n')) {
53
- if (visibleWidth(paragraph) <= width) {
54
- lines.push(paragraph);
55
- continue;
56
- }
57
- const words = paragraph.split(/\s+/);
58
- let cur = '';
59
- for (const w of words) {
60
- if (cur.length === 0) {
61
- cur = w;
62
- }
63
- else if (visibleWidth(cur) + 1 + visibleWidth(w) > width) {
64
- lines.push(cur);
65
- cur = w;
66
- }
67
- else {
68
- cur += ' ' + w;
69
- }
70
- }
71
- if (cur.length > 0)
72
- lines.push(cur);
73
- }
74
- return lines;
75
- }
76
- const B = {
77
- tl: '╭',
78
- tr: '╮',
79
- bl: '╰',
80
- br: '╯',
81
- h: '─',
82
- v: '│',
83
- };
84
- /** Render an array of lines inside a rounded Unicode box. */
85
- export function renderBox(lines, opts = {}) {
86
- const termWidth = stdout.columns ?? 80;
87
- // 86 cols comfortably fits the longest pre-formatted line in About
88
- // (tool name + padded description). Smaller terminals still get the cap.
89
- const width = Math.min(opts.width ?? 86, Math.max(40, termWidth - 2));
90
- const inner = width - 2; // 2 columns for the vertical borders
91
- const wrapped = lines.flatMap((l) => wrap(l, inner - 2)); // padding 1 each side
92
- const color = opts.borderColor ?? '';
93
- const reset = color ? ansi.reset : '';
94
- const top = `${color}${B.tl}${B.h.repeat(inner)}${B.tr}${reset}`;
95
- const bottom = `${color}${B.bl}${B.h.repeat(inner)}${B.br}${reset}`;
96
- const body = wrapped.map((l) => `${color}${B.v}${reset} ${padRight(l, inner - 2)} ${color}${B.v}${reset}`);
97
- return [top, ...body, bottom].join('\n');
98
- }
99
- /** Read a single keypress from stdin without echoing. Returns the raw key
100
- * (a control sequence for arrows, '\r' for enter, etc.). */
101
- export function readKey() {
102
- return new Promise((resolve) => {
103
- const wasRaw = stdin.isTTY ? stdin.isRaw : false;
104
- if (stdin.isTTY)
105
- stdin.setRawMode(true);
106
- stdin.resume();
107
- stdin.setEncoding('utf8');
108
- const onData = (data) => {
109
- const key = data.toString();
110
- stdin.off('data', onData);
111
- if (stdin.isTTY)
112
- stdin.setRawMode(wasRaw);
113
- stdin.pause();
114
- resolve(key);
115
- };
116
- stdin.on('data', onData);
117
- });
118
- }
119
- /** Classify a raw key into a logical name. */
120
- export function classifyKey(raw) {
121
- if (raw === KEY.CTRL_C)
122
- return 'ctrl-c';
123
- if (raw === KEY.ESC)
124
- return 'esc';
125
- if (raw === KEY.ENTER_CR || raw === KEY.ENTER_LF)
126
- return 'enter';
127
- if (raw === KEY.UP)
128
- return 'up';
129
- if (raw === KEY.DOWN)
130
- return 'down';
131
- if (raw === KEY.LEFT)
132
- return 'left';
133
- if (raw === KEY.RIGHT)
134
- return 'right';
135
- if (raw.length === 1)
136
- return raw.toLowerCase();
137
- return raw;
138
- }
139
- export function clearScreen() {
140
- stdout.write(ansi.clearScreen);
141
- }
142
- export function hideCursor() {
143
- stdout.write(ansi.hideCursor);
144
- }
145
- export function showCursor() {
146
- stdout.write(ansi.showCursor);
147
- }
148
- //# sourceMappingURL=tty.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tty.js","sourceRoot":"","sources":["../../src/commands/tty.ts"],"names":[],"mappings":"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"}