@tanstack/ai-bedrock 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +95 -0
- package/dist/esm/adapters/converse-text.d.ts +93 -0
- package/dist/esm/adapters/converse-text.js +430 -0
- package/dist/esm/adapters/converse-text.js.map +1 -0
- package/dist/esm/adapters/responses-text.d.ts +23 -0
- package/dist/esm/adapters/responses-text.js +22 -0
- package/dist/esm/adapters/responses-text.js.map +1 -0
- package/dist/esm/adapters/text.d.ts +30 -0
- package/dist/esm/adapters/text.js +38 -0
- package/dist/esm/adapters/text.js.map +1 -0
- package/dist/esm/converse/message-converter.d.ts +14 -0
- package/dist/esm/converse/message-converter.js +181 -0
- package/dist/esm/converse/message-converter.js.map +1 -0
- package/dist/esm/converse/provider-options.d.ts +19 -0
- package/dist/esm/converse/stream-processor.d.ts +46 -0
- package/dist/esm/converse/stream-processor.js +203 -0
- package/dist/esm/converse/stream-processor.js.map +1 -0
- package/dist/esm/converse/structured-output.d.ts +8 -0
- package/dist/esm/converse/structured-output.js +20 -0
- package/dist/esm/converse/structured-output.js.map +1 -0
- package/dist/esm/converse/tool-converter.d.ts +11 -0
- package/dist/esm/converse/tool-converter.js +21 -0
- package/dist/esm/converse/tool-converter.js.map +1 -0
- package/dist/esm/index.d.ts +29 -0
- package/dist/esm/index.js +62 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/message-types.d.ts +25 -0
- package/dist/esm/model-catalog.generated.d.ts +127 -0
- package/dist/esm/model-catalog.generated.js +90 -0
- package/dist/esm/model-catalog.generated.js.map +1 -0
- package/dist/esm/model-meta.d.ts +38 -0
- package/dist/esm/model-meta.js +14 -0
- package/dist/esm/model-meta.js.map +1 -0
- package/dist/esm/text/responses-provider-options.d.ts +29 -0
- package/dist/esm/text/text-provider-options.d.ts +36 -0
- package/dist/esm/utils/auth.d.ts +20 -0
- package/dist/esm/utils/auth.js +49 -0
- package/dist/esm/utils/auth.js.map +1 -0
- package/dist/esm/utils/client.d.ts +19 -0
- package/dist/esm/utils/client.js +35 -0
- package/dist/esm/utils/client.js.map +1 -0
- package/dist/esm/utils/index.d.ts +1 -0
- package/dist/esm/utils/openai-sigv4-fetch.d.ts +10 -0
- package/dist/esm/utils/openai-sigv4-fetch.js +35 -0
- package/dist/esm/utils/openai-sigv4-fetch.js.map +1 -0
- package/package.json +67 -0
- package/src/adapters/converse-text.ts +603 -0
- package/src/adapters/responses-text.ts +73 -0
- package/src/adapters/text.ts +97 -0
- package/src/converse/message-converter.ts +268 -0
- package/src/converse/provider-options.ts +19 -0
- package/src/converse/stream-processor.ts +309 -0
- package/src/converse/structured-output.ts +24 -0
- package/src/converse/tool-converter.ts +49 -0
- package/src/index.ts +190 -0
- package/src/message-types.ts +24 -0
- package/src/model-catalog.generated.ts +88 -0
- package/src/model-meta.ts +69 -0
- package/src/text/responses-provider-options.ts +28 -0
- package/src/text/text-provider-options.ts +33 -0
- package/src/utils/auth.ts +80 -0
- package/src/utils/client.ts +62 -0
- package/src/utils/index.ts +7 -0
- package/src/utils/openai-sigv4-fetch.ts +55 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ToolConfiguration } from '@aws-sdk/client-bedrock-runtime'
|
|
2
|
+
import type { DocumentType } from '@smithy/types'
|
|
3
|
+
|
|
4
|
+
export const STRUCTURED_TOOL_NAME = 'structured_output'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Converse has no native json_schema response_format. Structured output is
|
|
8
|
+
* achieved by forcing a single tool whose input schema is the requested output
|
|
9
|
+
* schema; the model's tool-use `input` is the structured result.
|
|
10
|
+
*/
|
|
11
|
+
export function buildStructuredToolConfig(schema: unknown): ToolConfiguration {
|
|
12
|
+
return {
|
|
13
|
+
tools: [
|
|
14
|
+
{
|
|
15
|
+
toolSpec: {
|
|
16
|
+
name: STRUCTURED_TOOL_NAME,
|
|
17
|
+
description: 'Return the final answer as structured JSON.',
|
|
18
|
+
inputSchema: { json: schema as DocumentType },
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
toolChoice: { tool: { name: STRUCTURED_TOOL_NAME } },
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ToolChoice,
|
|
3
|
+
ToolConfiguration,
|
|
4
|
+
} from '@aws-sdk/client-bedrock-runtime'
|
|
5
|
+
import type { DocumentType } from '@smithy/types'
|
|
6
|
+
|
|
7
|
+
export interface ConverseToolInput {
|
|
8
|
+
name: string
|
|
9
|
+
description?: string
|
|
10
|
+
inputSchema: unknown
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type ToolChoiceInput =
|
|
14
|
+
| 'auto'
|
|
15
|
+
| 'required'
|
|
16
|
+
| 'none'
|
|
17
|
+
| { type: 'tool'; name: string }
|
|
18
|
+
|
|
19
|
+
export function toToolConfig(
|
|
20
|
+
tools: Array<ConverseToolInput>,
|
|
21
|
+
choice: ToolChoiceInput | undefined,
|
|
22
|
+
): ToolConfiguration | undefined {
|
|
23
|
+
if (!tools.length) return undefined
|
|
24
|
+
// `none` means "don't call tools" — omit the tool config entirely, since
|
|
25
|
+
// Bedrock treats a present tool config with no `toolChoice` as auto.
|
|
26
|
+
if (choice === 'none') return undefined
|
|
27
|
+
const toolChoice = mapChoice(choice)
|
|
28
|
+
return {
|
|
29
|
+
tools: tools.map((t) => ({
|
|
30
|
+
toolSpec: {
|
|
31
|
+
name: t.name,
|
|
32
|
+
...(t.description ? { description: t.description } : {}),
|
|
33
|
+
inputSchema: { json: t.inputSchema as DocumentType },
|
|
34
|
+
},
|
|
35
|
+
})),
|
|
36
|
+
...(toolChoice ? { toolChoice } : {}),
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function mapChoice(
|
|
41
|
+
choice: ToolChoiceInput | undefined,
|
|
42
|
+
): ToolChoice | undefined {
|
|
43
|
+
if (!choice || choice === 'auto') return { auto: {} }
|
|
44
|
+
if (choice === 'required') return { any: {} }
|
|
45
|
+
// `none` is handled earlier in toToolConfig (omits the tool config); this
|
|
46
|
+
// branch keeps the string union narrowed so `choice.name` type-checks.
|
|
47
|
+
if (choice === 'none') return undefined
|
|
48
|
+
return { tool: { name: choice.name } }
|
|
49
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @tanstack/ai-bedrock
|
|
3
|
+
*
|
|
4
|
+
* Amazon Bedrock adapter for TanStack AI via Bedrock's OpenAI-compatible APIs
|
|
5
|
+
* and the native Converse API. The public `bedrockText` / `createBedrockText`
|
|
6
|
+
* factory branches between the Converse adapter (DEFAULT), the Chat Completions
|
|
7
|
+
* adapter (`api: 'chat'`), and the Responses adapter (`api: 'responses'`).
|
|
8
|
+
*/
|
|
9
|
+
import { BedrockTextAdapter } from './adapters/text'
|
|
10
|
+
import { BedrockResponsesTextAdapter } from './adapters/responses-text'
|
|
11
|
+
import { BedrockConverseTextAdapter } from './adapters/converse-text'
|
|
12
|
+
import { BEDROCK_CHAT_MODELS, BEDROCK_RESPONSES_MODELS } from './model-meta'
|
|
13
|
+
import type { BedrockTextConfig } from './adapters/text'
|
|
14
|
+
import type { BedrockResponsesConfig } from './adapters/responses-text'
|
|
15
|
+
import type { BedrockConverseConfig } from './adapters/converse-text'
|
|
16
|
+
import type { BedrockClientConfig } from './utils'
|
|
17
|
+
import type {
|
|
18
|
+
BedrockChatModels,
|
|
19
|
+
BedrockConverseModels,
|
|
20
|
+
BedrockResponsesModels,
|
|
21
|
+
} from './model-meta'
|
|
22
|
+
|
|
23
|
+
/** Config for the branching factory's converse mode (default, or api: 'converse'). */
|
|
24
|
+
export type BedrockConverseApiConfig = BedrockConverseConfig & {
|
|
25
|
+
api?: 'converse'
|
|
26
|
+
}
|
|
27
|
+
/** Config for the branching factory's chat mode (api: 'chat' required). */
|
|
28
|
+
export type BedrockChatApiConfig = BedrockTextConfig & {
|
|
29
|
+
api: 'chat'
|
|
30
|
+
}
|
|
31
|
+
/** Config for the branching factory's responses mode (api: 'responses' required). */
|
|
32
|
+
export type BedrockResponsesApiConfig = BedrockResponsesConfig & {
|
|
33
|
+
api: 'responses'
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
type AnyBedrockAdapter =
|
|
37
|
+
| BedrockConverseTextAdapter<BedrockConverseModels>
|
|
38
|
+
| BedrockTextAdapter<BedrockChatModels>
|
|
39
|
+
| BedrockResponsesTextAdapter<BedrockResponsesModels>
|
|
40
|
+
|
|
41
|
+
/** Cast-free runtime guard: is this model in the Responses-capable subset? */
|
|
42
|
+
function isResponsesModel(model: string): model is BedrockResponsesModels {
|
|
43
|
+
return BEDROCK_RESPONSES_MODELS.some((m) => m === model)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Cast-free runtime guard: is this model in the Chat-capable subset? */
|
|
47
|
+
function isChatModel(model: string): model is BedrockChatModels {
|
|
48
|
+
return BEDROCK_CHAT_MODELS.some((m) => m === model)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Strip the `api` discriminator from a config without an unused-var lint error. */
|
|
52
|
+
function stripApi<T extends { api?: unknown }>(config: T): Omit<T, 'api'> {
|
|
53
|
+
const { api, ...rest } = config
|
|
54
|
+
void api
|
|
55
|
+
return rest
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Shared branching used by both public factories. Constructs the adapter
|
|
60
|
+
* classes directly so their constructors run the full auth cascade lazily
|
|
61
|
+
* (config.apiKey → BEDROCK_API_KEY → AWS_BEARER_TOKEN_BEDROCK → SigV4). No
|
|
62
|
+
* eager env-key fetch here, so `auth: 'sigv4'` never throws for a missing key.
|
|
63
|
+
*
|
|
64
|
+
* Default path → Converse adapter; opt-in via `api: 'chat'` or `api: 'responses'`.
|
|
65
|
+
*/
|
|
66
|
+
function build(
|
|
67
|
+
model: BedrockConverseModels,
|
|
68
|
+
config?: BedrockClientConfig & { api?: 'converse' | 'chat' | 'responses' },
|
|
69
|
+
): AnyBedrockAdapter {
|
|
70
|
+
if (config?.api === 'responses') {
|
|
71
|
+
const rest = stripApi(config)
|
|
72
|
+
if (!isResponsesModel(model)) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
`Model "${model}" is not available on the Bedrock Responses API. ` +
|
|
75
|
+
`Responses-capable models: ${BEDROCK_RESPONSES_MODELS.join(', ')}.`,
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
return new BedrockResponsesTextAdapter(rest, model)
|
|
79
|
+
}
|
|
80
|
+
if (config?.api === 'chat') {
|
|
81
|
+
if (!isChatModel(model)) {
|
|
82
|
+
throw new Error(
|
|
83
|
+
`Model "${model}" is not available on the Bedrock Chat Completions API. ` +
|
|
84
|
+
`Chat-capable models: ${BEDROCK_CHAT_MODELS.join(', ')}.`,
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
return new BedrockTextAdapter(stripApi(config), model)
|
|
88
|
+
}
|
|
89
|
+
// Default + explicit 'converse'
|
|
90
|
+
return new BedrockConverseTextAdapter(config ? stripApi(config) : {}, model)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// --- createBedrockText: explicit key, overloaded on `api` ---
|
|
94
|
+
export function createBedrockText<TModel extends BedrockConverseModels>(
|
|
95
|
+
model: TModel,
|
|
96
|
+
apiKey: string,
|
|
97
|
+
config?: BedrockConverseApiConfig,
|
|
98
|
+
): BedrockConverseTextAdapter<TModel>
|
|
99
|
+
export function createBedrockText<TModel extends BedrockChatModels>(
|
|
100
|
+
model: TModel,
|
|
101
|
+
apiKey: string,
|
|
102
|
+
config: BedrockChatApiConfig,
|
|
103
|
+
): BedrockTextAdapter<TModel>
|
|
104
|
+
export function createBedrockText<TModel extends BedrockResponsesModels>(
|
|
105
|
+
model: TModel,
|
|
106
|
+
apiKey: string,
|
|
107
|
+
config: BedrockResponsesApiConfig,
|
|
108
|
+
): BedrockResponsesTextAdapter<TModel>
|
|
109
|
+
export function createBedrockText(
|
|
110
|
+
model: BedrockConverseModels,
|
|
111
|
+
apiKey: string,
|
|
112
|
+
config?:
|
|
113
|
+
| BedrockConverseApiConfig
|
|
114
|
+
| BedrockChatApiConfig
|
|
115
|
+
| BedrockResponsesApiConfig,
|
|
116
|
+
): AnyBedrockAdapter {
|
|
117
|
+
// Explicit apiKey is authoritative — spread config first so it can't override.
|
|
118
|
+
return build(model, { ...config, apiKey })
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// --- bedrockText: env-key counterpart, same overloads ---
|
|
122
|
+
export function bedrockText<TModel extends BedrockConverseModels>(
|
|
123
|
+
model: TModel,
|
|
124
|
+
config?: BedrockConverseApiConfig,
|
|
125
|
+
): BedrockConverseTextAdapter<TModel>
|
|
126
|
+
export function bedrockText<TModel extends BedrockChatModels>(
|
|
127
|
+
model: TModel,
|
|
128
|
+
config: BedrockChatApiConfig,
|
|
129
|
+
): BedrockTextAdapter<TModel>
|
|
130
|
+
export function bedrockText<TModel extends BedrockResponsesModels>(
|
|
131
|
+
model: TModel,
|
|
132
|
+
config: BedrockResponsesApiConfig,
|
|
133
|
+
): BedrockResponsesTextAdapter<TModel>
|
|
134
|
+
export function bedrockText(
|
|
135
|
+
model: BedrockConverseModels,
|
|
136
|
+
config?:
|
|
137
|
+
| BedrockConverseApiConfig
|
|
138
|
+
| BedrockChatApiConfig
|
|
139
|
+
| BedrockResponsesApiConfig,
|
|
140
|
+
): AnyBedrockAdapter {
|
|
141
|
+
// No eager env-key fetch: the adapter constructor resolves auth lazily so
|
|
142
|
+
// SigV4 (and the env-key fallback) work without a forced API key here.
|
|
143
|
+
return build(model, config)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// --- Re-exports ---
|
|
147
|
+
export {
|
|
148
|
+
BedrockTextAdapter,
|
|
149
|
+
createBedrockChat,
|
|
150
|
+
type BedrockTextConfig,
|
|
151
|
+
type BedrockTextProviderOptions,
|
|
152
|
+
} from './adapters/text'
|
|
153
|
+
export {
|
|
154
|
+
BedrockResponsesTextAdapter,
|
|
155
|
+
createBedrockResponsesText,
|
|
156
|
+
type BedrockResponsesConfig,
|
|
157
|
+
type BedrockResponsesProviderOptions,
|
|
158
|
+
} from './adapters/responses-text'
|
|
159
|
+
export {
|
|
160
|
+
BedrockConverseTextAdapter,
|
|
161
|
+
createBedrockConverse,
|
|
162
|
+
type BedrockConverseConfig,
|
|
163
|
+
} from './adapters/converse-text'
|
|
164
|
+
export type { BedrockConverseProviderOptions } from './converse/provider-options'
|
|
165
|
+
export {
|
|
166
|
+
resolveBedrockAuth,
|
|
167
|
+
withBedrockDefaults,
|
|
168
|
+
type BedrockClientConfig,
|
|
169
|
+
type BedrockEndpoint,
|
|
170
|
+
type ResolvedBedrockAuth,
|
|
171
|
+
} from './utils'
|
|
172
|
+
export {
|
|
173
|
+
BEDROCK_CHAT_MODELS,
|
|
174
|
+
BEDROCK_RESPONSES_MODELS,
|
|
175
|
+
BEDROCK_CONVERSE_MODELS,
|
|
176
|
+
type BedrockChatModels,
|
|
177
|
+
type BedrockResponsesModels,
|
|
178
|
+
type BedrockConverseModels,
|
|
179
|
+
type BedrockChatModelProviderOptionsByName,
|
|
180
|
+
type BedrockChatModelToolCapabilitiesByName,
|
|
181
|
+
type BedrockModelInputModalitiesByName,
|
|
182
|
+
} from './model-meta'
|
|
183
|
+
export type {
|
|
184
|
+
BedrockMessageMetadataByModality,
|
|
185
|
+
BedrockTextMetadata,
|
|
186
|
+
BedrockImageMetadata,
|
|
187
|
+
BedrockAudioMetadata,
|
|
188
|
+
BedrockVideoMetadata,
|
|
189
|
+
BedrockDocumentMetadata,
|
|
190
|
+
} from './message-types'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bedrock content-part metadata by modality, used for type inference when
|
|
3
|
+
* constructing multimodal messages. Bedrock's OpenAI-compatible Chat
|
|
4
|
+
* Completions accepts the standard OpenAI image-detail hint; other modalities
|
|
5
|
+
* carry no extra metadata today.
|
|
6
|
+
*/
|
|
7
|
+
export interface BedrockTextMetadata {}
|
|
8
|
+
|
|
9
|
+
export interface BedrockImageMetadata {
|
|
10
|
+
/** Image processing detail: 'auto' (default), 'low', or 'high'. */
|
|
11
|
+
detail?: 'auto' | 'low' | 'high'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface BedrockAudioMetadata {}
|
|
15
|
+
export interface BedrockVideoMetadata {}
|
|
16
|
+
export interface BedrockDocumentMetadata {}
|
|
17
|
+
|
|
18
|
+
export interface BedrockMessageMetadataByModality {
|
|
19
|
+
text: BedrockTextMetadata
|
|
20
|
+
image: BedrockImageMetadata
|
|
21
|
+
audio: BedrockAudioMetadata
|
|
22
|
+
video: BedrockVideoMetadata
|
|
23
|
+
document: BedrockDocumentMetadata
|
|
24
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// GENERATED by scripts/fetch-bedrock-models.ts — do not edit by hand.
|
|
2
|
+
// Refresh: AWS_REGION=us-east-1 pnpm tsx scripts/fetch-bedrock-models.ts
|
|
3
|
+
export const GENERATED_BEDROCK_MODELS = [
|
|
4
|
+
{
|
|
5
|
+
id: 'openai.gpt-oss-120b-1:0',
|
|
6
|
+
input: ['text'],
|
|
7
|
+
output: ['text'],
|
|
8
|
+
apis: { converse: true, chat: true, responses: true },
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
id: 'openai.gpt-oss-20b-1:0',
|
|
12
|
+
input: ['text'],
|
|
13
|
+
output: ['text'],
|
|
14
|
+
apis: { converse: true, chat: true, responses: true },
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
id: 'us.anthropic.claude-sonnet-4-5-20250929-v1:0',
|
|
18
|
+
input: ['text', 'image', 'document'],
|
|
19
|
+
output: ['text'],
|
|
20
|
+
apis: { converse: true, chat: false, responses: false },
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: 'us.anthropic.claude-haiku-4-5-20251001-v1:0',
|
|
24
|
+
input: ['text', 'image', 'document'],
|
|
25
|
+
output: ['text'],
|
|
26
|
+
apis: { converse: true, chat: false, responses: false },
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: 'us.anthropic.claude-3-7-sonnet-20250219-v1:0',
|
|
30
|
+
input: ['text', 'image', 'document'],
|
|
31
|
+
output: ['text'],
|
|
32
|
+
apis: { converse: true, chat: false, responses: false },
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 'us.anthropic.claude-3-5-sonnet-20241022-v2:0',
|
|
36
|
+
input: ['text', 'image', 'document'],
|
|
37
|
+
output: ['text'],
|
|
38
|
+
apis: { converse: true, chat: false, responses: false },
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: 'us.anthropic.claude-3-5-haiku-20241022-v1:0',
|
|
42
|
+
input: ['text'],
|
|
43
|
+
output: ['text'],
|
|
44
|
+
apis: { converse: true, chat: false, responses: false },
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: 'us.amazon.nova-pro-v1:0',
|
|
48
|
+
input: ['text', 'image', 'document'],
|
|
49
|
+
output: ['text'],
|
|
50
|
+
apis: { converse: true, chat: false, responses: false },
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: 'us.amazon.nova-lite-v1:0',
|
|
54
|
+
input: ['text', 'image', 'document'],
|
|
55
|
+
output: ['text'],
|
|
56
|
+
apis: { converse: true, chat: false, responses: false },
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: 'us.amazon.nova-micro-v1:0',
|
|
60
|
+
input: ['text'],
|
|
61
|
+
output: ['text'],
|
|
62
|
+
apis: { converse: true, chat: false, responses: false },
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
id: 'us.meta.llama3-3-70b-instruct-v1:0',
|
|
66
|
+
input: ['text'],
|
|
67
|
+
output: ['text'],
|
|
68
|
+
apis: { converse: true, chat: false, responses: false },
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: 'us.meta.llama4-maverick-17b-instruct-v1:0',
|
|
72
|
+
input: ['text', 'image'],
|
|
73
|
+
output: ['text'],
|
|
74
|
+
apis: { converse: true, chat: false, responses: false },
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: 'us.mistral.pixtral-large-2502-v1:0',
|
|
78
|
+
input: ['text', 'image'],
|
|
79
|
+
output: ['text'],
|
|
80
|
+
apis: { converse: true, chat: false, responses: false },
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
id: 'us.deepseek.r1-v1:0',
|
|
84
|
+
input: ['text'],
|
|
85
|
+
output: ['text'],
|
|
86
|
+
apis: { converse: true, chat: false, responses: false },
|
|
87
|
+
},
|
|
88
|
+
] as const
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { GENERATED_BEDROCK_MODELS } from './model-catalog.generated'
|
|
2
|
+
import type { BedrockTextProviderOptions } from './text/text-provider-options'
|
|
3
|
+
import type { BedrockConverseProviderOptions } from './converse/provider-options'
|
|
4
|
+
|
|
5
|
+
type Entry = (typeof GENERATED_BEDROCK_MODELS)[number]
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Type-level per-API filter over the generated catalog. Because the catalog is
|
|
9
|
+
* `as const`, `Extract` preserves literal `id` unions (no widening to `string`).
|
|
10
|
+
*/
|
|
11
|
+
type IdsWhere<TApi extends 'converse' | 'chat' | 'responses'> = Extract<
|
|
12
|
+
Entry,
|
|
13
|
+
{ apis: Record<TApi, true> }
|
|
14
|
+
>['id']
|
|
15
|
+
|
|
16
|
+
export type BedrockConverseModels = IdsWhere<'converse'>
|
|
17
|
+
export type BedrockChatModels = IdsWhere<'chat'>
|
|
18
|
+
export type BedrockResponsesModels = IdsWhere<'responses'>
|
|
19
|
+
|
|
20
|
+
/** Runtime catalogs. Cast-free narrowing via a type predicate (the ai-bedrock pattern). */
|
|
21
|
+
// Every catalog entry advertises `converse: true` (Converse is the universal
|
|
22
|
+
// Bedrock surface), so the id list is the full catalog — no runtime filter needed.
|
|
23
|
+
export const BEDROCK_CONVERSE_MODELS: ReadonlyArray<BedrockConverseModels> =
|
|
24
|
+
GENERATED_BEDROCK_MODELS.map((m) => m.id)
|
|
25
|
+
|
|
26
|
+
export const BEDROCK_CHAT_MODELS: ReadonlyArray<BedrockChatModels> =
|
|
27
|
+
GENERATED_BEDROCK_MODELS.filter(
|
|
28
|
+
(m): m is Extract<Entry, { apis: { chat: true } }> => m.apis.chat,
|
|
29
|
+
).map((m) => m.id)
|
|
30
|
+
|
|
31
|
+
export const BEDROCK_RESPONSES_MODELS: ReadonlyArray<BedrockResponsesModels> =
|
|
32
|
+
GENERATED_BEDROCK_MODELS.filter(
|
|
33
|
+
(m): m is Extract<Entry, { apis: { responses: true } }> => m.apis.responses,
|
|
34
|
+
).map((m) => m.id)
|
|
35
|
+
|
|
36
|
+
/** Per-model input modalities (drives type-safe multimodal content). Covers ALL models. */
|
|
37
|
+
export type BedrockModelInputModalitiesByName = {
|
|
38
|
+
[E in Entry as E['id']]: E['input']
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Provider options per model. Same options for every model; keyed over the full catalog. */
|
|
42
|
+
export type BedrockChatModelProviderOptionsByName = {
|
|
43
|
+
[E in Entry as E['id']]: BedrockTextProviderOptions
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Converse provider options per model (narrower than the Chat Completions set). */
|
|
47
|
+
export type BedrockConverseModelProviderOptionsByName = {
|
|
48
|
+
[E in Entry as E['id']]: BedrockConverseProviderOptions
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** No provider-specific tools — empty tuple makes cross-provider ProviderTool a compile error. */
|
|
52
|
+
export type BedrockChatModelToolCapabilitiesByName = {
|
|
53
|
+
[E in Entry as E['id']]: readonly []
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export type ResolveProviderOptions<TModel extends string> =
|
|
57
|
+
TModel extends keyof BedrockChatModelProviderOptionsByName
|
|
58
|
+
? BedrockChatModelProviderOptionsByName[TModel]
|
|
59
|
+
: BedrockTextProviderOptions
|
|
60
|
+
|
|
61
|
+
export type ResolveConverseProviderOptions<TModel extends string> =
|
|
62
|
+
TModel extends keyof BedrockConverseModelProviderOptionsByName
|
|
63
|
+
? BedrockConverseModelProviderOptionsByName[TModel]
|
|
64
|
+
: BedrockConverseProviderOptions
|
|
65
|
+
|
|
66
|
+
export type ResolveInputModalities<TModel extends string> =
|
|
67
|
+
TModel extends keyof BedrockModelInputModalitiesByName
|
|
68
|
+
? BedrockModelInputModalitiesByName[TModel]
|
|
69
|
+
: readonly ['text']
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bedrock Responses API provider options. Mantle's Responses endpoint adds
|
|
3
|
+
* stateful conversation management on top of the OpenAI Responses fields.
|
|
4
|
+
*
|
|
5
|
+
* @see https://docs.aws.amazon.com/bedrock/latest/userguide/bedrock-mantle.html
|
|
6
|
+
*/
|
|
7
|
+
export interface BedrockResponsesProviderOptions {
|
|
8
|
+
/** Continue a stored conversation from a prior response. */
|
|
9
|
+
previous_response_id?: string | null
|
|
10
|
+
/** Whether Bedrock retains the response for 30 days (default true). Set false to opt out. */
|
|
11
|
+
store?: boolean | null
|
|
12
|
+
metadata?: { [key: string]: string } | null
|
|
13
|
+
max_output_tokens?: number | null
|
|
14
|
+
temperature?: number | null
|
|
15
|
+
top_p?: number | null
|
|
16
|
+
parallel_tool_calls?: boolean | null
|
|
17
|
+
tool_choice?:
|
|
18
|
+
| 'none'
|
|
19
|
+
| 'auto'
|
|
20
|
+
| 'required'
|
|
21
|
+
| { type: 'function'; name: string }
|
|
22
|
+
| null
|
|
23
|
+
/** Reasoning controls for reasoning-capable models. */
|
|
24
|
+
reasoning?: { effort?: 'low' | 'medium' | 'high' } | null
|
|
25
|
+
user?: string | null
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type ExternalResponsesProviderOptions = BedrockResponsesProviderOptions
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bedrock Chat Completions provider options. Bedrock accepts the standard
|
|
3
|
+
* OpenAI Chat Completions request fields; we surface the commonly-used ones
|
|
4
|
+
* plus `reasoning_effort` (supported by gpt-oss and reasoning models).
|
|
5
|
+
*
|
|
6
|
+
* @see https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-openai.html
|
|
7
|
+
*/
|
|
8
|
+
export interface BedrockTextProviderOptions {
|
|
9
|
+
frequency_penalty?: number | null
|
|
10
|
+
presence_penalty?: number | null
|
|
11
|
+
logit_bias?: { [token: string]: number } | null
|
|
12
|
+
logprobs?: boolean | null
|
|
13
|
+
top_logprobs?: number | null
|
|
14
|
+
max_completion_tokens?: number | null
|
|
15
|
+
metadata?: { [key: string]: string } | null
|
|
16
|
+
n?: number | null
|
|
17
|
+
parallel_tool_calls?: boolean | null
|
|
18
|
+
/** gpt-oss / reasoning models: 'low' | 'medium' (default) | 'high'. */
|
|
19
|
+
reasoning_effort?: 'low' | 'medium' | 'high' | null
|
|
20
|
+
seed?: number | null
|
|
21
|
+
stop?: string | Array<string> | null
|
|
22
|
+
temperature?: number | null
|
|
23
|
+
tool_choice?:
|
|
24
|
+
| 'none'
|
|
25
|
+
| 'auto'
|
|
26
|
+
| 'required'
|
|
27
|
+
| { type: 'function'; function: { name: string } }
|
|
28
|
+
| null
|
|
29
|
+
top_p?: number | null
|
|
30
|
+
user?: string | null
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type ExternalTextProviderOptions = BedrockTextProviderOptions
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { AwsCredentialIdentityProvider } from '@smithy/types'
|
|
2
|
+
import type * as CredentialProviders from '@aws-sdk/credential-providers'
|
|
3
|
+
|
|
4
|
+
export type BedrockEndpoint = 'runtime' | 'mantle'
|
|
5
|
+
|
|
6
|
+
/** SigV4 service name differs per endpoint. */
|
|
7
|
+
export function sigv4Service(endpoint: BedrockEndpoint): string {
|
|
8
|
+
return endpoint === 'mantle' ? 'bedrock-mantle' : 'bedrock'
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type ResolvedBedrockAuth =
|
|
12
|
+
| { kind: 'bearer'; token: string }
|
|
13
|
+
| {
|
|
14
|
+
kind: 'sigv4'
|
|
15
|
+
region: string
|
|
16
|
+
service: string
|
|
17
|
+
credentials: AwsCredentialIdentityProvider
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const DEFAULT_REGION = 'us-east-1'
|
|
21
|
+
|
|
22
|
+
function readApiKeyFromEnv(): string | undefined {
|
|
23
|
+
// Bedrock is server-only (the AWS SDK is Node-only), so the key always comes
|
|
24
|
+
// from process.env. Read it directly: a property access never throws, so —
|
|
25
|
+
// unlike the previous try/catch around getApiKeyFromEnv — we no longer swallow
|
|
26
|
+
// unrelated errors as "key not set". Each var is blank-checked independently
|
|
27
|
+
// so a present-but-blank BEDROCK_API_KEY falls through to
|
|
28
|
+
// AWS_BEARER_TOKEN_BEDROCK (and only then to SigV4) rather than masking it.
|
|
29
|
+
const env = typeof process !== 'undefined' ? process.env : undefined
|
|
30
|
+
for (const value of [env?.BEDROCK_API_KEY, env?.AWS_BEARER_TOKEN_BEDROCK]) {
|
|
31
|
+
if (value && value.trim() !== '') return value
|
|
32
|
+
}
|
|
33
|
+
return undefined
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface BedrockAuthConfig {
|
|
37
|
+
apiKey?: string
|
|
38
|
+
region?: string
|
|
39
|
+
auth?: 'apikey' | 'sigv4' | 'auto'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** apiKey -> BEDROCK_API_KEY -> AWS_BEARER_TOKEN_BEDROCK -> SigV4 (credential chain). */
|
|
43
|
+
export function resolveBedrockAuth(
|
|
44
|
+
config: BedrockAuthConfig,
|
|
45
|
+
endpoint: BedrockEndpoint,
|
|
46
|
+
): ResolvedBedrockAuth {
|
|
47
|
+
const mode = config.auth ?? 'auto'
|
|
48
|
+
const region = config.region ?? DEFAULT_REGION
|
|
49
|
+
|
|
50
|
+
if (mode !== 'sigv4') {
|
|
51
|
+
const token = config.apiKey ?? readApiKeyFromEnv()
|
|
52
|
+
if (token) return { kind: 'bearer', token }
|
|
53
|
+
if (mode === 'apikey') {
|
|
54
|
+
throw new Error(
|
|
55
|
+
'No Bedrock API key found. Set BEDROCK_API_KEY (or ' +
|
|
56
|
+
'AWS_BEARER_TOKEN_BEDROCK), pass `apiKey`, or use auth: "sigv4".',
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
kind: 'sigv4',
|
|
63
|
+
region,
|
|
64
|
+
service: sigv4Service(endpoint),
|
|
65
|
+
// Lazy credential provider: the AWS SDK is Node/server-only, so we defer the
|
|
66
|
+
// dynamic import until SigV4 actually needs to resolve credentials. The
|
|
67
|
+
// specifier is held in a variable (not a string literal) so bundler dep
|
|
68
|
+
// scanners (e.g. Vite/esbuild optimizeDeps) cannot statically discover the
|
|
69
|
+
// AWS SDK and try to pre-bundle it for the browser — it would fail on the
|
|
70
|
+
// SDK's Node-only `fromTokenFile` export chain. `typeof import(...)` is a
|
|
71
|
+
// type-only reference (erased at emit) so we keep full typing.
|
|
72
|
+
credentials: async (...args) => {
|
|
73
|
+
const mod = '@aws-sdk/credential-providers'
|
|
74
|
+
const { fromNodeProviderChain } = (await import(
|
|
75
|
+
/* @vite-ignore */ mod
|
|
76
|
+
)) as typeof CredentialProviders
|
|
77
|
+
return fromNodeProviderChain()(...args)
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { resolveBedrockAuth } from './auth'
|
|
2
|
+
import { createSigV4Fetch } from './openai-sigv4-fetch'
|
|
3
|
+
import type { ClientOptions } from 'openai'
|
|
4
|
+
import type { BedrockEndpoint } from './auth'
|
|
5
|
+
|
|
6
|
+
export type { BedrockEndpoint } from './auth'
|
|
7
|
+
export { resolveBedrockAuth } from './auth'
|
|
8
|
+
export type { ResolvedBedrockAuth } from './auth'
|
|
9
|
+
|
|
10
|
+
export interface BedrockClientConfig extends Omit<
|
|
11
|
+
ClientOptions,
|
|
12
|
+
'apiKey' | 'baseURL'
|
|
13
|
+
> {
|
|
14
|
+
/** Bedrock API key (bearer). Optional — falls back to env, then SigV4. */
|
|
15
|
+
apiKey?: string
|
|
16
|
+
/** Full AWS region (e.g. 'us-east-1'). Default 'us-east-1'. */
|
|
17
|
+
region?: string
|
|
18
|
+
/** Chat adapter only; the responses adapter forces 'mantle'. Default 'runtime'. */
|
|
19
|
+
endpoint?: BedrockEndpoint
|
|
20
|
+
/** Auth strategy. Default 'auto' (apiKey → env → SigV4). */
|
|
21
|
+
auth?: 'apikey' | 'sigv4' | 'auto'
|
|
22
|
+
/** Explicit override; wins over the computed endpoint URL (used by E2E → aimock). */
|
|
23
|
+
baseURL?: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const DEFAULT_REGION = 'us-east-1'
|
|
27
|
+
/** OpenAI SDK requires a non-empty apiKey even when a signed fetch overrides Authorization. */
|
|
28
|
+
const SIGV4_PLACEHOLDER_KEY = 'bedrock-sigv4'
|
|
29
|
+
|
|
30
|
+
function buildBaseURL(region: string, endpoint: BedrockEndpoint): string {
|
|
31
|
+
return endpoint === 'mantle'
|
|
32
|
+
? `https://bedrock-mantle.${region}.api.aws/v1`
|
|
33
|
+
: `https://bedrock-runtime.${region}.amazonaws.com/openai/v1`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Builds OpenAI ClientOptions for the requested endpoint. `forced` pins the endpoint (responses → 'mantle'). */
|
|
37
|
+
export function withBedrockDefaults(
|
|
38
|
+
config: BedrockClientConfig,
|
|
39
|
+
forced?: BedrockEndpoint,
|
|
40
|
+
): ClientOptions {
|
|
41
|
+
const { region, endpoint, auth, apiKey, baseURL, fetch, ...rest } = config
|
|
42
|
+
const resolvedRegion = region ?? DEFAULT_REGION
|
|
43
|
+
const resolvedEndpoint = forced ?? endpoint ?? 'runtime'
|
|
44
|
+
const resolved = resolveBedrockAuth(
|
|
45
|
+
{ apiKey, region: resolvedRegion, auth },
|
|
46
|
+
resolvedEndpoint,
|
|
47
|
+
)
|
|
48
|
+
if (resolved.kind === 'bearer') {
|
|
49
|
+
return {
|
|
50
|
+
...rest,
|
|
51
|
+
baseURL: baseURL ?? buildBaseURL(resolvedRegion, resolvedEndpoint),
|
|
52
|
+
apiKey: resolved.token,
|
|
53
|
+
...(fetch ? { fetch } : {}),
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
...rest,
|
|
58
|
+
baseURL: baseURL ?? buildBaseURL(resolvedRegion, resolvedEndpoint),
|
|
59
|
+
apiKey: SIGV4_PLACEHOLDER_KEY,
|
|
60
|
+
fetch: fetch ?? createSigV4Fetch(resolved),
|
|
61
|
+
}
|
|
62
|
+
}
|