diff --git a/CHANGELOG.md b/CHANGELOG.md index 04c309ff2..7b11baeff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ - CLI: speed up `clawdbot sandbox-explain` by avoiding heavy plugin imports when normalizing channel ids. - Browser: remote profile tab operations prefer persistent Playwright and avoid silent HTTP fallbacks. (#1057) — thanks @mukhtharcm. - Browser: remote profile tab ops follow-up: shared Playwright loader, Playwright-based focus, and more coverage (incl. opt-in live Browserless test). (follow-up to #1057) — thanks @mukhtharcm. +- Browser: refresh extension relay tab metadata after navigation so `/json/list` stays current. (#1073) — thanks @roshanasingh4. - WhatsApp: scope self-chat response prefix; inject pending-only group history and clear after any processed message. - Agents: drop unsigned Gemini tool calls and avoid JSON Schema `format` keyword collisions. - Agents: avoid duplicate sends by replying with `NO_REPLY` after `message` tool sends. diff --git a/src/browser/extension-relay.test.ts b/src/browser/extension-relay.test.ts index 172268832..04c9dc374 100644 --- a/src/browser/extension-relay.test.ts +++ b/src/browser/extension-relay.test.ts @@ -90,6 +90,23 @@ function createMessageQueue(ws: WebSocket) { return { next }; } +async function waitForListMatch( + fetchList: () => Promise, + predicate: (value: T) => boolean, + timeoutMs = 2000, + intervalMs = 50, +): Promise { + const deadline = Date.now() + timeoutMs; + while (true) { + const value = await fetchList(); + if (predicate(value)) return value; + if (Date.now() >= deadline) { + throw new Error("timeout waiting for list update"); + } + await new Promise((resolve) => setTimeout(resolve, intervalMs)); + } +} + describe("chrome extension relay server", () => { let cdpUrl = ""; @@ -174,12 +191,21 @@ describe("chrome extension relay server", () => { }), ); - const list2 = (await fetch(`${cdpUrl}/json/list`).then((r) => r.json())) as Array<{ - id?: string; - url?: string; - title?: string; - }>; - expect(list2.some((t) => t.id === "t1" && t.url === "https://www.derstandard.at/" && t.title === "DER STANDARD")).toBe(true); + const list2 = await waitForListMatch( + async () => + (await fetch(`${cdpUrl}/json/list`).then((r) => r.json())) as Array<{ + id?: string; + url?: string; + title?: string; + }>, + (list) => + list.some( + (t) => t.id === "t1" && t.url === "https://www.derstandard.at/" && t.title === "DER STANDARD", + ), + ); + expect( + list2.some((t) => t.id === "t1" && t.url === "https://www.derstandard.at/" && t.title === "DER STANDARD"), + ).toBe(true); const cdp = new WebSocket(`ws://127.0.0.1:${port}/cdp`); await waitForOpen(cdp); diff --git a/src/cli/hooks-cli.ts b/src/cli/hooks-cli.ts index a5a72cea2..6f4aa7f04 100644 --- a/src/cli/hooks-cli.ts +++ b/src/cli/hooks-cli.ts @@ -677,15 +677,15 @@ export function registerHooksCli(program: Command): void { for (const hookId of targets) { const record = installs[hookId]; if (!record) { - defaultRuntime.log(chalk.yellow(`No install record for \"${hookId}\".`)); + defaultRuntime.log(chalk.yellow(`No install record for "${hookId}".`)); continue; } if (record.source !== "npm") { - defaultRuntime.log(chalk.yellow(`Skipping \"${hookId}\" (source: ${record.source}).`)); + defaultRuntime.log(chalk.yellow(`Skipping "${hookId}" (source: ${record.source}).`)); continue; } if (!record.spec) { - defaultRuntime.log(chalk.yellow(`Skipping \"${hookId}\" (missing npm spec).`)); + defaultRuntime.log(chalk.yellow(`Skipping "${hookId}" (missing npm spec).`)); continue; }