mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-29 14:34:55 -07:00
refactor(logging): Centralize console logging with debugLogger (#11590)
This commit is contained in:
@@ -21,6 +21,7 @@ import {
|
||||
DEFAULT_GEMINI_EMBEDDING_MODEL,
|
||||
DEFAULT_GEMINI_MODEL,
|
||||
type GeminiCLIExtension,
|
||||
debugLogger,
|
||||
} from '@google/gemini-cli-core';
|
||||
|
||||
import { logger } from '../utils/logger.js';
|
||||
@@ -125,7 +126,7 @@ export function mergeMcpServers(
|
||||
for (const extension of extensions) {
|
||||
Object.entries(extension.mcpServers || {}).forEach(([key, server]) => {
|
||||
if (mcpServers[key]) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Skipping extension MCP config for server with key "${key}" as it already exists.`,
|
||||
);
|
||||
return;
|
||||
|
||||
@@ -16,7 +16,7 @@ import type { AddressInfo } from 'node:net';
|
||||
import { createApp, updateCoderAgentCardUrl } from './app.js';
|
||||
import type { TaskMetadata } from '../types.js';
|
||||
import { createMockConfig } from '../utils/testing_utils.js';
|
||||
import type { Config } from '@google/gemini-cli-core';
|
||||
import { debugLogger, type Config } from '@google/gemini-cli-core';
|
||||
|
||||
// Mock the logger to avoid polluting test output
|
||||
// Comment out to help debug
|
||||
@@ -115,7 +115,7 @@ describe('Agent Server Endpoints', () => {
|
||||
try {
|
||||
fs.rmSync(testWorkspace, { recursive: true, force: true });
|
||||
} catch (e) {
|
||||
console.warn(`Could not remove temp dir '${testWorkspace}':`, e);
|
||||
debugLogger.warn(`Could not remove temp dir '${testWorkspace}':`, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5,7 +5,11 @@
|
||||
*/
|
||||
|
||||
import { type CommandModule } from 'yargs';
|
||||
import { FatalConfigError, getErrorMessage } from '@google/gemini-cli-core';
|
||||
import {
|
||||
debugLogger,
|
||||
FatalConfigError,
|
||||
getErrorMessage,
|
||||
} from '@google/gemini-cli-core';
|
||||
import { enableExtension } from '../../config/extension.js';
|
||||
import { SettingScope } from '../../config/settings.js';
|
||||
import { ExtensionEnablementManager } from '../../config/extensions/extensionEnablement.js';
|
||||
@@ -28,11 +32,11 @@ export function handleEnable(args: EnableArgs) {
|
||||
enableExtension(args.name, SettingScope.User, extensionEnablementManager);
|
||||
}
|
||||
if (args.scope) {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`Extension "${args.name}" successfully enabled for scope "${args.scope}".`,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`Extension "${args.name}" successfully enabled in all scopes.`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,20 +4,11 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {
|
||||
vi,
|
||||
describe,
|
||||
it,
|
||||
expect,
|
||||
beforeEach,
|
||||
afterEach,
|
||||
type Mock,
|
||||
type MockInstance,
|
||||
} from 'vitest';
|
||||
import { vi, describe, it, expect, beforeEach, type Mock } from 'vitest';
|
||||
import { listMcpServers } from './list.js';
|
||||
import { loadSettings } from '../../config/settings.js';
|
||||
import { ExtensionStorage, loadExtensions } from '../../config/extension.js';
|
||||
import { createTransport } from '@google/gemini-cli-core';
|
||||
import { createTransport, debugLogger } from '@google/gemini-cli-core';
|
||||
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
||||
|
||||
vi.mock('../../config/settings.js', () => ({
|
||||
@@ -43,6 +34,12 @@ vi.mock('@google/gemini-cli-core', () => ({
|
||||
})),
|
||||
GEMINI_DIR: '.gemini',
|
||||
getErrorMessage: (e: unknown) => (e instanceof Error ? e.message : String(e)),
|
||||
debugLogger: {
|
||||
log: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
debug: vi.fn(),
|
||||
},
|
||||
}));
|
||||
vi.mock('@modelcontextprotocol/sdk/client/index.js');
|
||||
|
||||
@@ -64,15 +61,12 @@ interface MockTransport {
|
||||
}
|
||||
|
||||
describe('mcp list command', () => {
|
||||
let consoleSpy: MockInstance;
|
||||
let mockClient: MockClient;
|
||||
let mockTransport: MockTransport;
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
|
||||
consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
|
||||
mockTransport = { close: vi.fn() };
|
||||
mockClient = {
|
||||
connect: vi.fn(),
|
||||
@@ -86,16 +80,12 @@ describe('mcp list command', () => {
|
||||
mockedGetUserExtensionsDir.mockReturnValue('/mocked/extensions/dir');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
consoleSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('should display message when no servers configured', async () => {
|
||||
mockedLoadSettings.mockReturnValue({ merged: { mcpServers: {} } });
|
||||
|
||||
await listMcpServers();
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalledWith('No MCP servers configured.');
|
||||
expect(debugLogger.log).toHaveBeenCalledWith('No MCP servers configured.');
|
||||
});
|
||||
|
||||
it('should display different server types with connected status', async () => {
|
||||
@@ -114,18 +104,18 @@ describe('mcp list command', () => {
|
||||
|
||||
await listMcpServers();
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalledWith('Configured MCP servers:\n');
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
expect(debugLogger.log).toHaveBeenCalledWith('Configured MCP servers:\n');
|
||||
expect(debugLogger.log).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
'stdio-server: /path/to/server arg1 (stdio) - Connected',
|
||||
),
|
||||
);
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
expect(debugLogger.log).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
'sse-server: https://example.com/sse (sse) - Connected',
|
||||
),
|
||||
);
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
expect(debugLogger.log).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
'http-server: https://example.com/http (http) - Connected',
|
||||
),
|
||||
@@ -145,7 +135,7 @@ describe('mcp list command', () => {
|
||||
|
||||
await listMcpServers();
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
expect(debugLogger.log).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
'test-server: /test/server (stdio) - Disconnected',
|
||||
),
|
||||
@@ -171,12 +161,12 @@ describe('mcp list command', () => {
|
||||
|
||||
await listMcpServers();
|
||||
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
expect(debugLogger.log).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
'config-server: /config/server (stdio) - Connected',
|
||||
),
|
||||
);
|
||||
expect(consoleSpy).toHaveBeenCalledWith(
|
||||
expect(debugLogger.log).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
'extension-server (from test-extension): /ext/server (stdio) - Connected',
|
||||
),
|
||||
|
||||
@@ -8,7 +8,11 @@
|
||||
import type { CommandModule } from 'yargs';
|
||||
import { loadSettings } from '../../config/settings.js';
|
||||
import type { MCPServerConfig } from '@google/gemini-cli-core';
|
||||
import { MCPServerStatus, createTransport } from '@google/gemini-cli-core';
|
||||
import {
|
||||
MCPServerStatus,
|
||||
createTransport,
|
||||
debugLogger,
|
||||
} from '@google/gemini-cli-core';
|
||||
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
||||
import { loadExtensions } from '../../config/extension.js';
|
||||
import { ExtensionEnablementManager } from '../../config/extensions/extensionEnablement.js';
|
||||
@@ -84,11 +88,11 @@ export async function listMcpServers(): Promise<void> {
|
||||
const serverNames = Object.keys(mcpServers);
|
||||
|
||||
if (serverNames.length === 0) {
|
||||
console.log('No MCP servers configured.');
|
||||
debugLogger.log('No MCP servers configured.');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Configured MCP servers:\n');
|
||||
debugLogger.log('Configured MCP servers:\n');
|
||||
|
||||
for (const serverName of serverNames) {
|
||||
const server = mcpServers[serverName];
|
||||
@@ -125,7 +129,7 @@ export async function listMcpServers(): Promise<void> {
|
||||
serverInfo += `${server.command} ${server.args?.join(' ') || ''} (stdio)`;
|
||||
}
|
||||
|
||||
console.log(`${statusIndicator} ${serverInfo} - ${statusText}`);
|
||||
debugLogger.log(`${statusIndicator} ${serverInfo} - ${statusText}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
// File for 'gemini mcp remove' command
|
||||
import type { CommandModule } from 'yargs';
|
||||
import { loadSettings, SettingScope } from '../../config/settings.js';
|
||||
import { debugLogger } from '@google/gemini-cli-core';
|
||||
|
||||
async function removeMcpServer(
|
||||
name: string,
|
||||
@@ -23,7 +24,7 @@ async function removeMcpServer(
|
||||
const mcpServers = existingSettings.mcpServers || {};
|
||||
|
||||
if (!mcpServers[name]) {
|
||||
console.log(`Server "${name}" not found in ${scope} settings.`);
|
||||
debugLogger.log(`Server "${name}" not found in ${scope} settings.`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -31,7 +32,7 @@ async function removeMcpServer(
|
||||
|
||||
settings.setValue(settingsScope, 'mcpServers', mcpServers);
|
||||
|
||||
console.log(`Server "${name}" removed from ${scope} settings.`);
|
||||
debugLogger.log(`Server "${name}" removed from ${scope} settings.`);
|
||||
}
|
||||
|
||||
export const removeCommand: CommandModule = {
|
||||
|
||||
@@ -1073,8 +1073,6 @@ describe('Settings Loading and Merging', () => {
|
||||
);
|
||||
|
||||
const settings = loadSettings(MOCK_WORKSPACE_DIR);
|
||||
const e = settings.user.settings.model?.chatCompression;
|
||||
console.log(e);
|
||||
|
||||
expect(settings.user.settings.model?.chatCompression).toEqual({
|
||||
contextPercentageThreshold: 0.5,
|
||||
|
||||
@@ -10,6 +10,7 @@ import { homedir, platform } from 'node:os';
|
||||
import * as dotenv from 'dotenv';
|
||||
import process from 'node:process';
|
||||
import {
|
||||
debugLogger,
|
||||
FatalConfigError,
|
||||
GEMINI_DIR,
|
||||
getErrorMessage,
|
||||
@@ -753,7 +754,7 @@ export function migrateDeprecatedSettings(
|
||||
const processScope = (scope: SettingScope) => {
|
||||
const settings = loadedSettings.forScope(scope).settings;
|
||||
if (settings.extensions?.disabled) {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`Migrating deprecated extensions.disabled settings from ${scope} settings...`,
|
||||
);
|
||||
const extensionEnablementManager = new ExtensionEnablementManager();
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { debugLogger } from '@google/gemini-cli-core';
|
||||
import type { SlashCommand } from '../ui/commands/types.js';
|
||||
import type { ICommandLoader } from './types.js';
|
||||
|
||||
@@ -57,7 +58,7 @@ export class CommandService {
|
||||
if (result.status === 'fulfilled') {
|
||||
allCommands.push(...result.value);
|
||||
} else {
|
||||
console.debug('A command loader failed:', result.reason);
|
||||
debugLogger.debug('A command loader failed:', result.reason);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ import {
|
||||
AuthType,
|
||||
clearCachedCredentialFile,
|
||||
ShellExecutionService,
|
||||
debugLogger,
|
||||
} from '@google/gemini-cli-core';
|
||||
import { validateAuthMethod } from '../config/auth.js';
|
||||
import { loadHierarchicalGeminiMemory } from '../config/config.js';
|
||||
@@ -389,7 +390,7 @@ export const AppContainer = (props: AppContainerProps) => {
|
||||
config.isBrowserLaunchSuppressed()
|
||||
) {
|
||||
await runExitCleanup();
|
||||
console.log(`
|
||||
debugLogger.log(`
|
||||
----------------------------------------------------------------
|
||||
Logging in with Google... Please restart Gemini CLI to continue.
|
||||
----------------------------------------------------------------
|
||||
@@ -558,7 +559,7 @@ Logging in with Google... Please restart Gemini CLI to continue.
|
||||
Date.now(),
|
||||
);
|
||||
if (config.getDebugMode()) {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`[DEBUG] Refreshed memory content in config: ${memoryContent.substring(
|
||||
0,
|
||||
200,
|
||||
@@ -933,7 +934,7 @@ Logging in with Google... Please restart Gemini CLI to continue.
|
||||
(key: Key) => {
|
||||
// Debug log keystrokes if enabled
|
||||
if (settings.merged.general?.debugKeystrokeLogging) {
|
||||
console.log('[DEBUG] Keystroke:', JSON.stringify(key));
|
||||
debugLogger.log('[DEBUG] Keystroke:', JSON.stringify(key));
|
||||
}
|
||||
|
||||
if (keyMatchers[Command.QUIT](key)) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import { SettingScope } from '../../config/settings.js';
|
||||
import {
|
||||
AuthType,
|
||||
clearCachedCredentialFile,
|
||||
debugLogger,
|
||||
type Config,
|
||||
} from '@google/gemini-cli-core';
|
||||
import { useKeypress } from '../hooks/useKeypress.js';
|
||||
@@ -108,7 +109,7 @@ export function AuthDialog({
|
||||
config.isBrowserLaunchSuppressed()
|
||||
) {
|
||||
runExitCleanup();
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`
|
||||
----------------------------------------------------------------
|
||||
Logging in with Google... Please restart Gemini CLI to continue.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import type { LoadedSettings } from '../../config/settings.js';
|
||||
import { AuthType, type Config } from '@google/gemini-cli-core';
|
||||
import { AuthType, debugLogger, type Config } from '@google/gemini-cli-core';
|
||||
import { getErrorMessage } from '@google/gemini-cli-core';
|
||||
import { AuthState } from '../types.js';
|
||||
import { validateAuthMethod } from '../../config/auth.js';
|
||||
@@ -80,7 +80,7 @@ export const useAuthCommand = (settings: LoadedSettings, config: Config) => {
|
||||
try {
|
||||
await config.refreshAuth(authType);
|
||||
|
||||
console.log(`Authenticated via "${authType}".`);
|
||||
debugLogger.log(`Authenticated via "${authType}".`);
|
||||
setAuthError(null);
|
||||
setAuthState(AuthState.Authenticated);
|
||||
} catch (e) {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { debugLogger } from '@google/gemini-cli-core';
|
||||
import { copyToClipboard } from '../utils/commandUtils.js';
|
||||
import type { SlashCommand, SlashCommandActionReturn } from './types.js';
|
||||
import { CommandKind } from './types.js';
|
||||
@@ -45,7 +46,7 @@ export const copyCommand: SlashCommand = {
|
||||
};
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
console.debug(message);
|
||||
debugLogger.debug(message);
|
||||
|
||||
return {
|
||||
type: 'message',
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
import type { SlashCommand, SlashCommandActionReturn } from './types.js';
|
||||
import { CommandKind } from './types.js';
|
||||
import { getUrlOpenCommand } from '../../ui/utils/commandUtils.js';
|
||||
import { debugLogger } from '@google/gemini-cli-core';
|
||||
|
||||
export const GITHUB_WORKFLOW_PATHS = [
|
||||
'gemini-dispatch/gemini-dispatch.yml',
|
||||
@@ -84,7 +85,7 @@ export async function updateGitignore(gitRepoRoot: string): Promise<void> {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.debug('Failed to update .gitignore:', error);
|
||||
debugLogger.debug('Failed to update .gitignore:', error);
|
||||
// Continue without failing the whole command
|
||||
}
|
||||
}
|
||||
@@ -109,7 +110,7 @@ export const setupGithubCommand: SlashCommand = {
|
||||
try {
|
||||
gitRepoRoot = getGitRepoRoot();
|
||||
} catch (_error) {
|
||||
console.debug(`Failed to get git repo root:`, _error);
|
||||
debugLogger.debug(`Failed to get git repo root:`, _error);
|
||||
throw new Error(
|
||||
'Unable to determine the GitHub repository. /setup-github must be run from a git repository.',
|
||||
);
|
||||
@@ -125,7 +126,7 @@ export const setupGithubCommand: SlashCommand = {
|
||||
try {
|
||||
await fs.promises.mkdir(githubWorkflowsDir, { recursive: true });
|
||||
} catch (_error) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`Failed to create ${githubWorkflowsDir} directory:`,
|
||||
_error,
|
||||
);
|
||||
|
||||
@@ -37,6 +37,7 @@ import {
|
||||
type SettingsValue,
|
||||
TOGGLE_TYPES,
|
||||
} from '../../config/settingsSchema.js';
|
||||
import { debugLogger } from '@google/gemini-cli-core';
|
||||
|
||||
interface SettingsDialogProps {
|
||||
settings: LoadedSettings;
|
||||
@@ -162,7 +163,7 @@ export function SettingsDialog({
|
||||
newValue,
|
||||
currentScopeSettings,
|
||||
);
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`[DEBUG SettingsDialog] Saving ${key} immediately with value:`,
|
||||
newValue,
|
||||
);
|
||||
@@ -207,7 +208,7 @@ export function SettingsDialog({
|
||||
setModifiedSettings((prev) => {
|
||||
const updated = new Set(prev).add(key);
|
||||
const needsRestart = hasRestartRequiredSettings(updated);
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`[DEBUG SettingsDialog] Modified settings:`,
|
||||
Array.from(updated),
|
||||
'Needs restart:',
|
||||
|
||||
@@ -9,6 +9,7 @@ import * as path from 'node:path';
|
||||
import type { PartListUnion, PartUnion } from '@google/genai';
|
||||
import type { AnyToolInvocation, Config } from '@google/gemini-cli-core';
|
||||
import {
|
||||
debugLogger,
|
||||
getErrorMessage,
|
||||
isNodeError,
|
||||
unescapePath,
|
||||
@@ -372,7 +373,7 @@ export async function handleAtCommand({
|
||||
}
|
||||
|
||||
const message = `Ignored ${totalIgnored} files:\n${messages.join('\n')}`;
|
||||
console.log(message);
|
||||
debugLogger.log(message);
|
||||
onDebugMessage(message);
|
||||
}
|
||||
|
||||
|
||||
@@ -222,8 +222,6 @@ export const useShellCommandProcessor = (
|
||||
shellExecutionConfig,
|
||||
);
|
||||
|
||||
console.log(terminalHeight, terminalWidth);
|
||||
|
||||
executionPid = pid;
|
||||
if (pid) {
|
||||
setActiveShellPtyId(pid);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { debugLogger } from '@google/gemini-cli-core';
|
||||
import { useState, useCallback } from 'react';
|
||||
|
||||
interface Logger {
|
||||
@@ -69,7 +70,10 @@ export function useInputHistoryStore(): UseInputHistoryStoreReturn {
|
||||
setIsInitialized(true);
|
||||
} catch (error) {
|
||||
// Start with empty history even if logger initialization fails
|
||||
console.warn('Failed to initialize input history from logger:', error);
|
||||
debugLogger.warn(
|
||||
'Failed to initialize input history from logger:',
|
||||
error,
|
||||
);
|
||||
setPastSessionMessages([]);
|
||||
recalculateHistory([], []);
|
||||
setIsInitialized(true);
|
||||
|
||||
@@ -20,7 +20,7 @@ import type {
|
||||
Status as CoreStatus,
|
||||
EditorType,
|
||||
} from '@google/gemini-cli-core';
|
||||
import { CoreToolScheduler } from '@google/gemini-cli-core';
|
||||
import { CoreToolScheduler, debugLogger } from '@google/gemini-cli-core';
|
||||
import { useCallback, useState, useMemo } from 'react';
|
||||
import type {
|
||||
HistoryItemToolGroup,
|
||||
@@ -198,7 +198,7 @@ function mapCoreStatusToDisplayStatus(coreStatus: CoreStatus): ToolCallStatus {
|
||||
return ToolCallStatus.Pending;
|
||||
default: {
|
||||
const exhaustiveCheck: never = coreStatus;
|
||||
console.warn(`Unknown core status encountered: ${exhaustiveCheck}`);
|
||||
debugLogger.warn(`Unknown core status encountered: ${exhaustiveCheck}`);
|
||||
return ToolCallStatus.Error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import type { Message } from '../types.js';
|
||||
import { MessageType } from '../types.js';
|
||||
import type { Config } from '@google/gemini-cli-core';
|
||||
import { debugLogger, type Config } from '@google/gemini-cli-core';
|
||||
import type { LoadedSettings } from '../../config/settings.js';
|
||||
|
||||
export function createShowMemoryAction(
|
||||
@@ -27,7 +27,7 @@ export function createShowMemoryAction(
|
||||
const debugMode = config.getDebugMode();
|
||||
|
||||
if (debugMode) {
|
||||
console.log('[DEBUG] Show Memory command invoked.');
|
||||
debugLogger.log('[DEBUG] Show Memory command invoked.');
|
||||
}
|
||||
|
||||
const currentMemory = config.getUserMemory();
|
||||
@@ -38,10 +38,10 @@ export function createShowMemoryAction(
|
||||
: [contextFileName];
|
||||
|
||||
if (debugMode) {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`[DEBUG] Showing memory. Content from config.getUserMemory() (first 200 chars): ${currentMemory.substring(0, 200)}...`,
|
||||
);
|
||||
console.log(`[DEBUG] Number of context files loaded: ${fileCount}`);
|
||||
debugLogger.log(`[DEBUG] Number of context files loaded: ${fileCount}`);
|
||||
}
|
||||
|
||||
if (fileCount > 0) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
type CommandContext,
|
||||
type SlashCommand,
|
||||
} from '../commands/types.js';
|
||||
import { debugLogger } from '@google/gemini-cli-core';
|
||||
|
||||
// Type alias for improved type safety based on actual fzf result structure
|
||||
type FzfCommandResult = {
|
||||
@@ -189,7 +190,7 @@ function useCommandSuggestions(
|
||||
|
||||
// Safety check: ensure leafCommand and completion exist
|
||||
if (!leafCommand?.completion) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
'Attempted argument completion without completion function',
|
||||
);
|
||||
return;
|
||||
|
||||
@@ -8,6 +8,7 @@ import { useCallback, useReducer, useEffect } from 'react';
|
||||
import type { Key } from './useKeypress.js';
|
||||
import type { TextBuffer } from '../components/shared/text-buffer.js';
|
||||
import { useVimMode } from '../contexts/VimModeContext.js';
|
||||
import { debugLogger } from '@google/gemini-cli-core';
|
||||
|
||||
export type VimMode = 'NORMAL' | 'INSERT';
|
||||
|
||||
@@ -394,7 +395,7 @@ export function useVim(buffer: TextBuffer, onSubmit?: (value: string) => void) {
|
||||
normalizedKey = normalizeKey(key);
|
||||
} catch (error) {
|
||||
// Handle malformed key inputs gracefully
|
||||
console.warn('Malformed key input in vim mode:', key, error);
|
||||
debugLogger.warn('Malformed key input in vim mode:', key, error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { debugLogger } from '@google/gemini-cli-core';
|
||||
|
||||
// Mapping from common CSS color names (lowercase) to hex codes (lowercase)
|
||||
// Excludes names directly supported by Ink
|
||||
export const CSS_NAME_TO_HEX_MAP: Readonly<Record<string, string>> = {
|
||||
@@ -224,7 +226,7 @@ export function resolveColor(colorValue: string): string | undefined {
|
||||
}
|
||||
|
||||
// 4. Could not resolve
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`[ColorUtils] Could not resolve color "${colorValue}" to an Ink-compatible format.`,
|
||||
);
|
||||
return undefined;
|
||||
|
||||
@@ -25,6 +25,7 @@ import { ANSI } from './ansi.js';
|
||||
import { ANSILight } from './ansi-light.js';
|
||||
import { NoColorTheme } from './no-color.js';
|
||||
import process from 'node:process';
|
||||
import { debugLogger } from '@google/gemini-cli-core';
|
||||
|
||||
export interface ThemeDisplay {
|
||||
name: string;
|
||||
@@ -75,7 +76,7 @@ class ThemeManager {
|
||||
const validation = validateCustomTheme(customThemeConfig);
|
||||
if (validation.isValid) {
|
||||
if (validation.warning) {
|
||||
console.warn(`Theme "${name}": ${validation.warning}`);
|
||||
debugLogger.warn(`Theme "${name}": ${validation.warning}`);
|
||||
}
|
||||
const themeWithDefaults: CustomTheme = {
|
||||
...DEFAULT_THEME.colors,
|
||||
@@ -88,10 +89,10 @@ class ThemeManager {
|
||||
const theme = createCustomTheme(themeWithDefaults);
|
||||
this.customThemes.set(name, theme);
|
||||
} catch (error) {
|
||||
console.warn(`Failed to load custom theme "${name}":`, error);
|
||||
debugLogger.warn(`Failed to load custom theme "${name}":`, error);
|
||||
}
|
||||
} else {
|
||||
console.warn(`Invalid custom theme "${name}": ${validation.error}`);
|
||||
debugLogger.warn(`Invalid custom theme "${name}": ${validation.error}`);
|
||||
}
|
||||
}
|
||||
// If the current active theme is a custom theme, keep it if still valid
|
||||
@@ -246,7 +247,7 @@ class ThemeManager {
|
||||
// 2. Perform security check.
|
||||
const homeDir = path.resolve(os.homedir());
|
||||
if (!canonicalPath.startsWith(homeDir)) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Theme file at "${themePath}" is outside your home directory. ` +
|
||||
`Only load themes from trusted sources.`,
|
||||
);
|
||||
@@ -259,14 +260,14 @@ class ThemeManager {
|
||||
|
||||
const validation = validateCustomTheme(customThemeConfig);
|
||||
if (!validation.isValid) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Invalid custom theme from file "${themePath}": ${validation.error}`,
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (validation.warning) {
|
||||
console.warn(`Theme from "${themePath}": ${validation.warning}`);
|
||||
debugLogger.warn(`Theme from "${themePath}": ${validation.warning}`);
|
||||
}
|
||||
|
||||
// 4. Create and cache the theme.
|
||||
@@ -286,7 +287,10 @@ class ThemeManager {
|
||||
if (
|
||||
!(error instanceof Error && 'code' in error && error.code === 'ENOENT')
|
||||
) {
|
||||
console.warn(`Could not load theme from file "${themePath}":`, error);
|
||||
debugLogger.warn(
|
||||
`Could not load theme from file "${themePath}":`,
|
||||
error,
|
||||
);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { debugLogger } from '@google/gemini-cli-core';
|
||||
import type { SpawnOptions } from 'node:child_process';
|
||||
import { spawn } from 'node:child_process';
|
||||
|
||||
@@ -165,7 +166,7 @@ export const getUrlOpenCommand = (): string => {
|
||||
default:
|
||||
// Default to xdg-open, which appears to be supported for the less popular operating systems.
|
||||
openCmd = 'xdg-open';
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Unknown platform: ${process.platform}. Attempting to open URLs with: ${openCmd}.`,
|
||||
);
|
||||
break;
|
||||
|
||||
@@ -30,6 +30,7 @@ import { exec } from 'node:child_process';
|
||||
import { promisify } from 'node:util';
|
||||
import { isKittyProtocolEnabled } from './kittyProtocolDetector.js';
|
||||
import { VSCODE_SHIFT_ENTER_SEQUENCE } from './platformConstants.js';
|
||||
import { debugLogger } from '@google/gemini-cli-core';
|
||||
|
||||
const execAsync = promisify(exec);
|
||||
|
||||
@@ -88,7 +89,7 @@ async function detectTerminal(): Promise<SupportedTerminal | null> {
|
||||
return 'vscode';
|
||||
} catch (error) {
|
||||
// Continue detection even if process check fails
|
||||
console.debug('Parent process detection failed:', error);
|
||||
debugLogger.debug('Parent process detection failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +104,7 @@ async function backupFile(filePath: string): Promise<void> {
|
||||
await fs.copyFile(filePath, backupPath);
|
||||
} catch (error) {
|
||||
// Log backup errors but continue with operation
|
||||
console.warn(`Failed to create backup of ${filePath}:`, error);
|
||||
debugLogger.warn(`Failed to create backup of ${filePath}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import updateNotifier from 'update-notifier';
|
||||
import semver from 'semver';
|
||||
import { getPackageJson } from '../../utils/package.js';
|
||||
import type { LoadedSettings } from '../../config/settings.js';
|
||||
import { debugLogger } from '@google/gemini-cli-core';
|
||||
|
||||
export const FETCH_TIMEOUT_MS = 2000;
|
||||
|
||||
@@ -101,7 +102,7 @@ export async function checkForUpdates(
|
||||
|
||||
return null;
|
||||
} catch (e) {
|
||||
console.warn('Failed to check for updates: ' + e);
|
||||
debugLogger.warn('Failed to check for updates: ' + e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { debugLogger } from '@google/gemini-cli-core';
|
||||
import { execSync } from 'node:child_process';
|
||||
import { ProxyAgent } from 'undici';
|
||||
|
||||
@@ -24,7 +25,7 @@ export const isGitHubRepository = (): boolean => {
|
||||
return pattern.test(remotes);
|
||||
} catch (_error) {
|
||||
// If any filesystem error occurs, assume not a git repo
|
||||
console.debug(`Failed to get git remote:`, _error);
|
||||
debugLogger.debug(`Failed to get git remote:`, _error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -83,7 +84,10 @@ export const getLatestGitHubRelease = async (
|
||||
}
|
||||
return releaseTag;
|
||||
} catch (_error) {
|
||||
console.debug(`Failed to determine latest run-gemini-cli release:`, _error);
|
||||
debugLogger.debug(
|
||||
`Failed to determine latest run-gemini-cli release:`,
|
||||
_error,
|
||||
);
|
||||
throw new Error(
|
||||
`Unable to determine the latest run-gemini-cli release on GitHub.`,
|
||||
);
|
||||
|
||||
@@ -9,10 +9,16 @@ import { getInstallationInfo, PackageManager } from './installationInfo.js';
|
||||
import * as fs from 'node:fs';
|
||||
import * as path from 'node:path';
|
||||
import * as childProcess from 'node:child_process';
|
||||
import { isGitRepository } from '@google/gemini-cli-core';
|
||||
import { isGitRepository, debugLogger } from '@google/gemini-cli-core';
|
||||
|
||||
vi.mock('@google/gemini-cli-core', () => ({
|
||||
isGitRepository: vi.fn(),
|
||||
debugLogger: {
|
||||
log: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
debug: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('fs', async (importOriginal) => {
|
||||
@@ -59,7 +65,6 @@ describe('getInstallationInfo', () => {
|
||||
});
|
||||
|
||||
it('should return UNKNOWN and log error if realpathSync fails', () => {
|
||||
const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
process.argv[1] = '/path/to/cli';
|
||||
const error = new Error('realpath failed');
|
||||
mockedRealPathSync.mockImplementation(() => {
|
||||
@@ -69,8 +74,7 @@ describe('getInstallationInfo', () => {
|
||||
const info = getInstallationInfo(projectRoot, false);
|
||||
|
||||
expect(info.packageManager).toBe(PackageManager.UNKNOWN);
|
||||
expect(consoleSpy).toHaveBeenCalledWith(error);
|
||||
consoleSpy.mockRestore();
|
||||
expect(debugLogger.log).toHaveBeenCalledWith(error);
|
||||
});
|
||||
|
||||
it('should detect running from a local git clone', () => {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { isGitRepository } from '@google/gemini-cli-core';
|
||||
import { debugLogger, isGitRepository } from '@google/gemini-cli-core';
|
||||
import * as fs from 'node:fs';
|
||||
import * as path from 'node:path';
|
||||
import * as childProcess from 'node:child_process';
|
||||
@@ -174,7 +174,7 @@ export function getInstallationInfo(
|
||||
: 'Installed with npm. Attempting to automatically update now...',
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
debugLogger.log(error);
|
||||
return { packageManager: PackageManager.UNKNOWN, isGlobal: false };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { debugLogger } from '@google/gemini-cli-core';
|
||||
|
||||
export async function readStdin(): Promise<string> {
|
||||
const MAX_STDIN_SIZE = 8 * 1024 * 1024; // 8MB
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -30,7 +32,7 @@ export async function readStdin(): Promise<string> {
|
||||
if (totalSize + chunk.length > MAX_STDIN_SIZE) {
|
||||
const remainingSize = MAX_STDIN_SIZE - totalSize;
|
||||
data += chunk.slice(0, remainingSize);
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Warning: stdin input truncated to ${MAX_STDIN_SIZE} bytes.`,
|
||||
);
|
||||
process.stdin.destroy(); // Stop reading further
|
||||
|
||||
@@ -14,7 +14,11 @@ import { quote, parse } from 'shell-quote';
|
||||
import { USER_SETTINGS_DIR } from '../config/settings.js';
|
||||
import { promisify } from 'node:util';
|
||||
import type { Config, SandboxConfig } from '@google/gemini-cli-core';
|
||||
import { FatalSandboxError, GEMINI_DIR } from '@google/gemini-cli-core';
|
||||
import {
|
||||
debugLogger,
|
||||
FatalSandboxError,
|
||||
GEMINI_DIR,
|
||||
} from '@google/gemini-cli-core';
|
||||
import { ConsolePatcher } from '../ui/utils/ConsolePatcher.js';
|
||||
import { randomBytes } from 'node:crypto';
|
||||
|
||||
@@ -92,7 +96,7 @@ async function shouldUseCurrentUserInSandbox(): Promise<boolean> {
|
||||
} catch (_err) {
|
||||
// Silently ignore if /etc/os-release is not found or unreadable.
|
||||
// The default (false) will be applied in this case.
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
'Warning: Could not read /etc/os-release to auto-detect Debian/Ubuntu for UID/GID default.',
|
||||
);
|
||||
}
|
||||
@@ -301,7 +305,7 @@ export async function start_sandbox(
|
||||
});
|
||||
// install handlers to stop proxy on exit/signal
|
||||
const stopProxy = () => {
|
||||
console.log('stopping proxy ...');
|
||||
debugLogger.log('stopping proxy ...');
|
||||
if (proxyProcess?.pid) {
|
||||
process.kill(-proxyProcess.pid, 'SIGTERM');
|
||||
}
|
||||
@@ -325,7 +329,7 @@ export async function start_sandbox(
|
||||
`Proxy command '${proxyCommand}' exited with code ${code}, signal ${signal}`,
|
||||
);
|
||||
});
|
||||
console.log('waiting for proxy to start ...');
|
||||
debugLogger.log('waiting for proxy to start ...');
|
||||
await execAsync(
|
||||
`until timeout 0.25 curl -s http://localhost:8877; do sleep 0.25; done`,
|
||||
);
|
||||
@@ -559,7 +563,7 @@ export async function start_sandbox(
|
||||
containerName = `gemini-cli-integration-test-${randomBytes(4).toString(
|
||||
'hex',
|
||||
)}`;
|
||||
console.log(`ContainerName: ${containerName}`);
|
||||
debugLogger.log(`ContainerName: ${containerName}`);
|
||||
} else {
|
||||
let index = 0;
|
||||
const containerNameCheck = execSync(
|
||||
@@ -571,7 +575,7 @@ export async function start_sandbox(
|
||||
index++;
|
||||
}
|
||||
containerName = `${imageName}-${index}`;
|
||||
console.log(`ContainerName (regular): ${containerName}`);
|
||||
debugLogger.log(`ContainerName (regular): ${containerName}`);
|
||||
}
|
||||
args.push('--name', containerName, '--hostname', containerName);
|
||||
|
||||
@@ -773,7 +777,7 @@ export async function start_sandbox(
|
||||
});
|
||||
// install handlers to stop proxy on exit/signal
|
||||
const stopProxy = () => {
|
||||
console.log('stopping proxy container ...');
|
||||
debugLogger.log('stopping proxy container ...');
|
||||
execSync(`${config.command} rm -f ${SANDBOX_PROXY_NAME}`);
|
||||
};
|
||||
process.on('exit', stopProxy);
|
||||
@@ -795,7 +799,7 @@ export async function start_sandbox(
|
||||
`Proxy container command '${proxyContainerCommand}' exited with code ${code}, signal ${signal}`,
|
||||
);
|
||||
});
|
||||
console.log('waiting for proxy to start ...');
|
||||
debugLogger.log('waiting for proxy to start ...');
|
||||
await execAsync(
|
||||
`until timeout 0.25 curl -s http://localhost:8877; do sleep 0.25; done`,
|
||||
);
|
||||
@@ -821,7 +825,7 @@ export async function start_sandbox(
|
||||
sandboxProcess?.on('close', (code, signal) => {
|
||||
process.stdin.resume();
|
||||
if (code !== 0 && code !== null) {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`Sandbox process exited with code: ${code}, signal: ${signal}`,
|
||||
);
|
||||
}
|
||||
@@ -847,7 +851,7 @@ async function imageExists(sandbox: string, image: string): Promise<boolean> {
|
||||
}
|
||||
|
||||
checkProcess.on('error', (err) => {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Failed to start '${sandbox}' command for image check: ${err.message}`,
|
||||
);
|
||||
resolve(false);
|
||||
@@ -882,7 +886,7 @@ async function pullImage(sandbox: string, image: string): Promise<boolean> {
|
||||
};
|
||||
|
||||
const onError = (err: Error) => {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Failed to start '${sandbox} pull ${image}' command: ${err.message}`,
|
||||
);
|
||||
cleanup();
|
||||
@@ -895,7 +899,7 @@ async function pullImage(sandbox: string, image: string): Promise<boolean> {
|
||||
cleanup();
|
||||
resolve(true);
|
||||
} else {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Failed to pull image ${image}. '${sandbox} pull ${image}' exited with code ${code}.`,
|
||||
);
|
||||
if (stderrData.trim()) {
|
||||
@@ -953,7 +957,7 @@ async function ensureSandboxImageIsPresent(
|
||||
console.info(`Sandbox image ${image} is now available after pulling.`);
|
||||
return true;
|
||||
} else {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Sandbox image ${image} still not found after a pull attempt. This might indicate an issue with the image name or registry, or the pull command reported success but failed to make the image available.`,
|
||||
);
|
||||
return false;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import * as fs from 'node:fs/promises';
|
||||
import * as path from 'node:path';
|
||||
import { type Config } from '@google/gemini-cli-core';
|
||||
import { debugLogger, type Config } from '@google/gemini-cli-core';
|
||||
import type { Settings, SessionRetentionSettings } from '../config/settings.js';
|
||||
import { getAllSessionFiles, type SessionFileEntry } from './sessionUtils.js';
|
||||
|
||||
@@ -88,11 +88,11 @@ export async function cleanupExpiredSessions(
|
||||
|
||||
if (config.getDebugMode()) {
|
||||
if (sessionToDelete.sessionInfo === null) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`Deleted corrupted session file: ${sessionToDelete.fileName}`,
|
||||
);
|
||||
} else {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`Deleted expired session: ${sessionToDelete.sessionInfo.id} (${sessionToDelete.sessionInfo.lastUpdated})`,
|
||||
);
|
||||
}
|
||||
@@ -125,7 +125,7 @@ export async function cleanupExpiredSessions(
|
||||
result.skipped = result.scanned - result.deleted - result.failed;
|
||||
|
||||
if (config.getDebugMode() && result.deleted > 0) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`Session cleanup: deleted ${result.deleted}, skipped ${result.skipped}, failed ${result.failed}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -53,10 +53,7 @@ describe('validateNonInterActiveAuth', () => {
|
||||
throw new Error(`process.exit(${code}) called`);
|
||||
});
|
||||
vi.spyOn(auth, 'validateAuthMethod').mockReturnValue(null);
|
||||
refreshAuthMock = vi.fn().mockImplementation(async () => {
|
||||
console.log('DEBUG: refreshAuthMock called');
|
||||
return 'refreshed';
|
||||
});
|
||||
refreshAuthMock = vi.fn().mockImplementation(async () => 'refreshed');
|
||||
mockSettings = {
|
||||
system: { path: '', settings: {} },
|
||||
systemDefaults: { path: '', settings: {} },
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
DEFAULT_GEMINI_MODEL,
|
||||
DEFAULT_GEMINI_MODEL_AUTO,
|
||||
DEFAULT_GEMINI_FLASH_MODEL,
|
||||
debugLogger,
|
||||
} from '@google/gemini-cli-core';
|
||||
import * as acp from './acp.js';
|
||||
import { AcpFileSystemService } from './fileSystemService.js';
|
||||
@@ -592,7 +593,7 @@ class Session {
|
||||
const reason = respectGitIgnore
|
||||
? 'git-ignored and will be skipped'
|
||||
: 'ignored by custom patterns';
|
||||
console.warn(`Path ${pathName} is ${reason}.`);
|
||||
debugLogger.warn(`Path ${pathName} is ${reason}.`);
|
||||
continue;
|
||||
}
|
||||
let currentPathSpec = pathName;
|
||||
@@ -739,7 +740,7 @@ class Session {
|
||||
|
||||
if (pathSpecsToRead.length === 0 && embeddedContext.length === 0) {
|
||||
// Fallback for lone "@" or completely invalid @-commands resulting in empty initialQueryText
|
||||
console.warn('No valid file paths found in @ commands to read.');
|
||||
debugLogger.warn('No valid file paths found in @ commands to read.');
|
||||
return [{ text: initialQueryText }];
|
||||
}
|
||||
|
||||
@@ -802,7 +803,7 @@ class Session {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
'read_many_files tool returned no content or empty content.',
|
||||
);
|
||||
}
|
||||
@@ -855,7 +856,7 @@ class Session {
|
||||
|
||||
debug(msg: string) {
|
||||
if (this.config.getDebugMode()) {
|
||||
console.warn(msg);
|
||||
debugLogger.warn(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import { templateString } from './utils.js';
|
||||
import { parseThought } from '../utils/thoughtUtils.js';
|
||||
import { type z } from 'zod';
|
||||
import { zodToJsonSchema } from 'zod-to-json-schema';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
/** A callback function to report on agent activity. */
|
||||
export type ActivityCallback = (activity: SubagentActivityEvent) => void;
|
||||
@@ -506,7 +507,7 @@ export class AgentExecutor<TOutput extends z.ZodTypeAny> {
|
||||
if (!allowedToolNames.has(functionCall.name as string)) {
|
||||
const error = `Unauthorized tool call: '${functionCall.name}' is not available to this agent.`;
|
||||
|
||||
console.warn(`[AgentExecutor] Blocked call: ${error}`);
|
||||
debugLogger.warn(`[AgentExecutor] Blocked call: ${error}`);
|
||||
|
||||
syncResponseParts.push({
|
||||
functionResponse: {
|
||||
|
||||
@@ -8,6 +8,7 @@ import type { Config } from '../config/config.js';
|
||||
import type { AgentDefinition } from './types.js';
|
||||
import { CodebaseInvestigatorAgent } from './codebase-investigator.js';
|
||||
import { type z } from 'zod';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
/**
|
||||
* Manages the discovery, loading, validation, and registration of
|
||||
@@ -26,7 +27,7 @@ export class AgentRegistry {
|
||||
this.loadBuiltInAgents();
|
||||
|
||||
if (this.config.getDebugMode()) {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`[AgentRegistry] Initialized with ${this.agents.size} agents.`,
|
||||
);
|
||||
}
|
||||
@@ -72,14 +73,14 @@ export class AgentRegistry {
|
||||
): void {
|
||||
// Basic validation
|
||||
if (!definition.name || !definition.description) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`[AgentRegistry] Skipping invalid agent definition. Missing name or description.`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.agents.has(definition.name) && this.config.getDebugMode()) {
|
||||
console.log(`[AgentRegistry] Overriding agent '${definition.name}'`);
|
||||
debugLogger.log(`[AgentRegistry] Overriding agent '${definition.name}'`);
|
||||
}
|
||||
|
||||
this.agents.set(definition.name, definition);
|
||||
|
||||
@@ -25,6 +25,7 @@ import readline from 'node:readline';
|
||||
import { Storage } from '../config/storage.js';
|
||||
import { OAuthCredentialStorage } from './oauth-credential-storage.js';
|
||||
import { FORCE_ENCRYPTED_FILE_ENV_VAR } from '../mcp/token-storage/index.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
const userAccountManager = new UserAccountManager();
|
||||
|
||||
@@ -110,10 +111,10 @@ async function initOauthClient(
|
||||
await fetchAndCacheUserInfo(client);
|
||||
} catch (error) {
|
||||
// Non-fatal, continue with existing auth.
|
||||
console.warn('Failed to fetch user info:', getErrorMessage(error));
|
||||
debugLogger.warn('Failed to fetch user info:', getErrorMessage(error));
|
||||
}
|
||||
}
|
||||
console.log('Loaded cached credentials.');
|
||||
debugLogger.log('Loaded cached credentials.');
|
||||
return client;
|
||||
}
|
||||
|
||||
@@ -122,13 +123,13 @@ async function initOauthClient(
|
||||
// the identity of the user logged into Cloud Shell.
|
||||
if (authType === AuthType.CLOUD_SHELL) {
|
||||
try {
|
||||
console.log("Attempting to authenticate via Cloud Shell VM's ADC.");
|
||||
debugLogger.log("Attempting to authenticate via Cloud Shell VM's ADC.");
|
||||
const computeClient = new Compute({
|
||||
// We can leave this empty, since the metadata server will provide
|
||||
// the service account email.
|
||||
});
|
||||
await computeClient.getAccessToken();
|
||||
console.log('Authentication successful.');
|
||||
debugLogger.log('Authentication successful.');
|
||||
|
||||
// Do not cache creds in this case; note that Compute client will handle its own refresh
|
||||
return computeClient;
|
||||
@@ -161,7 +162,7 @@ async function initOauthClient(
|
||||
} else {
|
||||
const webLogin = await authWithWeb(client);
|
||||
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`\n\nCode Assist login required.\n` +
|
||||
`Attempting to open authentication page in your browser.\n` +
|
||||
`Otherwise navigate to:\n\n${webLogin.authUrl}\n\n`,
|
||||
@@ -193,7 +194,7 @@ async function initOauthClient(
|
||||
`Failed to open browser: ${getErrorMessage(err)}`,
|
||||
);
|
||||
}
|
||||
console.log('Waiting for authentication...');
|
||||
debugLogger.log('Waiting for authentication...');
|
||||
|
||||
// Add timeout to prevent infinite waiting when browser tab gets stuck
|
||||
const authTimeout = 5 * 60 * 1000; // 5 minutes timeout
|
||||
@@ -236,10 +237,12 @@ async function authWithUserCode(client: OAuth2Client): Promise<boolean> {
|
||||
code_challenge: codeVerifier.codeChallenge,
|
||||
state,
|
||||
});
|
||||
console.log('Please visit the following URL to authorize the application:');
|
||||
console.log('');
|
||||
console.log(authUrl);
|
||||
console.log('');
|
||||
debugLogger.log(
|
||||
'Please visit the following URL to authorize the application:',
|
||||
);
|
||||
debugLogger.log('');
|
||||
debugLogger.log(authUrl);
|
||||
debugLogger.log('');
|
||||
|
||||
const code = await new Promise<string>((resolve) => {
|
||||
const rl = readline.createInterface({
|
||||
@@ -337,7 +340,7 @@ async function authWithWeb(client: OAuth2Client): Promise<OauthWebLogin> {
|
||||
try {
|
||||
await fetchAndCacheUserInfo(client);
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
'Failed to retrieve Google Account ID during authentication:',
|
||||
getErrorMessage(error),
|
||||
);
|
||||
@@ -462,7 +465,7 @@ async function loadCachedCredentials(client: OAuth2Client): Promise<boolean> {
|
||||
return true;
|
||||
} catch (error) {
|
||||
// Log specific error for debugging, but continue trying other paths
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`Failed to load credentials from ${keyFile}:`,
|
||||
getErrorMessage(error),
|
||||
);
|
||||
|
||||
@@ -157,6 +157,7 @@ import {
|
||||
DEFAULT_FILE_FILTERING_OPTIONS,
|
||||
DEFAULT_MEMORY_FILE_FILTERING_OPTIONS,
|
||||
} from './constants.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
export type { FileFilteringOptions };
|
||||
export {
|
||||
@@ -1123,7 +1124,7 @@ export class Config {
|
||||
// the tool registry.
|
||||
const messageBusEnabled = this.getEnableMessageBusIntegration();
|
||||
if (this.debugMode && messageBusEnabled) {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`[DEBUG] enableMessageBusIntegration setting: ${messageBusEnabled}`,
|
||||
);
|
||||
}
|
||||
@@ -1131,7 +1132,7 @@ export class Config {
|
||||
? [...args, this.getMessageBus()]
|
||||
: args;
|
||||
if (this.debugMode && messageBusEnabled) {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`[DEBUG] Registering ${className} with messageBus: ${messageBusEnabled ? 'YES' : 'NO'}`,
|
||||
);
|
||||
}
|
||||
@@ -1206,7 +1207,7 @@ export class Config {
|
||||
);
|
||||
}
|
||||
} else if (this.getDebugMode()) {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`[Config] Skipping registration of agent '${definition.name}' due to allow/exclude configuration.`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1385,34 +1385,11 @@ ${JSON.stringify(
|
||||
// Assert
|
||||
expect(finalResult).toBeInstanceOf(Turn);
|
||||
|
||||
// Debug: Check how many times checkNextSpeaker was called
|
||||
const callCount = mockCheckNextSpeaker.mock.calls.length;
|
||||
|
||||
// If infinite loop protection is working, checkNextSpeaker should be called many times
|
||||
// but stop at MAX_TURNS (100). Since each recursive call should trigger checkNextSpeaker,
|
||||
// we expect it to be called multiple times before hitting the limit
|
||||
expect(mockCheckNextSpeaker).toHaveBeenCalled();
|
||||
|
||||
// The test should demonstrate that the infinite loop protection works:
|
||||
// - If checkNextSpeaker is called many times (close to MAX_TURNS), it shows the loop was happening
|
||||
// - If it's only called once, the recursive behavior might not be triggered
|
||||
if (callCount === 0) {
|
||||
throw new Error(
|
||||
'checkNextSpeaker was never called - the recursive condition was not met',
|
||||
);
|
||||
} else if (callCount === 1) {
|
||||
// This might be expected behavior if the turn has pending tool calls or other conditions prevent recursion
|
||||
console.log(
|
||||
'checkNextSpeaker called only once - no infinite loop occurred',
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
`checkNextSpeaker called ${callCount} times - infinite loop protection worked`,
|
||||
);
|
||||
// If called multiple times, we expect it to be stopped before MAX_TURNS
|
||||
expect(callCount).toBeLessThanOrEqual(100); // Should not exceed MAX_TURNS
|
||||
}
|
||||
|
||||
// The stream should produce events and eventually terminate
|
||||
expect(eventCount).toBeGreaterThanOrEqual(1);
|
||||
expect(eventCount).toBeLessThan(200); // Should not exceed our safety limit
|
||||
@@ -1537,11 +1514,6 @@ ${JSON.stringify(
|
||||
// the loop should stop at MAX_TURNS (100)
|
||||
expect(callCount).toBeLessThanOrEqual(100); // Should not exceed MAX_TURNS
|
||||
expect(eventCount).toBeLessThanOrEqual(200); // Should have reasonable number of events
|
||||
|
||||
console.log(
|
||||
`Infinite loop protection working: checkNextSpeaker called ${callCount} times, ` +
|
||||
`${eventCount} events generated (properly bounded by MAX_TURNS)`,
|
||||
);
|
||||
});
|
||||
|
||||
it('should yield ContextWindowWillOverflow when the context window is about to overflow', async () => {
|
||||
|
||||
@@ -52,6 +52,7 @@ import type { IdeContext, File } from '../ide/types.js';
|
||||
import { handleFallback } from '../fallback/handler.js';
|
||||
import type { RoutingContext } from '../routing/routingStrategy.js';
|
||||
import { uiTelemetryService } from '../telemetry/uiTelemetry.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
export function isThinkingSupported(model: string) {
|
||||
return model.startsWith('gemini-2.5') || model === DEFAULT_GEMINI_MODEL_AUTO;
|
||||
@@ -341,7 +342,7 @@ My setup is complete. I will provide my first command in the next turn.
|
||||
];
|
||||
|
||||
if (this.config.getDebugMode()) {
|
||||
console.log(contextParts.join('\n'));
|
||||
debugLogger.log(contextParts.join('\n'));
|
||||
}
|
||||
return {
|
||||
contextParts,
|
||||
@@ -451,7 +452,7 @@ My setup is complete. I will provide my first command in the next turn.
|
||||
];
|
||||
|
||||
if (this.config.getDebugMode()) {
|
||||
console.log(contextParts.join('\n'));
|
||||
debugLogger.log(contextParts.join('\n'));
|
||||
}
|
||||
return {
|
||||
contextParts,
|
||||
|
||||
@@ -8,6 +8,7 @@ import path from 'node:path';
|
||||
import { promises as fs } from 'node:fs';
|
||||
import type { Content } from '@google/genai';
|
||||
import type { Storage } from '../config/storage.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
const LOG_FILE_NAME = 'logs.json';
|
||||
|
||||
@@ -82,7 +83,7 @@ export class Logger {
|
||||
const fileContent = await fs.readFile(this.logFilePath, 'utf-8');
|
||||
const parsedLogs = JSON.parse(fileContent);
|
||||
if (!Array.isArray(parsedLogs)) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`Log file at ${this.logFilePath} is not a valid JSON array. Starting with empty logs.`,
|
||||
);
|
||||
await this._backupCorruptedLogFile('malformed_array');
|
||||
@@ -102,14 +103,14 @@ export class Logger {
|
||||
return [];
|
||||
}
|
||||
if (error instanceof SyntaxError) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`Invalid JSON in log file ${this.logFilePath}. Backing up and starting fresh.`,
|
||||
error,
|
||||
);
|
||||
await this._backupCorruptedLogFile('invalid_json');
|
||||
return [];
|
||||
}
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`Failed to read or parse log file ${this.logFilePath}:`,
|
||||
error,
|
||||
);
|
||||
@@ -122,7 +123,7 @@ export class Logger {
|
||||
const backupPath = `${this.logFilePath}.${reason}.${Date.now()}.bak`;
|
||||
try {
|
||||
await fs.rename(this.logFilePath, backupPath);
|
||||
console.debug(`Backed up corrupted log file to ${backupPath}`);
|
||||
debugLogger.debug(`Backed up corrupted log file to ${backupPath}`);
|
||||
} catch (_backupError) {
|
||||
// If rename fails (e.g. file doesn't exist), no need to log an error here as the primary error (e.g. invalid JSON) is already handled.
|
||||
}
|
||||
@@ -166,7 +167,7 @@ export class Logger {
|
||||
entryToAppend: LogEntry,
|
||||
): Promise<LogEntry | null> {
|
||||
if (!this.logFilePath) {
|
||||
console.debug('Log file path not set. Cannot persist log entry.');
|
||||
debugLogger.debug('Log file path not set. Cannot persist log entry.');
|
||||
throw new Error('Log file path not set during update attempt.');
|
||||
}
|
||||
|
||||
@@ -174,7 +175,7 @@ export class Logger {
|
||||
try {
|
||||
currentLogsOnDisk = await this._readLogFile();
|
||||
} catch (readError) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
'Critical error reading log file before append:',
|
||||
readError,
|
||||
);
|
||||
@@ -205,7 +206,7 @@ export class Logger {
|
||||
);
|
||||
|
||||
if (entryExists) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`Duplicate log entry detected and skipped: session ${entryToAppend.sessionId}, messageId ${entryToAppend.messageId}`,
|
||||
);
|
||||
this.logs = currentLogsOnDisk; // Ensure in-memory is synced with disk
|
||||
@@ -223,7 +224,7 @@ export class Logger {
|
||||
this.logs = currentLogsOnDisk;
|
||||
return entryToAppend; // Return the successfully appended entry
|
||||
} catch (error) {
|
||||
console.debug('Error writing to log file:', error);
|
||||
debugLogger.debug('Error writing to log file:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -242,7 +243,7 @@ export class Logger {
|
||||
|
||||
async logMessage(type: MessageSenderType, message: string): Promise<void> {
|
||||
if (!this.initialized || this.sessionId === undefined) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
'Logger not initialized or session ID missing. Cannot log message.',
|
||||
);
|
||||
return;
|
||||
@@ -341,7 +342,7 @@ export class Logger {
|
||||
const fileContent = await fs.readFile(path, 'utf-8');
|
||||
const parsedContent = JSON.parse(fileContent);
|
||||
if (!Array.isArray(parsedContent)) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Checkpoint file at ${path} is not a valid JSON array. Returning empty checkpoint.`,
|
||||
);
|
||||
return [];
|
||||
|
||||
@@ -22,6 +22,7 @@ import { isGitRepository } from '../utils/gitUtils.js';
|
||||
import { CodebaseInvestigatorAgent } from '../agents/codebase-investigator.js';
|
||||
import type { Config } from '../config/config.js';
|
||||
import { GEMINI_DIR } from '../utils/paths.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
export function resolvePathFromEnv(envVar?: string): {
|
||||
isSwitch: boolean;
|
||||
@@ -56,7 +57,7 @@ export function resolvePathFromEnv(envVar?: string): {
|
||||
}
|
||||
} catch (error) {
|
||||
// If os.homedir() fails, we catch the error instead of crashing.
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Could not resolve home directory for path: ${trimmedEnvVar}`,
|
||||
error,
|
||||
);
|
||||
|
||||
@@ -24,10 +24,11 @@ import * as path from 'node:path';
|
||||
import { EnvHttpProxyAgent } from 'undici';
|
||||
import { ListToolsResultSchema } from '@modelcontextprotocol/sdk/types.js';
|
||||
import { IDE_REQUEST_TIMEOUT_MS } from './constants.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
const logger = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
debug: (...args: any[]) => console.debug('[DEBUG] [IDEClient]', ...args),
|
||||
debug: (...args: any[]) => debugLogger.debug('[DEBUG] [IDEClient]', ...args),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
error: (...args: any[]) => console.error('[ERROR] [IDEClient]', ...args),
|
||||
};
|
||||
|
||||
@@ -13,6 +13,7 @@ import type { OAuthToken } from './token-storage/types.js';
|
||||
import { MCPOAuthTokenStorage } from './oauth-token-storage.js';
|
||||
import { getErrorMessage } from '../utils/errors.js';
|
||||
import { OAuthUtils } from './oauth-utils.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
export const OAUTH_DISPLAY_MESSAGE_EVENT = 'oauth-display-message' as const;
|
||||
|
||||
@@ -258,7 +259,9 @@ export class MCPOAuthProvider {
|
||||
|
||||
server.on('error', reject);
|
||||
server.listen(REDIRECT_PORT, () => {
|
||||
console.log(`OAuth callback server listening on port ${REDIRECT_PORT}`);
|
||||
debugLogger.log(
|
||||
`OAuth callback server listening on port ${REDIRECT_PORT}`,
|
||||
);
|
||||
});
|
||||
|
||||
// Timeout after 5 minutes
|
||||
@@ -314,7 +317,7 @@ export class MCPOAuthProvider {
|
||||
OAuthUtils.buildResourceParameter(mcpServerUrl),
|
||||
);
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Could not add resource parameter: ${getErrorMessage(error)}`,
|
||||
);
|
||||
}
|
||||
@@ -371,7 +374,7 @@ export class MCPOAuthProvider {
|
||||
OAuthUtils.buildResourceParameter(resourceUrl),
|
||||
);
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Could not add resource parameter: ${getErrorMessage(error)}`,
|
||||
);
|
||||
}
|
||||
@@ -413,7 +416,7 @@ export class MCPOAuthProvider {
|
||||
!contentType.includes('application/json') &&
|
||||
!contentType.includes('application/x-www-form-urlencoded')
|
||||
) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Token endpoint returned unexpected content-type: ${contentType}. ` +
|
||||
`Expected application/json or application/x-www-form-urlencoded. ` +
|
||||
`Will attempt to parse response.`,
|
||||
@@ -493,7 +496,7 @@ export class MCPOAuthProvider {
|
||||
OAuthUtils.buildResourceParameter(mcpServerUrl),
|
||||
);
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Could not add resource parameter: ${getErrorMessage(error)}`,
|
||||
);
|
||||
}
|
||||
@@ -535,7 +538,7 @@ export class MCPOAuthProvider {
|
||||
!contentType.includes('application/json') &&
|
||||
!contentType.includes('application/x-www-form-urlencoded')
|
||||
) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Token refresh endpoint returned unexpected content-type: ${contentType}. ` +
|
||||
`Expected application/json or application/x-www-form-urlencoded. ` +
|
||||
`Will attempt to parse response.`,
|
||||
@@ -593,13 +596,13 @@ export class MCPOAuthProvider {
|
||||
if (events) {
|
||||
events.emit(OAUTH_DISPLAY_MESSAGE_EVENT, message);
|
||||
} else {
|
||||
console.log(message);
|
||||
debugLogger.log(message);
|
||||
}
|
||||
};
|
||||
|
||||
// If no authorization URL is provided, try to discover OAuth configuration
|
||||
if (!config.authorizationUrl && mcpServerUrl) {
|
||||
console.debug(`Starting OAuth for MCP server "${serverName}"…
|
||||
debugLogger.debug(`Starting OAuth for MCP server "${serverName}"…
|
||||
✓ No authorization URL; using OAuth discovery`);
|
||||
|
||||
// First check if the server requires authentication via WWW-Authenticate header
|
||||
@@ -636,7 +639,7 @@ export class MCPOAuthProvider {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`Failed to check endpoint for authentication requirements: ${getErrorMessage(error)}`,
|
||||
);
|
||||
}
|
||||
@@ -681,7 +684,7 @@ export class MCPOAuthProvider {
|
||||
const authUrl = new URL(config.authorizationUrl);
|
||||
const serverUrl = `${authUrl.protocol}//${authUrl.host}`;
|
||||
|
||||
console.debug('→ Attempting dynamic client registration...');
|
||||
debugLogger.debug('→ Attempting dynamic client registration...');
|
||||
|
||||
// Get the authorization server metadata for registration
|
||||
const authServerMetadata =
|
||||
@@ -707,7 +710,7 @@ export class MCPOAuthProvider {
|
||||
config.clientSecret = clientRegistration.client_secret;
|
||||
}
|
||||
|
||||
console.debug('✓ Dynamic client registration successful');
|
||||
debugLogger.debug('✓ Dynamic client registration successful');
|
||||
} else {
|
||||
throw new Error(
|
||||
'No client ID provided and dynamic registration not supported',
|
||||
@@ -747,7 +750,7 @@ ${authUrl}
|
||||
try {
|
||||
await openBrowserSecurely(authUrl);
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
'Failed to open browser automatically:',
|
||||
getErrorMessage(error),
|
||||
);
|
||||
@@ -756,7 +759,9 @@ ${authUrl}
|
||||
// Wait for callback
|
||||
const { code } = await callbackPromise;
|
||||
|
||||
console.debug('✓ Authorization code received, exchanging for tokens...');
|
||||
debugLogger.debug(
|
||||
'✓ Authorization code received, exchanging for tokens...',
|
||||
);
|
||||
|
||||
// Exchange code for tokens
|
||||
const tokenResponse = await this.exchangeCodeForToken(
|
||||
@@ -791,7 +796,7 @@ ${authUrl}
|
||||
config.tokenUrl,
|
||||
mcpServerUrl,
|
||||
);
|
||||
console.debug('✓ Authentication successful! Token saved.');
|
||||
debugLogger.debug('✓ Authentication successful! Token saved.');
|
||||
|
||||
// Verify token was saved
|
||||
const savedToken = await this.tokenStorage.getCredentials(serverName);
|
||||
@@ -802,7 +807,7 @@ ${authUrl}
|
||||
.update(savedToken.token.accessToken)
|
||||
.digest('hex')
|
||||
.slice(0, 8);
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`✓ Token verification successful (fingerprint: ${tokenFingerprint})`,
|
||||
);
|
||||
} else {
|
||||
@@ -829,29 +834,31 @@ ${authUrl}
|
||||
serverName: string,
|
||||
config: MCPOAuthConfig,
|
||||
): Promise<string | null> {
|
||||
console.debug(`Getting valid token for server: ${serverName}`);
|
||||
debugLogger.debug(`Getting valid token for server: ${serverName}`);
|
||||
const credentials = await this.tokenStorage.getCredentials(serverName);
|
||||
|
||||
if (!credentials) {
|
||||
console.debug(`No credentials found for server: ${serverName}`);
|
||||
debugLogger.debug(`No credentials found for server: ${serverName}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const { token } = credentials;
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`Found token for server: ${serverName}, expired: ${this.tokenStorage.isTokenExpired(token)}`,
|
||||
);
|
||||
|
||||
// Check if token is expired
|
||||
if (!this.tokenStorage.isTokenExpired(token)) {
|
||||
console.debug(`Returning valid token for server: ${serverName}`);
|
||||
debugLogger.debug(`Returning valid token for server: ${serverName}`);
|
||||
return token.accessToken;
|
||||
}
|
||||
|
||||
// Try to refresh if we have a refresh token
|
||||
if (token.refreshToken && config.clientId && credentials.tokenUrl) {
|
||||
try {
|
||||
console.log(`Refreshing expired token for MCP server: ${serverName}`);
|
||||
debugLogger.log(
|
||||
`Refreshing expired token for MCP server: ${serverName}`,
|
||||
);
|
||||
|
||||
const newTokenResponse = await this.refreshAccessToken(
|
||||
config,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
import type { MCPOAuthConfig } from './oauth-provider.js';
|
||||
import { getErrorMessage } from '../utils/errors.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
/**
|
||||
* OAuth authorization server metadata as per RFC 8414.
|
||||
@@ -94,7 +95,7 @@ export class OAuthUtils {
|
||||
}
|
||||
return (await response.json()) as OAuthProtectedResourceMetadata;
|
||||
} catch (error) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`Failed to fetch protected resource metadata from ${resourceMetadataUrl}: ${getErrorMessage(error)}`,
|
||||
);
|
||||
return null;
|
||||
@@ -117,7 +118,7 @@ export class OAuthUtils {
|
||||
}
|
||||
return (await response.json()) as OAuthAuthorizationServerMetadata;
|
||||
} catch (error) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`Failed to fetch authorization server metadata from ${authServerMetadataUrl}: ${getErrorMessage(error)}`,
|
||||
);
|
||||
return null;
|
||||
@@ -205,7 +206,7 @@ export class OAuthUtils {
|
||||
}
|
||||
}
|
||||
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`Metadata discovery failed for authorization server ${authServerUrl}`,
|
||||
);
|
||||
return null;
|
||||
@@ -249,7 +250,7 @@ export class OAuthUtils {
|
||||
if (authServerMetadata) {
|
||||
const config = this.metadataToOAuthConfig(authServerMetadata);
|
||||
if (authServerMetadata.registration_endpoint) {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
'Dynamic client registration is supported at:',
|
||||
authServerMetadata.registration_endpoint,
|
||||
);
|
||||
@@ -259,14 +260,14 @@ export class OAuthUtils {
|
||||
}
|
||||
|
||||
// Fallback: try well-known endpoints at the base URL
|
||||
console.debug(`Trying OAuth discovery fallback at ${serverUrl}`);
|
||||
debugLogger.debug(`Trying OAuth discovery fallback at ${serverUrl}`);
|
||||
const authServerMetadata =
|
||||
await this.discoverAuthorizationServerMetadata(serverUrl);
|
||||
|
||||
if (authServerMetadata) {
|
||||
const config = this.metadataToOAuthConfig(authServerMetadata);
|
||||
if (authServerMetadata.registration_endpoint) {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
'Dynamic client registration is supported at:',
|
||||
authServerMetadata.registration_endpoint,
|
||||
);
|
||||
@@ -276,7 +277,7 @@ export class OAuthUtils {
|
||||
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`Failed to discover OAuth configuration: ${getErrorMessage(error)}`,
|
||||
);
|
||||
return null;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import type { DiscoveredMCPPrompt } from '../tools/mcp-client.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
export class PromptRegistry {
|
||||
private prompts: Map<string, DiscoveredMCPPrompt> = new Map();
|
||||
@@ -16,7 +17,7 @@ export class PromptRegistry {
|
||||
registerPrompt(prompt: DiscoveredMCPPrompt): void {
|
||||
if (this.prompts.has(prompt.name)) {
|
||||
const newName = `${prompt.serverName}_${prompt.name}`;
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Prompt with name "${prompt.name}" is already registered. Renaming to "${newName}".`,
|
||||
);
|
||||
this.prompts.set(newName, { ...prompt, name: newName });
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
isFunctionCall,
|
||||
isFunctionResponse,
|
||||
} from '../../utils/messageInspectors.js';
|
||||
import { debugLogger } from '../../utils/debugLogger.js';
|
||||
|
||||
const CLASSIFIER_GENERATION_CONFIG: GenerateContentConfig = {
|
||||
temperature: 0,
|
||||
@@ -153,7 +154,7 @@ export class ClassifierStrategy implements RoutingStrategy {
|
||||
promptId = `classifier-router-fallback-${Date.now()}-${Math.random()
|
||||
.toString(16)
|
||||
.slice(2)}`;
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Could not find promptId in context. This is unexpected. Using a fallback ID: ${promptId}`,
|
||||
);
|
||||
}
|
||||
@@ -206,7 +207,7 @@ export class ClassifierStrategy implements RoutingStrategy {
|
||||
} catch (error) {
|
||||
// If the classifier fails for any reason (API error, parsing error, etc.),
|
||||
// we log it and return null to allow the composite strategy to proceed.
|
||||
console.warn(`[Routing] ClassifierStrategy failed:`, error);
|
||||
debugLogger.warn(`[Routing] ClassifierStrategy failed:`, error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
isFunctionCall,
|
||||
isFunctionResponse,
|
||||
} from '../utils/messageInspectors.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
const TOOL_CALL_LOOP_THRESHOLD = 5;
|
||||
const CONTENT_LOOP_THRESHOLD = 10;
|
||||
@@ -431,14 +432,14 @@ export class LoopDetectionService {
|
||||
});
|
||||
} catch (e) {
|
||||
// Do nothing, treat it as a non-loop.
|
||||
this.config.getDebugMode() ? console.error(e) : console.debug(e);
|
||||
this.config.getDebugMode() ? console.error(e) : debugLogger.debug(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof result['confidence'] === 'number') {
|
||||
if (result['confidence'] > 0.9) {
|
||||
if (typeof result['reasoning'] === 'string' && result['reasoning']) {
|
||||
console.warn(result['reasoning']);
|
||||
debugLogger.warn(result['reasoning']);
|
||||
}
|
||||
logLoopDetected(
|
||||
this.config,
|
||||
|
||||
@@ -8,6 +8,7 @@ import type { Config } from '../config/config.js';
|
||||
import { isPerformanceMonitoringActive } from './metrics.js';
|
||||
import { getMemoryMonitor } from './memory-monitor.js';
|
||||
import { ActivityType } from './activity-types.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
/**
|
||||
* Activity event data structure
|
||||
@@ -152,7 +153,7 @@ export class ActivityMonitor {
|
||||
listener(event);
|
||||
} catch (error) {
|
||||
// Silently catch listener errors to avoid disrupting the application
|
||||
console.debug('ActivityMonitor listener error:', error);
|
||||
debugLogger.debug('ActivityMonitor listener error:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ import {
|
||||
detectIdeFromEnv,
|
||||
isCloudShell,
|
||||
} from '../../ide/detect-ide.js';
|
||||
import { debugLogger } from '../../utils/debugLogger.js';
|
||||
|
||||
export enum EventNames {
|
||||
START_SESSION = 'start_session',
|
||||
@@ -238,7 +239,7 @@ export class ClearcutLogger {
|
||||
]);
|
||||
|
||||
if (wasAtCapacity && this.config?.getDebugMode()) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`ClearcutLogger: Dropped old event to prevent memory leak (queue size: ${this.events.size})`,
|
||||
);
|
||||
}
|
||||
@@ -282,14 +283,14 @@ export class ClearcutLogger {
|
||||
}
|
||||
|
||||
this.flushToClearcut().catch((error) => {
|
||||
console.debug('Error flushing to Clearcut:', error);
|
||||
debugLogger.debug('Error flushing to Clearcut:', error);
|
||||
});
|
||||
}
|
||||
|
||||
async flushToClearcut(): Promise<LogResponse> {
|
||||
if (this.flushing) {
|
||||
if (this.config?.getDebugMode()) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
'ClearcutLogger: Flush already in progress, marking pending flush.',
|
||||
);
|
||||
}
|
||||
@@ -299,7 +300,7 @@ export class ClearcutLogger {
|
||||
this.flushing = true;
|
||||
|
||||
if (this.config?.getDebugMode()) {
|
||||
console.log('Flushing log events to Clearcut.');
|
||||
debugLogger.log('Flushing log events to Clearcut.');
|
||||
}
|
||||
const eventsToSend = this.events.toArray() as LogEventEntry[][];
|
||||
this.events.clear();
|
||||
@@ -359,7 +360,7 @@ export class ClearcutLogger {
|
||||
// Fire and forget the pending flush
|
||||
this.flushToClearcut().catch((error) => {
|
||||
if (this.config?.getDebugMode()) {
|
||||
console.debug('Error in pending flush to Clearcut:', error);
|
||||
debugLogger.debug('Error in pending flush to Clearcut:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -451,7 +452,7 @@ export class ClearcutLogger {
|
||||
// Flush start event immediately
|
||||
this.enqueueLogEvent(this.createLogEvent(EventNames.START_SESSION, data));
|
||||
this.flushToClearcut().catch((error) => {
|
||||
console.debug('Error flushing to Clearcut:', error);
|
||||
debugLogger.debug('Error flushing to Clearcut:', error);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -668,14 +669,14 @@ export class ClearcutLogger {
|
||||
logFlashFallbackEvent(): void {
|
||||
this.enqueueLogEvent(this.createLogEvent(EventNames.FLASH_FALLBACK, []));
|
||||
this.flushToClearcut().catch((error) => {
|
||||
console.debug('Error flushing to Clearcut:', error);
|
||||
debugLogger.debug('Error flushing to Clearcut:', error);
|
||||
});
|
||||
}
|
||||
|
||||
logRipgrepFallbackEvent(): void {
|
||||
this.enqueueLogEvent(this.createLogEvent(EventNames.RIPGREP_FALLBACK, []));
|
||||
this.flushToClearcut().catch((error) => {
|
||||
console.debug('Error flushing to Clearcut:', error);
|
||||
debugLogger.debug('Error flushing to Clearcut:', error);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -811,7 +812,7 @@ export class ClearcutLogger {
|
||||
// Flush immediately on session end.
|
||||
this.enqueueLogEvent(this.createLogEvent(EventNames.END_SESSION, []));
|
||||
this.flushToClearcut().catch((error) => {
|
||||
console.debug('Error flushing to Clearcut:', error);
|
||||
debugLogger.debug('Error flushing to Clearcut:', error);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -910,7 +911,7 @@ export class ClearcutLogger {
|
||||
this.createLogEvent(EventNames.EXTENSION_INSTALL, data),
|
||||
);
|
||||
this.flushToClearcut().catch((error) => {
|
||||
console.debug('Error flushing to Clearcut:', error);
|
||||
debugLogger.debug('Error flushing to Clearcut:', error);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -930,7 +931,7 @@ export class ClearcutLogger {
|
||||
this.createLogEvent(EventNames.EXTENSION_UNINSTALL, data),
|
||||
);
|
||||
this.flushToClearcut().catch((error) => {
|
||||
console.debug('Error flushing to Clearcut:', error);
|
||||
debugLogger.debug('Error flushing to Clearcut:', error);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -962,7 +963,7 @@ export class ClearcutLogger {
|
||||
this.createLogEvent(EventNames.EXTENSION_UPDATE, data),
|
||||
);
|
||||
this.flushToClearcut().catch((error) => {
|
||||
console.debug('Error flushing to Clearcut:', error);
|
||||
debugLogger.debug('Error flushing to Clearcut:', error);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1047,7 +1048,7 @@ export class ClearcutLogger {
|
||||
this.createLogEvent(EventNames.EXTENSION_ENABLE, data),
|
||||
);
|
||||
this.flushToClearcut().catch((error) => {
|
||||
console.debug('Error flushing to Clearcut:', error);
|
||||
debugLogger.debug('Error flushing to Clearcut:', error);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1082,7 +1083,7 @@ export class ClearcutLogger {
|
||||
this.createLogEvent(EventNames.EXTENSION_DISABLE, data),
|
||||
);
|
||||
this.flushToClearcut().catch((error) => {
|
||||
console.debug('Error flushing to Clearcut:', error);
|
||||
debugLogger.debug('Error flushing to Clearcut:', error);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1240,7 +1241,7 @@ export class ClearcutLogger {
|
||||
|
||||
getConfigJson() {
|
||||
const configJson = safeJsonStringifyBooleanValuesOnly(this.config);
|
||||
console.debug(configJson);
|
||||
debugLogger.debug(configJson);
|
||||
return safeJsonStringifyBooleanValuesOnly(this.config);
|
||||
}
|
||||
|
||||
@@ -1254,7 +1255,7 @@ export class ClearcutLogger {
|
||||
|
||||
// Log a warning if we're dropping events
|
||||
if (eventsToSend.length > MAX_RETRY_EVENTS && this.config?.getDebugMode()) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`ClearcutLogger: Dropping ${
|
||||
eventsToSend.length - MAX_RETRY_EVENTS
|
||||
} events due to retry queue limit. Total events: ${
|
||||
@@ -1269,7 +1270,7 @@ export class ClearcutLogger {
|
||||
|
||||
if (numEventsToRequeue === 0) {
|
||||
if (this.config?.getDebugMode()) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`ClearcutLogger: No events re-queued (queue size: ${this.events.size})`,
|
||||
);
|
||||
}
|
||||
@@ -1292,7 +1293,7 @@ export class ClearcutLogger {
|
||||
}
|
||||
|
||||
if (this.config?.getDebugMode()) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`ClearcutLogger: Re-queued ${numEventsToRequeue} events for retry (queue size: ${this.events.size})`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import {
|
||||
GcpLogExporter,
|
||||
} from './gcp-exporters.js';
|
||||
import { TelemetryTarget } from './index.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
// For troubleshooting, set the log level to DiagLogLevel.DEBUG
|
||||
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.INFO);
|
||||
@@ -184,7 +185,7 @@ export function initializeTelemetry(config: Config): void {
|
||||
try {
|
||||
sdk.start();
|
||||
if (config.getDebugMode()) {
|
||||
console.log('OpenTelemetry SDK started successfully.');
|
||||
debugLogger.log('OpenTelemetry SDK started successfully.');
|
||||
}
|
||||
telemetryInitialized = true;
|
||||
initializeMetrics(config);
|
||||
@@ -211,7 +212,7 @@ export async function shutdownTelemetry(config: Config): Promise<void> {
|
||||
ClearcutLogger.getInstance()?.shutdown();
|
||||
await sdk.shutdown();
|
||||
if (config.getDebugMode()) {
|
||||
console.log('OpenTelemetry SDK shut down successfully.');
|
||||
debugLogger.log('OpenTelemetry SDK shut down successfully.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error shutting down SDK:', error);
|
||||
|
||||
@@ -34,6 +34,7 @@ import type {
|
||||
import { IdeClient } from '../ide/ide-client.js';
|
||||
import { safeLiteralReplace } from '../utils/textUtils.js';
|
||||
import { EDIT_TOOL_NAME, READ_FILE_TOOL_NAME } from './tool-names.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
export function applyReplacement(
|
||||
currentContent: string | null,
|
||||
@@ -255,12 +256,12 @@ class EditToolInvocation implements ToolInvocation<EditToolParams, ToolResult> {
|
||||
throw error;
|
||||
}
|
||||
const errorMsg = error instanceof Error ? error.message : String(error);
|
||||
console.log(`Error preparing edit: ${errorMsg}`);
|
||||
debugLogger.log(`Error preparing edit: ${errorMsg}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (editData.error) {
|
||||
console.log(`Error: ${editData.error.display}`);
|
||||
debugLogger.log(`Error: ${editData.error.display}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -388,7 +388,7 @@ class GrepToolInvocation extends BaseToolInvocation<
|
||||
});
|
||||
return this.parseGrepOutput(output, absolutePath);
|
||||
} catch (gitError: unknown) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`GrepLogic: git grep failed: ${getErrorMessage(
|
||||
gitError,
|
||||
)}. Falling back...`,
|
||||
@@ -397,7 +397,7 @@ class GrepToolInvocation extends BaseToolInvocation<
|
||||
}
|
||||
|
||||
// --- Strategy 2: System grep ---
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
'GrepLogic: System grep is being considered as fallback strategy.',
|
||||
);
|
||||
|
||||
@@ -494,7 +494,7 @@ class GrepToolInvocation extends BaseToolInvocation<
|
||||
});
|
||||
return this.parseGrepOutput(output, absolutePath);
|
||||
} catch (grepError: unknown) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`GrepLogic: System grep failed: ${getErrorMessage(
|
||||
grepError,
|
||||
)}. Falling back...`,
|
||||
@@ -503,7 +503,7 @@ class GrepToolInvocation extends BaseToolInvocation<
|
||||
}
|
||||
|
||||
// --- Strategy 3: Pure JavaScript Fallback ---
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
'GrepLogic: Falling back to JavaScript grep implementation.',
|
||||
);
|
||||
strategyUsed = 'javascript fallback';
|
||||
@@ -541,7 +541,7 @@ class GrepToolInvocation extends BaseToolInvocation<
|
||||
} catch (readError: unknown) {
|
||||
// Ignore errors like permission denied or file gone during read
|
||||
if (!isNodeError(readError) || readError.code !== 'ENOENT') {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`GrepLogic: Could not read/process ${fileAbsolutePath}: ${getErrorMessage(
|
||||
readError,
|
||||
)}`,
|
||||
|
||||
@@ -41,6 +41,7 @@ import type {
|
||||
WorkspaceContext,
|
||||
} from '../utils/workspaceContext.js';
|
||||
import type { ToolRegistry } from './tool-registry.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
export const MCP_DEFAULT_TIMEOUT_MSEC = 10 * 60 * 1000; // default to 10 minutes
|
||||
|
||||
@@ -321,7 +322,7 @@ async function handleAutomaticOAuth(
|
||||
wwwAuthenticate: string,
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
console.log(`🔐 '${mcpServerName}' requires OAuth authentication`);
|
||||
debugLogger.log(`🔐 '${mcpServerName}' requires OAuth authentication`);
|
||||
|
||||
// Always try to parse the resource metadata URI from the www-authenticate header
|
||||
let oauthConfig;
|
||||
@@ -358,13 +359,13 @@ async function handleAutomaticOAuth(
|
||||
// Perform OAuth authentication
|
||||
// Pass the server URL for proper discovery
|
||||
const serverUrl = mcpServerConfig.httpUrl || mcpServerConfig.url;
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`Starting OAuth authentication for server '${mcpServerName}'...`,
|
||||
);
|
||||
const authProvider = new MCPOAuthProvider(new MCPOAuthTokenStorage());
|
||||
await authProvider.authenticate(mcpServerName, oauthAuthConfig, serverUrl);
|
||||
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`OAuth authentication successful for server '${mcpServerName}'`,
|
||||
);
|
||||
return true;
|
||||
@@ -840,12 +841,12 @@ export async function connectToMcpServer(
|
||||
},
|
||||
);
|
||||
if (hasStoredTokens) {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`Stored OAuth token for SSE server '${mcpServerName}' was rejected. ` +
|
||||
`Please re-authenticate using: /mcp auth ${mcpServerName}`,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`401 error received for SSE server '${mcpServerName}' without OAuth configuration. ` +
|
||||
`Please authenticate using: /mcp auth ${mcpServerName}`,
|
||||
);
|
||||
@@ -862,7 +863,7 @@ export async function connectToMcpServer(
|
||||
|
||||
// If we didn't get the header from the error string, try to get it from the server
|
||||
if (!wwwAuthenticate && hasNetworkTransport(mcpServerConfig)) {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`No www-authenticate header in error, trying to fetch it from server...`,
|
||||
);
|
||||
try {
|
||||
@@ -880,13 +881,13 @@ export async function connectToMcpServer(
|
||||
if (response.status === 401) {
|
||||
wwwAuthenticate = response.headers.get('www-authenticate');
|
||||
if (wwwAuthenticate) {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`Found www-authenticate header from server: ${wwwAuthenticate}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (fetchError) {
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`Failed to fetch www-authenticate header: ${getErrorMessage(
|
||||
fetchError,
|
||||
)}`,
|
||||
@@ -895,7 +896,7 @@ export async function connectToMcpServer(
|
||||
}
|
||||
|
||||
if (wwwAuthenticate) {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`Received 401 with www-authenticate header: ${wwwAuthenticate}`,
|
||||
);
|
||||
|
||||
@@ -907,7 +908,7 @@ export async function connectToMcpServer(
|
||||
);
|
||||
if (oauthSuccess) {
|
||||
// Retry connection with OAuth token
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`Retrying connection to '${mcpServerName}' with OAuth token...`,
|
||||
);
|
||||
|
||||
@@ -1000,12 +1001,12 @@ export async function connectToMcpServer(
|
||||
},
|
||||
);
|
||||
if (hasStoredTokens) {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`Stored OAuth token for SSE server '${mcpServerName}' was rejected. ` +
|
||||
`Please re-authenticate using: /mcp auth ${mcpServerName}`,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`401 error received for SSE server '${mcpServerName}' without OAuth configuration. ` +
|
||||
`Please authenticate using: /mcp auth ${mcpServerName}`,
|
||||
);
|
||||
@@ -1018,7 +1019,9 @@ export async function connectToMcpServer(
|
||||
}
|
||||
|
||||
// For SSE/HTTP servers, try to discover OAuth configuration from the base URL
|
||||
console.log(`🔍 Attempting OAuth discovery for '${mcpServerName}'...`);
|
||||
debugLogger.log(
|
||||
`🔍 Attempting OAuth discovery for '${mcpServerName}'...`,
|
||||
);
|
||||
|
||||
if (hasNetworkTransport(mcpServerConfig)) {
|
||||
const serverUrl = new URL(
|
||||
@@ -1030,7 +1033,7 @@ export async function connectToMcpServer(
|
||||
// Try to discover OAuth configuration from the base URL
|
||||
const oauthConfig = await OAuthUtils.discoverOAuthConfig(baseUrl);
|
||||
if (oauthConfig) {
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`Discovered OAuth configuration from base URL for server '${mcpServerName}'`,
|
||||
);
|
||||
|
||||
@@ -1046,7 +1049,7 @@ export async function connectToMcpServer(
|
||||
// Pass the server URL for proper discovery
|
||||
const authServerUrl =
|
||||
mcpServerConfig.httpUrl || mcpServerConfig.url;
|
||||
console.log(
|
||||
debugLogger.log(
|
||||
`Starting OAuth authentication for server '${mcpServerName}'...`,
|
||||
);
|
||||
const authProvider = new MCPOAuthProvider(
|
||||
@@ -1257,7 +1260,9 @@ export async function createTransport(
|
||||
|
||||
if (accessToken) {
|
||||
hasOAuthConfig = true;
|
||||
console.log(`Found stored OAuth token for server '${mcpServerName}'`);
|
||||
debugLogger.log(
|
||||
`Found stored OAuth token for server '${mcpServerName}'`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1322,7 +1327,10 @@ export async function createTransport(
|
||||
if (debugMode) {
|
||||
transport.stderr!.on('data', (data) => {
|
||||
const stderrStr = data.toString().trim();
|
||||
console.debug(`[DEBUG] [MCP STDERR (${mcpServerName})]: `, stderrStr);
|
||||
debugLogger.debug(
|
||||
`[DEBUG] [MCP STDERR (${mcpServerName})]: `,
|
||||
stderrStr,
|
||||
);
|
||||
});
|
||||
}
|
||||
return transport;
|
||||
@@ -1340,7 +1348,7 @@ export function isEnabled(
|
||||
mcpServerConfig: MCPServerConfig,
|
||||
): boolean {
|
||||
if (!funcDecl.name) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Discovered a function declaration without a name from MCP server '${mcpServerName}'. Skipping.`,
|
||||
);
|
||||
return false;
|
||||
|
||||
@@ -733,8 +733,6 @@ Content of file[1]
|
||||
const invocation = tool.build({ paths: files });
|
||||
await invocation.execute(new AbortController().signal);
|
||||
|
||||
console.log('Execution order:', executionOrder);
|
||||
|
||||
// Verify concurrent execution pattern
|
||||
// In parallel execution: all "start:" events should come before all "end:" events
|
||||
// In sequential execution: "start:file1", "end:file1", "start:file2", "end:file2", etc.
|
||||
|
||||
@@ -19,6 +19,7 @@ import type { Config } from '../config/config.js';
|
||||
import { fileExists } from '../utils/fileUtils.js';
|
||||
import { Storage } from '../config/storage.js';
|
||||
import { GREP_TOOL_NAME } from './tool-names.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
const DEFAULT_TOTAL_MAX_MATCHES = 20000;
|
||||
|
||||
@@ -179,7 +180,7 @@ class GrepToolInvocation extends BaseToolInvocation<
|
||||
const totalMaxMatches = DEFAULT_TOTAL_MAX_MATCHES;
|
||||
|
||||
if (this.config.getDebugMode()) {
|
||||
console.log(`[GrepTool] Total result limit: ${totalMaxMatches}`);
|
||||
debugLogger.log(`[GrepTool] Total result limit: ${totalMaxMatches}`);
|
||||
}
|
||||
|
||||
for (const searchDir of searchDirectories) {
|
||||
|
||||
@@ -39,6 +39,7 @@ import { logSmartEditCorrectionEvent } from '../telemetry/loggers.js';
|
||||
|
||||
import { correctPath } from '../utils/pathCorrector.js';
|
||||
import { EDIT_TOOL_NAME, READ_FILE_TOOL_NAME } from './tool-names.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
interface ReplacementContext {
|
||||
params: EditToolParams;
|
||||
currentContent: string;
|
||||
@@ -616,12 +617,12 @@ class EditToolInvocation implements ToolInvocation<EditToolParams, ToolResult> {
|
||||
throw error;
|
||||
}
|
||||
const errorMsg = error instanceof Error ? error.message : String(error);
|
||||
console.log(`Error preparing edit: ${errorMsg}`);
|
||||
debugLogger.log(`Error preparing edit: ${errorMsg}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (editData.error) {
|
||||
console.log(`Error: ${editData.error.display}`);
|
||||
debugLogger.log(`Error: ${editData.error.display}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import { parse } from 'shell-quote';
|
||||
import { ToolErrorType } from './tool-error.js';
|
||||
import { safeJsonStringify } from '../utils/safeJsonStringify.js';
|
||||
import type { EventEmitter } from 'node:events';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
type ToolParams = Record<string, unknown>;
|
||||
|
||||
@@ -187,7 +188,7 @@ export class ToolRegistry {
|
||||
tool = tool.asFullyQualifiedTool();
|
||||
} else {
|
||||
// Decide on behavior: throw error, log warning, or allow overwrite
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Tool with name "${tool.name}" is already registered. Overwriting.`,
|
||||
);
|
||||
}
|
||||
@@ -379,7 +380,7 @@ export class ToolRegistry {
|
||||
// register each function as a tool
|
||||
for (const func of functions) {
|
||||
if (!func.name) {
|
||||
console.warn('Discovered a tool with no name. Skipping.');
|
||||
debugLogger.warn('Discovered a tool with no name. Skipping.');
|
||||
continue;
|
||||
}
|
||||
const parameters =
|
||||
|
||||
@@ -32,6 +32,7 @@ import {
|
||||
WebFetchFallbackAttemptEvent,
|
||||
} from '../telemetry/index.js';
|
||||
import { WEB_FETCH_TOOL_NAME } from './tool-names.js';
|
||||
import { debugLogger } from '../utils/debugLogger.js';
|
||||
|
||||
const URL_FETCH_TIMEOUT_MS = 10000;
|
||||
const MAX_CONTENT_LENGTH = 100000;
|
||||
@@ -274,7 +275,7 @@ ${textContent}
|
||||
DEFAULT_GEMINI_FLASH_MODEL,
|
||||
);
|
||||
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`[WebFetchTool] Full response for prompt "${userPrompt.substring(
|
||||
0,
|
||||
50,
|
||||
@@ -367,7 +368,7 @@ ${sourceListFormatted.join('\n')}`;
|
||||
|
||||
const llmContent = responseText;
|
||||
|
||||
console.debug(
|
||||
debugLogger.debug(
|
||||
`[WebFetchTool] Formatted tool response for prompt "${userPrompt}:\n\n":`,
|
||||
llmContent,
|
||||
);
|
||||
|
||||
@@ -8,11 +8,13 @@ import * as fs from 'node:fs/promises';
|
||||
import * as path from 'node:path';
|
||||
import type { FileDiscoveryService } from '../services/fileDiscoveryService.js';
|
||||
import type { FileFilteringOptions } from '../config/constants.js';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
// Simple console logger for now.
|
||||
// TODO: Integrate with a more robust server-side logger.
|
||||
const logger = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
debug: (...args: any[]) => console.debug('[DEBUG] [BfsFileSearch]', ...args),
|
||||
debug: (...args: any[]) =>
|
||||
debugLogger.debug('[DEBUG] [BfsFileSearch]', ...args),
|
||||
};
|
||||
|
||||
interface BfsFileSearchOptions {
|
||||
@@ -84,7 +86,7 @@ export async function bfsFileSearch(
|
||||
} catch (error) {
|
||||
// Warn user that a directory could not be read, as this affects search results.
|
||||
const message = (error as Error)?.message ?? 'Unknown error';
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`[WARN] Skipping unreadable directory: ${currentDir} (${message})`,
|
||||
);
|
||||
if (debug) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import type { FileSystemService } from '../services/fileSystemService.js';
|
||||
import { ToolErrorType } from '../tools/tool-error.js';
|
||||
import { BINARY_EXTENSIONS } from './ignorePatterns.js';
|
||||
import { createRequire as createModuleRequire } from 'node:module';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
const requireModule = createModuleRequire(import.meta.url);
|
||||
|
||||
@@ -260,7 +261,7 @@ export async function isBinaryFile(filePath: string): Promise<boolean> {
|
||||
// If >30% non-printable characters, consider it binary
|
||||
return nonPrintableCount / bytesRead > 0.3;
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Failed to check if file is binary: ${filePath}`,
|
||||
error instanceof Error ? error.message : String(error),
|
||||
);
|
||||
@@ -270,7 +271,7 @@ export async function isBinaryFile(filePath: string): Promise<boolean> {
|
||||
try {
|
||||
await fh.close();
|
||||
} catch (closeError) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Failed to close file handle for: ${filePath}`,
|
||||
closeError instanceof Error ? closeError.message : String(closeError),
|
||||
);
|
||||
|
||||
@@ -11,6 +11,7 @@ import { getErrorMessage, isNodeError } from './errors.js';
|
||||
import type { FileDiscoveryService } from '../services/fileDiscoveryService.js';
|
||||
import type { FileFilteringOptions } from '../config/constants.js';
|
||||
import { DEFAULT_FILE_FILTERING_OPTIONS } from '../config/constants.js';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
const MAX_ITEMS = 200;
|
||||
const TRUNCATION_INDICATOR = '...';
|
||||
@@ -104,7 +105,7 @@ async function readFullStructure(
|
||||
isNodeError(error) &&
|
||||
(error.code === 'EACCES' || error.code === 'ENOENT')
|
||||
) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Warning: Could not read directory ${currentPath}: ${error.message}`,
|
||||
);
|
||||
if (currentPath === rootPath && error.code === 'ENOENT') {
|
||||
|
||||
@@ -10,6 +10,7 @@ import { type BaseLlmClient } from '../core/baseLlmClient.js';
|
||||
import { LruCache } from './LruCache.js';
|
||||
import { DEFAULT_GEMINI_FLASH_MODEL } from '../config/models.js';
|
||||
import { promptIdContext } from './promptIdContext.js';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
const MAX_CACHE_SIZE = 50;
|
||||
|
||||
@@ -112,7 +113,7 @@ export async function FixLLMEditWithInstruction(
|
||||
let promptId = promptIdContext.getStore();
|
||||
if (!promptId) {
|
||||
promptId = `llm-fixer-fallback-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Could not find promptId in context. This is unexpected. Using a fallback ID: ${promptId}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,15 +16,17 @@ import type { FileFilteringOptions } from '../config/constants.js';
|
||||
import { DEFAULT_MEMORY_FILE_FILTERING_OPTIONS } from '../config/constants.js';
|
||||
import { GEMINI_DIR } from './paths.js';
|
||||
import type { GeminiCLIExtension } from '../config/config.js';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
// Simple console logger, similar to the one previously in CLI's config.ts
|
||||
// TODO: Integrate with a more robust server-side logger if available/appropriate.
|
||||
const logger = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
debug: (...args: any[]) =>
|
||||
console.debug('[DEBUG] [MemoryDiscovery]', ...args),
|
||||
debugLogger.debug('[DEBUG] [MemoryDiscovery]', ...args),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
warn: (...args: any[]) => console.warn('[WARN] [MemoryDiscovery]', ...args),
|
||||
warn: (...args: any[]) =>
|
||||
debugLogger.warn('[WARN] [MemoryDiscovery]', ...args),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
error: (...args: any[]) =>
|
||||
console.error('[ERROR] [MemoryDiscovery]', ...args),
|
||||
|
||||
@@ -8,14 +8,16 @@ import * as fs from 'node:fs/promises';
|
||||
import * as path from 'node:path';
|
||||
import { isSubpath } from './paths.js';
|
||||
import { marked, type Token } from 'marked';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
// Simple console logger for import processing
|
||||
const logger = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
debug: (...args: any[]) =>
|
||||
console.debug('[DEBUG] [ImportProcessor]', ...args),
|
||||
debugLogger.debug('[DEBUG] [ImportProcessor]', ...args),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
warn: (...args: any[]) => console.warn('[WARN] [ImportProcessor]', ...args),
|
||||
warn: (...args: any[]) =>
|
||||
debugLogger.warn('[WARN] [ImportProcessor]', ...args),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
error: (...args: any[]) =>
|
||||
console.error('[ERROR] [ImportProcessor]', ...args),
|
||||
|
||||
@@ -9,6 +9,7 @@ import { DEFAULT_GEMINI_FLASH_MODEL } from '../config/models.js';
|
||||
import type { BaseLlmClient } from '../core/baseLlmClient.js';
|
||||
import type { GeminiChat } from '../core/geminiChat.js';
|
||||
import { isFunctionResponse } from './messageInspectors.js';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
const CHECK_PROMPT = `Analyze *only* the content and structure of your immediately preceding response (your last turn in the conversation history). Based *strictly* on that response, determine who should logically speak next: the 'user' or the 'model' (you).
|
||||
**Decision Rules (apply in order):**
|
||||
@@ -126,7 +127,7 @@ export async function checkNextSpeaker(
|
||||
}
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
'Failed to talk to Gemini endpoint when seeing if conversation should continue.',
|
||||
error,
|
||||
);
|
||||
|
||||
@@ -10,6 +10,7 @@ import { ApiError } from '@google/genai';
|
||||
import type { HttpError } from './retry.js';
|
||||
import { retryWithBackoff } from './retry.js';
|
||||
import { setSimulate429 } from './testUtils.js';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
// Helper to create a mock function that fails a certain number of times
|
||||
const createFailingFunction = (
|
||||
@@ -43,7 +44,7 @@ describe('retryWithBackoff', () => {
|
||||
// Disable 429 simulation for tests
|
||||
setSimulate429(false);
|
||||
// Suppress unhandled promise rejection warnings for tests that expect errors
|
||||
console.warn = vi.fn();
|
||||
debugLogger.warn = vi.fn();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
isGenericQuotaExceededError,
|
||||
} from './quotaErrorDetection.js';
|
||||
import { delay, createAbortError } from './delay.js';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
const FETCH_FAILED_MESSAGE =
|
||||
'exception TypeError: fetch failed sending request';
|
||||
@@ -168,7 +169,7 @@ export async function retryWithBackoff<T>(
|
||||
}
|
||||
} catch (fallbackError) {
|
||||
// If fallback fails, continue with original error
|
||||
console.warn('Fallback to Flash model failed:', fallbackError);
|
||||
debugLogger.warn('Fallback to Flash model failed:', fallbackError);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,7 +196,7 @@ export async function retryWithBackoff<T>(
|
||||
}
|
||||
} catch (fallbackError) {
|
||||
// If fallback fails, continue with original error
|
||||
console.warn('Fallback to Flash model failed:', fallbackError);
|
||||
debugLogger.warn('Fallback to Flash model failed:', fallbackError);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,7 +228,7 @@ export async function retryWithBackoff<T>(
|
||||
}
|
||||
} catch (fallbackError) {
|
||||
// If fallback fails, continue with original error
|
||||
console.warn('Fallback to Flash model failed:', fallbackError);
|
||||
debugLogger.warn('Fallback to Flash model failed:', fallbackError);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,7 +245,7 @@ export async function retryWithBackoff<T>(
|
||||
|
||||
if (delayDurationMs > 0) {
|
||||
// Respect Retry-After header if present and parsed
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Attempt ${attempt} failed with status ${delayErrorStatus ?? 'unknown'}. Retrying after explicit delay of ${delayDurationMs}ms...`,
|
||||
error,
|
||||
);
|
||||
@@ -367,13 +368,13 @@ function logRetryAttempt(
|
||||
}
|
||||
|
||||
if (errorStatus === 429) {
|
||||
console.warn(message, error);
|
||||
debugLogger.warn(message, error);
|
||||
} else if (errorStatus && errorStatus >= 500 && errorStatus < 600) {
|
||||
console.error(message, error);
|
||||
} else if (error instanceof Error) {
|
||||
// Fallback for errors that might not have a status but have a message
|
||||
if (error.message.includes('429')) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Attempt ${attempt} failed with 429 error (no Retry-After header). Retrying with backoff...`,
|
||||
error,
|
||||
);
|
||||
@@ -383,9 +384,9 @@ function logRetryAttempt(
|
||||
error,
|
||||
);
|
||||
} else {
|
||||
console.warn(message, error); // Default to warn for other errors
|
||||
debugLogger.warn(message, error); // Default to warn for other errors
|
||||
}
|
||||
} else {
|
||||
console.warn(message, error); // Default to warn if error type is unknown
|
||||
debugLogger.warn(message, error); // Default to warn if error type is unknown
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import { execSync } from 'node:child_process';
|
||||
import os from 'node:os';
|
||||
import { detect as chardetDetect } from 'chardet';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
// Cache for system encoding to avoid repeated detection
|
||||
// Use undefined to indicate "not yet checked" vs null meaning "checked but failed"
|
||||
@@ -66,7 +67,7 @@ export function getSystemEncoding(): string | null {
|
||||
`Unable to parse Windows code page from 'chcp' output "${output.trim()}". `,
|
||||
);
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Failed to get Windows code page using 'chcp' command: ${error instanceof Error ? error.message : String(error)}. ` +
|
||||
`Will attempt to detect encoding from command output instead.`,
|
||||
);
|
||||
@@ -88,7 +89,7 @@ export function getSystemEncoding(): string | null {
|
||||
.toString()
|
||||
.trim();
|
||||
} catch (_e) {
|
||||
console.warn('Failed to get locale charmap.');
|
||||
debugLogger.warn('Failed to get locale charmap.');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -141,7 +142,7 @@ export function windowsCodePageToEncoding(cp: number): string | null {
|
||||
return map[cp];
|
||||
}
|
||||
|
||||
console.warn(`Unable to determine encoding for windows code page ${cp}.`);
|
||||
debugLogger.warn(`Unable to determine encoding for windows code page ${cp}.`);
|
||||
return null; // Return null if no mapping found
|
||||
}
|
||||
|
||||
@@ -159,7 +160,7 @@ export function detectEncodingFromBuffer(buffer: Buffer): string | null {
|
||||
return detected.toLowerCase();
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to detect encoding with chardet:', error);
|
||||
debugLogger.warn('Failed to detect encoding with chardet:', error);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import path from 'node:path';
|
||||
import { promises as fsp, readFileSync } from 'node:fs';
|
||||
import { Storage } from '../config/storage.js';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
interface UserAccounts {
|
||||
active: string | null;
|
||||
@@ -33,7 +34,7 @@ export class UserAccountManager {
|
||||
|
||||
// Inlined validation logic
|
||||
if (typeof parsed !== 'object' || parsed === null) {
|
||||
console.log('Invalid accounts file schema, starting fresh.');
|
||||
debugLogger.log('Invalid accounts file schema, starting fresh.');
|
||||
return defaultState;
|
||||
}
|
||||
const { active, old } = parsed as Partial<UserAccounts>;
|
||||
@@ -43,7 +44,7 @@ export class UserAccountManager {
|
||||
(Array.isArray(old) && old.every((i) => typeof i === 'string')));
|
||||
|
||||
if (!isValid) {
|
||||
console.log('Invalid accounts file schema, starting fresh.');
|
||||
debugLogger.log('Invalid accounts file schema, starting fresh.');
|
||||
return defaultState;
|
||||
}
|
||||
|
||||
@@ -66,7 +67,10 @@ export class UserAccountManager {
|
||||
) {
|
||||
return defaultState;
|
||||
}
|
||||
console.log('Error during sync read of accounts, starting fresh.', error);
|
||||
debugLogger.log(
|
||||
'Error during sync read of accounts, starting fresh.',
|
||||
error,
|
||||
);
|
||||
return defaultState;
|
||||
}
|
||||
}
|
||||
@@ -84,7 +88,7 @@ export class UserAccountManager {
|
||||
) {
|
||||
return defaultState;
|
||||
}
|
||||
console.log('Could not parse accounts file, starting fresh.', error);
|
||||
debugLogger.log('Could not parse accounts file, starting fresh.', error);
|
||||
return defaultState;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { isNodeError } from '../utils/errors.js';
|
||||
import * as fs from 'node:fs';
|
||||
import * as path from 'node:path';
|
||||
import * as process from 'node:process';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
export type Unsubscribe = () => void;
|
||||
|
||||
@@ -72,7 +73,7 @@ export class WorkspaceContext {
|
||||
this.directories.add(resolved);
|
||||
this.notifyDirectoriesChanged();
|
||||
} catch (err) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`[WARN] Skipping unreadable directory: ${directory} (${err instanceof Error ? err.message : String(err)})`,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user