fix: keep extension relay list current (#1073)
Thanks @roshanasingh4. Co-authored-by: Roshan Singh <88576930+roshanasingh4@users.noreply.github.com>
This commit is contained in:
@@ -58,6 +58,7 @@
|
|||||||
- CLI: speed up `clawdbot sandbox-explain` by avoiding heavy plugin imports when normalizing channel ids.
|
- 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 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: 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.
|
- 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: 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.
|
- Agents: avoid duplicate sends by replying with `NO_REPLY` after `message` tool sends.
|
||||||
|
|||||||
@@ -90,6 +90,23 @@ function createMessageQueue(ws: WebSocket) {
|
|||||||
return { next };
|
return { next };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function waitForListMatch<T>(
|
||||||
|
fetchList: () => Promise<T>,
|
||||||
|
predicate: (value: T) => boolean,
|
||||||
|
timeoutMs = 2000,
|
||||||
|
intervalMs = 50,
|
||||||
|
): Promise<T> {
|
||||||
|
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", () => {
|
describe("chrome extension relay server", () => {
|
||||||
let cdpUrl = "";
|
let cdpUrl = "";
|
||||||
|
|
||||||
@@ -174,12 +191,21 @@ describe("chrome extension relay server", () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
const list2 = (await fetch(`${cdpUrl}/json/list`).then((r) => r.json())) as Array<{
|
const list2 = await waitForListMatch(
|
||||||
id?: string;
|
async () =>
|
||||||
url?: string;
|
(await fetch(`${cdpUrl}/json/list`).then((r) => r.json())) as Array<{
|
||||||
title?: string;
|
id?: string;
|
||||||
}>;
|
url?: string;
|
||||||
expect(list2.some((t) => t.id === "t1" && t.url === "https://www.derstandard.at/" && t.title === "DER STANDARD")).toBe(true);
|
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`);
|
const cdp = new WebSocket(`ws://127.0.0.1:${port}/cdp`);
|
||||||
await waitForOpen(cdp);
|
await waitForOpen(cdp);
|
||||||
|
|||||||
@@ -677,15 +677,15 @@ export function registerHooksCli(program: Command): void {
|
|||||||
for (const hookId of targets) {
|
for (const hookId of targets) {
|
||||||
const record = installs[hookId];
|
const record = installs[hookId];
|
||||||
if (!record) {
|
if (!record) {
|
||||||
defaultRuntime.log(chalk.yellow(`No install record for \"${hookId}\".`));
|
defaultRuntime.log(chalk.yellow(`No install record for "${hookId}".`));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (record.source !== "npm") {
|
if (record.source !== "npm") {
|
||||||
defaultRuntime.log(chalk.yellow(`Skipping \"${hookId}\" (source: ${record.source}).`));
|
defaultRuntime.log(chalk.yellow(`Skipping "${hookId}" (source: ${record.source}).`));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!record.spec) {
|
if (!record.spec) {
|
||||||
defaultRuntime.log(chalk.yellow(`Skipping \"${hookId}\" (missing npm spec).`));
|
defaultRuntime.log(chalk.yellow(`Skipping "${hookId}" (missing npm spec).`));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user