@remcp/runtime 0.2.145 → 0.2.147

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 CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.147 — 2026-10-14
4
+
5
+ - Accelerated Chrome CDP tab discovery by validating existing page URLs with eight concurrent, bounded DNS/safety workers instead of sequential lookups.
6
+ - Limited enumeration to 1,000 candidate pages and 500 returned tabs while retaining ordering and the existing private-network/unsafe-scheme safety policy.
7
+ - Added regression coverage for concurrent discovery, ordered output, bounded work, and blocked pages; tool schemas and the 83-operation MCP surface remain unchanged.
8
+
9
+ ## 0.2.146 — 2026-10-04
10
+
11
+ - No local runtime tool behavior or schema changes. This patch keeps `@remcp/runtime` aligned with the ReMCP 0.2.146 OpenAI submission-metadata release.
12
+ - The 83-operation runtime surface and MCP annotations remain unchanged; the release only synchronizes reviewer-facing metadata required by the OpenAI Apps submission form.
13
+
3
14
  ## 0.2.145 — 2026-10-04
4
15
 
5
16
  - No local runtime tool behavior or schema changes. This patch keeps @remcp/runtime aligned with the ReMCP 0.2.145 Plugin Directory metadata release.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remcp/runtime",
3
- "version": "0.2.145",
3
+ "version": "0.2.147",
4
4
  "description": "First-party ReMCP local device runtime: filesystem, terminal, computer-use, browser, diagnostics and document tools over MCP.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -317,22 +317,43 @@ export async function browserCapabilityAvailable(endpoint, timeoutMs = 500) {
317
317
  }
318
318
  }
319
319
 
320
- export async function listBrowserTargets(endpoint) {
321
- assertBrowserRemoteEnabled();
322
- await ensureBrowserEndpoint(endpoint);
323
- const list = await requestJson('/json/list', endpoint);
320
+ // Validating every tab sequentially can require hundreds of serial DNS lookups,
321
+ // making browser_tabs exceed the relay's deadline on machines with many tabs.
322
+ // Keep DNS and security validation, but bound both the work and its concurrency.
323
+ export async function filterBrowserTargets(list, { validate = assertResolvedPageUrl } = {}) {
324
324
  if (!Array.isArray(list)) return [];
325
- const targets = [];
325
+ const candidates = [];
326
326
  for (const item of list) {
327
327
  if (!item || item.type !== 'page' || !item.webSocketDebuggerUrl) continue;
328
- try {
329
- await assertResolvedPageUrl(item.url);
330
- targets.push(item);
331
- } catch {}
328
+ candidates.push(item);
329
+ if (candidates.length >= 1000) break;
330
+ }
331
+ const safe = new Array(candidates.length).fill(false);
332
+ let cursor = 0;
333
+ await Promise.all(Array.from({ length: Math.min(8, candidates.length) }, async () => {
334
+ while (cursor < candidates.length) {
335
+ const index = cursor++;
336
+ try {
337
+ await validate(candidates[index].url);
338
+ safe[index] = true;
339
+ } catch {
340
+ // Exclude unsafe/unresolvable pages without exposing them to the caller.
341
+ }
342
+ }
343
+ }));
344
+ const targets = [];
345
+ for (let i = 0; i < candidates.length && targets.length < 500; i++) {
346
+ if (safe[i]) targets.push(candidates[i]);
332
347
  }
333
348
  return targets;
334
349
  }
335
350
 
351
+ export async function listBrowserTargets(endpoint) {
352
+ assertBrowserRemoteEnabled();
353
+ await ensureBrowserEndpoint(endpoint);
354
+ return filterBrowserTargets(await requestJson('/json/list', endpoint));
355
+ }
356
+
336
357
  function validatedTargetWebSocketUrl(target, endpoint) {
337
358
  let socketUrl;
338
359
  try { socketUrl = new URL(String(target?.webSocketDebuggerUrl)); }