
























@@ -372,6 +372,43 @@ function shouldPreferHostForProfile(profileName: string | undefined) {
372372return capabilities.usesChromeMcp;
373373}
374374375+const DEFAULT_EXISTING_SESSION_MANAGE_TIMEOUT_MS = 45_000;
376+const EXISTING_SESSION_MANAGE_ACTIONS = new Set([
377+"status",
378+"start",
379+"stop",
380+"profiles",
381+"tabs",
382+"open",
383+"focus",
384+"close",
385+]);
386+387+function usesExistingSessionManageFlow(params: { action: string; profileName?: string }) {
388+if (!EXISTING_SESSION_MANAGE_ACTIONS.has(params.action)) {
389+return false;
390+}
391+const cfg = browserToolDeps.loadConfig();
392+const resolved = resolveBrowserConfig(cfg.browser, cfg);
393+const profile = resolveProfile(resolved, params.profileName ?? resolved.defaultProfile);
394+if (profile && getBrowserProfileCapabilities(profile).usesChromeMcp) {
395+return true;
396+}
397+if (params.action !== "profiles") {
398+return false;
399+}
400+return Object.keys(resolved.profiles).some((name) => {
401+const candidate = resolveProfile(resolved, name);
402+return candidate ? getBrowserProfileCapabilities(candidate).usesChromeMcp : false;
403+});
404+}
405+406+function readToolTimeoutMs(params: Record<string, unknown>) {
407+return typeof params.timeoutMs === "number" && Number.isFinite(params.timeoutMs)
408+ ? Math.max(1, Math.floor(params.timeoutMs))
409+ : undefined;
410+}
411+375412export function createBrowserTool(opts?: {
376413sandboxBridgeUrl?: string;
377414allowHostControl?: boolean;
@@ -402,6 +439,7 @@ export function createBrowserTool(opts?: {
402439const action = readStringParam(params, "action", { required: true });
403440const profile = readStringParam(params, "profile");
404441const requestedNode = readStringParam(params, "node");
442+const requestedTimeoutMs = readToolTimeoutMs(params);
405443let target = readStringParam(params, "target") as "sandbox" | "host" | "node" | undefined;
406444const configuredNode = browserToolDeps.loadConfig().gateway?.nodes?.browser?.node?.trim();
407445@@ -469,6 +507,11 @@ export function createBrowserTool(opts?: {
469507return proxy.result;
470508}
471509 : null;
510+const toolTimeoutMs =
511+requestedTimeoutMs ??
512+(usesExistingSessionManageFlow({ action, profileName: profile })
513+ ? DEFAULT_EXISTING_SESSION_MANAGE_TIMEOUT_MS
514+ : undefined);
472515473516switch (action) {
474517case "doctor":
@@ -489,55 +532,74 @@ export function createBrowserTool(opts?: {
489532method: "GET",
490533path: "/",
491534 profile,
535+timeoutMs: toolTimeoutMs,
492536}),
493537);
494538}
495-return jsonResult(await browserToolDeps.browserStatus(baseUrl, { profile }));
539+return jsonResult(
540+await browserToolDeps.browserStatus(baseUrl, { profile, timeoutMs: toolTimeoutMs }),
541+);
496542case "start":
497543if (proxyRequest) {
498544await proxyRequest({
499545method: "POST",
500546path: "/start",
501547 profile,
548+timeoutMs: toolTimeoutMs,
502549});
503550return jsonResult(
504551await proxyRequest({
505552method: "GET",
506553path: "/",
507554 profile,
555+timeoutMs: toolTimeoutMs,
508556}),
509557);
510558}
511-await browserToolDeps.browserStart(baseUrl, { profile });
512-return jsonResult(await browserToolDeps.browserStatus(baseUrl, { profile }));
559+await browserToolDeps.browserStart(baseUrl, { profile, timeoutMs: toolTimeoutMs });
560+return jsonResult(
561+await browserToolDeps.browserStatus(baseUrl, { profile, timeoutMs: toolTimeoutMs }),
562+);
513563case "stop":
514564if (proxyRequest) {
515565await proxyRequest({
516566method: "POST",
517567path: "/stop",
518568 profile,
569+timeoutMs: toolTimeoutMs,
519570});
520571return jsonResult(
521572await proxyRequest({
522573method: "GET",
523574path: "/",
524575 profile,
576+timeoutMs: toolTimeoutMs,
525577}),
526578);
527579}
528-await browserToolDeps.browserStop(baseUrl, { profile });
529-return jsonResult(await browserToolDeps.browserStatus(baseUrl, { profile }));
580+await browserToolDeps.browserStop(baseUrl, { profile, timeoutMs: toolTimeoutMs });
581+return jsonResult(
582+await browserToolDeps.browserStatus(baseUrl, { profile, timeoutMs: toolTimeoutMs }),
583+);
530584case "profiles":
531585if (proxyRequest) {
532586const result = await proxyRequest({
533587method: "GET",
534588path: "/profiles",
589+timeoutMs: toolTimeoutMs,
535590});
536591return jsonResult(result);
537592}
538-return jsonResult({ profiles: await browserToolDeps.browserProfiles(baseUrl) });
593+return jsonResult({
594+profiles: await browserToolDeps.browserProfiles(baseUrl, { timeoutMs: toolTimeoutMs }),
595+});
539596case "tabs":
540-return await executeTabsAction({ baseUrl, profile, proxyRequest });
597+return await executeTabsAction({
598+ baseUrl,
599+ profile,
600+timeoutMs: toolTimeoutMs,
601+ proxyRequest,
602+});
541603case "open": {
542604const targetUrl = readTargetUrlParam(params);
543605const label = normalizeOptionalString(params.label);
@@ -547,12 +609,14 @@ export function createBrowserTool(opts?: {
547609path: "/tabs/open",
548610 profile,
549611body: { url: targetUrl, ...(label ? { label } : {}) },
612+timeoutMs: toolTimeoutMs,
550613});
551614return jsonResult(result);
552615}
553616const opened = await browserToolDeps.browserOpenTab(baseUrl, targetUrl, {
554617 profile,
555618 label,
619+timeoutMs: toolTimeoutMs,
556620});
557621browserToolDeps.trackSessionBrowserTab({
558622sessionKey: opts?.agentSessionKey,
@@ -572,10 +636,14 @@ export function createBrowserTool(opts?: {
572636path: "/tabs/focus",
573637 profile,
574638body: { targetId },
639+timeoutMs: toolTimeoutMs,
575640});
576641return jsonResult(result);
577642}
578-await browserToolDeps.browserFocusTab(baseUrl, targetId, { profile });
643+await browserToolDeps.browserFocusTab(baseUrl, targetId, {
644+ profile,
645+timeoutMs: toolTimeoutMs,
646+});
579647return jsonResult({ ok: true });
580648}
581649case "close": {
@@ -586,25 +654,37 @@ export function createBrowserTool(opts?: {
586654method: "DELETE",
587655path: `/tabs/${encodeURIComponent(targetId)}`,
588656 profile,
657+timeoutMs: toolTimeoutMs,
589658})
590659 : await proxyRequest({
591660method: "POST",
592661path: "/act",
593662 profile,
594663body: { kind: "close" },
664+timeoutMs: toolTimeoutMs,
595665});
596666return jsonResult(result);
597667}
598668if (targetId) {
599-await browserToolDeps.browserCloseTab(baseUrl, targetId, { profile });
669+await browserToolDeps.browserCloseTab(baseUrl, targetId, {
670+ profile,
671+timeoutMs: toolTimeoutMs,
672+});
600673browserToolDeps.untrackSessionBrowserTab({
601674sessionKey: opts?.agentSessionKey,
602675 targetId,
603676 baseUrl,
604677 profile,
605678});
606679} else {
607-await browserToolDeps.browserAct(baseUrl, { kind: "close" }, { profile });
680+await browserToolDeps.browserAct(
681+baseUrl,
682+{ kind: "close" },
683+{
684+ profile,
685+timeoutMs: toolTimeoutMs,
686+},
687+);
608688}
609689return jsonResult({ ok: true });
610690}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。