@browserbridge/bbx 1.0.0 → 1.0.1

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 (52) hide show
  1. package/README.md +3 -1
  2. package/docs/api-reference.md +33 -33
  3. package/docs/mcp-vs-cli.md +104 -104
  4. package/docs/publishing.md +1 -3
  5. package/docs/quickstart.md +6 -6
  6. package/docs/unpacked-extension.md +72 -0
  7. package/manifest.json +3 -17
  8. package/package.json +44 -42
  9. package/packages/agent-client/src/cli-helpers.js +10 -5
  10. package/packages/agent-client/src/cli.js +65 -135
  11. package/packages/agent-client/src/client.js +37 -17
  12. package/packages/agent-client/src/command-registry.js +101 -69
  13. package/packages/agent-client/src/detect.js +3 -6
  14. package/packages/agent-client/src/install.js +10 -27
  15. package/packages/agent-client/src/mcp-config.js +11 -30
  16. package/packages/agent-client/src/runtime.js +41 -20
  17. package/packages/agent-client/src/setup-status.js +13 -28
  18. package/packages/extension/src/background-helpers.js +51 -36
  19. package/packages/extension/src/background-routing.js +11 -13
  20. package/packages/extension/src/background.js +562 -299
  21. package/packages/extension/src/content-script-helpers.js +17 -16
  22. package/packages/extension/src/content-script.js +175 -109
  23. package/packages/extension/src/sidepanel-helpers.js +3 -1
  24. package/packages/extension/ui/popup.js +39 -20
  25. package/packages/extension/ui/sidepanel.js +108 -191
  26. package/packages/extension/ui/ui.css +2 -1
  27. package/packages/mcp-server/src/handlers.js +546 -250
  28. package/packages/mcp-server/src/server.js +558 -257
  29. package/packages/native-host/bin/bridge-daemon.js +6 -2
  30. package/packages/native-host/bin/install-manifest.js +2 -2
  31. package/packages/native-host/bin/postinstall.js +4 -2
  32. package/packages/native-host/src/config.js +11 -7
  33. package/packages/native-host/src/daemon.js +143 -92
  34. package/packages/native-host/src/install-manifest.js +73 -22
  35. package/packages/native-host/src/native-host.js +55 -40
  36. package/packages/protocol/src/budget.js +3 -7
  37. package/packages/protocol/src/capabilities.js +3 -3
  38. package/packages/protocol/src/errors.js +11 -11
  39. package/packages/protocol/src/protocol.js +104 -71
  40. package/packages/protocol/src/registry.js +300 -45
  41. package/packages/protocol/src/summary.js +249 -106
  42. package/packages/protocol/src/types.js +1 -1
  43. package/skills/browser-bridge/SKILL.md +1 -1
  44. package/skills/browser-bridge/agents/openai.yaml +3 -3
  45. package/skills/browser-bridge/references/interaction.md +33 -11
  46. package/skills/browser-bridge/references/patch-workflow.md +3 -0
  47. package/skills/browser-bridge/references/protocol.md +125 -70
  48. package/skills/browser-bridge/references/tailwind.md +12 -11
  49. package/skills/browser-bridge/references/token-efficiency.md +23 -22
  50. package/skills/browser-bridge/references/ui-workflows.md +8 -0
  51. package/packages/extension/ui/offscreen.html +0 -6
  52. package/packages/extension/ui/offscreen.js +0 -61
@@ -22,12 +22,20 @@
22
22
  * }} PopupStateMessage
23
23
  */
24
24
 
25
- const nativeIndicator = /** @type {HTMLSpanElement} */ (document.getElementById('native-indicator'));
25
+ const nativeIndicator =
26
+ /** @type {HTMLSpanElement} */ (document.getElementById('native-indicator'));
26
27
  const button = /** @type {HTMLButtonElement} */ (document.getElementById('communication-action'));
27
- const accessEyebrow = /** @type {HTMLDivElement} */ (document.getElementById('popup-access-eyebrow'));
28
- const accessDetail = /** @type {HTMLParagraphElement} */ (document.getElementById('popup-access-detail'));
29
- const accessDisclosure = /** @type {HTMLParagraphElement} */ (document.getElementById('popup-disclosure'));
30
- const controlCard = /** @type {HTMLElement | null} */ (document.querySelector('.popup-control-card'));
28
+ const accessEyebrow = /** @type {HTMLDivElement} */ (
29
+ document.getElementById('popup-access-eyebrow')
30
+ );
31
+ const accessDetail = /** @type {HTMLParagraphElement} */ (
32
+ document.getElementById('popup-access-detail')
33
+ );
34
+ const accessDisclosure =
35
+ /** @type {HTMLParagraphElement} */ (document.getElementById('popup-disclosure'));
36
+ const controlCard = /** @type {HTMLElement | null} */ (
37
+ document.querySelector('.popup-control-card')
38
+ );
31
39
  const windowedPopup = isWindowedPopup();
32
40
  /** @type {number | null} */
33
41
  let popupScopeTabId = null;
@@ -53,7 +61,10 @@ async function resolveInitialScopeTabId() {
53
61
  }
54
62
 
55
63
  try {
56
- const [activeTab] = await chrome.tabs.query({ active: true, currentWindow: true });
64
+ const [activeTab] = await chrome.tabs.query({
65
+ active: true,
66
+ currentWindow: true,
67
+ });
57
68
  return typeof activeTab?.id === 'number' ? activeTab.id : null;
58
69
  } catch {
59
70
  return null;
@@ -69,7 +80,7 @@ async function connectPopupPort() {
69
80
  nextPort.onMessage.addListener(handlePopupMessage);
70
81
  nextPort.postMessage({
71
82
  type: 'state.request',
72
- ...(popupScopeTabId ? { scopeTabId: popupScopeTabId } : {})
83
+ ...(popupScopeTabId ? { scopeTabId: popupScopeTabId } : {}),
73
84
  });
74
85
  port = nextPort;
75
86
  }
@@ -109,7 +120,8 @@ function renderPopupState(currentTab) {
109
120
 
110
121
  if (!currentTab) {
111
122
  accessEyebrow.textContent = 'Window access unavailable';
112
- accessDetail.textContent = 'Open a normal web page to manage Browser Bridge for this Chrome window.';
123
+ accessDetail.textContent =
124
+ 'Open a normal web page to manage Browser Bridge for this Chrome window.';
113
125
  accessDisclosure.hidden = false;
114
126
  button.textContent = 'Enable Window Access';
115
127
  button.disabled = true;
@@ -121,17 +133,21 @@ function renderPopupState(currentTab) {
121
133
 
122
134
  if (currentTab.enabled && currentTab.restricted) {
123
135
  accessEyebrow.textContent = 'Window access enabled';
124
- accessDetail.textContent = 'This page cannot be interacted with. Switch to a normal web page to use Browser Bridge.';
136
+ accessDetail.textContent =
137
+ 'This page cannot be interacted with. Switch to a normal web page to use Browser Bridge.';
125
138
  accessDisclosure.hidden = false;
126
139
  } else if (currentTab.enabled) {
127
140
  accessEyebrow.textContent = 'Window access enabled';
128
- accessDetail.textContent = 'Your connected agent can inspect and interact with pages in this Chrome window.';
141
+ accessDetail.textContent =
142
+ 'Your connected agent can inspect and interact with pages in this Chrome window.';
129
143
  } else if (currentTab.accessRequested) {
130
144
  accessEyebrow.textContent = 'Window access requested';
131
- accessDetail.textContent = 'An agent requested access for this Chrome window. Enable it to allow page inspection and interaction.';
145
+ accessDetail.textContent =
146
+ 'An agent requested access for this Chrome window. Enable it to allow page inspection and interaction.';
132
147
  } else {
133
148
  accessEyebrow.textContent = 'Window access';
134
- accessDetail.textContent = 'Enable Browser Bridge to let your connected agent inspect and interact with pages in this Chrome window.';
149
+ accessDetail.textContent =
150
+ 'Enable Browser Bridge to let your connected agent inspect and interact with pages in this Chrome window.';
135
151
  }
136
152
 
137
153
  button.textContent = currentTab.enabled ? 'Disable Window Access' : 'Enable Window Access';
@@ -146,9 +162,7 @@ function renderPopupState(currentTab) {
146
162
  */
147
163
  function renderNativeStatus(connected) {
148
164
  if (!nativeIndicator) return;
149
- const label = connected
150
- ? 'Native host connected'
151
- : 'Native host disconnected';
165
+ const label = connected ? 'Native host connected' : 'Native host disconnected';
152
166
  nativeIndicator.dataset.connected = String(connected);
153
167
  nativeIndicator.title = label;
154
168
  nativeIndicator.setAttribute('aria-label', label);
@@ -162,7 +176,9 @@ function renderNativeStatus(connected) {
162
176
  } else if (!nativeDiagnosticTimer) {
163
177
  nativeDiagnosticTimer = setTimeout(() => {
164
178
  nativeDiagnosticTimer = null;
165
- showDiagnostic(`Native host unreachable. Run: npm install -g @browserbridge/bbx && ${getInstallCommand()}`);
179
+ showDiagnostic(
180
+ `Native host unreachable. Run: npm install -g @browserbridge/bbx && ${getInstallCommand()}`
181
+ );
166
182
  }, NATIVE_DIAGNOSTIC_DELAY_MS);
167
183
  }
168
184
  }
@@ -176,7 +192,8 @@ function showDiagnostic(message) {
176
192
  if (!el) {
177
193
  el = document.createElement('div');
178
194
  el.id = 'native-diagnostic';
179
- el.style.cssText = 'padding:8px 12px;margin:8px 0;background:var(--status-badge-bg,#fef3cd);color:var(--text-primary,#856404);border-radius:6px;font-size:12px;line-height:1.4';
195
+ el.style.cssText =
196
+ 'padding:8px 12px;margin:8px 0;background:var(--status-badge-bg,#fef3cd);color:var(--text-primary,#856404);border-radius:6px;font-size:12px;line-height:1.4';
180
197
  const container = document.querySelector('.popup-content') || document.body;
181
198
  container.prepend(el);
182
199
  }
@@ -202,7 +219,7 @@ function setCommunicationEnabled(enabled) {
202
219
  port.postMessage({
203
220
  type: 'scope.set_enabled',
204
221
  enabled,
205
- ...(scopedTabId ? { tabId: scopedTabId } : {})
222
+ ...(scopedTabId ? { tabId: scopedTabId } : {}),
206
223
  });
207
224
  }
208
225
 
@@ -255,7 +272,9 @@ async function resizeWindowToContent() {
255
272
  const panel = /** @type {HTMLElement | null} */ (document.querySelector('.panel-popup'));
256
273
  const panelRect = panel?.getBoundingClientRect();
257
274
  const contentWidth = Math.ceil(panelRect?.width ?? document.body.getBoundingClientRect().width);
258
- const contentHeight = Math.ceil(panelRect?.height ?? document.body.getBoundingClientRect().height);
275
+ const contentHeight = Math.ceil(
276
+ panelRect?.height ?? document.body.getBoundingClientRect().height
277
+ );
259
278
  const frameWidth = Math.max(window.outerWidth - window.innerWidth, 0);
260
279
  const frameHeight = Math.max(window.outerHeight - window.innerHeight, 0);
261
280
  const targetWidth = Math.min(Math.max(contentWidth + frameWidth + 2, 420), 560);
@@ -268,7 +287,7 @@ async function resizeWindowToContent() {
268
287
  /** @type {chrome.windows.UpdateInfo} */
269
288
  const updateInfo = {
270
289
  width: targetWidth,
271
- height: targetHeight
290
+ height: targetHeight,
272
291
  };
273
292
 
274
293
  if (typeof currentWindow.left === 'number' && typeof currentWindow.width === 'number') {