buroventures-harald-code-core
Version:
Harald Code Core - Core functionality for AI-powered coding assistant
547 lines • 18.1 kB
JavaScript
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import * as path from 'node:path';
import process from 'node:process';
import { createContentGeneratorConfig, } from '../core/contentGenerator.js';
import { PromptRegistry } from '../prompts/prompt-registry.js';
import { ToolRegistry } from '../tools/tool-registry.js';
import { LSTool } from '../tools/ls.js';
import { ReadFileTool } from '../tools/read-file.js';
import { GrepTool } from '../tools/grep.js';
import { GlobTool } from '../tools/glob.js';
import { EditTool } from '../tools/edit.js';
import { ShellTool } from '../tools/shell.js';
import { WriteFileTool } from '../tools/write-file.js';
import { WebFetchTool } from '../tools/web-fetch.js';
import { ReadManyFilesTool } from '../tools/read-many-files.js';
import { MemoryTool, setGeminiMdFilename, GEMINI_CONFIG_DIR as GEMINI_DIR, } from '../tools/memoryTool.js';
import { WebSearchTool } from '../tools/web-search.js';
import { GeminiClient } from '../core/client.js';
import { FileDiscoveryService } from '../services/fileDiscoveryService.js';
import { GitService } from '../services/gitService.js';
import { getProjectTempDir } from '../utils/paths.js';
import { initializeTelemetry, DEFAULT_TELEMETRY_TARGET, DEFAULT_OTLP_ENDPOINT, StartSessionEvent, } from '../telemetry/index.js';
import { DEFAULT_GEMINI_EMBEDDING_MODEL, DEFAULT_GEMINI_FLASH_MODEL, } from './models.js';
import { ClearcutLogger } from '../telemetry/clearcut-logger/clearcut-logger.js';
import { shouldAttemptBrowserLaunch } from '../utils/browser.js';
import { IdeClient } from '../ide/ide-client.js';
import { WorkspaceContext } from '../utils/workspaceContext.js';
export var ApprovalMode;
(function (ApprovalMode) {
ApprovalMode["DEFAULT"] = "default";
ApprovalMode["AUTO_EDIT"] = "autoEdit";
ApprovalMode["YOLO"] = "yolo";
})(ApprovalMode || (ApprovalMode = {}));
// For memory files
export const DEFAULT_MEMORY_FILE_FILTERING_OPTIONS = {
respectGitIgnore: false,
respectGeminiIgnore: true,
};
// For all other files
export const DEFAULT_FILE_FILTERING_OPTIONS = {
respectGitIgnore: true,
respectGeminiIgnore: true,
};
export class MCPServerConfig {
command;
args;
env;
cwd;
url;
httpUrl;
headers;
tcp;
timeout;
trust;
description;
includeTools;
excludeTools;
extensionName;
oauth;
authProviderType;
constructor(
// For stdio transport
command, args, env, cwd,
// For sse transport
url,
// For streamable http transport
httpUrl, headers,
// For websocket transport
tcp,
// Common
timeout, trust,
// Metadata
description, includeTools, excludeTools, extensionName,
// OAuth configuration
oauth, authProviderType) {
this.command = command;
this.args = args;
this.env = env;
this.cwd = cwd;
this.url = url;
this.httpUrl = httpUrl;
this.headers = headers;
this.tcp = tcp;
this.timeout = timeout;
this.trust = trust;
this.description = description;
this.includeTools = includeTools;
this.excludeTools = excludeTools;
this.extensionName = extensionName;
this.oauth = oauth;
this.authProviderType = authProviderType;
}
}
export var AuthProviderType;
(function (AuthProviderType) {
AuthProviderType["DYNAMIC_DISCOVERY"] = "dynamic_discovery";
AuthProviderType["GOOGLE_CREDENTIALS"] = "google_credentials";
})(AuthProviderType || (AuthProviderType = {}));
export class Config {
toolRegistry;
promptRegistry;
sessionId;
contentGeneratorConfig;
embeddingModel;
sandbox;
targetDir;
workspaceContext;
debugMode;
question;
fullContext;
coreTools;
excludeTools;
toolDiscoveryCommand;
toolCallCommand;
mcpServerCommand;
mcpServers;
userMemory;
geminiMdFileCount;
approvalMode;
showMemoryUsage;
accessibility;
telemetrySettings;
usageStatisticsEnabled;
geminiClient;
fileFiltering;
fileDiscoveryService = null;
gitService = undefined;
checkpointing;
proxy;
cwd;
bugCommand;
model;
extensionContextFilePaths;
noBrowser;
ideModeFeature;
ideMode;
ideClient;
inFallbackMode = false;
systemPromptMappings;
maxSessionTurns;
sessionTokenLimit;
maxFolderItems;
listExtensions;
_extensions;
_blockedMcpServers;
flashFallbackHandler;
quotaErrorOccurred = false;
summarizeToolOutput;
experimentalAcp = false;
enableOpenAILogging;
sampling_params;
contentGenerator;
settings; // Settings object for API key rotation
constructor(params) {
this.sessionId = params.sessionId;
this.embeddingModel =
params.embeddingModel ?? DEFAULT_GEMINI_EMBEDDING_MODEL;
this.sandbox = params.sandbox;
this.targetDir = path.resolve(params.targetDir);
this.workspaceContext = new WorkspaceContext(this.targetDir, params.includeDirectories ?? []);
this.debugMode = params.debugMode;
this.question = params.question;
this.fullContext = params.fullContext ?? false;
this.coreTools = params.coreTools;
this.excludeTools = params.excludeTools;
this.toolDiscoveryCommand = params.toolDiscoveryCommand;
this.toolCallCommand = params.toolCallCommand;
this.mcpServerCommand = params.mcpServerCommand;
this.mcpServers = params.mcpServers;
this.userMemory = params.userMemory ?? '';
this.geminiMdFileCount = params.geminiMdFileCount ?? 0;
this.approvalMode = params.approvalMode ?? ApprovalMode.DEFAULT;
this.showMemoryUsage = params.showMemoryUsage ?? false;
this.accessibility = params.accessibility ?? {};
this.telemetrySettings = {
enabled: params.telemetry?.enabled ?? false,
target: params.telemetry?.target ?? DEFAULT_TELEMETRY_TARGET,
otlpEndpoint: params.telemetry?.otlpEndpoint ?? DEFAULT_OTLP_ENDPOINT,
logPrompts: params.telemetry?.logPrompts ?? true,
outfile: params.telemetry?.outfile,
};
this.usageStatisticsEnabled = params.usageStatisticsEnabled ?? true;
this.fileFiltering = {
respectGitIgnore: params.fileFiltering?.respectGitIgnore ?? true,
respectGeminiIgnore: params.fileFiltering?.respectGeminiIgnore ?? true,
enableRecursiveFileSearch: params.fileFiltering?.enableRecursiveFileSearch ?? true,
};
this.checkpointing = params.checkpointing ?? false;
this.proxy = params.proxy;
this.cwd = params.cwd ?? process.cwd();
this.fileDiscoveryService = params.fileDiscoveryService ?? null;
this.bugCommand = params.bugCommand;
this.model = params.model;
this.extensionContextFilePaths = params.extensionContextFilePaths ?? [];
this.maxSessionTurns = params.maxSessionTurns ?? -1;
this.sessionTokenLimit = params.sessionTokenLimit ?? 32000;
this.maxFolderItems = params.maxFolderItems ?? 20;
this.experimentalAcp = params.experimentalAcp ?? false;
this.listExtensions = params.listExtensions ?? false;
this._extensions = params.extensions ?? [];
this._blockedMcpServers = params.blockedMcpServers ?? [];
this.noBrowser = params.noBrowser ?? false;
this.summarizeToolOutput = params.summarizeToolOutput;
this.ideModeFeature = params.ideModeFeature ?? false;
this.ideMode = params.ideMode ?? false;
this.ideClient =
params.ideClient ??
IdeClient.getInstance(this.ideMode && this.ideModeFeature);
this.systemPromptMappings = params.systemPromptMappings;
this.enableOpenAILogging = params.enableOpenAILogging ?? false;
this.sampling_params = params.sampling_params;
this.contentGenerator = params.contentGenerator;
this.settings = params.settings;
if (params.contextFileName) {
setGeminiMdFilename(params.contextFileName);
}
if (this.telemetrySettings.enabled) {
initializeTelemetry(this);
}
if (this.getUsageStatisticsEnabled()) {
ClearcutLogger.getInstance(this)?.logStartSessionEvent(new StartSessionEvent(this));
}
else {
console.log('Data collection is disabled.');
}
}
async initialize() {
// Initialize centralized FileDiscoveryService
this.getFileService();
if (this.getCheckpointingEnabled()) {
await this.getGitService();
}
this.promptRegistry = new PromptRegistry();
this.toolRegistry = await this.createToolRegistry();
}
async refreshAuth(authMethod) {
// Save the current conversation history before creating a new client
let existingHistory = [];
if (this.geminiClient && this.geminiClient.isInitialized()) {
existingHistory = this.geminiClient.getHistory();
}
// Create new content generator config
const newContentGeneratorConfig = createContentGeneratorConfig(this, authMethod);
// Create and initialize new client in local variable first
const newGeminiClient = new GeminiClient(this);
await newGeminiClient.initialize(newContentGeneratorConfig, this.settings);
// Only assign to instance properties after successful initialization
this.contentGeneratorConfig = newContentGeneratorConfig;
this.geminiClient = newGeminiClient;
// Restore the conversation history to the new client
if (existingHistory.length > 0) {
this.geminiClient.setHistory(existingHistory);
}
// Reset the session flag since we're explicitly changing auth and using default model
this.inFallbackMode = false;
}
getSessionId() {
return this.sessionId;
}
getContentGeneratorConfig() {
return this.contentGeneratorConfig;
}
getModel() {
return this.contentGeneratorConfig?.model || this.model;
}
setModel(newModel) {
if (this.contentGeneratorConfig) {
this.contentGeneratorConfig.model = newModel;
}
}
isInFallbackMode() {
return this.inFallbackMode;
}
setFallbackMode(active) {
this.inFallbackMode = active;
}
setFlashFallbackHandler(handler) {
this.flashFallbackHandler = handler;
}
getMaxSessionTurns() {
return this.maxSessionTurns;
}
getSessionTokenLimit() {
return this.sessionTokenLimit;
}
getMaxFolderItems() {
return this.maxFolderItems;
}
setQuotaErrorOccurred(value) {
this.quotaErrorOccurred = value;
}
getQuotaErrorOccurred() {
return this.quotaErrorOccurred;
}
getEmbeddingModel() {
return this.embeddingModel;
}
getSandbox() {
return this.sandbox;
}
isRestrictiveSandbox() {
const sandboxConfig = this.getSandbox();
const seatbeltProfile = process.env.SEATBELT_PROFILE;
return (!!sandboxConfig &&
sandboxConfig.command === 'sandbox-exec' &&
!!seatbeltProfile &&
seatbeltProfile.startsWith('restrictive-'));
}
getTargetDir() {
return this.targetDir;
}
getProjectRoot() {
return this.targetDir;
}
getWorkspaceContext() {
return this.workspaceContext;
}
getToolRegistry() {
return Promise.resolve(this.toolRegistry);
}
getPromptRegistry() {
return this.promptRegistry;
}
getDebugMode() {
return this.debugMode;
}
getQuestion() {
return this.question;
}
getFullContext() {
return this.fullContext;
}
getCoreTools() {
return this.coreTools;
}
getExcludeTools() {
return this.excludeTools;
}
getToolDiscoveryCommand() {
return this.toolDiscoveryCommand;
}
getToolCallCommand() {
return this.toolCallCommand;
}
getMcpServerCommand() {
return this.mcpServerCommand;
}
getMcpServers() {
return this.mcpServers;
}
getUserMemory() {
return this.userMemory;
}
setUserMemory(newUserMemory) {
this.userMemory = newUserMemory;
}
getGeminiMdFileCount() {
return this.geminiMdFileCount;
}
setGeminiMdFileCount(count) {
this.geminiMdFileCount = count;
}
getApprovalMode() {
return this.approvalMode;
}
setApprovalMode(mode) {
this.approvalMode = mode;
}
getShowMemoryUsage() {
return this.showMemoryUsage;
}
getAccessibility() {
return this.accessibility;
}
getTelemetryEnabled() {
return this.telemetrySettings.enabled ?? false;
}
getTelemetryLogPromptsEnabled() {
return this.telemetrySettings.logPrompts ?? true;
}
getTelemetryOtlpEndpoint() {
return this.telemetrySettings.otlpEndpoint ?? DEFAULT_OTLP_ENDPOINT;
}
getTelemetryTarget() {
return this.telemetrySettings.target ?? DEFAULT_TELEMETRY_TARGET;
}
getTelemetryOutfile() {
return this.telemetrySettings.outfile;
}
getGeminiClient() {
return this.geminiClient;
}
getGeminiDir() {
return path.join(this.targetDir, GEMINI_DIR);
}
getProjectTempDir() {
return getProjectTempDir(this.getProjectRoot());
}
getEnableRecursiveFileSearch() {
return this.fileFiltering.enableRecursiveFileSearch;
}
getFileFilteringRespectGitIgnore() {
return this.fileFiltering.respectGitIgnore;
}
getFileFilteringRespectGeminiIgnore() {
return this.fileFiltering.respectGeminiIgnore;
}
getFileFilteringOptions() {
return {
respectGitIgnore: this.fileFiltering.respectGitIgnore,
respectGeminiIgnore: this.fileFiltering.respectGeminiIgnore,
};
}
getCheckpointingEnabled() {
return this.checkpointing;
}
getProxy() {
return this.proxy;
}
getWorkingDir() {
return this.cwd;
}
getBugCommand() {
return this.bugCommand;
}
getFileService() {
if (!this.fileDiscoveryService) {
this.fileDiscoveryService = new FileDiscoveryService(this.targetDir);
}
return this.fileDiscoveryService;
}
getUsageStatisticsEnabled() {
return this.usageStatisticsEnabled;
}
getExtensionContextFilePaths() {
return this.extensionContextFilePaths;
}
getExperimentalAcp() {
return this.experimentalAcp;
}
getListExtensions() {
return this.listExtensions;
}
getExtensions() {
return this._extensions;
}
getBlockedMcpServers() {
return this._blockedMcpServers;
}
getNoBrowser() {
return this.noBrowser;
}
isBrowserLaunchSuppressed() {
return this.getNoBrowser() || !shouldAttemptBrowserLaunch();
}
getSummarizeToolOutputConfig() {
return this.summarizeToolOutput;
}
getIdeModeFeature() {
return this.ideModeFeature;
}
getIdeClient() {
return this.ideClient;
}
getIdeMode() {
return this.ideMode;
}
setIdeMode(value) {
this.ideMode = value;
}
setIdeClientDisconnected() {
this.ideClient.setDisconnected();
}
setIdeClientConnected() {
this.ideClient.reconnect(this.ideMode && this.ideModeFeature);
}
getEnableOpenAILogging() {
return this.enableOpenAILogging;
}
getSamplingParams() {
return this.sampling_params;
}
getContentGeneratorTimeout() {
return this.contentGenerator?.timeout;
}
getContentGeneratorMaxRetries() {
return this.contentGenerator?.maxRetries;
}
getSystemPromptMappings() {
return this.systemPromptMappings;
}
async getGitService() {
if (!this.gitService) {
this.gitService = new GitService(this.targetDir);
await this.gitService.initialize();
}
return this.gitService;
}
async createToolRegistry() {
const registry = new ToolRegistry(this);
// helper to create & register core tools that are enabled
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const registerCoreTool = (ToolClass, ...args) => {
const className = ToolClass.name;
const toolName = ToolClass.Name || className;
const coreTools = this.getCoreTools();
const excludeTools = this.getExcludeTools();
let isEnabled = false;
if (coreTools === undefined) {
isEnabled = true;
}
else {
isEnabled = coreTools.some((tool) => tool === className ||
tool === toolName ||
tool.startsWith(`${className}(`) ||
tool.startsWith(`${toolName}(`));
}
if (excludeTools?.includes(className) ||
excludeTools?.includes(toolName)) {
isEnabled = false;
}
if (isEnabled) {
registry.registerTool(new ToolClass(...args));
}
};
registerCoreTool(LSTool, this);
registerCoreTool(ReadFileTool, this);
registerCoreTool(GrepTool, this);
registerCoreTool(GlobTool, this);
registerCoreTool(EditTool, this);
registerCoreTool(WriteFileTool, this);
registerCoreTool(WebFetchTool, this);
registerCoreTool(ReadManyFilesTool, this);
registerCoreTool(ShellTool, this);
registerCoreTool(MemoryTool);
registerCoreTool(WebSearchTool, this);
await registry.discoverAllTools();
return registry;
}
}
// Export model constants for use in CLI
export { DEFAULT_GEMINI_FLASH_MODEL };
//# sourceMappingURL=config.js.map