mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-07 02:22:46 +00:00
fix(browser): accept top-level act fields with nested requests (#93674)
* fix(browser): accept top-level act fields with nested requests Co-authored-by: Capivariano <11271294+angelusbr@users.noreply.github.com> * fix(clownfish): address review for gitcrawl-416-autonomous-terminal-gap (1) Co-authored-by: Capivariano <11271294+angelusbr@users.noreply.github.com> --------- Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com> Co-authored-by: Capivariano <11271294+angelusbr@users.noreply.github.com>
This commit is contained in:
@@ -1435,6 +1435,73 @@ describe("browser tool act compatibility", () => {
|
||||
expect(opts.profile).toBeUndefined();
|
||||
});
|
||||
|
||||
it("backfills missing flattened fields into nested act requests", async () => {
|
||||
const tool = createBrowserTool();
|
||||
await tool.execute?.("call-1", {
|
||||
action: "act",
|
||||
kind: "click",
|
||||
ref: "f1e3",
|
||||
selector: "#title",
|
||||
targetId: "tab-1",
|
||||
timeoutMs: 5000,
|
||||
request: {
|
||||
kind: "click",
|
||||
doubleClick: true,
|
||||
},
|
||||
});
|
||||
|
||||
const request = lastMockCallArg<{
|
||||
kind?: string;
|
||||
ref?: string;
|
||||
selector?: string;
|
||||
targetId?: string;
|
||||
timeoutMs?: number;
|
||||
doubleClick?: boolean;
|
||||
}>(browserActionsMocks.browserAct, 1);
|
||||
expect(request).toEqual({
|
||||
kind: "click",
|
||||
ref: "f1e3",
|
||||
selector: "#title",
|
||||
targetId: "tab-1",
|
||||
timeoutMs: 5000,
|
||||
doubleClick: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps nested act request fields authoritative when flattened fields differ", async () => {
|
||||
const tool = createBrowserTool();
|
||||
await tool.execute?.("call-1", {
|
||||
action: "act",
|
||||
kind: "click",
|
||||
ref: "legacy-ref",
|
||||
selector: "#legacy",
|
||||
targetId: "legacy-tab",
|
||||
timeoutMs: 5000,
|
||||
request: {
|
||||
kind: "click",
|
||||
ref: "nested-ref",
|
||||
selector: "#nested",
|
||||
targetId: "nested-tab",
|
||||
timeoutMs: 7000,
|
||||
},
|
||||
});
|
||||
|
||||
const request = lastMockCallArg<{
|
||||
kind?: string;
|
||||
ref?: string;
|
||||
selector?: string;
|
||||
targetId?: string;
|
||||
timeoutMs?: number;
|
||||
}>(browserActionsMocks.browserAct, 1);
|
||||
expect(request).toEqual({
|
||||
kind: "click",
|
||||
ref: "nested-ref",
|
||||
selector: "#nested",
|
||||
targetId: "nested-tab",
|
||||
timeoutMs: 7000,
|
||||
});
|
||||
});
|
||||
|
||||
it("applies configured browser action timeout when act timeout is omitted", async () => {
|
||||
configMocks.loadConfig.mockReturnValue({ browser: { actionTimeoutMs: 45_000 } });
|
||||
|
||||
|
||||
@@ -163,6 +163,7 @@ function readTargetUrlParam(params: Record<string, unknown>) {
|
||||
}
|
||||
|
||||
const LEGACY_BROWSER_ACT_REQUEST_KEYS = [
|
||||
"kind",
|
||||
"targetId",
|
||||
"ref",
|
||||
"doubleClick",
|
||||
@@ -190,10 +191,31 @@ const LEGACY_BROWSER_ACT_REQUEST_KEYS = [
|
||||
"timeoutMs",
|
||||
] as const;
|
||||
|
||||
const LEGACY_BROWSER_ACT_SHARED_REQUEST_KEYS = new Set<
|
||||
(typeof LEGACY_BROWSER_ACT_REQUEST_KEYS)[number]
|
||||
>(["targetId"]);
|
||||
|
||||
function readActRequestParam(params: Record<string, unknown>) {
|
||||
const requestParam = params.request;
|
||||
if (requestParam && typeof requestParam === "object") {
|
||||
return requestParam as Parameters<typeof browserAct>[1];
|
||||
const request = { ...(requestParam as Record<string, unknown>) };
|
||||
const hasMismatchedKind =
|
||||
typeof request.kind === "string" &&
|
||||
typeof params.kind === "string" &&
|
||||
request.kind !== params.kind;
|
||||
for (const key of LEGACY_BROWSER_ACT_REQUEST_KEYS) {
|
||||
if (Object.hasOwn(request, key) || !Object.hasOwn(params, key)) {
|
||||
continue;
|
||||
}
|
||||
// Flattened act fields are legacy shape repair. Only the tab scope is
|
||||
// safe across kind mismatches; action-specific fields can corrupt the
|
||||
// explicit nested request.
|
||||
if (hasMismatchedKind && !LEGACY_BROWSER_ACT_SHARED_REQUEST_KEYS.has(key)) {
|
||||
continue;
|
||||
}
|
||||
request[key] = params[key];
|
||||
}
|
||||
return request as Parameters<typeof browserAct>[1];
|
||||
}
|
||||
|
||||
const kind = readStringParam(params, "kind");
|
||||
@@ -201,7 +223,7 @@ function readActRequestParam(params: Record<string, unknown>) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const request: Record<string, unknown> = { kind };
|
||||
const request: Record<string, unknown> = {};
|
||||
for (const key of LEGACY_BROWSER_ACT_REQUEST_KEYS) {
|
||||
if (!Object.hasOwn(params, key)) {
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user