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