@browserbridge/bbx 1.0.1 → 1.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.
Files changed (63) hide show
  1. package/README.md +4 -4
  2. package/package.json +11 -13
  3. package/packages/agent-client/src/cli-helpers.js +33 -0
  4. package/packages/agent-client/src/cli.js +116 -41
  5. package/packages/agent-client/src/client.js +29 -4
  6. package/packages/agent-client/src/command-registry.js +3 -0
  7. package/packages/agent-client/src/detect.js +159 -48
  8. package/packages/agent-client/src/install.js +24 -1
  9. package/packages/agent-client/src/mcp-config.js +29 -10
  10. package/packages/agent-client/src/setup-status.js +12 -4
  11. package/packages/mcp-server/src/bin.js +57 -5
  12. package/packages/mcp-server/src/handlers.js +28 -7
  13. package/packages/mcp-server/src/server.js +12 -2
  14. package/packages/native-host/bin/bridge-daemon.js +33 -4
  15. package/packages/native-host/bin/install-manifest.js +24 -2
  16. package/packages/native-host/src/config.js +131 -6
  17. package/packages/native-host/src/daemon-process.js +396 -0
  18. package/packages/native-host/src/daemon.js +217 -68
  19. package/packages/native-host/src/framing.js +131 -11
  20. package/packages/native-host/src/install-manifest.js +121 -7
  21. package/packages/native-host/src/native-host.js +110 -73
  22. package/packages/protocol/src/capabilities.js +3 -0
  23. package/packages/protocol/src/defaults.js +1 -0
  24. package/packages/protocol/src/errors.js +4 -0
  25. package/packages/protocol/src/payload-cost.js +19 -6
  26. package/packages/protocol/src/protocol.js +143 -7
  27. package/packages/protocol/src/registry.js +11 -0
  28. package/packages/protocol/src/summary.js +18 -10
  29. package/packages/protocol/src/types.js +28 -3
  30. package/skills/browser-bridge/SKILL.md +2 -1
  31. package/skills/browser-bridge/references/interaction.md +1 -0
  32. package/skills/browser-bridge/references/protocol.md +2 -1
  33. package/CHANGELOG.md +0 -55
  34. package/assets/banner.jpg +0 -0
  35. package/assets/logo.png +0 -0
  36. package/assets/logo.svg +0 -65
  37. package/docs/api-reference.md +0 -157
  38. package/docs/cli-guide.md +0 -128
  39. package/docs/index.md +0 -25
  40. package/docs/manual-setup.md +0 -140
  41. package/docs/mcp-vs-cli.md +0 -258
  42. package/docs/publishing.md +0 -112
  43. package/docs/quickstart.md +0 -104
  44. package/docs/troubleshooting.md +0 -59
  45. package/docs/unpacked-extension.md +0 -72
  46. package/docs/usage-scenarios.md +0 -136
  47. package/manifest.json +0 -38
  48. package/packages/extension/assets/icon-128.png +0 -0
  49. package/packages/extension/assets/icon-16.png +0 -0
  50. package/packages/extension/assets/icon-32.png +0 -0
  51. package/packages/extension/assets/icon-48.png +0 -0
  52. package/packages/extension/src/background-helpers.js +0 -474
  53. package/packages/extension/src/background-routing.js +0 -89
  54. package/packages/extension/src/background.js +0 -3490
  55. package/packages/extension/src/content-script-helpers.js +0 -282
  56. package/packages/extension/src/content-script.js +0 -2043
  57. package/packages/extension/src/debugger-coordinator.js +0 -188
  58. package/packages/extension/src/sidepanel-helpers.js +0 -104
  59. package/packages/extension/ui/popup.html +0 -35
  60. package/packages/extension/ui/popup.js +0 -298
  61. package/packages/extension/ui/sidepanel.html +0 -102
  62. package/packages/extension/ui/sidepanel.js +0 -1771
  63. package/packages/extension/ui/ui.css +0 -1160
@@ -1,282 +0,0 @@
1
- // @ts-check
2
-
3
- (() => {
4
- const globalState =
5
- /** @type {typeof globalThis & { __BBX_CONTENT_HELPERS__?: Record<string, unknown> }} */ (
6
- globalThis
7
- );
8
-
9
- if (globalState.__BBX_CONTENT_HELPERS__) {
10
- return;
11
- }
12
-
13
- /**
14
- * @typedef {{
15
- * maxNodes: number,
16
- * maxDepth: number,
17
- * textBudget: number,
18
- * includeBbox: boolean,
19
- * attributeAllowlist: string[]
20
- * }} Budget
21
- */
22
-
23
- const NON_TEXT_INPUT_TYPES = new Set([
24
- 'button',
25
- 'checkbox',
26
- 'color',
27
- 'file',
28
- 'hidden',
29
- 'image',
30
- 'radio',
31
- 'range',
32
- 'reset',
33
- 'submit',
34
- ]);
35
-
36
- /**
37
- * @param {number | string | null | undefined} value
38
- * @param {number} minimum
39
- * @param {number} maximum
40
- * @returns {number}
41
- */
42
- function clamp(value, minimum, maximum) {
43
- return Math.min(Math.max(Number(value) || minimum, minimum), maximum);
44
- }
45
-
46
- /**
47
- * @param {unknown} value
48
- * @returns {string[]}
49
- */
50
- function normalizeList(value) {
51
- if (!Array.isArray(value)) {
52
- return [];
53
- }
54
-
55
- return [...new Set(value.filter((item) => typeof item === 'string' && item.trim()))];
56
- }
57
-
58
- /**
59
- * @param {Record<string, any>} [options={}]
60
- * @returns {Budget}
61
- */
62
- function applyBudget(options = {}) {
63
- return {
64
- maxNodes: clamp(options.maxNodes ?? 25, 1, 250),
65
- maxDepth: clamp(options.maxDepth ?? 4, 1, 20),
66
- textBudget: clamp(options.textBudget ?? 600, 32, 10000),
67
- includeBbox: options.includeBbox !== false,
68
- attributeAllowlist: normalizeList(options.attributeAllowlist),
69
- };
70
- }
71
-
72
- /**
73
- * @param {string} value
74
- * @param {number} budget
75
- * @returns {{ value: string, truncated: boolean, omitted: number }}
76
- */
77
- function truncateText(value, budget) {
78
- if (!value) {
79
- return { value: '', truncated: false, omitted: 0 };
80
- }
81
-
82
- if (value.length <= budget) {
83
- return { value, truncated: false, omitted: 0 };
84
- }
85
-
86
- return {
87
- value: `${value.slice(0, Math.max(0, budget - 1))}\u2026`,
88
- truncated: true,
89
- omitted: value.length - budget,
90
- };
91
- }
92
-
93
- /**
94
- * @param {string} selector
95
- * @returns {string}
96
- */
97
- function escapeTailwindSelector(selector) {
98
- return selector.replace(
99
- /(\.[-\w]+)\[([^\]]+)\]/g,
100
- (_, prefix, value) => `${prefix}\\[${value}\\]`
101
- );
102
- }
103
-
104
- /**
105
- * @param {Element} el
106
- * @returns {string}
107
- */
108
- function getInputImplicitRole(el) {
109
- if (!(el instanceof HTMLInputElement)) return 'textbox';
110
- const type = el.type.toLowerCase();
111
- /** @type {Record<string, string>} */
112
- const map = {
113
- button: 'button',
114
- checkbox: 'checkbox',
115
- radio: 'radio',
116
- range: 'slider',
117
- search: 'searchbox',
118
- submit: 'button',
119
- reset: 'button',
120
- image: 'button',
121
- };
122
- return map[type] || 'textbox';
123
- }
124
-
125
- /**
126
- * @param {Element} el
127
- * @returns {string}
128
- */
129
- function getImplicitRole(el) {
130
- const tag = el.tagName.toLowerCase();
131
- /** @type {Record<string, string>} */
132
- const roleMap = {
133
- a: el.hasAttribute('href') ? 'link' : '',
134
- article: 'article',
135
- aside: 'complementary',
136
- button: 'button',
137
- dialog: 'dialog',
138
- footer: 'contentinfo',
139
- form: 'form',
140
- h1: 'heading',
141
- h2: 'heading',
142
- h3: 'heading',
143
- h4: 'heading',
144
- h5: 'heading',
145
- h6: 'heading',
146
- header: 'banner',
147
- img: 'img',
148
- input: getInputImplicitRole(el),
149
- li: 'listitem',
150
- main: 'main',
151
- nav: 'navigation',
152
- ol: 'list',
153
- option: 'option',
154
- progress: 'progressbar',
155
- section: 'region',
156
- select: 'listbox',
157
- table: 'table',
158
- td: 'cell',
159
- textarea: 'textbox',
160
- th: 'columnheader',
161
- tr: 'row',
162
- ul: 'list',
163
- };
164
- return roleMap[tag] || '';
165
- }
166
-
167
- /**
168
- * @param {string} role
169
- * @returns {string}
170
- */
171
- function getImplicitRoleSelector(role) {
172
- /** @type {Record<string, string>} */
173
- const map = {
174
- link: 'a[href]',
175
- article: 'article',
176
- complementary: 'aside',
177
- button:
178
- 'button, input[type=button], input[type=submit], input[type=reset], input[type=image]',
179
- dialog: 'dialog',
180
- contentinfo: 'footer',
181
- form: 'form',
182
- heading: 'h1, h2, h3, h4, h5, h6',
183
- banner: 'header',
184
- img: 'img',
185
- textbox:
186
- 'input:not([type=button]):not([type=checkbox]):not([type=radio]):not([type=range]):not([type=submit]):not([type=reset]):not([type=image]):not([type=hidden]), textarea',
187
- listitem: 'li',
188
- main: 'main',
189
- navigation: 'nav',
190
- list: 'ol, ul',
191
- option: 'option',
192
- progressbar: 'progress',
193
- region: 'section',
194
- listbox: 'select',
195
- table: 'table',
196
- cell: 'td',
197
- columnheader: 'th',
198
- row: 'tr',
199
- checkbox: 'input[type=checkbox]',
200
- radio: 'input[type=radio]',
201
- slider: 'input[type=range]',
202
- searchbox: 'input[type=search]',
203
- };
204
- return map[role] || '';
205
- }
206
-
207
- /**
208
- * @param {DOMRect | DOMRectReadOnly} rect
209
- * @returns {{ x: number, y: number, width: number, height: number }}
210
- */
211
- function toRect(rect) {
212
- return {
213
- x: rect.x + window.scrollX,
214
- y: rect.y + window.scrollY,
215
- width: rect.width,
216
- height: rect.height,
217
- };
218
- }
219
-
220
- /**
221
- * @param {string[]} values
222
- * @param {string | null | undefined} candidate
223
- * @returns {void}
224
- */
225
- function pushUnique(values, candidate) {
226
- if (!candidate) {
227
- return;
228
- }
229
-
230
- const normalized = candidate.replace(/\s+/g, ' ').trim();
231
- if (normalized && !values.includes(normalized)) {
232
- values.push(normalized);
233
- }
234
- }
235
-
236
- /**
237
- * @param {Element} element
238
- * @returns {string}
239
- */
240
- function extractElementText(element) {
241
- /** @type {string[]} */
242
- const parts = [];
243
-
244
- pushUnique(parts, element.getAttribute('aria-label'));
245
- pushUnique(parts, element.getAttribute('name'));
246
- pushUnique(parts, element.getAttribute('placeholder'));
247
- pushUnique(parts, element.getAttribute('title'));
248
-
249
- if ('value' in element && typeof element.value === 'string' && element.value.trim()) {
250
- pushUnique(parts, element.value);
251
- }
252
-
253
- const ownText = [...element.childNodes]
254
- .filter((node) => node.nodeType === Node.TEXT_NODE)
255
- .map((node) => node.textContent || '')
256
- .join(' ')
257
- .replace(/\s+/g, ' ')
258
- .trim();
259
-
260
- pushUnique(parts, ownText);
261
-
262
- if (!parts.length && element.childElementCount === 0) {
263
- pushUnique(parts, (element.textContent || '').replace(/\s+/g, ' ').trim());
264
- }
265
-
266
- return parts.join(' | ');
267
- }
268
-
269
- globalState.__BBX_CONTENT_HELPERS__ = Object.freeze({
270
- NON_TEXT_INPUT_TYPES,
271
- applyBudget,
272
- clamp,
273
- escapeTailwindSelector,
274
- extractElementText,
275
- getImplicitRole,
276
- getImplicitRoleSelector,
277
- getInputImplicitRole,
278
- normalizeList,
279
- toRect,
280
- truncateText,
281
- });
282
- })();