@btraut/browser-bridge 0.13.0 → 0.13.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.
- package/CHANGELOG.md +7 -0
- package/dist/api.js +157 -39
- package/dist/api.js.map +3 -3
- package/dist/index.js +90 -39
- package/dist/index.js.map +3 -3
- package/extension/dist/background.js +92 -80
- package/extension/dist/background.js.map +3 -3
- package/extension/manifest.json +1 -1
- package/package.json +1 -1
- package/skills/browser-bridge/skill.json +1 -1
|
@@ -1,56 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
var
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __commonJS = (cb, mod) => function __require() {
|
|
8
|
-
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
19
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
20
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
21
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
22
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
23
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
24
|
-
mod
|
|
25
|
-
));
|
|
26
|
-
|
|
27
|
-
// packages/shared/dist/contract-version.js
|
|
28
|
-
var require_contract_version = __commonJS({
|
|
29
|
-
"packages/shared/dist/contract-version.js"(exports) {
|
|
30
|
-
"use strict";
|
|
31
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
-
exports.resolveContractVersionMismatch = exports.DRIVE_WS_PROTOCOL_VERSION = exports.HTTP_CONTRACT_VERSION = exports.HTTP_CONTRACT_VERSION_HEADER = void 0;
|
|
33
|
-
exports.HTTP_CONTRACT_VERSION_HEADER = "x-browser-bridge-contract-version";
|
|
34
|
-
exports.HTTP_CONTRACT_VERSION = "2026-02-17.1";
|
|
35
|
-
exports.DRIVE_WS_PROTOCOL_VERSION = "2026-02-17.1";
|
|
36
|
-
var resolveContractVersionMismatch = (receivedVersion) => {
|
|
37
|
-
if (!receivedVersion || receivedVersion.trim().length === 0) {
|
|
38
|
-
return void 0;
|
|
39
|
-
}
|
|
40
|
-
if (receivedVersion === exports.HTTP_CONTRACT_VERSION) {
|
|
41
|
-
return void 0;
|
|
42
|
-
}
|
|
43
|
-
return {
|
|
44
|
-
expected: exports.HTTP_CONTRACT_VERSION,
|
|
45
|
-
received: receivedVersion
|
|
46
|
-
};
|
|
47
|
-
};
|
|
48
|
-
exports.resolveContractVersionMismatch = resolveContractVersionMismatch;
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
// packages/extension/src/background.ts
|
|
53
|
-
var import_contract_version = __toESM(require_contract_version());
|
|
1
|
+
// packages/shared/src/contract-version.ts
|
|
2
|
+
var DRIVE_WS_PROTOCOL_VERSION = "2026-02-17.1";
|
|
54
3
|
|
|
55
4
|
// packages/extension/src/error-sanitizer.ts
|
|
56
5
|
var TRAILING_PUNCTUATION_RE = /[.,;:!?]+$/;
|
|
@@ -487,6 +436,54 @@ var PermissionPromptController = class {
|
|
|
487
436
|
}
|
|
488
437
|
};
|
|
489
438
|
|
|
439
|
+
// packages/extension/src/drive-reliability.ts
|
|
440
|
+
var TRANSIENT_TAB_CHANNEL_ERROR_PATTERNS = [
|
|
441
|
+
"receiving end does not exist",
|
|
442
|
+
"message channel closed before a response was received",
|
|
443
|
+
"the message port closed before a response was received",
|
|
444
|
+
"extension port is moved into back/forward cache"
|
|
445
|
+
];
|
|
446
|
+
var TAB_CHANNEL_RETRY_DELAYS_MS = [120, 200, 320, 500, 750, 1e3, 1200];
|
|
447
|
+
var normalizePathname = (pathname) => {
|
|
448
|
+
if (pathname.length === 0) {
|
|
449
|
+
return "/";
|
|
450
|
+
}
|
|
451
|
+
if (pathname.length > 1 && pathname.endsWith("/")) {
|
|
452
|
+
return pathname.slice(0, -1);
|
|
453
|
+
}
|
|
454
|
+
return pathname;
|
|
455
|
+
};
|
|
456
|
+
var isTransientTabChannelError = (message) => {
|
|
457
|
+
if (typeof message !== "string") {
|
|
458
|
+
return false;
|
|
459
|
+
}
|
|
460
|
+
const normalized = message.toLowerCase();
|
|
461
|
+
return TRANSIENT_TAB_CHANNEL_ERROR_PATTERNS.some(
|
|
462
|
+
(pattern) => normalized.includes(pattern)
|
|
463
|
+
);
|
|
464
|
+
};
|
|
465
|
+
var getTabChannelRetryDelayMs = (attempt) => {
|
|
466
|
+
if (!Number.isInteger(attempt) || attempt < 1) {
|
|
467
|
+
return void 0;
|
|
468
|
+
}
|
|
469
|
+
return TAB_CHANNEL_RETRY_DELAYS_MS[attempt - 1];
|
|
470
|
+
};
|
|
471
|
+
var isLikelyNavigationCommitted = (requestedUrl, tabUrl) => {
|
|
472
|
+
if (typeof requestedUrl !== "string" || typeof tabUrl !== "string") {
|
|
473
|
+
return false;
|
|
474
|
+
}
|
|
475
|
+
if (requestedUrl === tabUrl) {
|
|
476
|
+
return true;
|
|
477
|
+
}
|
|
478
|
+
try {
|
|
479
|
+
const requested = new URL(requestedUrl);
|
|
480
|
+
const actual = new URL(tabUrl);
|
|
481
|
+
return requested.origin === actual.origin && normalizePathname(requested.pathname) === normalizePathname(actual.pathname) && requested.search === actual.search;
|
|
482
|
+
} catch {
|
|
483
|
+
return requestedUrl === tabUrl;
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
|
|
490
487
|
// packages/extension/src/connection-state.ts
|
|
491
488
|
var toIso = (ms) => new Date(ms).toISOString();
|
|
492
489
|
var ConnectionStateTracker = class {
|
|
@@ -1166,12 +1163,18 @@ var sendToTab = async (tabId, action, params, options) => {
|
|
|
1166
1163
|
chrome.tabs.sendMessage(tabId, message, (response) => {
|
|
1167
1164
|
const error = chrome.runtime.lastError;
|
|
1168
1165
|
if (error) {
|
|
1166
|
+
const retryable = isTransientTabChannelError(error.message);
|
|
1169
1167
|
finish({
|
|
1170
1168
|
ok: false,
|
|
1171
1169
|
error: {
|
|
1172
1170
|
code: "EVALUATION_FAILED",
|
|
1173
1171
|
message: error.message,
|
|
1174
|
-
retryable
|
|
1172
|
+
retryable,
|
|
1173
|
+
...retryable ? {
|
|
1174
|
+
details: {
|
|
1175
|
+
reason: "transient_tab_channel_error"
|
|
1176
|
+
}
|
|
1177
|
+
} : {}
|
|
1175
1178
|
}
|
|
1176
1179
|
});
|
|
1177
1180
|
return;
|
|
@@ -1191,27 +1194,20 @@ var sendToTab = async (tabId, action, params, options) => {
|
|
|
1191
1194
|
});
|
|
1192
1195
|
});
|
|
1193
1196
|
};
|
|
1194
|
-
|
|
1195
|
-
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt += 1) {
|
|
1197
|
+
for (let attempt = 1; ; attempt += 1) {
|
|
1196
1198
|
const result = await attemptSend();
|
|
1197
1199
|
if (result.ok) {
|
|
1198
1200
|
return result;
|
|
1199
1201
|
}
|
|
1200
|
-
|
|
1201
|
-
const isNoReceiver = typeof message === "string" && message.toLowerCase().includes("receiving end does not exist");
|
|
1202
|
-
if (!isNoReceiver || attempt === MAX_ATTEMPTS) {
|
|
1202
|
+
if (!isTransientTabChannelError(result.error?.message)) {
|
|
1203
1203
|
return result;
|
|
1204
1204
|
}
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
ok: false,
|
|
1209
|
-
error: {
|
|
1210
|
-
code: "INTERNAL",
|
|
1211
|
-
message: "Failed to send message to content script.",
|
|
1212
|
-
retryable: false
|
|
1205
|
+
const retryDelayMs = getTabChannelRetryDelayMs(attempt);
|
|
1206
|
+
if (retryDelayMs === void 0) {
|
|
1207
|
+
return result;
|
|
1213
1208
|
}
|
|
1214
|
-
|
|
1209
|
+
await delayMs(retryDelayMs);
|
|
1210
|
+
}
|
|
1215
1211
|
};
|
|
1216
1212
|
var refreshAgentTabBranding = async (tabId) => {
|
|
1217
1213
|
const result = await sendToTab(
|
|
@@ -1494,7 +1490,7 @@ var DriveSocket = class {
|
|
|
1494
1490
|
}
|
|
1495
1491
|
const params = {
|
|
1496
1492
|
version: manifest.version,
|
|
1497
|
-
protocol_version:
|
|
1493
|
+
protocol_version: DRIVE_WS_PROTOCOL_VERSION,
|
|
1498
1494
|
capabilities: buildNegotiatedCapabilities(debuggerCapabilityEnabled),
|
|
1499
1495
|
core_host: endpoint.host,
|
|
1500
1496
|
core_port: endpoint.port,
|
|
@@ -1817,26 +1813,38 @@ var DriveSocket = class {
|
|
|
1817
1813
|
tabId = await getDefaultTabId();
|
|
1818
1814
|
}
|
|
1819
1815
|
const waitMode = params.wait === "none" || params.wait === "domcontentloaded" ? params.wait : "domcontentloaded";
|
|
1816
|
+
const domContentLoadedSignal = waitMode === "domcontentloaded" ? waitForDomContentLoaded(tabId, 3e4) : null;
|
|
1817
|
+
const warnings = [];
|
|
1820
1818
|
await wrapChromeVoid(
|
|
1821
1819
|
(callback) => chrome.tabs.update(tabId, { url }, () => callback())
|
|
1822
1820
|
);
|
|
1823
1821
|
markTabActive(tabId);
|
|
1824
|
-
if (
|
|
1822
|
+
if (domContentLoadedSignal) {
|
|
1825
1823
|
try {
|
|
1826
|
-
await
|
|
1824
|
+
await domContentLoadedSignal;
|
|
1827
1825
|
} catch (error) {
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1826
|
+
const tab = await getTab(tabId).catch(() => void 0);
|
|
1827
|
+
if (tab && isLikelyNavigationCommitted(url, tab.url ?? void 0)) {
|
|
1828
|
+
warnings.push(
|
|
1829
|
+
"Timed out waiting for DOMContentLoaded, but the tab URL already updated to the requested target."
|
|
1830
|
+
);
|
|
1831
|
+
} else {
|
|
1832
|
+
respondError({
|
|
1833
|
+
code: "TIMEOUT",
|
|
1834
|
+
message: error instanceof Error ? error.message : "Timed out waiting.",
|
|
1835
|
+
retryable: true
|
|
1836
|
+
});
|
|
1837
|
+
return;
|
|
1838
|
+
}
|
|
1834
1839
|
}
|
|
1835
1840
|
}
|
|
1836
1841
|
if (tabId === agentTabId) {
|
|
1837
1842
|
void refreshAgentTabBranding(tabId);
|
|
1838
1843
|
}
|
|
1839
|
-
respondOk({
|
|
1844
|
+
respondOk({
|
|
1845
|
+
ok: true,
|
|
1846
|
+
...warnings.length > 0 ? { warnings } : {}
|
|
1847
|
+
});
|
|
1840
1848
|
return;
|
|
1841
1849
|
}
|
|
1842
1850
|
case "drive.go_back":
|
|
@@ -1882,14 +1890,18 @@ var DriveSocket = class {
|
|
|
1882
1890
|
}
|
|
1883
1891
|
} catch {
|
|
1884
1892
|
if (!result.ok) {
|
|
1885
|
-
respondError(
|
|
1893
|
+
respondError({
|
|
1894
|
+
...result.error
|
|
1895
|
+
});
|
|
1886
1896
|
return;
|
|
1887
1897
|
}
|
|
1888
1898
|
}
|
|
1889
1899
|
if (tabId === agentTabId) {
|
|
1890
1900
|
void refreshAgentTabBranding(tabId);
|
|
1891
1901
|
}
|
|
1892
|
-
respondOk({
|
|
1902
|
+
respondOk({
|
|
1903
|
+
ok: true
|
|
1904
|
+
});
|
|
1893
1905
|
return;
|
|
1894
1906
|
}
|
|
1895
1907
|
case "drive.tab_list": {
|