mirror of
https://github.com/tiennm99/ccs.git
synced 2026-08-05 22:24:04 +00:00
refactor(cliproxy/executor): extract browser-setup and account-resolution
Phases 04+05 of #1162. Splits two more concerns out of the orchestrator: - src/cliproxy/executor/browser-launch-setup.ts (118 LOC): resolveBrowserLaunchFlags + resolveBrowserRuntime. Encapsulates browser flag resolution, attach config, blocked-override warning, and runtime setup including MCP sync. - src/cliproxy/executor/account-resolution.ts (197 LOC): resolveRuntimeQuotaMonitorProviders, resolveAccounts (--accounts / --use / --nickname / OAuth ban-risk warn / default touch), applyAccountSafetyGuards, touchDefaultAccount. - New tests: 184 + 430 LOC covering both modules. index.ts: 1045 -> 895 LOC (-150). resolveRuntimeQuotaMonitorProviders re-exported from index.ts for __testExports backwards compat. Behavior unchanged; full suite passes 1824/1824. Refs #1162
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* 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/unified-config-loader';
|
||||
|
||||
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 };
|
||||
}
|
||||
Reference in New Issue
Block a user