Files
BrowserSkill/apps/extension/src/tools/network.ts
T
NianJiu 4549ed0892 fix(extension): make tool cancellation cooperative (#89)
Tool cancellation is now cooperative end-to-end: the queue stays busy until compensation completes, cancellation is checked cooperatively across the pipeline, the fallback window is compensated too, and cleanup_failed is surfaced explicitly. Includes a gated delayed-compensation E2E test.
2026-08-13 17:31:23 +08:00

69 lines
2.1 KiB
TypeScript

import { ChromiumCdp } from "@/browser-driver/chromium-cdp";
import type { SessionManager } from "@/session-manager/manager";
import type { NetworkParams, NetworkResult, RpcError } from "@/transport/types";
import {
type ChromeTabsApi,
chromeTabsApi,
isRpcError,
lookupSession,
parseBufferedReadBounds,
resolveTargetTab,
} from "./shared";
export interface NetworkCdpRunner {
trackSessionTab?(sessionId: string, tabId: number): void;
ensureNetworkCapture(tabId: number): Promise<void>;
networkEntriesSince(
tabId: number,
since: number | undefined,
limit: number,
maxTextChars: number,
): NetworkResult;
}
export interface NetworkDeps {
cdp: NetworkCdpRunner;
tabsApi: ChromeTabsApi;
}
function defaultNetworkDeps(): NetworkDeps {
return {
cdp: new ChromiumCdp(),
tabsApi: chromeTabsApi,
};
}
export async function handleNetwork(
manager: SessionManager,
params: NetworkParams,
deps: NetworkDeps = defaultNetworkDeps(),
signal?: AbortSignal,
): Promise<NetworkResult | RpcError> {
if (signal?.aborted) return { code: "cancelled", message: "network aborted" };
const ctxOrErr = lookupSession(manager, params, "network");
if (isRpcError(ctxOrErr)) return ctxOrErr;
const bounds = parseBufferedReadBounds(params);
if (isRpcError(bounds)) return bounds;
const target = await resolveTargetTab(manager, ctxOrErr, params.tab_id, deps.tabsApi);
if (isRpcError(target)) return target;
if (signal?.aborted) return { code: "cancelled", message: "network aborted" };
try {
if (signal?.aborted) return { code: "cancelled", message: "network aborted" };
deps.cdp.trackSessionTab?.(ctxOrErr.sessionId, target.tabId);
await deps.cdp.ensureNetworkCapture(target.tabId);
if (signal?.aborted) return { code: "cancelled", message: "network aborted" };
return deps.cdp.networkEntriesSince(
target.tabId,
bounds.since,
bounds.limit,
bounds.maxTextChars,
);
} catch (err) {
return {
code: "cdp_failed",
message: err instanceof Error ? err.message : String(err),
};
}
}