feat(cli): add browser automation commands

This commit is contained in:
Tam Nhu Tran
2026-04-16 18:49:24 -04:00
parent b6aef885ad
commit 4e30c9b080
42 changed files with 3028 additions and 32 deletions
+56
View File
@@ -23,6 +23,7 @@ import {
DEFAULT_THINKING_CONFIG,
DEFAULT_OFFICIAL_CHANNELS_CONFIG,
DEFAULT_DASHBOARD_AUTH_CONFIG,
DEFAULT_BROWSER_CONFIG,
DEFAULT_IMAGE_ANALYSIS_CONFIG,
DEFAULT_LOGGING_CONFIG,
} from './unified-config-types';
@@ -34,6 +35,7 @@ import type {
OfficialChannelsConfig,
OfficialChannelId,
DashboardAuthConfig,
BrowserConfig,
ImageAnalysisConfig,
LoggingConfig,
CursorConfig,
@@ -46,6 +48,7 @@ import {
normalizeOfficialChannelIds,
resolveLegacyDiscordSelection,
} from '../channels/official-channels-runtime';
import { getRecommendedBrowserUserDataDir } from '../utils/browser/browser-settings';
import { canonicalizeImageAnalysisConfig } from '../utils/hooks/image-analysis-backend-resolver';
import { normalizeSearxngBaseUrl } from '../utils/websearch/types';
@@ -54,6 +57,32 @@ const CONFIG_JSON = 'config.json';
const CONFIG_LOCK = 'config.yaml.lock';
const LOCK_STALE_MS = 5000; // Lock is stale after 5 seconds
function normalizeBrowserDevtoolsPort(value: number | undefined): number {
if (!Number.isFinite(value)) {
return DEFAULT_BROWSER_CONFIG.claude.devtools_port;
}
const port = Math.floor(value as number);
if (port < 1 || port > 65535) {
return DEFAULT_BROWSER_CONFIG.claude.devtools_port;
}
return port;
}
function canonicalizeBrowserConfig(config?: BrowserConfig): BrowserConfig {
return {
claude: {
enabled: config?.claude?.enabled ?? DEFAULT_BROWSER_CONFIG.claude.enabled,
user_data_dir: config?.claude?.user_data_dir?.trim() || getRecommendedBrowserUserDataDir(),
devtools_port: normalizeBrowserDevtoolsPort(config?.claude?.devtools_port),
},
codex: {
enabled: config?.codex?.enabled ?? DEFAULT_BROWSER_CONFIG.codex.enabled,
},
};
}
/**
* Get path to unified config.yaml
*/
@@ -592,6 +621,7 @@ function mergeWithDefaults(partial: Partial<UnifiedConfig>): UnifiedConfig {
partial.dashboard_auth?.session_timeout_hours ??
DEFAULT_DASHBOARD_AUTH_CONFIG.session_timeout_hours,
},
browser: canonicalizeBrowserConfig(partial.browser),
// Image analysis config - enabled by default for CLIProxy providers
image_analysis: canonicalizeImageAnalysisConfig({
enabled: partial.image_analysis?.enabled ?? DEFAULT_IMAGE_ANALYSIS_CONFIG.enabled,
@@ -916,6 +946,23 @@ function generateYamlWithComments(config: UnifiedConfig): string {
lines.push('');
}
// Browser automation section
if (config.browser) {
lines.push('# ----------------------------------------------------------------------------');
lines.push('# Browser Automation: Claude browser attach and Codex browser tooling');
lines.push('# Claude attach reuses a running Chrome/Chromium session with remote debugging.');
lines.push('# Codex tooling controls whether CCS injects Playwright MCP overrides.');
lines.push('#');
lines.push('# claude.user_data_dir should point at the Chrome user-data directory for the');
lines.push('# dedicated attach session. claude.devtools_port is the expected debugging port.');
lines.push('# Configure via: Settings > Browser or `ccs browser ...`.');
lines.push('# ----------------------------------------------------------------------------');
lines.push(
yaml.dump({ browser: config.browser }, { indent: 2, lineWidth: -1, quotingType: '"' }).trim()
);
lines.push('');
}
// Image analysis section
if (config.image_analysis) {
lines.push('# ----------------------------------------------------------------------------');
@@ -1334,6 +1381,15 @@ export function getDashboardAuthConfig(): DashboardAuthConfig {
};
}
/**
* Get browser automation configuration.
* Returns canonicalized defaults if not configured.
*/
export function getBrowserConfig(): BrowserConfig {
const config = loadOrCreateUnifiedConfig();
return canonicalizeBrowserConfig(config.browser);
}
/**
* Get image_analysis configuration.
* Returns defaults if not configured.
+40
View File
@@ -812,6 +812,40 @@ export const DEFAULT_DASHBOARD_AUTH_CONFIG: DashboardAuthConfig = {
session_timeout_hours: 24,
};
/**
* Browser automation configuration.
* Controls Claude browser attach and Codex browser tooling.
*/
export interface BrowserClaudeConfig {
/** Enable Claude browser attach (default: false) */
enabled: boolean;
/** Chrome user-data directory used for attach mode */
user_data_dir: string;
/** DevTools port used for attach mode (default: 9222) */
devtools_port: number;
}
export interface BrowserCodexConfig {
/** Enable Codex browser tooling injection (default: true) */
enabled: boolean;
}
export interface BrowserConfig {
claude: BrowserClaudeConfig;
codex: BrowserCodexConfig;
}
export const DEFAULT_BROWSER_CONFIG: BrowserConfig = {
claude: {
enabled: false,
user_data_dir: '',
devtools_port: 9222,
},
codex: {
enabled: true,
},
};
/**
* Image analysis configuration.
* Routes image/PDF files through CLIProxy for vision analysis.
@@ -895,6 +929,8 @@ export interface UnifiedConfig {
channels?: OfficialChannelsConfig;
/** Dashboard authentication configuration (optional) */
dashboard_auth?: DashboardAuthConfig;
/** Browser automation configuration */
browser?: BrowserConfig;
/** Image analysis configuration (vision via CLIProxy) */
image_analysis?: ImageAnalysisConfig;
}
@@ -1041,6 +1077,10 @@ export function createEmptyUnifiedConfig(): UnifiedConfig {
thinking: { ...DEFAULT_THINKING_CONFIG },
channels: { ...DEFAULT_OFFICIAL_CHANNELS_CONFIG },
dashboard_auth: { ...DEFAULT_DASHBOARD_AUTH_CONFIG },
browser: {
claude: { ...DEFAULT_BROWSER_CONFIG.claude },
codex: { ...DEFAULT_BROWSER_CONFIG.codex },
},
image_analysis: { ...DEFAULT_IMAGE_ANALYSIS_CONFIG },
};
}