-
Notifications
You must be signed in to change notification settings - Fork 2k
feat: add Amazon Bedrock as inference provider #963
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 4 commits
6a47995
a7845c9
d5826d6
0efd1ef
5b47b98
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -47,6 +47,7 @@ const BUILD_ENDPOINT_URL = "https://integrate.api.nvidia.com/v1"; | |||||||||
| const OPENAI_ENDPOINT_URL = "https://api.openai.com/v1"; | ||||||||||
| const ANTHROPIC_ENDPOINT_URL = "https://api.anthropic.com"; | ||||||||||
| const GEMINI_ENDPOINT_URL = "https://generativelanguage.googleapis.com/v1beta/openai/"; | ||||||||||
| const BEDROCK_ENDPOINT_URL = `https://bedrock-mantle.${process.env.BEDROCK_REGION || process.env.AWS_REGION || ""}.api.aws/v1`; | ||||||||||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
|
||||||||||
| const REMOTE_PROVIDER_CONFIG = { | ||||||||||
| build: { | ||||||||||
|
|
@@ -112,6 +113,17 @@ const REMOTE_PROVIDER_CONFIG = { | |||||||||
| defaultModel: "", | ||||||||||
| skipVerify: true, | ||||||||||
| }, | ||||||||||
| bedrock: { | ||||||||||
| label: "Amazon Bedrock (OpenAI-compatible endpoint)", | ||||||||||
| providerName: "bedrock", | ||||||||||
| providerType: "openai", | ||||||||||
| credentialEnv: "BEDROCK_API_KEY", | ||||||||||
| endpointUrl: BEDROCK_ENDPOINT_URL, | ||||||||||
| helpUrl: "https://docs.aws.amazon.com/bedrock/latest/userguide/api-keys-generate.html", | ||||||||||
| modelMode: "curated", | ||||||||||
| defaultModel: "nvidia.nemotron-super-3-120b", | ||||||||||
| skipVerify: true, | ||||||||||
| }, | ||||||||||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
| }; | ||||||||||
|
|
||||||||||
| const REMOTE_MODEL_OPTIONS = { | ||||||||||
|
|
@@ -134,6 +146,15 @@ const REMOTE_MODEL_OPTIONS = { | |||||||||
| "gemini-2.5-flash", | ||||||||||
| "gemini-2.5-flash-lite", | ||||||||||
| ], | ||||||||||
| bedrock: [ | ||||||||||
| "nvidia.nemotron-nano-3-30b", | ||||||||||
| "nvidia.nemotron-super-3-120b", | ||||||||||
| "deepseek.v3.2", | ||||||||||
| "openai.gpt-oss-120b", | ||||||||||
| "mistral.devstral-2-123b", | ||||||||||
| "moonshotai.kimi-k2.5", | ||||||||||
| "minimax.minimax-m2.5", | ||||||||||
| ], | ||||||||||
| }; | ||||||||||
|
|
||||||||||
| // Non-interactive mode: set by --non-interactive flag or env var. | ||||||||||
|
|
@@ -478,6 +499,7 @@ function getSandboxInferenceConfig(model, provider = null, preferredInferenceApi | |||||||||
| supportsStore: false, | ||||||||||
| }; | ||||||||||
| break; | ||||||||||
| case "bedrock": | ||||||||||
| case "compatible-endpoint": | ||||||||||
| providerKey = "inference"; | ||||||||||
| primaryModelRef = `inference/${model}`; | ||||||||||
|
|
@@ -1193,10 +1215,10 @@ function getNonInteractiveProvider() { | |||||||||
| anthropiccompatible: "anthropicCompatible", | ||||||||||
| }; | ||||||||||
| const normalized = aliases[providerKey] || providerKey; | ||||||||||
| const validProviders = new Set(["build", "openai", "anthropic", "anthropicCompatible", "gemini", "ollama", "custom", "nim-local", "vllm"]); | ||||||||||
| const validProviders = new Set(["build", "openai", "anthropic", "anthropicCompatible", "gemini", "ollama", "custom", "nim-local", "vllm", "bedrock"]); | ||||||||||
| if (!validProviders.has(normalized)) { | ||||||||||
| console.error(` Unsupported NEMOCLAW_PROVIDER: ${providerKey}`); | ||||||||||
| console.error(" Valid values: build, openai, anthropic, anthropicCompatible, gemini, ollama, custom, nim-local, vllm"); | ||||||||||
| console.error(" Valid values: build, openai, anthropic, anthropicCompatible, gemini, ollama, custom, nim-local, vllm, bedrock"); | ||||||||||
| process.exit(1); | ||||||||||
| } | ||||||||||
|
|
||||||||||
|
|
@@ -1626,6 +1648,7 @@ async function setupNim(gpu) { | |||||||||
| (ollamaRunning ? " (suggested)" : ""), | ||||||||||
| }); | ||||||||||
| } | ||||||||||
| options.push({ key: "bedrock", label: "Amazon Bedrock (OpenAI-compatible endpoint)" }); | ||||||||||
| if (EXPERIMENTAL && gpu && gpu.nimCapable) { | ||||||||||
| options.push({ key: "nim-local", label: "Local NVIDIA NIM [experimental]" }); | ||||||||||
| } | ||||||||||
|
|
@@ -1723,7 +1746,7 @@ async function setupNim(gpu) { | |||||||||
| } | ||||||||||
| const defaultModel = requestedModel || remoteConfig.defaultModel; | ||||||||||
| let modelValidator = null; | ||||||||||
| if (selected.key === "openai" || selected.key === "gemini") { | ||||||||||
| if (selected.key === "openai" || selected.key === "gemini" || selected.key === "bedrock") { | ||||||||||
| modelValidator = (candidate) => | ||||||||||
| validateOpenAiLikeModel(remoteConfig.label, endpointUrl, candidate, getCredential(credentialEnv)); | ||||||||||
| } else if (selected.key === "anthropic") { | ||||||||||
|
|
@@ -1753,6 +1776,28 @@ async function setupNim(gpu) { | |||||||||
| if (validation.retry === "selection") { | ||||||||||
| continue selectionLoop; | ||||||||||
| } | ||||||||||
| } else if (selected.key === "bedrock") { | ||||||||||
| // Bedrock API keys are region-bound — require an explicit region. | ||||||||||
| if (!process.env.BEDROCK_REGION && !process.env.AWS_REGION) { | ||||||||||
| console.error(" BEDROCK_REGION or AWS_REGION must be set for Amazon Bedrock."); | ||||||||||
| if (isNonInteractive()) { | ||||||||||
| process.exit(1); | ||||||||||
| } | ||||||||||
| continue selectionLoop; | ||||||||||
| } | ||||||||||
| // Bedrock Mantle exposes an OpenAI-compatible API | ||||||||||
| const retryMessage = "Please choose a provider/model again."; | ||||||||||
| preferredInferenceApi = await validateOpenAiLikeSelection( | ||||||||||
| remoteConfig.label, | ||||||||||
| endpointUrl, | ||||||||||
| model, | ||||||||||
| credentialEnv, | ||||||||||
| retryMessage | ||||||||||
| ); | ||||||||||
| if (preferredInferenceApi) { | ||||||||||
| break; | ||||||||||
| } | ||||||||||
| continue selectionLoop; | ||||||||||
|
Comment on lines
+1791
to
+1804
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fresh non-interactive Bedrock runs will probe without the env-supplied key. Line 1740 accepts 💡 One way to keep env-only CI runs working+function resolveCredentialValue(envName) {
+ return envName ? (process.env[envName] || getCredential(envName) || "") : "";
+}
+
async function validateOpenAiLikeSelection(
label,
endpointUrl,
model,
credentialEnv = null,
retryMessage = "Please choose a provider/model again."
) {
- const apiKey = credentialEnv ? getCredential(credentialEnv) : "";
+ const apiKey = resolveCredentialValue(credentialEnv);
const probe = probeOpenAiLikeEndpoint(endpointUrl, model, apiKey);🤖 Prompt for AI Agents
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainLet me verify by checking the 🏁 Script executed: Length of output: 148 🏁 Script executed: Length of output: 6749
function getCredential(key) {
if (process.env[key]) return process.env[key]; // ← env-first
const creds = loadCredentials();
return creds[key] || null;
}It checks
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you made another review then
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: Length of output: 6160
🔴 1.
|
||||||||||
| Location | Value |
|---|---|
REMOTE_PROVIDER_CONFIG.bedrock.credentialEnv (Line 120, onboard.js) |
"BEDROCK_API_KEY" |
inference-config.js case "bedrock": (Line 117) |
"OPENAI_API_KEY" |
| PR description usage example | export OPENAI_API_KEY=<bedrock-api-key> |
During onboarding, the wizard checks/stores BEDROCK_API_KEY. Inside the sandbox, the config references OPENAI_API_KEY. A user following the PR docs (export OPENAI_API_KEY=...) will hit the onboarding credential prompt because BEDROCK_API_KEY is unset — and vice versa in CI. Pick one env var name and use it consistently in all three places.
🟡 3. printDashboard has no label for "bedrock" — shows raw provider name
Lines 6–13 of printDashboard map each known providerName to a human-readable string, but "bedrock" is absent, so the dashboard line reads Model nvidia.nemotron-super-3-120b (bedrock) instead of something like Amazon Bedrock. One-liner fix:
else if (provider === "ollama-local") providerLabel = "Local Ollama";
+ else if (provider === "bedrock") providerLabel = "Amazon Bedrock";
Uh oh!
There was an error while loading. Please reload this page.