mirror of
https://github.com/enricoros/big-AGI.git
synced 2026-05-10 21:50:14 -07:00
AIX/LLMs: Bedrock: support Bedrock Long-term API Keys
This commit is contained in:
@@ -29,6 +29,7 @@ AZURE_OPENAI_API_ENDPOINT=
|
||||
AZURE_OPENAI_API_KEY=
|
||||
ANTHROPIC_API_KEY=
|
||||
ANTHROPIC_API_HOST=
|
||||
BEDROCK_BEARER_TOKEN=
|
||||
BEDROCK_ACCESS_KEY_ID=
|
||||
BEDROCK_SECRET_ACCESS_KEY=
|
||||
BEDROCK_SESSION_TOKEN=
|
||||
@@ -105,6 +106,7 @@ requiring the user to enter an API key
|
||||
| `AZURE_DEPLOYMENTS_API_VERSION` | API version for the deployments listing endpoint | Optional, defaults to '2023-03-15-preview' |
|
||||
| `ANTHROPIC_API_KEY` | The API key for Anthropic | Optional |
|
||||
| `ANTHROPIC_API_HOST` | Changes the backend host for the Anthropic vendor, for proxies or custom endpoints | Optional |
|
||||
| `BEDROCK_BEARER_TOKEN` | Bedrock long-term API key (`ABSK...`). Takes priority over IAM credentials. Short-term keys only work for runtime, not model listing | Optional |
|
||||
| `BEDROCK_ACCESS_KEY_ID` | AWS IAM Access Key ID for Bedrock (Claude models via AWS) | Optional, but if set `BEDROCK_SECRET_ACCESS_KEY` must also be set |
|
||||
| `BEDROCK_SECRET_ACCESS_KEY` | AWS IAM Secret Access Key for Bedrock | Optional, but if set `BEDROCK_ACCESS_KEY_ID` must also be set |
|
||||
| `BEDROCK_SESSION_TOKEN` | AWS Session Token for temporary/STS credentials | Optional |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ANTHROPIC_API_PATHS, anthropicAccess, anthropicBetaFeatures, AnthropicHeaderOptions } from '~/modules/llms/server/anthropic/anthropic.access';
|
||||
import { OPENAI_API_PATHS, openAIAccess } from '~/modules/llms/server/openai/openai.access';
|
||||
import { bedrockAccessAsync, bedrockServerConfig, bedrockURLRuntime } from '~/modules/llms/server/bedrock/bedrock.access';
|
||||
import { bedrockAccessAsync, bedrockResolveRegion, bedrockURLRuntime } from '~/modules/llms/server/bedrock/bedrock.access';
|
||||
import { geminiAccess } from '~/modules/llms/server/gemini/gemini.access';
|
||||
import { ollamaAccess } from '~/modules/llms/server/ollama/ollama.access';
|
||||
|
||||
@@ -90,7 +90,7 @@ export async function createChatGenerateDispatch(access: AixAPI_Access, model: A
|
||||
if (invokeAPI === 'converse')
|
||||
throw new Error('[Bedrock] Converse API is not yet implemented. Use Anthropic models with the InvokeModel API (invoke-anthropic).');
|
||||
|
||||
const region = bedrockServerConfig(access).region;
|
||||
const region = bedrockResolveRegion(access);
|
||||
const url = bedrockURLRuntime(region, model.id, streaming);
|
||||
|
||||
// body
|
||||
|
||||
@@ -51,7 +51,7 @@ export const backendRouter = createTRPCRouter({
|
||||
hasLlmAlibaba: !!env.ALIBABA_API_KEY || !!env.ALIBABA_API_HOST,
|
||||
hasLlmAnthropic: !!env.ANTHROPIC_API_KEY,
|
||||
hasLlmAzureOpenAI: !!env.AZURE_OPENAI_API_KEY && !!env.AZURE_OPENAI_API_ENDPOINT,
|
||||
hasLlmBedrock: !!env.BEDROCK_ACCESS_KEY_ID && !!env.BEDROCK_SECRET_ACCESS_KEY,
|
||||
hasLlmBedrock: !!env.BEDROCK_BEARER_TOKEN || (!!env.BEDROCK_ACCESS_KEY_ID && !!env.BEDROCK_SECRET_ACCESS_KEY),
|
||||
hasLlmDeepseek: !!env.DEEPSEEK_API_KEY,
|
||||
hasLlmGemini: !!env.GEMINI_API_KEY,
|
||||
hasLlmGroq: !!env.GROQ_API_KEY,
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
/**
|
||||
* Isomorphic AWS Bedrock API access - SigV4 signing via aws4fetch.
|
||||
* Isomorphic AWS Bedrock API access - SigV4 signing via aws4fetch + Bearer token auth.
|
||||
*
|
||||
* This module provides the access schema and signing logic for AWS Bedrock API calls.
|
||||
* It supports both the `bedrock` control plane (model listing) and `bedrock-runtime`
|
||||
* data plane (model invocation).
|
||||
*
|
||||
* Authentication uses explicit AWS credentials only (no credential chain) for
|
||||
* Edge Runtime compatibility. aws4fetch auto-detects service and region from URLs.
|
||||
* Two authentication modes:
|
||||
* - **Bearer token**: Simple `Authorization: Bearer <token>` header (AWS Bedrock API keys).
|
||||
* Long-term keys (`ABSK...`) support both control plane and runtime.
|
||||
* UNSUPPORTED: Short-term keys (`bedrock-api-key-...`) only support runtime (not model listing).
|
||||
* - **SigV4**: Traditional IAM credentials signing via aws4fetch
|
||||
*
|
||||
* Priority: client bearer > client IAM > server bearer > server IAM.
|
||||
* SigV4 uses explicit AWS credentials only (no credential chain) for Edge Runtime compatibility.
|
||||
*/
|
||||
|
||||
import * as z from 'zod/v4';
|
||||
@@ -17,11 +23,16 @@ import { AwsClient } from 'aws4fetch';
|
||||
import { env } from '~/server/env.server';
|
||||
|
||||
|
||||
// configuration
|
||||
const DEFAULT_BEDROCK_REGION = 'us-east-1'; // default region for Bedrock, used if not provided by client or env
|
||||
|
||||
|
||||
// --- Schema ---
|
||||
|
||||
export type BedrockAccessSchema = z.infer<typeof bedrockAccessSchema>;
|
||||
export const bedrockAccessSchema = z.object({
|
||||
dialect: z.literal('bedrock'),
|
||||
bedrockBearerToken: z.string().trim(),
|
||||
bedrockAccessKeyId: z.string().trim(),
|
||||
bedrockSecretAccessKey: z.string().trim(),
|
||||
bedrockSessionToken: z.string().trim().nullable(),
|
||||
@@ -30,26 +41,41 @@ export const bedrockAccessSchema = z.object({
|
||||
});
|
||||
|
||||
|
||||
// --- Credential & Region Resolution ---
|
||||
// --- Auth Resolution ---
|
||||
|
||||
/**
|
||||
* Resolve all Bedrock access config: credentials (all-or-none) + region.
|
||||
* If the user provides an access key, all credentials come from user; otherwise all from env.
|
||||
*/
|
||||
export function bedrockServerConfig(access: BedrockAccessSchema) {
|
||||
const userProvided = !!access.bedrockAccessKeyId;
|
||||
const accessKeyId = userProvided ? access.bedrockAccessKeyId : (env.BEDROCK_ACCESS_KEY_ID || '');
|
||||
const secretAccessKey = userProvided ? access.bedrockSecretAccessKey : (env.BEDROCK_SECRET_ACCESS_KEY || '');
|
||||
const sessionToken = (userProvided ? access.bedrockSessionToken : env.BEDROCK_SESSION_TOKEN) || undefined;
|
||||
const region = (userProvided ? access.bedrockRegion : env.BEDROCK_REGION) || 'us-east-1';
|
||||
type BedrockAuthBearer = { type: 'bearer'; bearerToken: string; region: string };
|
||||
type BedrockAuthSigV4 = { type: 'sigv4'; accessKeyId: string; secretAccessKey: string; sessionToken: string | undefined; region: string };
|
||||
|
||||
if (!accessKeyId || !secretAccessKey)
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'Missing AWS credentials. Add your Access Key ID and Secret Access Key on the UI (Models Setup) or server side (your deployment).',
|
||||
});
|
||||
/** Resolve Bedrock authentication. */
|
||||
function _bedrockResolveAuth(access: BedrockAccessSchema): BedrockAuthBearer | BedrockAuthSigV4 {
|
||||
|
||||
return { accessKeyId, secretAccessKey, sessionToken, region };
|
||||
// 1. Client bearer token (highest priority)
|
||||
let region = access.bedrockRegion || DEFAULT_BEDROCK_REGION; // client-provided region
|
||||
if (access.bedrockBearerToken)
|
||||
return { type: 'bearer', bearerToken: access.bedrockBearerToken, region };
|
||||
|
||||
// 2. Client IAM credentials
|
||||
if (access.bedrockAccessKeyId && access.bedrockSecretAccessKey)
|
||||
return { type: 'sigv4', accessKeyId: access.bedrockAccessKeyId, secretAccessKey: access.bedrockSecretAccessKey, sessionToken: access.bedrockSessionToken || undefined, region };
|
||||
|
||||
// 3. Server bearer token
|
||||
region = env.BEDROCK_REGION || DEFAULT_BEDROCK_REGION; // server-provided region (ignores client for security reasons)
|
||||
if (env.BEDROCK_BEARER_TOKEN)
|
||||
return { type: 'bearer', bearerToken: env.BEDROCK_BEARER_TOKEN, region };
|
||||
|
||||
// 4. Server IAM credentials
|
||||
if (env.BEDROCK_ACCESS_KEY_ID && env.BEDROCK_SECRET_ACCESS_KEY)
|
||||
return { type: 'sigv4', accessKeyId: env.BEDROCK_ACCESS_KEY_ID, secretAccessKey: env.BEDROCK_SECRET_ACCESS_KEY, sessionToken: env.BEDROCK_SESSION_TOKEN || undefined, region };
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'Missing AWS credentials. Add your Bedrock API Key or IAM Access Key on the UI (Models Setup) or server side (your deployment).',
|
||||
});
|
||||
}
|
||||
|
||||
/** Resolve the Bedrock region from access config. */
|
||||
export function bedrockResolveRegion(access: BedrockAccessSchema): string {
|
||||
return _bedrockResolveAuth(access).region;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,11 +91,11 @@ export function bedrockURLControlPlane(region: string, path: string): string {
|
||||
}
|
||||
|
||||
|
||||
// --- Bedrock Access (async SigV4) ---
|
||||
// --- Bedrock Access (Bearer or async SigV4) ---
|
||||
|
||||
/**
|
||||
* Signs a request for AWS Bedrock using SigV4 via aws4fetch.
|
||||
* Returns { headers, url } like anthropicAccess/geminiAccess, but async due to SigV4 signing.
|
||||
* Prepares a request for AWS Bedrock using either Bearer token or SigV4 signing.
|
||||
* Returns { headers, url } like anthropicAccess/geminiAccess, but async due to potential SigV4 signing.
|
||||
*/
|
||||
export async function bedrockAccessAsync(
|
||||
access: BedrockAccessSchema,
|
||||
@@ -78,14 +104,27 @@ export async function bedrockAccessAsync(
|
||||
body?: object,
|
||||
): Promise<{ headers: HeadersInit; url: string }> {
|
||||
|
||||
const { accessKeyId, secretAccessKey, sessionToken, region } = bedrockServerConfig(access);
|
||||
const auth = _bedrockResolveAuth(access);
|
||||
|
||||
// -- Bearer token: simple Authorization header --
|
||||
if (auth.type === 'bearer')
|
||||
return {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${auth.bearerToken}`,
|
||||
'Accept': 'application/json',
|
||||
...(method === 'POST' ? { 'Content-Type': 'application/json' } : {}),
|
||||
},
|
||||
url,
|
||||
};
|
||||
|
||||
|
||||
// -- SigV4: sign with aws4fetch --
|
||||
const awsClient = new AwsClient({
|
||||
service: 'bedrock', // Bedrock uses 'bedrock' as the SigV4 service name for both control plane and runtime
|
||||
accessKeyId,
|
||||
secretAccessKey,
|
||||
sessionToken,
|
||||
region,
|
||||
accessKeyId: auth.accessKeyId,
|
||||
secretAccessKey: auth.secretAccessKey,
|
||||
sessionToken: auth.sessionToken,
|
||||
region: auth.region,
|
||||
});
|
||||
|
||||
// sign the request - uses SubtleCrypto
|
||||
|
||||
@@ -16,7 +16,7 @@ import { anthropicInjectVariants, anthropicValidateModelDefs_DEV, AnthropicWire_
|
||||
import { ANTHROPIC_API_PATHS, anthropicAccess } from './anthropic/anthropic.access';
|
||||
|
||||
// protocol: Bedrock
|
||||
import { bedrockAccessAsync, bedrockURLControlPlane, bedrockServerConfig } from './bedrock/bedrock.access';
|
||||
import { bedrockAccessAsync, bedrockResolveRegion, bedrockURLControlPlane } from './bedrock/bedrock.access';
|
||||
import { bedrockModelsToDescriptions, BedrockWire_API_Models_List } from './bedrock/bedrock.models';
|
||||
|
||||
// protocol: Gemini
|
||||
@@ -169,7 +169,7 @@ function _listModelsCreateDispatch(access: AixAPI_Access, signal?: AbortSignal):
|
||||
fetchModels: async () => {
|
||||
|
||||
// construct URLs by region
|
||||
const { region } = bedrockServerConfig(access);
|
||||
const region = bedrockResolveRegion(access);
|
||||
const fmUrl = bedrockURLControlPlane(region, '/foundation-models?byInferenceType=ON_DEMAND');
|
||||
const ipUrl = bedrockURLControlPlane(region, '/inference-profiles?typeEquals=SYSTEM_DEFINED&maxResults=1000');
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { Autocomplete, AutocompleteOption, Box, FormControl, FormHelperText, FormLabel, Typography } from '@mui/joy';
|
||||
|
||||
import { Link } from '~/common/components/Link';
|
||||
import { Autocomplete, AutocompleteOption, Box, FormControl, FormLabel, Typography } from '@mui/joy';
|
||||
|
||||
|
||||
interface BedrockRegion {
|
||||
@@ -76,11 +74,11 @@ export function BedrockRegionAutocomplete(props: {
|
||||
<FormControl>
|
||||
<Box sx={{ display: 'flex', flexDirection: 'row', alignItems: 'baseline', justifyContent: 'space-between' }}>
|
||||
<FormLabel>
|
||||
AWS Region
|
||||
AWS Models Region
|
||||
</FormLabel>
|
||||
<FormHelperText sx={{ display: 'block' }}>
|
||||
see <Link level='body-sm' href='https://docs.aws.amazon.com/bedrock/latest/userguide/models-regions.html' target='_blank'>regions</Link>
|
||||
</FormHelperText>
|
||||
{/*<FormHelperText sx={{ display: 'block' }}>*/}
|
||||
{/* see <Link level='body-sm' href='https://docs.aws.amazon.com/bedrock/latest/userguide/models-regions.html' target='_blank'>regions</Link>*/}
|
||||
{/*</FormHelperText>*/}
|
||||
</Box>
|
||||
<Autocomplete<BedrockRegion, false, false, true>
|
||||
freeSolo
|
||||
|
||||
+83
-32
@@ -1,10 +1,10 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import { Box, IconButton, Typography } from '@mui/joy';
|
||||
import UnfoldLessIcon from '@mui/icons-material/UnfoldLess';
|
||||
import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore';
|
||||
import { Box, Divider, IconButton, Typography } from '@mui/joy';
|
||||
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
|
||||
|
||||
import type { DModelsServiceId } from '~/common/stores/llms/llms.service.types';
|
||||
import { AlreadySet } from '~/common/components/AlreadySet';
|
||||
import { ClaudeCrabIcon } from '~/common/components/icons/vendors/ClaudeCrabIcon';
|
||||
import { FormInputKey } from '~/common/components/forms/FormInputKey';
|
||||
import { InlineError } from '~/common/components/InlineError';
|
||||
@@ -16,7 +16,21 @@ import { useLlmUpdateModels } from '../../llm.client.hooks';
|
||||
import { useServiceSetup } from '../useServiceSetup';
|
||||
|
||||
import { BedrockRegionAutocomplete } from './BedrockRegionAutocomplete';
|
||||
import { isValidBedrockAccessKeyId, isValidBedrockSecretAccessKey, ModelVendorBedrock } from './bedrock.vendor';
|
||||
import { isValidBedrockAccessKeyId, isValidBedrockBearerToken, isValidBedrockSecretAccessKey, ModelVendorBedrock } from './bedrock.vendor';
|
||||
|
||||
|
||||
const _styles = {
|
||||
iamGrid: {
|
||||
display: 'grid',
|
||||
gridTemplateColumns: { xs: '1fr', md: '1fr 1fr' },
|
||||
gap: 'var(--Card-padding, 1rem)',
|
||||
},
|
||||
iamSectionDimmed: {
|
||||
opacity: 0.5,
|
||||
pointerEvents: 'none',
|
||||
transition: 'opacity 0.2s',
|
||||
},
|
||||
} as const;
|
||||
|
||||
|
||||
export function BedrockServiceSetup(props: { serviceId: DModelsServiceId }) {
|
||||
@@ -26,18 +40,33 @@ export function BedrockServiceSetup(props: { serviceId: DModelsServiceId }) {
|
||||
useServiceSetup(props.serviceId, ModelVendorBedrock);
|
||||
|
||||
// derived state
|
||||
const { bedrockAccessKeyId, bedrockSecretAccessKey, bedrockSessionToken, bedrockRegion } = serviceAccess;
|
||||
const { bedrockAccessKeyId, bedrockSecretAccessKey, bedrockBearerToken, bedrockRegion } = serviceAccess;
|
||||
const needsUserKey = !serviceHasCloudTenantConfig;
|
||||
|
||||
// advanced mode
|
||||
// const advanced = useToggleableBoolean(!!bedrockSessionToken);
|
||||
const [showSetupInstructions, setShowSetupInstructions] = React.useState(false);
|
||||
|
||||
// Bearer validation
|
||||
const bearerTokenValid = isValidBedrockBearerToken(bedrockBearerToken);
|
||||
const bearerTokenError = !!bedrockBearerToken && !bearerTokenValid;
|
||||
|
||||
// IAM validation
|
||||
const accessKeyValid = isValidBedrockAccessKeyId(bedrockAccessKeyId);
|
||||
const secretKeyValid = isValidBedrockSecretAccessKey(bedrockSecretAccessKey);
|
||||
const accessKeyError = (!!bedrockAccessKeyId) && !accessKeyValid;
|
||||
const secretKeyError = (!!bedrockSecretAccessKey) && !secretKeyValid;
|
||||
const shallFetchSucceed = bedrockAccessKeyId ? (accessKeyValid && secretKeyValid) : !needsUserKey;
|
||||
const accessKeyError = !!bedrockAccessKeyId && !accessKeyValid;
|
||||
const secretKeyError = !!bedrockSecretAccessKey && !secretKeyValid;
|
||||
|
||||
// bearer token takes implicit priority - dim IAM when bearer is active
|
||||
const hasBearer = !!bedrockBearerToken;
|
||||
// const hasIAM = !!bedrockAccessKeyId || !!bedrockSecretAccessKey;
|
||||
|
||||
|
||||
// fetch: succeed if valid client credentials exist, or server-configured
|
||||
const shallFetchSucceed =
|
||||
bedrockBearerToken ? bearerTokenValid
|
||||
: bedrockAccessKeyId ? (accessKeyValid && secretKeyValid)
|
||||
: !needsUserKey;
|
||||
|
||||
// fetch models
|
||||
const { isFetching, refetch, isError, error } =
|
||||
@@ -49,40 +78,63 @@ export function BedrockServiceSetup(props: { serviceId: DModelsServiceId }) {
|
||||
<Box sx={{ display: 'flex', gap: 2, alignItems: 'flex-start' }}>
|
||||
<ClaudeCrabIcon sx={{ fontSize: '2rem', mt: 0.5 }} />
|
||||
<Box sx={{ flex: 1 }}>
|
||||
Access Claude models through your <Link color='neutral' href='https://aws.amazon.com/bedrock/' level='body-sm' target='_blank'>AWS Bedrock</Link> account.
|
||||
Requires an IAM Access Key with Bedrock permissions - Bedrock does not support search.
|
||||
Access Claude models through your <Link color='neutral' href='https://aws.amazon.com/bedrock/' level='body-sm' target='_blank'>AWS Bedrock</Link> account
|
||||
using a long-term <strong>API Key</strong> or <strong>IAM credentials</strong>.
|
||||
{showSetupInstructions && (
|
||||
<Typography level='body-xs' component='ol' sx={{ pl: 2, mt: 1, display: 'flex', flexDirection: 'column', gap: 0.5 }}>
|
||||
<li>Open the <Link href='https://console.aws.amazon.com/iam/' target='_blank'>AWS IAM Console</Link></li>
|
||||
<li>Go to <strong>Users</strong> -> <strong>Create user</strong> (e.g. <code>big-agi-bedrock</code>, no console access)</li>
|
||||
<li>Attach the <strong>AmazonBedrockFullAccess</strong> policy</li>
|
||||
<li>Open the user -> <strong>Security credentials</strong> -> <strong>Create access key</strong></li>
|
||||
<li>Select <strong>"Application running outside AWS"</strong> -> Create</li>
|
||||
<li>Copy the <strong>Access Key ID</strong> and <strong>Secret Access Key</strong> (shown only once)</li>
|
||||
<li>Enter them below with your <strong>AWS Region</strong></li>
|
||||
<li><strong>API Key</strong>: in the <Link href='https://console.aws.amazon.com/bedrock/' target='_blank'>Bedrock Console</Link>, create a long-term key (<code>ABSK...</code>). Short-term keys don't support model listing</li>
|
||||
<li><strong>AWS IAM</strong>: in the <Link href='https://console.aws.amazon.com/iam/' target='_blank'>IAM Console</Link>, create a user with the <strong>AmazonBedrockFullAccess</strong> permission policy. Open the user, go to <strong>Security credentials</strong>, then <strong>Create access key</strong> (<strong>"Application running outside AWS"</strong>) and copy both keys</li>
|
||||
<li>Select your <strong>AWS Models Region</strong> below</li>
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
<IconButton size='sm' variant='plain' color='neutral' onClick={() => setShowSetupInstructions(on => !on)}>
|
||||
{showSetupInstructions ? <UnfoldLessIcon /> : <UnfoldMoreIcon />}
|
||||
<IconButton size='sm' variant={showSetupInstructions ? 'solid' : 'soft'} color='neutral' onClick={() => setShowSetupInstructions(on => !on)}>
|
||||
<InfoOutlinedIcon />
|
||||
</IconButton>
|
||||
</Box>
|
||||
</ApproximateCosts>
|
||||
|
||||
|
||||
{/* Bearer token (API Key) - highest client-side priority */}
|
||||
<FormInputKey
|
||||
autoCompleteId='bedrock-access-key-id' label='AWS Access Key ID'
|
||||
rightLabel={!needsUserKey ? 'Set on server' : undefined}
|
||||
value={bedrockAccessKeyId} onChange={value => updateSettings({ bedrockAccessKeyId: value })}
|
||||
required={needsUserKey} isError={accessKeyError}
|
||||
placeholder='AKIA...'
|
||||
autoCompleteId='bedrock-bearer-token' label='Bedrock long-term API Key'
|
||||
rightLabel={<>{needsUserKey
|
||||
? undefined
|
||||
: <AlreadySet />
|
||||
}</>}
|
||||
value={bedrockBearerToken} onChange={value => updateSettings({ bedrockBearerToken: value })}
|
||||
required={false} // required={needsUserKey && !hasIAM}
|
||||
isError={bearerTokenError}
|
||||
placeholder='ABSK...'
|
||||
/>
|
||||
|
||||
<FormInputKey
|
||||
autoCompleteId='bedrock-secret-access-key' label='AWS Secret Access Key'
|
||||
value={bedrockSecretAccessKey} onChange={value => updateSettings({ bedrockSecretAccessKey: value })}
|
||||
required={needsUserKey} isError={secretKeyError}
|
||||
placeholder='wJalr...'
|
||||
/>
|
||||
<Divider>or</Divider>
|
||||
|
||||
{/* IAM credentials - side by side on md+, stacked on mobile, dimmed when bearer is active */}
|
||||
<Box sx={hasBearer ? _styles.iamSectionDimmed : undefined}>
|
||||
<Box sx={_styles.iamGrid}>
|
||||
<FormInputKey
|
||||
autoCompleteId='bedrock-access-key-id' label='AWS Access Key ID'
|
||||
rightLabel={<>{needsUserKey
|
||||
? undefined
|
||||
: <AlreadySet />
|
||||
}</>}
|
||||
value={bedrockAccessKeyId} onChange={value => updateSettings({ bedrockAccessKeyId: value })}
|
||||
required={false} // required={needsUserKey && !hasBearer}
|
||||
isError={accessKeyError}
|
||||
placeholder='AKIA...'
|
||||
/>
|
||||
|
||||
<FormInputKey
|
||||
autoCompleteId='bedrock-secret-access-key' label='AWS Secret Access Key'
|
||||
value={bedrockSecretAccessKey} onChange={value => updateSettings({ bedrockSecretAccessKey: value })}
|
||||
required={false} // required={needsUserKey && !hasBearer}
|
||||
isError={secretKeyError}
|
||||
placeholder='wJalr...'
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
|
||||
<BedrockRegionAutocomplete
|
||||
value={bedrockRegion || ''}
|
||||
@@ -99,8 +151,7 @@ export function BedrockServiceSetup(props: { serviceId: DModelsServiceId }) {
|
||||
{/* onChange={text => updateSettings({ bedrockSessionToken: text })}*/}
|
||||
{/*/>}*/}
|
||||
|
||||
<SetupFormRefetchButton refetch={refetch} disabled={!shallFetchSucceed || isFetching} loading={isFetching} error={isError} />
|
||||
{/*<SetupFormRefetchButton refetch={refetch} disabled={!shallFetchSucceed || isFetching} loading={isFetching} error={isError} advanced={advanced} />*/}
|
||||
<SetupFormRefetchButton refetch={refetch} disabled={!shallFetchSucceed || isFetching} loading={isFetching} error={isError} /*advanced={advanced}*/ />
|
||||
|
||||
{isError && <InlineError error={error} />}
|
||||
|
||||
|
||||
+16
-4
@@ -5,10 +5,12 @@ import type { IModelVendor } from '../IModelVendor';
|
||||
|
||||
|
||||
// validation
|
||||
export const isValidBedrockBearerToken = (key?: string) => !!key && key.length >= 20;
|
||||
export const isValidBedrockAccessKeyId = (key?: string) => !!key && key.length >= 16;
|
||||
export const isValidBedrockSecretAccessKey = (key?: string) => !!key && key.length >= 16;
|
||||
|
||||
export interface DBedrockServiceSettings {
|
||||
bedrockBearerToken: string;
|
||||
bedrockAccessKeyId: string;
|
||||
bedrockSecretAccessKey: string;
|
||||
bedrockSessionToken: string;
|
||||
@@ -31,6 +33,7 @@ export const ModelVendorBedrock: IModelVendor<DBedrockServiceSettings, BedrockAc
|
||||
|
||||
// functions
|
||||
initializeSetup: () => ({
|
||||
bedrockBearerToken: '',
|
||||
bedrockAccessKeyId: '',
|
||||
bedrockSecretAccessKey: '',
|
||||
bedrockSessionToken: '',
|
||||
@@ -40,9 +43,18 @@ export const ModelVendorBedrock: IModelVendor<DBedrockServiceSettings, BedrockAc
|
||||
|
||||
getTransportAccess: (partialSetup): BedrockAccessSchema => ({
|
||||
dialect: 'bedrock',
|
||||
bedrockAccessKeyId: partialSetup?.bedrockAccessKeyId || '',
|
||||
bedrockSecretAccessKey: partialSetup?.bedrockSecretAccessKey || '',
|
||||
bedrockSessionToken: partialSetup?.bedrockSessionToken || null,
|
||||
// bearer token takes priority; don't send IAM credentials alongside it
|
||||
...(partialSetup?.bedrockBearerToken ? {
|
||||
bedrockBearerToken: partialSetup.bedrockBearerToken,
|
||||
bedrockAccessKeyId: '',
|
||||
bedrockSecretAccessKey: '',
|
||||
bedrockSessionToken: null,
|
||||
} : {
|
||||
bedrockBearerToken: '',
|
||||
bedrockAccessKeyId: partialSetup?.bedrockAccessKeyId || '',
|
||||
bedrockSecretAccessKey: partialSetup?.bedrockSecretAccessKey || '',
|
||||
bedrockSessionToken: partialSetup?.bedrockSessionToken || null,
|
||||
}),
|
||||
bedrockRegion: partialSetup?.bedrockRegion || 'us-west-2',
|
||||
clientSideFetch: _csfBedrockAvailable(partialSetup) && !!partialSetup?.csf,
|
||||
}),
|
||||
@@ -53,5 +65,5 @@ export const ModelVendorBedrock: IModelVendor<DBedrockServiceSettings, BedrockAc
|
||||
};
|
||||
|
||||
function _csfBedrockAvailable(s?: Partial<DBedrockServiceSettings>) {
|
||||
return !!s?.bedrockAccessKeyId && !!s?.bedrockSecretAccessKey;
|
||||
return !!s?.bedrockBearerToken || (!!s?.bedrockAccessKeyId && !!s?.bedrockSecretAccessKey);
|
||||
}
|
||||
|
||||
@@ -53,7 +53,8 @@ export const env = createEnv({
|
||||
ANTHROPIC_API_KEY: z.string().optional(),
|
||||
ANTHROPIC_API_HOST: z.url().optional(),
|
||||
|
||||
// LLM: AWS Bedrock (using 2 or 3 auth values)
|
||||
// LLM: AWS Bedrock (bearer token OR IAM credentials)
|
||||
BEDROCK_BEARER_TOKEN: z.string().optional(), // Bedrock long-term API key (ABSK...) - takes priority over IAM credentials; short-term keys only work for runtime, not model listing
|
||||
BEDROCK_ACCESS_KEY_ID: z.string().optional(),
|
||||
BEDROCK_SECRET_ACCESS_KEY: z.string().optional(),
|
||||
BEDROCK_SESSION_TOKEN: z.string().optional(), // required with the other 2 on corporate accounts sometimes
|
||||
|
||||
Reference in New Issue
Block a user