Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import { registerGhostProvider } from "./services/ghost" // kilocode_change
import { registerMainThreadForwardingLogger } from "./utils/fowardingLogger" // kilocode_change
import { getKiloCodeWrapperProperties } from "./core/kilocode/wrapper" // kilocode_change
import { registerAutocompleteProvider } from "./services/autocomplete" // kilocode_change
import { checkAnthropicApiKeyConflict } from "./utils/anthropicApiKeyWarning"

/**
* Built using https://github.com/microsoft/vscode-webview-ui-toolkit
Expand Down Expand Up @@ -280,6 +281,13 @@ export async function activate(context: vscode.ExtensionContext) {
)
}

// Check for env var conflicts that might confuse users
try {
checkAnthropicApiKeyConflict()
} catch (error) {
outputChannel.appendLine(`Failed to check API key conflicts: ${error}`)
}

registerCommands({ context, outputChannel, provider })

/**
Expand Down
100 changes: 100 additions & 0 deletions src/utils/__tests__/anthropicApiKeyWarning.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"
import * as vscode from "vscode"

import { checkAnthropicApiKeyConflict } from "../anthropicApiKeyWarning"

// Mock VS Code API
vi.mock("vscode", () => ({
workspace: {
getConfiguration: vi.fn(),
},
window: {
showWarningMessage: vi.fn(),
},
env: {
openExternal: vi.fn(),
},
Uri: {
parse: vi.fn(),
},
}))

describe("anthropicApiKeyWarning", () => {
const mockGetConfiguration = vi.mocked(vscode.workspace.getConfiguration)
const mockShowWarningMessage = vi.mocked(vscode.window.showWarningMessage)

beforeEach(() => {
vi.clearAllMocks()
})

afterEach(() => {
// Clean up environment variable
delete process.env.ANTHROPIC_API_KEY
})

describe("checkAnthropicApiKeyConflict", () => {
it("should not show warning when ANTHROPIC_API_KEY is not set", () => {
// Ensure environment variable is not set
delete process.env.ANTHROPIC_API_KEY

checkAnthropicApiKeyConflict()

expect(mockGetConfiguration).not.toHaveBeenCalled()
expect(mockShowWarningMessage).not.toHaveBeenCalled()
})

it("should not show warning when ANTHROPIC_API_KEY is set but provider is not claude-code", () => {
// Set environment variable
process.env.ANTHROPIC_API_KEY = "test-key"

// Mock configuration to return different provider
const mockConfig = {
get: vi.fn().mockReturnValue("anthropic"),
}
mockGetConfiguration.mockReturnValue(mockConfig as any)

checkAnthropicApiKeyConflict()

expect(mockGetConfiguration).toHaveBeenCalledWith("kilo-code")
expect(mockConfig.get).toHaveBeenCalledWith("apiProvider")
expect(mockShowWarningMessage).not.toHaveBeenCalled()
})

it("should show warning when ANTHROPIC_API_KEY is set and provider is claude-code", () => {
process.env.ANTHROPIC_API_KEY = "test-key"

const mockConfig = {
get: vi.fn().mockReturnValue("claude-code"),
}
mockGetConfiguration.mockReturnValue(mockConfig as any)
mockShowWarningMessage.mockResolvedValue(undefined)

checkAnthropicApiKeyConflict()

expect(mockGetConfiguration).toHaveBeenCalledWith("kilo-code")
expect(mockConfig.get).toHaveBeenCalledWith("apiProvider")
expect(mockShowWarningMessage).toHaveBeenCalledWith(
"An ANTHROPIC_API_KEY environment variable was detected. This may conflict with your subscription login and cause errors. Please unset it to ensure your Claude Max/Pro plan is used.",
"More Info",
"Got it",
)
})

it("should handle undefined apiProvider gracefully", () => {
// Set environment variable
process.env.ANTHROPIC_API_KEY = "test-key"

// Mock configuration to return undefined provider
const mockConfig = {
get: vi.fn().mockReturnValue(undefined),
}
mockGetConfiguration.mockReturnValue(mockConfig as any)

checkAnthropicApiKeyConflict()

expect(mockGetConfiguration).toHaveBeenCalledWith("kilo-code")
expect(mockConfig.get).toHaveBeenCalledWith("apiProvider")
expect(mockShowWarningMessage).not.toHaveBeenCalled()
})
})
})
32 changes: 32 additions & 0 deletions src/utils/anthropicApiKeyWarning.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import * as vscode from "vscode"

/**
* Check for potential ANTHROPIC_API_KEY conflicts with Claude Code provider.
* Shows a warning if the environment variable is set while using Claude Code provider.
* Fixes issue #2026 - users were getting confused when their env var conflicted with subscription.
*/
export function checkAnthropicApiKeyConflict(): void {
const anthropicKey = process.env.ANTHROPIC_API_KEY
if (!anthropicKey) {
return
}

const config = vscode.workspace.getConfiguration("kilo-code")
const provider = config.get<string>("apiProvider")

if (provider === "claude-code") {
showAnthropicApiKeyWarning()
}
}

function showAnthropicApiKeyWarning(): void {
const msg =
"An ANTHROPIC_API_KEY environment variable was detected. This may conflict with your subscription login and cause errors. Please unset it to ensure your Claude Max/Pro plan is used."

vscode.window.showWarningMessage(msg, "More Info", "Got it").then((choice) => {
if (choice === "More Info") {
vscode.env.openExternal(vscode.Uri.parse("https://github.com/Kilo-Org/kilocode/issues/2026"))
}
// User dismissed or clicked "Got it" - nothing else to do
})
}