diff --git a/src/core/controller/dictation/startRecording.ts b/src/core/controller/dictation/startRecording.ts index 12267732c9..84af801c8e 100644 --- a/src/core/controller/dictation/startRecording.ts +++ b/src/core/controller/dictation/startRecording.ts @@ -25,7 +25,7 @@ async function handleInstallWithCline( await controller.postStateToWebview() await controller.initTask(installTask) - HostProvider.get().logToChannel(`Started task to install ${dependencyName}`) + Logger.log(`[handleInstallWithCline] Started task to install ${dependencyName}`) } /** diff --git a/src/core/controller/index.ts b/src/core/controller/index.ts index 1f19db880f..191825b66c 100644 --- a/src/core/controller/index.ts +++ b/src/core/controller/index.ts @@ -119,7 +119,6 @@ export class Controller { constructor(readonly context: vscode.ExtensionContext) { PromptRegistry.getInstance() // Ensure prompts and tools are registered - HostProvider.get().logToChannel("ClineProvider instantiated") this.stateManager = StateManager.get() StateManager.get().registerCallbacks({ onPersistenceError: async ({ error }: PersistenceErrorEvent) => { @@ -154,6 +153,8 @@ export class Controller { // Check CLI installation status once on startup checkCliInstallation(this) + + Logger.log("[Controller] ClineProvider instantiated") } /* diff --git a/src/core/controller/models/refreshVercelAiGatewayModels.ts b/src/core/controller/models/refreshVercelAiGatewayModels.ts index cecc1cf102..bdf8b1508d 100644 --- a/src/core/controller/models/refreshVercelAiGatewayModels.ts +++ b/src/core/controller/models/refreshVercelAiGatewayModels.ts @@ -120,7 +120,7 @@ export async function refreshVercelAiGatewayModels(_controller: Controller): Pro } await fs.writeFile(vercelAiGatewayModelsFilePath, JSON.stringify(models)) - Logger.log("Vercel AI Gateway models fetched and saved", JSON.stringify(models).slice(0, 300)) + Logger.log("Vercel AI Gateway models fetched and saved") } else { Logger.error("Invalid response from Vercel AI Gateway API") } diff --git a/src/core/controller/state/checkCliInstallation.ts b/src/core/controller/state/checkCliInstallation.ts index fcff76fc28..be19ab6f07 100644 --- a/src/core/controller/state/checkCliInstallation.ts +++ b/src/core/controller/state/checkCliInstallation.ts @@ -1,5 +1,4 @@ import { Boolean } from "@shared/proto/cline/common" -import { Logger } from "@/shared/services/Logger" import { isClineCliInstalled } from "@/utils/cli-detector" import { Controller } from ".." @@ -12,8 +11,7 @@ export async function checkCliInstallation(_controller: Controller): Promise { - HostProvider.get().logToChannel("Starting new task") await sidebarController.clearTask() await sidebarController.postStateToWebview() await sendChatButtonClickedEvent() await sidebarController.initTask(task, images) - HostProvider.get().logToChannel( - `Task started with message: ${task ? `"${task}"` : "undefined"} and ${images?.length || 0} image(s)`, - ) }, sendMessage: async (message?: string, images?: string[]) => { - HostProvider.get().logToChannel( - `Sending message: ${message ? `"${message}"` : "undefined"} with ${images?.length || 0} image(s)`, - ) if (sidebarController.task) { await sidebarController.task.handleWebviewAskResponse("messageResponse", message || "", images || []) } else { - HostProvider.get().logToChannel("No active task to send message to") + Logger.error("No active task to send message to") } }, pressPrimaryButton: async () => { - HostProvider.get().logToChannel("Pressing primary button") if (sidebarController.task) { await sidebarController.task.handleWebviewAskResponse("yesButtonClicked", "", []) } else { - HostProvider.get().logToChannel("No active task to press button for") + Logger.error("No active task to press button for") } }, pressSecondaryButton: async () => { - HostProvider.get().logToChannel("Pressing secondary button") if (sidebarController.task) { await sidebarController.task.handleWebviewAskResponse("noButtonClicked", "", []) } else { - HostProvider.get().logToChannel("No active task to press button for") + Logger.error("No active task to press button for") } }, } diff --git a/src/hosts/vscode/VscodeWebviewProvider.ts b/src/hosts/vscode/VscodeWebviewProvider.ts index 5ce86ad14f..ceb408061e 100644 --- a/src/hosts/vscode/VscodeWebviewProvider.ts +++ b/src/hosts/vscode/VscodeWebviewProvider.ts @@ -113,7 +113,7 @@ export class VscodeWebviewProvider extends WebviewProvider implements vscode.Web // if the extension is starting a new session, clear previous task state this.controller.clearTask() - HostProvider.get().logToChannel("Webview view resolved") + Logger.log("[VscodeWebviewProvider] Webview view resolved") // Title setting logic removed to allow VSCode to use the container title primarily. } diff --git a/src/integrations/checkpoints/CheckpointMigration.ts b/src/integrations/checkpoints/CheckpointMigration.ts index 93d80b93c9..f0a613fd4a 100644 --- a/src/integrations/checkpoints/CheckpointMigration.ts +++ b/src/integrations/checkpoints/CheckpointMigration.ts @@ -12,8 +12,6 @@ import { Logger } from "@/shared/services/Logger" */ export async function cleanupLegacyCheckpoints(): Promise { try { - HostProvider.get().logToChannel("Checking for legacy checkpoints...") - const tasksDir = path.join(HostProvider.get().globalStorageFsPath, "tasks") // Check if tasks directory exists @@ -45,29 +43,27 @@ export async function cleanupLegacyCheckpoints(): Promise { const checkpointsDir = path.join(mostRecentFolder.path, "checkpoints") if (await fileExistsAtPath(checkpointsDir)) { - HostProvider.get().logToChannel("Found legacy checkpoints directory, cleaning up...") - + const results = { deleted: [] as string[], failed: [] as string[] } // Legacy checkpoints found, delete checkpoints directories in all task folders for (const folder of folderStats) { const folderCheckpointsDir = path.join(folder.path, "checkpoints") if (await fileExistsAtPath(folderCheckpointsDir)) { - HostProvider.get().logToChannel(`Deleting legacy checkpoints in ${folder.folder}`) try { await fs.rm(folderCheckpointsDir, { recursive: true, force: true }) + results.deleted.push(folder.folder) } catch (_error) { // Ignore error if directory removal fails - HostProvider.get().logToChannel( - `Warning: Failed to delete checkpoints in ${folder.folder}, continuing...`, - ) + results.failed.push(folder.folder) } } } - HostProvider.get().logToChannel("Legacy checkpoints cleanup completed") + Logger.info( + `Legacy checkpoints cleanup completed. Deleted: ${results.deleted.length}, Failed: ${results.failed.length}`, + ) } } } catch (error) { - HostProvider.get().logToChannel(`Error cleaning up legacy checkpoints: ${error}`) - Logger.error("Error cleaning up legacy checkpoints:", error) + throw new Error("Error cleaning up legacy checkpoints.", { cause: error }) } } diff --git a/src/services/logging/distinctId.ts b/src/services/logging/distinctId.ts index abc644358c..6177bb99e1 100644 --- a/src/services/logging/distinctId.ts +++ b/src/services/logging/distinctId.ts @@ -32,7 +32,7 @@ export async function initializeDistinctId(context: ExtensionContext, uuid: () = setDistinctId(distinctId) - Logger.log("Telemetry distinct ID initialized:", distinctId) + Logger.log("[DistinctId] initialized:", distinctId) } /* @@ -46,7 +46,7 @@ async function getMachineId(): Promise { const id = await machineId() return id } catch (error) { - Logger.log("Failed to get machine ID from node-machine-id", error) + Logger.log("[DistinctId] Failed to get machine ID from node-machine-id", error) return undefined } } @@ -57,7 +57,7 @@ async function getMachineId(): Promise { */ export function setDistinctId(newId: string) { if (_distinctId && _distinctId !== newId) { - Logger.log(`Changing telemetry ID from ${_distinctId} to ${newId}.`) + Logger.log("[DistinctId] Updating...", `From ${_distinctId} to ${newId}`) } _distinctId = newId } @@ -69,7 +69,7 @@ export function setDistinctId(newId: string) { */ export function getDistinctId() { if (!_distinctId) { - Logger.error("Telemetry ID is not initialized. Call initializeDistinctId() first.") + Logger.debug("[DistinctId] Not initialized. Call initializeDistinctId() first.") } return _distinctId } diff --git a/src/shared/storage/ClineBlobStorage.ts b/src/shared/storage/ClineBlobStorage.ts index f3d12da706..9375de8f97 100644 --- a/src/shared/storage/ClineBlobStorage.ts +++ b/src/shared/storage/ClineBlobStorage.ts @@ -78,7 +78,7 @@ export class ClineBlobStorage extends ClineStorage { this.adapter = adapter this.settings = settings this.initialized = true - Logger.log("[ClineBlobStorage] Adapter created") + Logger.log(`[ClineBlobStorage] Adapter created for ${settings.adapterType}`) } } catch (error) { // Log but don't throw - allow startup to continue @@ -114,8 +114,8 @@ export class ClineBlobStorage extends ClineStorage { } try { return await this.adapter!.read(key) - } catch (error) { - Logger.error(`[ClineBlobStorage] failed to get '${key}':`, error) + } catch { + // Silently return undefined on read errors return undefined } } @@ -128,7 +128,6 @@ export class ClineBlobStorage extends ClineStorage { try { await this.adapter!.write(key, value) } catch (error) { - Logger.error(`[ClineBlobStorage] failed to store '${key}':`, error) throw error } } @@ -141,7 +140,6 @@ export class ClineBlobStorage extends ClineStorage { try { await this.adapter!.remove(key) } catch (error) { - Logger.error(`[ClineBlobStorage] failed to delete '${key}':`, error) throw error } } diff --git a/src/shared/storage/ClineSecretStorage.ts b/src/shared/storage/ClineSecretStorage.ts index dfc5c5a353..0c9fc227ae 100644 --- a/src/shared/storage/ClineSecretStorage.ts +++ b/src/shared/storage/ClineSecretStorage.ts @@ -36,8 +36,7 @@ export class ClineSecretStorage extends ClineStorage { protected async _get(key: string): Promise { try { return key ? await this.storage.get(key) : undefined - } catch (error) { - Logger.error("[ClineSecretStorage]", error) + } catch { return undefined } } @@ -51,12 +50,11 @@ export class ClineSecretStorage extends ClineStorage { await this.storage.store(key, value) } } catch (error) { - Logger.error("[ClineSecretStorage]", error) + Logger.error("[ClineSecretStorage] Failed to store", error) } } protected async _delete(key: string): Promise { - Logger.info("[ClineSecretStorage] deleting secret") await this.storage.delete(key) } } diff --git a/src/shared/storage/ClineStorage.ts b/src/shared/storage/ClineStorage.ts index 8c9a91fa49..94962fcb1f 100644 --- a/src/shared/storage/ClineStorage.ts +++ b/src/shared/storage/ClineStorage.ts @@ -48,8 +48,7 @@ export abstract class ClineStorage { public async get(key: string): Promise { try { return await this._get(key) - } catch (error) { - Logger.error(`[${this.name}] failed to get '${key}':`, error) + } catch { return undefined } } @@ -77,8 +76,8 @@ export abstract class ClineStorage { try { await this._delete(key) await this.fire(key) - } catch (error) { - Logger.error(`[${this.name}] failed to delete '${key}':`, error) + } catch { + // Silently fail on delete errors } } diff --git a/src/test/cline-api.test.ts b/src/test/cline-api.test.ts index 6fae4e7116..062459a90a 100644 --- a/src/test/cline-api.test.ts +++ b/src/test/cline-api.test.ts @@ -2,22 +2,23 @@ import { afterEach, beforeEach, describe, it } from "mocha" import * as should from "should" import * as sinon from "sinon" import { createClineAPI } from "@/exports" +import { Logger } from "@/shared/services/Logger" import type { ClineAPI } from "../exports/cline" import { setVscodeHostProviderMock } from "./host-provider-test-utils" describe("ClineAPI Core Functionality", () => { let api: ClineAPI let mockController: any - let mockLogToChannel: sinon.SinonStub<[string], void> + let mockLoggerError: sinon.SinonStub let sandbox: sinon.SinonSandbox let _getGlobalStateStub: sinon.SinonStub beforeEach(async () => { sandbox = sinon.createSandbox() - // Create mock log function - mockLogToChannel = sandbox.stub<[string], void>() - setVscodeHostProviderMock({ logToChannel: mockLogToChannel }) + // Stub Logger.error + mockLoggerError = sandbox.stub(Logger, "error") + setVscodeHostProviderMock({}) // Create a mock controller that matches what the real createClineAPI expects // We don't import the real Controller to avoid the webview dependencies @@ -64,11 +65,6 @@ describe("ClineAPI Core Functionality", () => { sinon.assert.called(mockController.clearTask) sinon.assert.called(mockController.postStateToWebview) sinon.assert.calledWith(mockController.initTask, taskDescription, images) - - // Verify logging - first it logs "Starting new task" - sinon.assert.calledWith(mockLogToChannel, "Starting new task") - // Then it logs the task details - sinon.assert.calledWith(mockLogToChannel, `Task started with message: "Create a test function" and 2 image(s)`) }) it("should handle undefined task description", async () => { @@ -76,16 +72,12 @@ describe("ClineAPI Core Functionality", () => { sinon.assert.called(mockController.clearTask) sinon.assert.calledWith(mockController.initTask, undefined, []) - - sinon.assert.calledWith(mockLogToChannel, "Task started with message: undefined and 0 image(s)") }) it("should handle task with no images", async () => { await api.startNewTask("Task without images") sinon.assert.calledWith(mockController.initTask, "Task without images", undefined) - - sinon.assert.calledWith(mockLogToChannel, `Task started with message: "Task without images" and 0 image(s)`) }) }) @@ -99,16 +91,12 @@ describe("ClineAPI Core Functionality", () => { await api.sendMessage("Test message", ["image.png"]) sinon.assert.calledWith(mockTask.handleWebviewAskResponse, "messageResponse", "Test message", ["image.png"]) - - sinon.assert.calledWith(mockLogToChannel, `Sending message: "Test message" with 1 image(s)`) }) it("should handle no active task gracefully", async () => { mockController.task = undefined await api.sendMessage("Message to nowhere", []) - - sinon.assert.calledWith(mockLogToChannel, "No active task to send message to") }) it("should handle empty message", async () => { @@ -131,8 +119,6 @@ describe("ClineAPI Core Functionality", () => { await api.sendMessage(undefined, []) sinon.assert.calledWith(mockTask.handleWebviewAskResponse, "messageResponse", "", []) - - sinon.assert.calledWith(mockLogToChannel, `Sending message: undefined with 0 image(s)`) }) }) @@ -147,8 +133,6 @@ describe("ClineAPI Core Functionality", () => { await api.pressPrimaryButton() sinon.assert.calledWith(mockTask.handleWebviewAskResponse, "yesButtonClicked", "", []) - - sinon.assert.calledWith(mockLogToChannel, "Pressing primary button") }) it("should handle primary button press with no active task", async () => { @@ -156,7 +140,7 @@ describe("ClineAPI Core Functionality", () => { await api.pressPrimaryButton() - sinon.assert.calledWith(mockLogToChannel, "No active task to press button for") + sinon.assert.calledWith(mockLoggerError, "No active task to press button for") }) }) @@ -170,8 +154,6 @@ describe("ClineAPI Core Functionality", () => { await api.pressSecondaryButton() sinon.assert.calledWith(mockTask.handleWebviewAskResponse, "noButtonClicked", "", []) - - sinon.assert.calledWith(mockLogToChannel, "Pressing secondary button") }) it("should handle secondary button press with no active task", async () => { @@ -179,7 +161,7 @@ describe("ClineAPI Core Functionality", () => { await api.pressSecondaryButton() - sinon.assert.calledWith(mockLogToChannel, "No active task to press button for") + sinon.assert.calledWith(mockLoggerError, "No active task to press button for") }) }) })