@remcp/runtime 0.2.179 → 0.2.180
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,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.180 — 2026-10-25
|
|
4
|
+
|
|
5
|
+
- Categorize lost CDP sessions, stale targets, navigation failures and browser guard failures without transmitting page content, URLs, target IDs or raw exception messages as telemetry categories.
|
|
6
|
+
- Treat nonempty `Page.navigate.errorText` as a failed tool call for both selected tabs and guarded new tabs.
|
|
7
|
+
- Preserve existing browser policies and existing runtime operation contracts; regression tests cover redaction and failure semantics.
|
|
8
|
+
|
|
9
|
+
|
|
3
10
|
## 0.2.176 — 2026-10-23
|
|
4
11
|
|
|
5
12
|
- Reduce screenshot CDP round-trips by batching viewport resolution with capture and reusing measured element dimensions.
|
package/package.json
CHANGED
package/src/error-classes.mjs
CHANGED
|
@@ -14,11 +14,28 @@ export function classifyRuntimeToolError(error, toolName = '') {
|
|
|
14
14
|
if (MISSING_CODES.has(code)) return 'not_found';
|
|
15
15
|
if (TIMEOUT_CODES.has(code)) return 'timeout';
|
|
16
16
|
if (browserTool && CONNECTION_CODES.has(code)) return 'browser_unavailable';
|
|
17
|
+
if (browserTool && code === 'BROWSER_TARGET_DISAPPEARED') return 'browser_target_stale';
|
|
17
18
|
if (/\bcancelled\b|\bcanceled\b|\baborted by the client\b/.test(message)) return 'cancelled';
|
|
18
19
|
if (/blocked (?:by|local|private)|outside the directories this device allows|private browser destination|blocked local browser scheme/.test(message)) return 'blocked';
|
|
19
20
|
if (browserTool && /browser cdp endpoint is unavailable|browser control is unavailable|cdp websocket (?:error|connection timed out)|local cdp endpoint did not become ready/.test(message)) {
|
|
20
21
|
return 'browser_unavailable';
|
|
21
22
|
}
|
|
23
|
+
if (browserTool) {
|
|
24
|
+
// Match only fixed CDP failure signatures; never emit the error text, tab ID,
|
|
25
|
+
// destination URL or selector as a telemetry category.
|
|
26
|
+
if (/browser child guard failed|browser request guard failed|browser safety guard failed/.test(message)) {
|
|
27
|
+
return 'browser_guard_failed';
|
|
28
|
+
}
|
|
29
|
+
if (/browser cdp target disappeared|target (?:was )?closed|no target with given id|target with given id not found|inspected target navigated or closed/.test(message)) {
|
|
30
|
+
return 'browser_target_stale';
|
|
31
|
+
}
|
|
32
|
+
if (/cdp websocket (?:closed|is not open)|session with given id not found|cdp session (?:closed|disconnected)/.test(message)) {
|
|
33
|
+
return 'browser_session_lost';
|
|
34
|
+
}
|
|
35
|
+
if (/browser navigation failed|cannot navigate (?:back|forward)|net::err_[a-z_]+/.test(message)) {
|
|
36
|
+
return 'browser_navigation_failed';
|
|
37
|
+
}
|
|
38
|
+
}
|
|
22
39
|
if (/permission denied|access is denied|not authorized|not authorised|accessibility permission/.test(message)) return 'permission';
|
|
23
40
|
if (/timed out|timeout after|time limit exceeded/.test(message)) return 'timeout';
|
|
24
41
|
if (/element not found|no element matches|no matching ui window|target not found|not found in the current/.test(message)) return 'not_found';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Page.navigate may resolve successfully while Chrome explicitly reports a
|
|
2
|
+
// navigation error. Treat that as a failed tool call, without echoing CDP's
|
|
3
|
+
// errorText (which may contain user data) into diagnostics.
|
|
4
|
+
export function requireSuccessfulBrowserNavigation(result) {
|
|
5
|
+
if (typeof result?.errorText === 'string' && result.errorText.trim()) {
|
|
6
|
+
throw new Error('Browser navigation failed: Chrome reported an unsuccessful navigation');
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { snapshotDelta } from './browser-snapshot-diff.mjs';
|
|
2
|
+
import { requireSuccessfulBrowserNavigation } from './browser-navigation-result.mjs';
|
|
2
3
|
import process from 'node:process';
|
|
3
4
|
import os from 'node:os';
|
|
4
5
|
import path from 'node:path';
|
|
@@ -75,6 +76,7 @@ export async function browserNavigate(args = {}) {
|
|
|
75
76
|
let historyUrl = null;
|
|
76
77
|
if (action === 'url') {
|
|
77
78
|
const result = await session.send('Page.navigate', { url });
|
|
79
|
+
requireSuccessfulBrowserNavigation(result);
|
|
78
80
|
frameId = result.frameId || null;
|
|
79
81
|
errorText = result.errorText || null;
|
|
80
82
|
} else if (action === 'reload') {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { requireSuccessfulBrowserNavigation } from './browser-navigation-result.mjs';
|
|
1
2
|
import process from 'node:process';
|
|
2
3
|
import os from 'node:os';
|
|
3
4
|
import path from 'node:path';
|
|
@@ -350,6 +351,7 @@ export async function createGuardedNewTab(url, args) {
|
|
|
350
351
|
await session.send('Page.enable');
|
|
351
352
|
const loaded = session.waitFor('Page.loadEventFired', clamp(args.timeout_ms, 15_000, 500, 120_000)).catch(() => null);
|
|
352
353
|
const navigation = await session.send('Page.navigate', { url });
|
|
354
|
+
requireSuccessfulBrowserNavigation(navigation);
|
|
353
355
|
if (loaded) await loaded;
|
|
354
356
|
const finalUrl = await evaluate(session, 'location.href');
|
|
355
357
|
await assertResolvedPageUrl(finalUrl);
|