mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 02:11:28 +00:00
119 lines
4.2 KiB
TypeScript
119 lines
4.2 KiB
TypeScript
/**
|
|
* Browser Launch Setup — Executor-level browser initialization
|
|
*
|
|
* Extracted from executor/index.ts (Phase 04).
|
|
* Handles:
|
|
* 1. Browser launch flag resolution and override parsing
|
|
* 2. Browser attach config + exposure resolution + blocked-override warning
|
|
* 3. Optional browser attach runtime resolution (devtools WebSocket)
|
|
* 4. Browser MCP ensure + sync-to-config-dir
|
|
*/
|
|
|
|
import { warn } from '../../utils/ui';
|
|
import {
|
|
type BrowserLaunchOverride,
|
|
ensureBrowserMcpOrThrow,
|
|
getBlockedBrowserOverrideWarning,
|
|
getEffectiveClaudeBrowserAttachConfig,
|
|
resolveBrowserExposure,
|
|
resolveBrowserLaunchFlagResolution,
|
|
resolveOptionalBrowserAttachRuntime,
|
|
syncBrowserMcpToConfigDir,
|
|
} from '../../utils/browser';
|
|
import { getBrowserConfig } from '../../config/config-loader-facade';
|
|
|
|
export interface BrowserLaunchSetupResult {
|
|
/** CLI override flag if --browser-launch / --no-browser-launch was passed */
|
|
browserLaunchOverride: BrowserLaunchOverride | undefined;
|
|
/** args list with --browser-launch* flags removed */
|
|
argsWithoutBrowserFlags: string[];
|
|
/** Devtools WebSocket env vars if browser attach runtime is active */
|
|
browserRuntimeEnv: Record<string, string> | undefined;
|
|
}
|
|
|
|
/**
|
|
* Phase 1 — resolve browser CLI flags and attach config.
|
|
* Call this immediately after resolveExecutorProxy so that
|
|
* argsWithoutBrowserFlags is available for downstream parsing.
|
|
*
|
|
* @returns partial setup result (no async work yet)
|
|
*/
|
|
export function resolveBrowserLaunchFlags(argsWithoutProxy: string[]): {
|
|
browserLaunchOverride: BrowserLaunchOverride | undefined;
|
|
argsWithoutBrowserFlags: string[];
|
|
} {
|
|
let browserLaunchOverride: BrowserLaunchOverride | undefined;
|
|
let argsWithoutBrowserFlags = argsWithoutProxy;
|
|
try {
|
|
const browserLaunchFlags = resolveBrowserLaunchFlagResolution(argsWithoutProxy);
|
|
browserLaunchOverride = browserLaunchFlags.override;
|
|
argsWithoutBrowserFlags = browserLaunchFlags.argsWithoutFlags;
|
|
} catch (error) {
|
|
console.error(warn((error as Error).message));
|
|
process.exit(1);
|
|
return { browserLaunchOverride: undefined, argsWithoutBrowserFlags };
|
|
}
|
|
|
|
const browserConfig = getBrowserConfig();
|
|
const browserAttachConfig = getEffectiveClaudeBrowserAttachConfig(browserConfig);
|
|
const claudeBrowserExposure = resolveBrowserExposure(
|
|
{
|
|
enabled: browserAttachConfig.enabled,
|
|
policy: browserConfig.claude.policy,
|
|
},
|
|
browserLaunchOverride
|
|
);
|
|
const blockedBrowserOverrideWarning = getBlockedBrowserOverrideWarning(
|
|
'Claude Browser Attach',
|
|
claudeBrowserExposure
|
|
);
|
|
if (blockedBrowserOverrideWarning) {
|
|
console.error(warn(blockedBrowserOverrideWarning));
|
|
}
|
|
|
|
return { browserLaunchOverride, argsWithoutBrowserFlags };
|
|
}
|
|
|
|
/**
|
|
* Phase 2 — resolve async browser attach runtime and MCP setup.
|
|
* Must be called AFTER phase-1 and AFTER ensureWebSearchMcpOrThrow().
|
|
*/
|
|
export async function resolveBrowserRuntime(
|
|
browserLaunchOverride: BrowserLaunchOverride | undefined,
|
|
inheritedClaudeConfigDir: string | undefined
|
|
): Promise<Pick<BrowserLaunchSetupResult, 'browserRuntimeEnv'>> {
|
|
const browserConfig = getBrowserConfig();
|
|
const browserAttachConfig = getEffectiveClaudeBrowserAttachConfig(browserConfig);
|
|
const claudeBrowserExposure = resolveBrowserExposure(
|
|
{
|
|
enabled: browserAttachConfig.enabled,
|
|
policy: browserConfig.claude.policy,
|
|
},
|
|
browserLaunchOverride
|
|
);
|
|
|
|
const browserAttachRuntime =
|
|
browserAttachConfig.enabled && claudeBrowserExposure.exposeForLaunch
|
|
? await resolveOptionalBrowserAttachRuntime(browserAttachConfig)
|
|
: undefined;
|
|
|
|
const browserRuntimeEnv = browserAttachRuntime?.runtimeEnv;
|
|
if (browserAttachRuntime?.warning) {
|
|
process.stderr.write(`${warn(browserAttachRuntime.warning)}\n`);
|
|
}
|
|
if (browserRuntimeEnv) {
|
|
ensureBrowserMcpOrThrow();
|
|
}
|
|
|
|
// Sync browser MCP config into inherited Claude instance if browser is active
|
|
if (browserRuntimeEnv && inheritedClaudeConfigDir) {
|
|
if (!syncBrowserMcpToConfigDir(inheritedClaudeConfigDir)) {
|
|
throw new Error(
|
|
'Browser MCP is enabled, but CCS could not sync the browser MCP config into the inherited Claude instance.'
|
|
);
|
|
}
|
|
}
|
|
|
|
return { browserRuntimeEnv };
|
|
}
|