feat(browser): complete camofox BrowserProvider with tabs, interaction, download capture and control lease
Contracts for browser API and browser.* agent capabilities; adapter implements close/list/restore sessions, tabs + reconcile, history, click/type/select/scroll/press, extract, waitForDownload (staged via DownloadSink, sha256), stale-ref guard and automation/human actor check. testkit mock camofox gains an interactive site (login redirect, captcha, click-driven page changes, downloads, PNG screenshots). Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
62290d4477
commit
c17d4b90bd
12 files changed
+1832
-101
No files matched your search
@@ -84,14 +84,13 @@ async function rejectKind(p: Promise<unknown>): Promise<string> {
|
||||
}
|
||||
|
||||
describe("能力声明", () => {
|
||||
it("静态声明:已实现能力 supported、M2 能力 false 并注明,默认全部未验证", () => {
|
||||
it("静态声明:全部能力 supported,verified 只来自配置;待核验项有注明", () => {
|
||||
const c = camofoxStaticCapabilities({ snapshot: true, interact: true });
|
||||
expect(c.navigate).toMatchObject({ supported: true, verified: false, source: "static" });
|
||||
expect(c.snapshot).toMatchObject({ supported: true, verified: true });
|
||||
// 未实现的能力即使配置了 verified 也不会被标为已验证
|
||||
expect(c.interact).toMatchObject({ supported: false, verified: false });
|
||||
expect(c.interact.note).toContain("M2");
|
||||
expect(c.takeover.supported).toBe(false);
|
||||
expect(c.interact).toMatchObject({ supported: true, verified: true });
|
||||
expect(c.interact.note).toContain("待核验");
|
||||
expect(c.takeover).toMatchObject({ supported: true, verified: false });
|
||||
expect(c.upstreamVersion).toBeNull();
|
||||
});
|
||||
|
||||
@@ -279,8 +278,8 @@ describe("串行锁", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("M2 未实现分支", () => {
|
||||
it("click/type/extract/waitForDownload/接管/关闭会话均抛 not_implemented", async () => {
|
||||
describe("未知会话", () => {
|
||||
it("交互/提取/下载/关闭对不存在的会话报 not_found;listSessions 只列内存镜像", async () => {
|
||||
const { provider } = await setup();
|
||||
const ref = { sessionId: "x" };
|
||||
const calls: Promise<unknown>[] = [
|
||||
@@ -288,18 +287,11 @@ describe("M2 未实现分支", () => {
|
||||
provider.type(ref, { ref: "e1" }, { kind: "text", text: "x" }),
|
||||
provider.extract(ref, {}),
|
||||
provider.waitForDownload(ref, { timeoutMs: 10, maxBytes: 10 }),
|
||||
provider.acquireControl({
|
||||
sessionId: "x",
|
||||
holderKind: "human",
|
||||
holder: "admin",
|
||||
reason: "登录验证",
|
||||
ttlMs: 1000,
|
||||
}),
|
||||
provider.releaseControl("lease"),
|
||||
provider.closeSession("x"),
|
||||
provider.listSessions(),
|
||||
];
|
||||
for (const c of calls) expect(await rejectKind(c)).toBe("not_implemented");
|
||||
for (const c of calls) expect(await rejectKind(c)).toBe("not_found");
|
||||
expect(await rejectKind(provider.releaseControl("lease"))).toBe("not_found");
|
||||
expect(await provider.listSessions()).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user