mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:40:44 +00:00
fix(browser): clarify DevToolsActivePort attach failures
This commit is contained in:
@@ -24,6 +24,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Anthropic/plugins: scope Anthropic `api: "anthropic-messages"` defaulting to Anthropic-owned providers, so `openai-codex` and other providers without an explicit `api` no longer get rewritten to the wrong transport. Fixes #64534.
|
||||
- fix(qqbot): add SSRF guard to direct-upload URL paths in uploadC2CMedia and uploadGroupMedia [AI-assisted]. (#69595) Thanks @pgondhi987.
|
||||
- fix(gateway): enforce allowRequestSessionKey gate on template-rendered mapping sessionKeys. (#69381) Thanks @pgondhi987.
|
||||
- Browser/Chrome MCP: surface `DevToolsActivePort` attach failures as browser-connectivity errors instead of a generic "waiting for tabs" timeout, and point signed-out fallbacks toward the managed `openclaw` profile.
|
||||
- Webchat/images: treat inline image attachments as media for empty-turn gating while still ignoring metadata-only blank turns. (#69474) Thanks @Jaswir.
|
||||
- Discord/think: only show `adaptive` in `/think` autocomplete for provider/model pairs that actually support provider-managed adaptive thinking, so GPT/OpenAI models no longer advertise an Anthropic-only option.
|
||||
- Thinking: only expose `max` for models that explicitly support provider max reasoning, and remap stored `max` settings to the largest supported thinking mode when users switch to another model.
|
||||
|
||||
@@ -471,6 +471,7 @@ Common signatures:
|
||||
- `browser.executablePath not found` → configured path is invalid.
|
||||
- `browser.cdpUrl must be http(s) or ws(s)` → the configured CDP URL uses an unsupported scheme such as `file:` or `ftp:`.
|
||||
- `browser.cdpUrl has invalid port` → the configured CDP URL has a bad or out-of-range port.
|
||||
- `Could not find DevToolsActivePort for chrome` → Chrome MCP existing-session could not attach to the selected browser data dir yet. Open the browser inspect page, enable remote debugging, keep the browser open, approve the first attach prompt, then retry. If signed-in state is not required, prefer the managed `openclaw` profile.
|
||||
- `No Chrome tabs found for profile="user"` → the Chrome MCP attach profile has no open local Chrome tabs.
|
||||
- `Remote CDP for profile "<name>" is not reachable` → the configured remote CDP endpoint is not reachable from the gateway host.
|
||||
- `Browser attachOnly is enabled ... not reachable` or `Browser attachOnly is enabled and CDP websocket ... is not reachable` → attach-only profile has no reachable target, or the HTTP endpoint answered but the CDP WebSocket still could not be opened.
|
||||
|
||||
@@ -123,6 +123,23 @@ export function createProfileAvailability({
|
||||
});
|
||||
};
|
||||
|
||||
const formatChromeMcpAttachFailure = (lastError: unknown): string => {
|
||||
const detail = lastError instanceof Error ? ` Last error: ${lastError.message}` : "";
|
||||
const message = lastError instanceof Error ? lastError.message : "";
|
||||
if (message.includes("DevToolsActivePort") || message.includes("Could not connect to Chrome")) {
|
||||
return (
|
||||
`Chrome MCP existing-session attach for profile "${profile.name}" could not connect to Chrome. ` +
|
||||
"Enable remote debugging in the browser inspect page, keep the browser open, approve the attach prompt, and retry. " +
|
||||
'If you do not need your signed-in browser session, use the managed "openclaw" profile instead.' +
|
||||
detail
|
||||
);
|
||||
}
|
||||
return (
|
||||
`Chrome MCP existing-session attach for profile "${profile.name}" timed out waiting for tabs to become available.` +
|
||||
` Approve the browser attach prompt, keep the browser open, and retry.${detail}`
|
||||
);
|
||||
};
|
||||
|
||||
const reconcileProfileRuntime = async (): Promise<void> => {
|
||||
const profileState = getProfileState();
|
||||
const reconcile = profileState.reconcile;
|
||||
@@ -181,11 +198,7 @@ export function createProfileAvailability({
|
||||
}
|
||||
await new Promise((r) => setTimeout(r, CHROME_MCP_ATTACH_READY_POLL_MS));
|
||||
}
|
||||
const detail = lastError instanceof Error ? ` Last error: ${lastError.message}` : "";
|
||||
throw new BrowserProfileUnavailableError(
|
||||
`Chrome MCP existing-session attach for profile "${profile.name}" timed out waiting for tabs to become available.` +
|
||||
` Approve the browser attach prompt, keep the browser open, and retry.${detail}`,
|
||||
);
|
||||
throw new BrowserProfileUnavailableError(formatChromeMcpAttachFailure(lastError));
|
||||
};
|
||||
|
||||
const ensureBrowserAvailable = async (): Promise<void> => {
|
||||
|
||||
@@ -75,6 +75,7 @@ beforeEach(() => {
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllEnvs();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
describe("browser server-context existing-session profile", () => {
|
||||
@@ -134,4 +135,25 @@ describe("browser server-context existing-session profile", () => {
|
||||
);
|
||||
expect(chromeMcp.closeChromeMcpSession).toHaveBeenCalledWith("chrome-live");
|
||||
});
|
||||
|
||||
it("surfaces DevToolsActivePort attach failures instead of a generic tab timeout", async () => {
|
||||
vi.useFakeTimers();
|
||||
fs.mkdirSync("/tmp/brave-profile", { recursive: true });
|
||||
vi.mocked(chromeMcp.listChromeMcpTabs).mockRejectedValue(
|
||||
new Error(
|
||||
"Could not connect to Chrome. Check if Chrome is running. Cause: Could not find DevToolsActivePort for chrome at /tmp/brave-profile/DevToolsActivePort",
|
||||
),
|
||||
);
|
||||
|
||||
const state = makeState();
|
||||
const ctx = createBrowserRouteContext({ getState: () => state });
|
||||
const live = ctx.forProfile("chrome-live");
|
||||
|
||||
const pending = live.ensureBrowserAvailable();
|
||||
const assertion = expect(pending).rejects.toThrow(
|
||||
/could not connect to Chrome.*managed "openclaw" profile.*DevToolsActivePort/s,
|
||||
);
|
||||
await vi.advanceTimersByTimeAsync(8_000);
|
||||
await assertion;
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user