From e8ebc1ebf9b0576637b676d54abbbd6985696d1f Mon Sep 17 00:00:00 2001 From: Oleh Luchkiv Date: Tue, 9 Sep 2025 14:06:02 -0500 Subject: [PATCH 1/6] Add BuildConfig.ts for build-time automated mode - Add BuildConfig.ts with AUTOMATED_MODE flag - Update AIChatPanel.ts to support automated mode - Bypass OAuth authentication in automated mode - Auto-enable evaluation mode for Docker deployments --- docker/Dockerfile | 20 ++++++++++++++----- front_end/panels/ai_chat/BUILD.gn | 2 ++ .../panels/ai_chat/common/EvaluationConfig.ts | 8 ++++++++ front_end/panels/ai_chat/core/BuildConfig.ts | 20 +++++++++++++++++++ front_end/panels/ai_chat/ui/AIChatPanel.ts | 8 ++++++++ 5 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 front_end/panels/ai_chat/core/BuildConfig.ts diff --git a/docker/Dockerfile b/docker/Dockerfile index 41f08a1b465..ebf2fe37cc1 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -42,12 +42,22 @@ RUN /workspace/depot_tools/ensure_bootstrap # Build standard DevTools first RUN npm run build -# Add Browser Operator fork and switch to it -RUN git remote add upstream https://github.com/BrowserOperator/browser-operator-core.git -RUN git fetch upstream -RUN git checkout upstream/main +# For development/testing - use current branch with automated mode changes +# In production, this would fetch from Browser Operator upstream +# RUN git remote add upstream https://github.com/BrowserOperator/browser-operator-core.git +# RUN git fetch upstream +# RUN git checkout upstream/main -# Build Browser Operator version +# Allow configurable automated mode +ARG AUTOMATED_MODE=true + +# Set build-time flags based on Docker arg +RUN if [ "$AUTOMATED_MODE" = "true" ]; then \ + sed -i 's/AUTOMATED_MODE: false/AUTOMATED_MODE: true/' \ + front_end/panels/ai_chat/core/BuildConfig.ts; \ + fi + +# Build Browser Operator version with current changes RUN npm run build # Production stage diff --git a/front_end/panels/ai_chat/BUILD.gn b/front_end/panels/ai_chat/BUILD.gn index 1fea191b0c1..5e364879389 100644 --- a/front_end/panels/ai_chat/BUILD.gn +++ b/front_end/panels/ai_chat/BUILD.gn @@ -48,6 +48,7 @@ devtools_module("ai_chat") { "core/Types.ts", "core/AgentService.ts", "core/Constants.ts", + "core/BuildConfig.ts", "core/structured_response.ts", "core/GraphConfigs.ts", "core/ConfigurableGraph.ts", @@ -176,6 +177,7 @@ _ai_chat_sources = [ "core/Types.ts", "core/AgentService.ts", "core/Constants.ts", + "core/BuildConfig.ts", "core/structured_response.ts", "core/GraphConfigs.ts", "core/ConfigurableGraph.ts", diff --git a/front_end/panels/ai_chat/common/EvaluationConfig.ts b/front_end/panels/ai_chat/common/EvaluationConfig.ts index 66ea9134ec3..be5169fe6cb 100644 --- a/front_end/panels/ai_chat/common/EvaluationConfig.ts +++ b/front_end/panels/ai_chat/common/EvaluationConfig.ts @@ -4,6 +4,7 @@ import { createLogger } from '../core/Logger.js'; import { WebSocketRPCClient } from './WebSocketRPCClient.js'; +import { BUILD_CONFIG } from '../core/BuildConfig.js'; const logger = createLogger('EvaluationConfig'); @@ -49,6 +50,13 @@ class EvaluationConfigStore { private loadFromLocalStorage(): void { try { + // In automated mode, set default to enabled if not already set + if (BUILD_CONFIG.AUTOMATED_MODE && + localStorage.getItem('ai_chat_evaluation_enabled') === null) { + localStorage.setItem('ai_chat_evaluation_enabled', 'true'); + logger.info('Automated mode: defaulted evaluation to enabled'); + } + const enabled = localStorage.getItem('ai_chat_evaluation_enabled') === 'true'; const endpoint = localStorage.getItem('ai_chat_evaluation_endpoint') || 'ws://localhost:8080'; const secretKey = localStorage.getItem('ai_chat_evaluation_secret_key') || ''; diff --git a/front_end/panels/ai_chat/core/BuildConfig.ts b/front_end/panels/ai_chat/core/BuildConfig.ts new file mode 100644 index 00000000000..91d89fec191 --- /dev/null +++ b/front_end/panels/ai_chat/core/BuildConfig.ts @@ -0,0 +1,20 @@ +// Copyright 2025 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * Build-time configuration for automated deployments and Docker environments. + * + * This file contains constants that are set during the build process to configure + * behavior for different deployment scenarios. + */ +export const BUILD_CONFIG = { + /** + * Automated mode flag for Docker/CI deployments. + * When true: + * - Bypasses OAuth authentication panel + * - Automatically enables evaluation mode + * - Optimized for headless/automated usage + */ + AUTOMATED_MODE: false, // Will be set to true during Docker build +} as const; \ No newline at end of file diff --git a/front_end/panels/ai_chat/ui/AIChatPanel.ts b/front_end/panels/ai_chat/ui/AIChatPanel.ts index ec1a673f090..5a405bf2b58 100644 --- a/front_end/panels/ai_chat/ui/AIChatPanel.ts +++ b/front_end/panels/ai_chat/ui/AIChatPanel.ts @@ -20,6 +20,7 @@ import { OpenRouterProvider } from '../LLM/OpenRouterProvider.js'; import { createLogger } from '../core/Logger.js'; import { isEvaluationEnabled, getEvaluationConfig } from '../common/EvaluationConfig.js'; import { EvaluationAgent } from '../evaluation/remote/EvaluationAgent.js'; +import { BUILD_CONFIG } from '../core/BuildConfig.js'; // Import of LiveAgentSessionComponent is not required here; the element is // registered by ChatView where it is used. @@ -1396,6 +1397,13 @@ export class AIChatPanel extends UI.Panel.Panel { */ #hasAnyProviderCredentials(): boolean { logger.info('=== CHECKING ALL PROVIDER CREDENTIALS ==='); + + // Skip auth check in automated mode + if (BUILD_CONFIG.AUTOMATED_MODE) { + logger.info('Build-time automated mode enabled, bypassing credential check'); + return true; + } + const selectedProvider = localStorage.getItem(PROVIDER_SELECTION_KEY) || 'openai'; logger.info('Currently selected provider:', selectedProvider); From 2ca75f8224f3a373edb2e7743a5c7487a539f9f6 Mon Sep 17 00:00:00 2001 From: Oleh Luchkiv Date: Wed, 10 Sep 2025 20:00:30 -0500 Subject: [PATCH 2/6] Automated build (skip credentials setup) vs manual build --- docker/README.md | 37 +++++++++++++++++++--- front_end/panels/ai_chat/ui/AIChatPanel.ts | 16 +--------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/docker/README.md b/docker/README.md index 379527aceb5..ece2c08ebf0 100644 --- a/docker/README.md +++ b/docker/README.md @@ -22,8 +22,11 @@ The Docker setup uses a multi-stage build process: From the repository root directory: ```bash -# Build the Docker image -docker build -f docker/Dockerfile -t devtools-frontend . +# Build with automated mode (default - bypasses OAuth, auto-enables evaluation) +docker build -f docker/Dockerfile -t browser-operator-automated . + +# Build with normal mode (requires manual authentication) +docker build -f docker/Dockerfile --build-arg AUTOMATED_MODE=false -t browser-operator-manual . # Or use docker-compose (recommended) docker-compose -f docker/docker-compose.yml build @@ -32,8 +35,11 @@ docker-compose -f docker/docker-compose.yml build ### Running the Container ```bash -# Using docker run -docker run -d -p 8000:8000 --name devtools-frontend devtools-frontend +# Automated mode (no authentication required, evaluation auto-enabled) +docker run -d -p 8000:8000 --name browser-operator-automated browser-operator-automated + +# Manual mode (requires OAuth/API key setup) +docker run -d -p 8000:8000 --name browser-operator-manual browser-operator-manual # Or using docker-compose (recommended) docker-compose -f docker/docker-compose.yml up -d @@ -67,6 +73,29 @@ docker/ └── README.md # This file ``` +## Automated Mode vs Manual Mode + +### Automated Mode (Default) +- **Purpose**: Optimized for Docker/CI environments and automated workflows +- **Authentication**: Bypasses OAuth panel - no manual setup required +- **Evaluation**: Automatically enables evaluation mode for API wrapper connectivity +- **Use cases**: Production deployments, CI/CD, headless automation, API integration + +### Manual Mode +- **Purpose**: Standard interactive usage +- **Authentication**: Requires OAuth setup or API key configuration +- **Evaluation**: Manual enable/disable in settings +- **Use cases**: Development, interactive testing, manual usage + +```bash +# Example automated mode workflow +docker build -f docker/Dockerfile -t browser-operator-automated . +docker run -d -p 8000:8000 --name browser-operator browser-operator-automated + +# Ready to use immediately - no authentication required! +# Evaluation server can connect automatically via WebSocket (ws://localhost:8080) +``` + ## Advanced Usage ### Development Mode diff --git a/front_end/panels/ai_chat/ui/AIChatPanel.ts b/front_end/panels/ai_chat/ui/AIChatPanel.ts index 5a405bf2b58..bfd9f3b7746 100644 --- a/front_end/panels/ai_chat/ui/AIChatPanel.ts +++ b/front_end/panels/ai_chat/ui/AIChatPanel.ts @@ -1396,16 +1396,12 @@ export class AIChatPanel extends UI.Panel.Panel { * @returns true if at least one provider has valid credentials */ #hasAnyProviderCredentials(): boolean { - logger.info('=== CHECKING ALL PROVIDER CREDENTIALS ==='); - // Skip auth check in automated mode if (BUILD_CONFIG.AUTOMATED_MODE) { - logger.info('Build-time automated mode enabled, bypassing credential check'); return true; } const selectedProvider = localStorage.getItem(PROVIDER_SELECTION_KEY) || 'openai'; - logger.info('Currently selected provider:', selectedProvider); // Check all providers except LiteLLM (unless LiteLLM is selected) const providers = ['openai', 'groq', 'openrouter']; @@ -1415,19 +1411,13 @@ export class AIChatPanel extends UI.Panel.Panel { providers.push('litellm'); } - logger.info('Providers to check:', providers); - for (const provider of providers) { - logger.info(`Checking provider: ${provider}`); const validation = LLMClient.validateProviderCredentials(provider); - logger.info(`Provider ${provider} validation result:`, validation); if (validation.isValid) { - logger.info(`✅ Found valid credentials for provider: ${provider}`); return true; } } - logger.info('❌ No valid credentials found for any provider'); return false; } @@ -2006,11 +1996,7 @@ export class AIChatPanel extends UI.Panel.Panel { // Add OAuth login state showOAuthLogin: (() => { const hasCredentials = this.#hasAnyProviderCredentials(); - const showOAuth = !hasCredentials; - logger.info('=== OAUTH LOGIN UI DECISION ==='); - logger.info('hasAnyProviderCredentials:', hasCredentials); - logger.info('showOAuthLogin will be set to:', showOAuth); - return showOAuth; + return !hasCredentials; })(), onOAuthLogin: this.#handleOAuthLogin.bind(this), }; From c249393f6d55c332872bc41784ce1e35319d8e9d Mon Sep 17 00:00:00 2001 From: Oleh Luchkiv Date: Wed, 10 Sep 2025 20:23:45 -0500 Subject: [PATCH 3/6] Simplify decision to show panel --- front_end/panels/ai_chat/ui/AIChatPanel.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/front_end/panels/ai_chat/ui/AIChatPanel.ts b/front_end/panels/ai_chat/ui/AIChatPanel.ts index bfd9f3b7746..6dd9055451a 100644 --- a/front_end/panels/ai_chat/ui/AIChatPanel.ts +++ b/front_end/panels/ai_chat/ui/AIChatPanel.ts @@ -1396,10 +1396,6 @@ export class AIChatPanel extends UI.Panel.Panel { * @returns true if at least one provider has valid credentials */ #hasAnyProviderCredentials(): boolean { - // Skip auth check in automated mode - if (BUILD_CONFIG.AUTOMATED_MODE) { - return true; - } const selectedProvider = localStorage.getItem(PROVIDER_SELECTION_KEY) || 'openai'; @@ -1995,6 +1991,9 @@ export class AIChatPanel extends UI.Panel.Panel { inputPlaceholder: this.#getInputPlaceholderText(), // Add OAuth login state showOAuthLogin: (() => { + if (BUILD_CONFIG.AUTOMATED_MODE) { + return false; + } const hasCredentials = this.#hasAnyProviderCredentials(); return !hasCredentials; })(), From b5670e87e8d9a1bb09867c0a69ef6b54f9e304b3 Mon Sep 17 00:00:00 2001 From: Oleh Luchkiv Date: Thu, 11 Sep 2025 13:31:44 -0500 Subject: [PATCH 4/6] Add Dockerfile.local for simplified local builds - Simple Dockerfile that uses pre-built local files - Uses nginx:alpine for lightweight serving - Designed for local development workflows --- docker/Dockerfile.local | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 docker/Dockerfile.local diff --git a/docker/Dockerfile.local b/docker/Dockerfile.local new file mode 100644 index 00000000000..17cc9c7712f --- /dev/null +++ b/docker/Dockerfile.local @@ -0,0 +1,10 @@ +# Simple Dockerfile that uses pre-built local files +FROM nginx:alpine + +# Copy the pre-built DevTools frontend from host +COPY out/Default/gen/front_end /usr/share/nginx/html + +# Copy nginx config +COPY docker/nginx.conf /etc/nginx/conf.d/default.conf + +EXPOSE 8000 \ No newline at end of file From 0e2116ff28e654c84a7fa12c57e59fca5a79792d Mon Sep 17 00:00:00 2001 From: Oleh Luchkiv Date: Thu, 11 Sep 2025 18:30:39 -0500 Subject: [PATCH 5/6] Fix Dockerfile --- docker/Dockerfile | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index ebf2fe37cc1..2a6cb50340b 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -42,14 +42,13 @@ RUN /workspace/depot_tools/ensure_bootstrap # Build standard DevTools first RUN npm run build -# For development/testing - use current branch with automated mode changes -# In production, this would fetch from Browser Operator upstream -# RUN git remote add upstream https://github.com/BrowserOperator/browser-operator-core.git -# RUN git fetch upstream -# RUN git checkout upstream/main +# Add Browser Operator fork and switch to it +RUN git remote add upstream https://github.com/BrowserOperator/browser-operator-core.git +RUN git fetch upstream +RUN git checkout upstream/main # Allow configurable automated mode -ARG AUTOMATED_MODE=true +ARG AUTOMATED_MODE=false # Set build-time flags based on Docker arg RUN if [ "$AUTOMATED_MODE" = "true" ]; then \ From 8d380e81101247fe233ab2f4f8ff443e5b8cf16f Mon Sep 17 00:00:00 2001 From: Oleh Luchkiv Date: Thu, 11 Sep 2025 18:35:00 -0500 Subject: [PATCH 6/6] Remove local version --- docker/Dockerfile.local | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 docker/Dockerfile.local diff --git a/docker/Dockerfile.local b/docker/Dockerfile.local deleted file mode 100644 index 17cc9c7712f..00000000000 --- a/docker/Dockerfile.local +++ /dev/null @@ -1,10 +0,0 @@ -# Simple Dockerfile that uses pre-built local files -FROM nginx:alpine - -# Copy the pre-built DevTools frontend from host -COPY out/Default/gen/front_end /usr/share/nginx/html - -# Copy nginx config -COPY docker/nginx.conf /etc/nginx/conf.d/default.conf - -EXPOSE 8000 \ No newline at end of file