diff --git a/src/__tests__/extension.spec.ts b/src/__tests__/extension.spec.ts index 5b072672699..0bdbb26d462 100644 --- a/src/__tests__/extension.spec.ts +++ b/src/__tests__/extension.spec.ts @@ -46,6 +46,11 @@ vi.mock("@dotenvx/dotenvx", () => ({ config: vi.fn(), })) +// Mock fs so the extension module can safely check for optional .env. +vi.mock("fs", () => ({ + existsSync: vi.fn().mockReturnValue(false), +})) + const mockBridgeOrchestratorDisconnect = vi.fn().mockResolvedValue(undefined) const mockCloudServiceInstance = { @@ -238,6 +243,36 @@ describe("extension.ts", () => { authStateChangedHandler = undefined }) + test("does not call dotenvx.config when optional .env does not exist", async () => { + vi.resetModules() + vi.clearAllMocks() + + const fs = await import("fs") + vi.mocked(fs.existsSync).mockReturnValue(false) + + const dotenvx = await import("@dotenvx/dotenvx") + + const { activate } = await import("../extension") + await activate(mockContext) + + expect(dotenvx.config).not.toHaveBeenCalled() + }) + + test("calls dotenvx.config when optional .env exists", async () => { + vi.resetModules() + vi.clearAllMocks() + + const fs = await import("fs") + vi.mocked(fs.existsSync).mockReturnValue(true) + + const dotenvx = await import("@dotenvx/dotenvx") + + const { activate } = await import("../extension") + await activate(mockContext) + + expect(dotenvx.config).toHaveBeenCalledTimes(1) + }) + test("authStateChangedHandler calls BridgeOrchestrator.disconnect when logged-out event fires", async () => { const { CloudService, BridgeOrchestrator } = await import("@roo-code/cloud") diff --git a/src/extension.ts b/src/extension.ts index bcfbe339932..262bf623378 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,15 +1,20 @@ import * as vscode from "vscode" import * as dotenvx from "@dotenvx/dotenvx" +import * as fs from "fs" import * as path from "path" // Load environment variables from .env file -try { - // Specify path to .env file in the project root directory - const envPath = path.join(__dirname, "..", ".env") - dotenvx.config({ path: envPath }) -} catch (e) { - // Silently handle environment loading errors - console.warn("Failed to load environment variables:", e) +// The extension-level .env is optional (not shipped in production builds). +// Avoid calling dotenvx when the file doesn't exist, otherwise dotenvx emits +// a noisy [MISSING_ENV_FILE] error to the extension host console. +const envPath = path.join(__dirname, "..", ".env") +if (fs.existsSync(envPath)) { + try { + dotenvx.config({ path: envPath }) + } catch (e) { + // Best-effort only: never fail extension activation due to optional env loading. + console.warn("Failed to load environment variables:", e) + } } import type { CloudUserInfo, AuthState } from "@roo-code/types"