@btraut/browser-bridge 0.10.0 → 0.11.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.
- package/CHANGELOG.md +16 -0
- package/README.md +19 -5
- package/dist/api.js +63 -12
- package/dist/api.js.map +2 -2
- package/dist/index.js +61 -13
- package/dist/index.js.map +2 -2
- package/extension/dist/options-ui.js +4 -4
- package/extension/dist/options-ui.js.map +2 -2
- package/extension/manifest.json +1 -1
- package/package.json +1 -1
- package/skills/browser-bridge/skill.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,12 +6,28 @@ The format is based on "Keep a Changelog", and this project adheres to Semantic
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.11.0] - 2026-02-16
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Runtime routing now defaults to single-instance mode on `127.0.0.1:3210`; deterministic per-worktree ports are used only in explicit isolated mode.
|
|
14
|
+
- Core startup now probes fallback ports only in isolated mode and preserves existing runtime metadata fields (including `extension_id`) when persisting host/port updates.
|
|
15
|
+
- `browser-bridge dev activate` is now explicitly an isolated-worktree workflow command and persists `isolated_mode: true` in runtime metadata.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- Eliminated normal-workflow extension disconnects caused by hidden default port drift between Core/CLI and extension routing.
|
|
20
|
+
|
|
9
21
|
## [0.10.0] - 2026-02-15
|
|
10
22
|
|
|
11
23
|
### Added
|
|
12
24
|
|
|
13
25
|
- CLI: support `-v` as a short alias for `--version`, with the value resolved from the installed package metadata.
|
|
14
26
|
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- README: switch the header image to an absolute GitHub URL so it renders correctly on npm package pages.
|
|
30
|
+
|
|
15
31
|
## [0.9.0] - 2026-02-15
|
|
16
32
|
|
|
17
33
|
### Fixed
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<img src="docs/assets/readme-header.png" alt="Browser Bridge header graphic" width="720" />
|
|
1
|
+
<img src="https://raw.githubusercontent.com/btraut/browser-bridge/main/docs/assets/readme-header.png" alt="Browser Bridge header graphic" width="720" />
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@btraut/browser-bridge) [](https://www.npmjs.com/package/@btraut/browser-bridge) [](https://github.com/btraut/browser-bridge/actions/workflows/ci.yml) [](LICENSE)
|
|
4
4
|
|
|
@@ -260,9 +260,23 @@ claude mcp add --transport stdio browser-bridge \
|
|
|
260
260
|
|
|
261
261
|
</details>
|
|
262
262
|
|
|
263
|
-
##
|
|
263
|
+
## ✅ Default Runtime (Normal Usage)
|
|
264
264
|
|
|
265
|
-
|
|
265
|
+
For normal usage, Browser Bridge is zero-setup:
|
|
266
|
+
|
|
267
|
+
- Core and CLI default to `127.0.0.1:3210`.
|
|
268
|
+
- The extension also defaults to `3210`.
|
|
269
|
+
- You do not need `dev activate` unless you intentionally opt into isolated worktree routing.
|
|
270
|
+
|
|
271
|
+
Optional status check:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
browser-bridge dev info --json
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## 🔁 Isolated Multi-Worktree Dev Loop (Advanced)
|
|
278
|
+
|
|
279
|
+
Use this loop when you intentionally run multiple worktree instances in parallel.
|
|
266
280
|
|
|
267
281
|
1. Resolve runtime for the current worktree:
|
|
268
282
|
|
|
@@ -272,7 +286,7 @@ browser-bridge dev info --json
|
|
|
272
286
|
|
|
273
287
|
Use the `port`, `worktreeId`, `metadataPath`, and `logDir` from output.
|
|
274
288
|
|
|
275
|
-
2. Activate extension routing for this worktree
|
|
289
|
+
2. Activate isolated extension routing for this worktree:
|
|
276
290
|
|
|
277
291
|
```bash
|
|
278
292
|
browser-bridge dev activate --extension-id <id>
|
|
@@ -295,7 +309,7 @@ tail -n 80 .context/logs/browser-bridge/core.jsonl
|
|
|
295
309
|
tail -n 80 .context/logs/browser-bridge/mcp-adapter.jsonl
|
|
296
310
|
```
|
|
297
311
|
|
|
298
|
-
-
|
|
312
|
+
- Default mode port is `3210`. In isolated mode, port is worktree-specific. Use `browser-bridge dev info` if you are unsure (or pass explicit `--port` / `BROWSER_BRIDGE_CORE_PORT`).
|
|
299
313
|
|
|
300
314
|
## 🩺 Diagnostics
|
|
301
315
|
|
package/dist/api.js
CHANGED
|
@@ -103,6 +103,8 @@ var ENV_CORE_HOST = "BROWSER_BRIDGE_CORE_HOST";
|
|
|
103
103
|
var ENV_VISION_HOST = "BROWSER_VISION_CORE_HOST";
|
|
104
104
|
var ENV_CORE_PORT = "BROWSER_BRIDGE_CORE_PORT";
|
|
105
105
|
var ENV_VISION_PORT = "BROWSER_VISION_CORE_PORT";
|
|
106
|
+
var ENV_ISOLATED_MODE = "BROWSER_BRIDGE_ISOLATED_MODE";
|
|
107
|
+
var ENV_VISION_ISOLATED_MODE = "BROWSER_VISION_ISOLATED_MODE";
|
|
106
108
|
var RUNTIME_METADATA_RELATIVE_PATH = ".context/browser-bridge/dev.json";
|
|
107
109
|
var DEFAULT_LOG_DIRECTORY_RELATIVE_PATH = ".context/logs/browser-bridge";
|
|
108
110
|
var resolveCwd = (cwd) => (0, import_node_path.resolve)(cwd ?? process.cwd());
|
|
@@ -119,6 +121,22 @@ var normalizeHost = (value) => {
|
|
|
119
121
|
const trimmed = value.trim();
|
|
120
122
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
121
123
|
};
|
|
124
|
+
var parseBoolean = (value) => {
|
|
125
|
+
if (typeof value === "boolean") {
|
|
126
|
+
return value;
|
|
127
|
+
}
|
|
128
|
+
if (typeof value !== "string") {
|
|
129
|
+
return void 0;
|
|
130
|
+
}
|
|
131
|
+
const normalized = value.trim().toLowerCase();
|
|
132
|
+
if (normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on") {
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
if (normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off") {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
return void 0;
|
|
139
|
+
};
|
|
122
140
|
var parsePort = (value, label, invalidPolicy) => {
|
|
123
141
|
if (value === void 0 || value === null) {
|
|
124
142
|
return void 0;
|
|
@@ -202,6 +220,13 @@ var resolveEnvPortRaw = (env) => {
|
|
|
202
220
|
}
|
|
203
221
|
return env[ENV_VISION_PORT];
|
|
204
222
|
};
|
|
223
|
+
var resolveEnvIsolatedMode = (env) => {
|
|
224
|
+
const bridge = parseBoolean(env[ENV_ISOLATED_MODE]);
|
|
225
|
+
if (bridge !== void 0) {
|
|
226
|
+
return bridge;
|
|
227
|
+
}
|
|
228
|
+
return parseBoolean(env[ENV_VISION_ISOLATED_MODE]);
|
|
229
|
+
};
|
|
205
230
|
var sanitizeMetadata = (raw) => {
|
|
206
231
|
if (!raw || typeof raw !== "object") {
|
|
207
232
|
return null;
|
|
@@ -212,8 +237,9 @@ var sanitizeMetadata = (raw) => {
|
|
|
212
237
|
const gitRoot = normalizeHost(candidate.git_root);
|
|
213
238
|
const worktreeId = normalizeHost(candidate.worktree_id);
|
|
214
239
|
const extensionId = normalizeHost(candidate.extension_id);
|
|
240
|
+
const isolatedMode = parseBoolean(candidate.isolated_mode);
|
|
215
241
|
const updatedAt = normalizeHost(candidate.updated_at);
|
|
216
|
-
if (!host && port === void 0 && !gitRoot && !worktreeId && !extensionId && !updatedAt) {
|
|
242
|
+
if (!host && port === void 0 && !gitRoot && !worktreeId && !extensionId && isolatedMode === void 0 && !updatedAt) {
|
|
217
243
|
return null;
|
|
218
244
|
}
|
|
219
245
|
return {
|
|
@@ -222,6 +248,7 @@ var sanitizeMetadata = (raw) => {
|
|
|
222
248
|
git_root: gitRoot,
|
|
223
249
|
worktree_id: worktreeId,
|
|
224
250
|
extension_id: extensionId,
|
|
251
|
+
isolated_mode: isolatedMode,
|
|
225
252
|
updated_at: updatedAt
|
|
226
253
|
};
|
|
227
254
|
};
|
|
@@ -367,6 +394,11 @@ var resolveCoreRuntime = (options = {}) => {
|
|
|
367
394
|
options.strictEnvPort ? "throw" : "ignore"
|
|
368
395
|
);
|
|
369
396
|
const metadataPort = parsePort(metadata?.port, "port", "ignore");
|
|
397
|
+
const optionIsolatedMode = options.isolatedMode;
|
|
398
|
+
const envIsolatedMode = resolveEnvIsolatedMode(env);
|
|
399
|
+
const metadataIsolatedMode = metadata?.isolated_mode;
|
|
400
|
+
const isolatedMode = optionIsolatedMode ?? envIsolatedMode ?? metadataIsolatedMode ?? false;
|
|
401
|
+
const isolatedModeSource = optionIsolatedMode !== void 0 ? "option" : envIsolatedMode !== void 0 ? "env" : metadataIsolatedMode !== void 0 ? "metadata" : "default";
|
|
370
402
|
let port;
|
|
371
403
|
let portSource;
|
|
372
404
|
if (optionPort !== void 0) {
|
|
@@ -375,12 +407,15 @@ var resolveCoreRuntime = (options = {}) => {
|
|
|
375
407
|
} else if (envPort !== void 0) {
|
|
376
408
|
port = envPort;
|
|
377
409
|
portSource = "env";
|
|
378
|
-
} else if (metadataPort !== void 0) {
|
|
410
|
+
} else if (metadataPort !== void 0 && isolatedMode) {
|
|
379
411
|
port = metadataPort;
|
|
380
412
|
portSource = "metadata";
|
|
381
|
-
} else {
|
|
413
|
+
} else if (isolatedMode) {
|
|
382
414
|
port = deterministicPort;
|
|
383
415
|
portSource = "deterministic";
|
|
416
|
+
} else {
|
|
417
|
+
port = LEGACY_DEFAULT_PORT;
|
|
418
|
+
portSource = "default";
|
|
384
419
|
}
|
|
385
420
|
return {
|
|
386
421
|
host,
|
|
@@ -391,7 +426,9 @@ var resolveCoreRuntime = (options = {}) => {
|
|
|
391
426
|
metadata,
|
|
392
427
|
gitRoot,
|
|
393
428
|
worktreeId: resolveWorktreeId({ cwd: resolvedCwd, gitRoot }),
|
|
394
|
-
deterministicPort
|
|
429
|
+
deterministicPort,
|
|
430
|
+
isolatedMode,
|
|
431
|
+
isolatedModeSource
|
|
395
432
|
};
|
|
396
433
|
};
|
|
397
434
|
|
|
@@ -5086,6 +5123,26 @@ var createCoreServer = (options = {}) => {
|
|
|
5086
5123
|
};
|
|
5087
5124
|
};
|
|
5088
5125
|
var CORE_PORT_PROBE_ATTEMPTS = 20;
|
|
5126
|
+
var buildRuntimeMetadataForPersist = (runtime, resolvedPort) => ({
|
|
5127
|
+
...runtime.metadata ?? {},
|
|
5128
|
+
host: runtime.host,
|
|
5129
|
+
port: resolvedPort,
|
|
5130
|
+
git_root: runtime.gitRoot ?? runtime.metadata?.git_root,
|
|
5131
|
+
worktree_id: runtime.worktreeId ?? runtime.metadata?.worktree_id,
|
|
5132
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
5133
|
+
});
|
|
5134
|
+
var resolveProbePortsForRuntime = (runtime) => {
|
|
5135
|
+
if (!runtime.isolatedMode) {
|
|
5136
|
+
return [runtime.port];
|
|
5137
|
+
}
|
|
5138
|
+
if (runtime.portSource === "metadata" || runtime.portSource === "deterministic") {
|
|
5139
|
+
return createBoundedPortProbeSequence(
|
|
5140
|
+
runtime.port,
|
|
5141
|
+
CORE_PORT_PROBE_ATTEMPTS
|
|
5142
|
+
);
|
|
5143
|
+
}
|
|
5144
|
+
return [runtime.port];
|
|
5145
|
+
};
|
|
5089
5146
|
var resolveSessionTtlMs = () => {
|
|
5090
5147
|
const env = process.env.BROWSER_BRIDGE_SESSION_TTL_MS || process.env.BROWSER_VISION_SESSION_TTL_MS;
|
|
5091
5148
|
if (env) {
|
|
@@ -5175,7 +5232,7 @@ var startCoreServer = async (options = {}) => {
|
|
|
5175
5232
|
registry: options.registry,
|
|
5176
5233
|
logger
|
|
5177
5234
|
});
|
|
5178
|
-
const probePorts =
|
|
5235
|
+
const probePorts = resolveProbePortsForRuntime(runtime);
|
|
5179
5236
|
let lastAddressInUseError;
|
|
5180
5237
|
for (const candidatePort of probePorts) {
|
|
5181
5238
|
const listenStart = process.hrtime.bigint();
|
|
@@ -5198,13 +5255,7 @@ var startCoreServer = async (options = {}) => {
|
|
|
5198
5255
|
});
|
|
5199
5256
|
try {
|
|
5200
5257
|
writeRuntimeMetadata(
|
|
5201
|
-
|
|
5202
|
-
host: runtime.host,
|
|
5203
|
-
port: resolvedPort,
|
|
5204
|
-
git_root: runtime.gitRoot ?? void 0,
|
|
5205
|
-
worktree_id: runtime.worktreeId ?? void 0,
|
|
5206
|
-
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
5207
|
-
},
|
|
5258
|
+
buildRuntimeMetadataForPersist(runtime, resolvedPort),
|
|
5208
5259
|
{ metadataPath: runtime.metadataPath }
|
|
5209
5260
|
);
|
|
5210
5261
|
logger.info("core.runtime_metadata.persisted", {
|