feat: dashboard provider support and session creation improvements (#1092)
Add provider icons and session creation from the dashboard UI. Sessions can now be created with cloud providers (Browserbase, Browserless, Browser Use, Kernel) in addition to local engines. CLI changes: - Track provider via .provider files alongside .engine files - Add WaitUntil::None variant to skip lifecycle event waits for providers - Auto-set waitUntil=none when --provider is used with navigate - Fix Browser Use: use direct WSS connection (wss://connect.browser-use.com) - Add connect_cdp_direct for providers with page-level CDP proxies - Fix resolve_cdp_url to convert https:// provider URLs to wss:// - Treat empty CDP session_id as None (omit from protocol messages) - Fix Browserbase: send explicit JSON body + Content-Type header - Increase CDP connect timeout to 25s for remote providers - Clean up .provider files on session close Dashboard changes: - Show provider or engine icon per session in sidebar - New session dialog with unified engine/provider selector grid - Async session creation with loading state and error display - Kill zombie daemons on provider connection failure - Parse CLI JSON error output for user-friendly messages - Default new session URL to https://agent-browser.dev
This commit is contained in:
@@ -4,7 +4,7 @@ import { atom } from "jotai";
|
||||
import { useCallback, useEffect, useRef } from "react";
|
||||
import { useAtomCallback } from "jotai/utils";
|
||||
import type { SessionInfo } from "@/types";
|
||||
import { execCommand, killSession, sessionArgs } from "@/lib/exec";
|
||||
import { type ExecResult, execCommand, killSession, sessionArgs } from "@/lib/exec";
|
||||
import { tabCacheAtom, engineCacheAtom } from "@/store/tabs";
|
||||
import { streamTabsAtom, streamEngineAtom } from "@/store/stream";
|
||||
|
||||
@@ -35,7 +35,7 @@ export const activePortAtom = atom(getPort());
|
||||
|
||||
export const polledSessionsAtom = atom<SessionInfo[]>([]);
|
||||
|
||||
export const pendingSessionsAtom = atom<{ session: string; engine: string }[]>(
|
||||
export const pendingSessionsAtom = atom<{ session: string; engine: string; provider?: string }[]>(
|
||||
[],
|
||||
);
|
||||
|
||||
@@ -57,6 +57,7 @@ export const sessionsAtom = atom((get) => {
|
||||
session: p.session,
|
||||
port: 0,
|
||||
engine: p.engine,
|
||||
provider: p.provider,
|
||||
pending: true as const,
|
||||
}));
|
||||
const merged = polled.map((s) =>
|
||||
@@ -88,16 +89,42 @@ export const activeExtensionsAtom = atom((get) => {
|
||||
|
||||
export const createSessionAtom = atom(
|
||||
null,
|
||||
(
|
||||
async (
|
||||
_get,
|
||||
set,
|
||||
{ name, engine }: { name: string; engine: string },
|
||||
) => {
|
||||
set(pendingSessionsAtom, (prev) => [...prev, { session: name, engine }]);
|
||||
execCommand(["--session", name, "--engine", engine, "open", "about:blank"]);
|
||||
{ name, engine, provider }: { name: string; engine: string; provider?: string },
|
||||
): Promise<string | null> => {
|
||||
set(pendingSessionsAtom, (prev) => [...prev, { session: name, engine, provider }]);
|
||||
const args = ["--session", name];
|
||||
if (provider) {
|
||||
args.push("--provider", provider);
|
||||
} else {
|
||||
args.push("--engine", engine);
|
||||
}
|
||||
args.push("open", "https://agent-browser.dev");
|
||||
const result = await execCommand(args);
|
||||
if (!result.success) {
|
||||
set(pendingSessionsAtom, (prev) => prev.filter((p) => p.session !== name));
|
||||
killSession(name);
|
||||
return parseExecError(result) || "Failed to create session";
|
||||
}
|
||||
return null;
|
||||
},
|
||||
);
|
||||
|
||||
function parseExecError(result: ExecResult): string {
|
||||
if (result.stderr) return result.stderr;
|
||||
if (result.stdout) {
|
||||
try {
|
||||
const json = JSON.parse(result.stdout);
|
||||
if (json.error) return json.error;
|
||||
} catch {
|
||||
// stdout wasn't JSON
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
export const closeSessionAtom = atom(null, (get, set, port: number) => {
|
||||
const sessions = get(sessionsAtom);
|
||||
const s = sessions.find((x) => x.port === port)?.session;
|
||||
|
||||
Reference in New Issue
Block a user