






















@@ -2,18 +2,28 @@ import {
22normalizeOptionalString,
33readStringValue,
44} from "openclaw/plugin-sdk/string-coerce-runtime";
5+import { formatErrorMessage } from "../../infra/errors.js";
56import type { BrowserRouteContext } from "../server-context.js";
67import {
78readBody,
89resolveTargetIdFromBody,
910resolveTargetIdFromQuery,
1011withPlaywrightRouteContext,
1112} from "./agent.shared.js";
13+import { readRouteFiniteNumber } from "./route-numeric.js";
1214import type { BrowserRequest, BrowserResponse, BrowserRouteRegistrar } from "./types.js";
1315import { asyncBrowserRoute, jsonError, toBoolean, toNumber, toStringOrEmpty } from "./utils.js";
14161517type StorageKind = "local" | "session";
161819+type GeolocationOptions = {
20+clear: boolean;
21+latitude?: number;
22+longitude?: number;
23+accuracy?: number;
24+origin?: string;
25+};
26+1727export function parseStorageKind(raw: string): StorageKind | null {
1828if (raw === "local" || raw === "session") {
1929return raw;
@@ -67,6 +77,49 @@ function parseStorageMutationFromRequest(req: BrowserRequest, res: BrowserRespon
6777return { body, parsed };
6878}
697980+function assertRange(
81+value: number | undefined,
82+fieldName: string,
83+min: number,
84+max: number,
85+): number | undefined {
86+if (value === undefined) {
87+return undefined;
88+}
89+if (value < min || value > max) {
90+throw new Error(`${fieldName} must be between ${min} and ${max}.`);
91+}
92+return value;
93+}
94+95+export function parseGeolocationOptions(body: Record<string, unknown>): GeolocationOptions {
96+const clear = toBoolean(body.clear) ?? false;
97+const origin = toStringOrEmpty(body.origin) || undefined;
98+if (clear) {
99+return { clear, origin };
100+}
101+const latitude = assertRange(
102+readRouteFiniteNumber(body.latitude, "latitude"),
103+"latitude",
104+-90,
105+90,
106+);
107+const longitude = assertRange(
108+readRouteFiniteNumber(body.longitude, "longitude"),
109+"longitude",
110+-180,
111+180,
112+);
113+const accuracy = readRouteFiniteNumber(body.accuracy, "accuracy");
114+if (accuracy !== undefined && accuracy < 0) {
115+throw new Error("accuracy must be non-negative.");
116+}
117+if (!clear && (latitude === undefined || longitude === undefined)) {
118+throw new Error("latitude and longitude are required (or set clear=true)");
119+}
120+return { clear, latitude, longitude, accuracy, origin };
121+}
122+70123export function registerBrowserAgentStorageRoutes(
71124app: BrowserRouteRegistrar,
72125ctx: BrowserRouteContext,
@@ -357,11 +410,12 @@ export function registerBrowserAgentStorageRoutes(
357410asyncBrowserRoute(async (req, res) => {
358411const body = readBody(req);
359412const targetId = resolveTargetIdFromBody(body);
360-const clear = toBoolean(body.clear) ?? false;
361-const latitude = toNumber(body.latitude);
362-const longitude = toNumber(body.longitude);
363-const accuracy = toNumber(body.accuracy) ?? undefined;
364-const origin = toStringOrEmpty(body.origin) || undefined;
413+let geolocation: GeolocationOptions;
414+try {
415+geolocation = parseGeolocationOptions(body);
416+} catch (err) {
417+return jsonError(res, 400, formatErrorMessage(err));
418+}
365419366420await withPlaywrightRouteContext({
367421 req,
@@ -373,11 +427,7 @@ export function registerBrowserAgentStorageRoutes(
373427await pw.setGeolocationViaPlaywright({
374428 cdpUrl,
375429targetId: tab.targetId,
376- latitude,
377- longitude,
378- accuracy,
379- origin,
380- clear,
430+ ...geolocation,
381431});
382432res.json({ ok: true, targetId: tab.targetId });
383433},
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。