mirror of
https://github.com/browseros-ai/BrowserOS.git
synced 2026-05-21 12:55:09 +00:00
* clean-up bunch of files for re-write * more clean-up and adding basic agent * Minor fix moved types into respective files. * Deleted bunch of old files backup Update gitignore Deleted a bunch of files Remove message manager Deleted old docs Update rules rename Profiler to profiler * Temporarily adding old code * Adding two small things back * backup * Implemented LangChainProvider and updated cursor rules backup LangChainProvider curosr rules * Implement tests for LangChainProvider -- unit test and integration test integration test passes integration test backup * Tool Design Tools Desing tools design * NavigationTool ready NavigationTool ready NavigationTool ready NaivgationTool ready backup * MessageManager MessageManager backup * Fixed integration test * Agent design new Updated agent design and added bunch of /NTN commands agent new design * Delete old agent design * MessageManagerReadOnly class * PlannerTool ready PlannerTool almost ready * ToolManager and DoneTool * Integration of BrowserAgent * BrowserAgent implementation v0.1 * BrowserAgent small fix v0.2 * Tool calling design too call design tool design claude * Update agent tool design with // NTN * add zod-to-json npm install * BrowserAGent v0.3 * BrowserAgent v0.4 * BrowserAgent v0.5 * fixes * Build error fixes in my NEWLY added code build errors fix * Build error fixes in old code (integration work) backup * Comment StreamEventProcessor for now, it is not used * Small build error fix * Small rename * Added integration test to check structuredLLM and changed to 4o-mini change default to nxtscape integration test * Small docstring * Simplified BrowserAgent code and added integration test Simplified BrowserAgent code BrowserAGent integrationt est * Update CLAUDE.md with project memory and instructions on how to write code Update CLAUDE.md with project memory and instructions on how to write code Project Memory * Just a mova.. Moved ToolManager outside. Build works. * TabOperations tool TabOperations Tool and fixing some test tab operations * Update CLAUDE.md * Added ClassificationTool classifiction tool classification prommpt * Refactored and simplified PlannerTool unit test and integration test * Updated Plnnaer tool * Update CLAUDE.md * BrowserAgent modified to do classification BrowserAgent with classification * minor fix to ToolManager * Instead of ToolCall and ToolResult -- just updating message manager once * minor fix to BrowserAgent integration test * Changed done to "done_tool" * Updated CLAUDE.md to reflect understanding of claude * Uncommented stream event processor * Renamed EventBus to StreamEventBus * Commented StreamEventProcessor * Event Processor * Integrated EventProcessor with BrowserAgent Added EventProcessor to BrowserAgetn * Renamed StreamEventBus to EventBus * Made EventBus required parameter in ExecutionContext * PlanGenerator rewrite PlanGenerator rewrite backup * For simple task, explicitly tell it to call done tool * Max attempts for simple task * backup * Revert "backup" This reverts commit 7d79a3d4d5774bfef79ec9827878b74edad3593f. * Consolidating where EventBus and EventProcessor are created and initialized backup * Update CLAUDE.md Update CLAUDE.md * Improving agent loop code Cleaned up processTooCall classification task * Create test-writer subAgent test-agent-prompt test agent prompt test-agent-prompt Update test-writer.md * BrowserAgent test Browseragent test BrowserAgent test * BrowserAgent refactor backup backup * Minor fixes * Minor fix * minor change -- NEW AGENT LOOP IS WORKING WELL * Update cursor rules * Small change * Improved BrowserAgent integration test Improved BrowserAgent integration test * Small change * Update CLAUDE.md * Different tools * FindElementTool is ready Find element update backup find element backup * Updated to test strings to say "tests..." * ScrollTool is ready * RefreshStateTool is updated as well * MessageManager updated * SearchTool is ready backup * Interaction Element is also ready * Add debugMessage emitter * ValidatorTool ready and tests are passing Validation Tool validator tool backup backup * GroupTabs tool ready * Registered all the tools * Planning changed to 5 steps * BrowserAgent integration test fix * Minor string changes * backup * Removed too many confusing events in EventProcessor -- there is only event.info right now * Abort control implemented backup Abort * Formatter for toolResult Formatter for toolResult backup * Always render using Markdown * Minor fix --------- Co-authored-by: Nikhil Sonti <nikhilsv92@gmail.com>
234 lines
8.5 KiB
TypeScript
234 lines
8.5 KiB
TypeScript
import { Logging } from '@/lib/utils/Logging'
|
|
import { isMockLLMSettings } from '@/config'
|
|
import {
|
|
LLMSettings,
|
|
LLMSettingsSchema,
|
|
PREFERENCE_KEYS,
|
|
ProviderType
|
|
} from './types'
|
|
|
|
// Type definitions for chrome.settingsPrivate API
|
|
declare global {
|
|
namespace chrome {
|
|
namespace settingsPrivate {
|
|
interface PrefObject {
|
|
key?: string
|
|
type?: string
|
|
value?: any
|
|
controlledBy?: string
|
|
enforcement?: string
|
|
recommendedValue?: any
|
|
userControlDisabled?: boolean
|
|
}
|
|
|
|
function getPref(name: string, callback: (pref: PrefObject) => void): void
|
|
function setPref(name: string, value: any, pageId: string, callback?: (success: boolean) => void): void
|
|
function getAllPrefs(callback: (prefs: PrefObject[]) => void): void
|
|
const onPrefsChanged: {
|
|
addListener(callback: (prefs: PrefObject[]) => void): void
|
|
removeListener(callback: (prefs: PrefObject[]) => void): void
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Mock preference values for development mode
|
|
*
|
|
* IMPORTANT: These are mock values for development/testing only!
|
|
* They will only be used when:
|
|
* 1. DEV_MODE is true in src/config.ts
|
|
* 2. chrome.settingsPrivate API is not available
|
|
*
|
|
* To test different providers, change 'nxtscape.default_provider' to:
|
|
* - 'nxtscape' (default) - Uses Nxtscape proxy, no real API key needed
|
|
* - 'openai' - Would require real API key in production
|
|
* - 'anthropic' - Would require real API key in production
|
|
* - 'gemini' - Would require real Google AI API key in production
|
|
* - 'ollama' - Requires local Ollama server running
|
|
*/
|
|
const MOCK_PREFERENCES: Record<string, string | undefined> = {
|
|
'nxtscape.default_provider': 'gemini', // Change this to test different providers
|
|
'nxtscape.nxtscape_model': 'claude-3-5-sonnet',
|
|
'nxtscape.openai_api_key': 'TBD',
|
|
'nxtscape.openai_model': 'gpt-4o',
|
|
'nxtscape.openai_base_url': undefined,
|
|
'nxtscape.anthropic_api_key': 'TBD',
|
|
'nxtscape.anthropic_model': 'claude-3-5-sonnet-latest',
|
|
'nxtscape.anthropic_base_url': undefined,
|
|
'nxtscape.gemini_api_key': 'TBD',
|
|
'nxtscape.gemini_model': 'gemini-2.0-flash',
|
|
'nxtscape.gemini_base_url': undefined,
|
|
'nxtscape.ollama_base_url': 'http://localhost:11434',
|
|
'nxtscape.ollama_model': 'qwen3:4b',
|
|
'nxtscape.ollama_api_key': undefined // Optional
|
|
}
|
|
|
|
/**
|
|
* Reads LLM settings from browser preferences
|
|
*/
|
|
export class LLMSettingsReader {
|
|
/**
|
|
* Override mock preferences for testing (DEV MODE ONLY)
|
|
* @param overrides - Partial preferences to override
|
|
*/
|
|
static setMockPreferences(overrides: Partial<typeof MOCK_PREFERENCES>): void {
|
|
if (!isMockLLMSettings()) {
|
|
Logging.log('LLMSettingsReader', 'setMockPreferences is only available in development mode', 'warning')
|
|
return
|
|
}
|
|
|
|
Object.assign(MOCK_PREFERENCES, overrides)
|
|
Logging.log('LLMSettingsReader', `Mock preferences updated: ${JSON.stringify(overrides)}`)
|
|
}
|
|
/**
|
|
* Read all LLM settings from Chrome storage
|
|
* @returns Promise resolving to LLM settings
|
|
*/
|
|
static async read(): Promise<LLMSettings> {
|
|
try {
|
|
Logging.log('LLMSettingsReader', 'Reading LLM settings from Chrome preferences')
|
|
|
|
// Get all preference values from Chrome storage
|
|
const preferences = await this.getPreferences()
|
|
|
|
// Construct settings object
|
|
const settings: LLMSettings = {
|
|
defaultProvider: this.getProviderType(preferences[PREFERENCE_KEYS.DEFAULT_PROVIDER]),
|
|
nxtscape: {
|
|
model: preferences[PREFERENCE_KEYS.NXTSCAPE_MODEL]
|
|
},
|
|
openai: {
|
|
apiKey: preferences[PREFERENCE_KEYS.OPENAI_API_KEY],
|
|
model: preferences[PREFERENCE_KEYS.OPENAI_MODEL],
|
|
baseUrl: preferences[PREFERENCE_KEYS.OPENAI_BASE_URL]
|
|
},
|
|
anthropic: {
|
|
apiKey: preferences[PREFERENCE_KEYS.ANTHROPIC_API_KEY],
|
|
model: preferences[PREFERENCE_KEYS.ANTHROPIC_MODEL],
|
|
baseUrl: preferences[PREFERENCE_KEYS.ANTHROPIC_BASE_URL]
|
|
},
|
|
gemini: {
|
|
apiKey: preferences[PREFERENCE_KEYS.GEMINI_API_KEY],
|
|
model: preferences[PREFERENCE_KEYS.GEMINI_MODEL],
|
|
baseUrl: preferences[PREFERENCE_KEYS.GEMINI_BASE_URL]
|
|
},
|
|
ollama: {
|
|
apiKey: preferences[PREFERENCE_KEYS.OLLAMA_API_KEY],
|
|
baseUrl: preferences[PREFERENCE_KEYS.OLLAMA_BASE_URL],
|
|
model: preferences[PREFERENCE_KEYS.OLLAMA_MODEL]
|
|
}
|
|
}
|
|
|
|
// Validate with Zod schema
|
|
const validated = LLMSettingsSchema.parse(settings)
|
|
|
|
Logging.log('LLMSettingsReader', `Settings loaded successfully. Provider: ${validated.defaultProvider}`)
|
|
|
|
return validated
|
|
} catch (error) {
|
|
const errorMessage = error instanceof Error ? error.message : String(error)
|
|
Logging.log('LLMSettingsReader', `Failed to read settings: ${errorMessage}`, 'error')
|
|
|
|
// Return default settings on error
|
|
return {
|
|
defaultProvider: 'nxtscape',
|
|
nxtscape: {},
|
|
openai: {},
|
|
anthropic: {},
|
|
gemini: {},
|
|
ollama: {}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get preferences from Chrome settings
|
|
* @returns Promise resolving to preference values
|
|
*/
|
|
private static async getPreferences(): Promise<Record<string, string | undefined>> {
|
|
// Check if chrome.settingsPrivate is available
|
|
if (typeof chrome === 'undefined' || !chrome.settingsPrivate || !chrome.settingsPrivate.getPref) {
|
|
// In development mode, return mock values for testing
|
|
if (isMockLLMSettings()) {
|
|
Logging.log('LLMSettingsReader', 'Chrome settingsPrivate API not available, using mock values for development', 'warning')
|
|
Logging.log('LLMSettingsReader', `Mock provider: ${MOCK_PREFERENCES['nxtscape.default_provider']}`)
|
|
return MOCK_PREFERENCES
|
|
}
|
|
|
|
Logging.log('LLMSettingsReader', 'Chrome settingsPrivate API not available, using defaults', 'warning')
|
|
return {}
|
|
}
|
|
|
|
// Get all preference values in parallel
|
|
const prefPromises = Object.entries(PREFERENCE_KEYS).map(([key, prefName]) =>
|
|
new Promise<[string, string | undefined]>((resolve) => {
|
|
chrome.settingsPrivate.getPref(prefName, (pref: chrome.settingsPrivate.PrefObject) => {
|
|
if (chrome.runtime.lastError) {
|
|
Logging.log('LLMSettingsReader',
|
|
`Failed to read preference ${prefName}: ${chrome.runtime.lastError.message}`, 'warning')
|
|
resolve([prefName, undefined])
|
|
} else {
|
|
// Extract the value from the preference object
|
|
const value = pref?.value as string | undefined
|
|
resolve([prefName, value])
|
|
}
|
|
})
|
|
})
|
|
)
|
|
|
|
// Wait for all preferences to be fetched
|
|
const prefEntries = await Promise.all(prefPromises)
|
|
|
|
// Convert array of entries back to object
|
|
return Object.fromEntries(prefEntries)
|
|
}
|
|
|
|
/**
|
|
* Convert string to provider type with validation
|
|
* @param value - Raw provider value
|
|
* @returns Valid provider type or default
|
|
*/
|
|
private static getProviderType(value: string | undefined): ProviderType {
|
|
const validProviders: ProviderType[] = ['nxtscape', 'openai', 'anthropic', 'gemini', 'ollama']
|
|
|
|
if (value && validProviders.includes(value as ProviderType)) {
|
|
return value as ProviderType
|
|
}
|
|
|
|
return 'nxtscape' // Default provider
|
|
}
|
|
|
|
/**
|
|
* Read a single preference value
|
|
* @param key - Preference key to read
|
|
* @returns Promise resolving to the preference value
|
|
*/
|
|
static async readPreference(key: string): Promise<string | undefined> {
|
|
// Check if chrome.settingsPrivate is available
|
|
if (typeof chrome === 'undefined' || !chrome.settingsPrivate || !chrome.settingsPrivate.getPref) {
|
|
// In development mode, return mock value for testing
|
|
if (isMockLLMSettings()) {
|
|
Logging.log('LLMSettingsReader', `Chrome settingsPrivate API not available, using mock value for ${key}`, 'warning')
|
|
return MOCK_PREFERENCES[key]
|
|
}
|
|
|
|
Logging.log('LLMSettingsReader', 'Chrome settingsPrivate API not available', 'warning')
|
|
return undefined
|
|
}
|
|
|
|
return new Promise((resolve) => {
|
|
chrome.settingsPrivate.getPref(key, (pref: chrome.settingsPrivate.PrefObject) => {
|
|
if (chrome.runtime.lastError) {
|
|
Logging.log('LLMSettingsReader',
|
|
`Failed to read preference ${key}: ${chrome.runtime.lastError.message}`, 'warning')
|
|
resolve(undefined)
|
|
} else {
|
|
// Extract the value from the preference object
|
|
const value = pref?.value as string | undefined
|
|
resolve(value)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
}
|