Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
26 changes: 22 additions & 4 deletions apps/cli/src/commands/cli/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,28 @@ export async function run(promptArg: string | undefined, flagOptions: FlagOption
extensionHostOptions.apiKey = flagOptions.apiKey || getApiKeyFromEnv(extensionHostOptions.provider)

if (!extensionHostOptions.apiKey) {
console.error(`[CLI] Error: No API key provided. Use --api-key or set the appropriate environment variable.`)
console.error(`[CLI] For ${extensionHostOptions.provider}, set ${getEnvVarName(extensionHostOptions.provider)}`)

process.exit(1)
if (extensionHostOptions.provider === "bedrock") {
// Bedrock can authenticate via AWS credential chain without an explicit API key.
// Validate that at least one credential source is available.
const hasProfile = !!process.env.AWS_PROFILE
const hasDirectCreds = !!(process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY)
if (!hasProfile && !hasDirectCreds) {
console.error(`[CLI] Error: No credentials found for Bedrock. Provide one of:`)
console.error(` --api-key or AWS_BEDROCK_API_KEY (bearer token / API key mode)`)
console.error(` AWS_PROFILE (profile-based auth)`)
console.error(` AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY (direct credentials)`)
console.error(` Or ensure a default credential chain is available (IMDS, ECS task role, etc.)`)
process.exit(1)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
}
} else {
console.error(
`[CLI] Error: No API key provided. Use --api-key or set the appropriate environment variable.`,
)
console.error(
`[CLI] For ${extensionHostOptions.provider}, set ${getEnvVarName(extensionHostOptions.provider)}`,
)
process.exit(1)
}
}

if (!fs.existsSync(extensionHostOptions.workspacePath)) {
Expand Down
3 changes: 2 additions & 1 deletion apps/cli/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Command } from "commander"

import { DEFAULT_FLAGS } from "@/types/constants.js"
import { supportedProviders } from "@/types/index.js"
import { VERSION } from "@/lib/utils/version.js"
import { run, logout, status, listCommands, listModes, listModels, listSessions, upgrade } from "@/commands/index.js"

Expand Down Expand Up @@ -35,7 +36,7 @@ program
.option("-d, --debug", "Enable debug output (includes detailed debug information)", false)
.option("-a, --require-approval", "Require manual approval for actions", false)
.option("-k, --api-key <key>", "API key for the LLM provider")
.option("--provider <provider>", "API provider (anthropic, openai-native, gemini, openrouter, etc.)")
.option("--provider <provider>", `API provider (${supportedProviders.join(", ")})`)
.option("-m, --model <model>", "Model to use", DEFAULT_FLAGS.model)
.option("--mode <mode>", "Mode to start in (code, architect, ask, debug, etc.)", DEFAULT_FLAGS.mode)
.option("--terminal-shell <path>", "Absolute path to shell executable for inline terminal commands")
Expand Down
31 changes: 31 additions & 0 deletions apps/cli/src/lib/utils/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { SupportedProvider } from "@/types/index.js"

const envVarMap: Record<SupportedProvider, string> = {
anthropic: "ANTHROPIC_API_KEY",
bedrock: "AWS_BEDROCK_API_KEY",
"openai-native": "OPENAI_API_KEY",
gemini: "GOOGLE_API_KEY",
openrouter: "OPENROUTER_API_KEY",
Expand Down Expand Up @@ -31,6 +32,36 @@ export function getProviderSettings(
if (apiKey) config.apiKey = apiKey
if (model) config.apiModelId = model
break
case "bedrock":
config.awsRegion = process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION || "us-east-1"
if (model) {
config.apiModelId = model
// Auto-enable cross-region inference when model ID has a regional prefix
// (e.g. "us.", "eu.", "apac.") — these are cross-region inference profiles
// that require awsUseCrossRegionInference to be set.
if (/^(us|eu|apac)\./.test(model)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This regex only covers us., eu., and apac. prefixes, but AWS_INFERENCE_PROFILE_MAPPING in packages/types/src/providers/bedrock.ts defines 8 prefixes: au., jp., ug., us., eu., apac., ca., sa.. A model like au.anthropic.claude-3-5-sonnet-20241022-v2:0 will silently get awsUseCrossRegionInference = false, causing a ResourceNotFoundException with no indication of why.

Would it make sense to derive this from the existing mapping rather than maintaining a parallel regex?

Suggested change
if (/^(us|eu|apac)\./.test(model)) {
if (AWS_INFERENCE_PROFILE_MAPPING.some(([, prefix]) => model.startsWith(prefix))) {

config.awsUseCrossRegionInference = true
}
}

if (apiKey) {
// Bearer token / API key mode (LiteLLM proxy, Bedrock gateway)
config.awsUseApiKey = true
config.awsApiKey = apiKey
} else if (process.env.AWS_PROFILE) {
// Profile-based auth
config.awsUseProfile = true
config.awsProfile = process.env.AWS_PROFILE
} else if (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) {
// Direct credentials from env
config.awsAccessKey = process.env.AWS_ACCESS_KEY_ID
config.awsSecretKey = process.env.AWS_SECRET_ACCESS_KEY
if (process.env.AWS_SESSION_TOKEN) {
config.awsSessionToken = process.env.AWS_SESSION_TOKEN
}
}
// else: fall through to default credential chain (SDK handles IMDS, ECS task role, etc.)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a user switches auth modes between CLI runs — e.g. from AWS_PROFILE in run 1 to direct AWS_ACCESS_KEY_ID credentials in run 2 — awsUseProfile=true can persist in ~/.vscode-mock/global-storage/global-state.json from run 1. The Bedrock handler checks awsUseProfile before awsAccessKey (bedrock.ts line 282), so run 2 silently authenticates with the stale profile instead of the new direct credentials.

Would explicitly clearing the non-winning flags fix this?

break
case "openai-native":
if (apiKey) config.openAiNativeApiKey = apiKey
if (model) config.apiModelId = model
Expand Down
1 change: 1 addition & 0 deletions apps/cli/src/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { OutputFormat } from "./json-events.js"

export const supportedProviders = [
"anthropic",
"bedrock",
"openai-native",
"gemini",
"openrouter",
Expand Down
Loading