@wmaurer/effect-ai-amazon-bedrock 0.1.0 → 0.3.0
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/CHANGELOG.md +24 -0
- package/README.md +97 -16
- package/dist/AmazonBedrockClient.d.ts +135 -23
- package/dist/AmazonBedrockClient.d.ts.map +1 -1
- package/dist/AmazonBedrockClient.js +36 -92
- package/dist/AmazonBedrockClient.js.map +1 -1
- package/dist/AmazonBedrockConfig.d.ts +6 -6
- package/dist/AmazonBedrockConfig.js +4 -4
- package/dist/AmazonBedrockEventStream.d.ts +2 -2
- package/dist/AmazonBedrockEventStream.js +3 -3
- package/dist/AmazonBedrockLanguageModel.d.ts +22 -22
- package/dist/AmazonBedrockLanguageModel.d.ts.map +1 -1
- package/dist/AmazonBedrockLanguageModel.js +77 -28
- package/dist/AmazonBedrockLanguageModel.js.map +1 -1
- package/dist/AmazonBedrockSchema.d.ts +76 -55
- package/dist/AmazonBedrockSchema.d.ts.map +1 -1
- package/dist/AmazonBedrockSchema.js +63 -50
- package/dist/AmazonBedrockSchema.js.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.js +6 -6
- package/dist/internal/credentials.d.ts +79 -0
- package/dist/internal/credentials.d.ts.map +1 -0
- package/dist/internal/credentials.js +241 -0
- package/dist/internal/credentials.js.map +1 -0
- package/dist/internal/errors.d.ts +2 -0
- package/dist/internal/errors.d.ts.map +1 -1
- package/dist/internal/errors.js +6 -0
- package/dist/internal/errors.js.map +1 -1
- package/dist/internal/utilities.d.ts +1 -1
- package/dist/internal/utilities.d.ts.map +1 -1
- package/dist/internal/utilities.js +4 -5
- package/dist/internal/utilities.js.map +1 -1
- package/package.json +1 -1
- package/src/AmazonBedrockClient.ts +184 -95
- package/src/AmazonBedrockConfig.ts +6 -6
- package/src/AmazonBedrockEventStream.ts +3 -3
- package/src/AmazonBedrockLanguageModel.ts +136 -62
- package/src/AmazonBedrockSchema.ts +77 -54
- package/src/index.ts +6 -6
- package/src/internal/credentials.ts +319 -0
- package/src/internal/errors.ts +5 -0
- package/src/internal/utilities.ts +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @wmaurer/effect-ai-amazon-bedrock
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
`generateObject` asks models outside Anthropic for the object through a tool. In 0.2.0 it sent them `outputConfig.textFormat`, which Nova, Mistral Large 2402, Pixtral Large, Llama, and Palmyra answered with a 400 in probes in `eu-west-1` and `us-east-1`, so `generateObject` on these models failed unless you set `structuredOutputs: false`.
|
|
6
|
+
|
|
7
|
+
- Choose how `generateObject` asks for the object from the provider that the model ID names. Claude models keep the 0.2.0 behavior. Meta and Writer models get the object tool unforced, with a system prompt line that tells the model to call it, because Llama and Palmyra reject a forced `toolChoice`. Models of every other provider get the forced object tool. An ARN that does not name its model, such as an application inference profile, keeps the 0.2.0 behavior. `Config.structuredOutputs` and `Config.forcedToolChoice` still override the choice.
|
|
8
|
+
- Models of other providers that accepted `outputConfig.textFormat` in the probes, such as gpt-5.x, Grok, Qwen, GLM, MiniMax, DeepSeek V3.2, and Mistral Large 3, also get the object tool now. The object tool replaces the tools that you pass to `generateObject`, and in 0.2.0 these models kept them. Set `structuredOutputs: true` to keep the 0.2.0 behavior.
|
|
9
|
+
- Force the object tool with `toolChoice` `{ any: {} }` in place of `{ tool: { name } }`. The object tool is the only tool in its request, so both force it, and Mistral Large 2402 and Pixtral Large accept only `any`. A `toolChoice` that you pass with your own tools goes to Bedrock as before.
|
|
10
|
+
- Fail `streamText` with an `AiError` whose reason is `InvalidOutputError` when Bedrock streams tool input that is not valid JSON. In 0.2.0 the stream died with a defect. Bedrock streamed such input for Qwen3 32B in each probe run.
|
|
11
|
+
- Decode a stop reason outside the nine that the Converse API names, and give it the finish reason `"other"`. In 0.2.0 such a reason failed `generateText` and `streamText` with an `InvalidOutputError`, and the text before it was lost. The `StopReason` type now admits any string, so a `switch` over it that was exhaustive needs a `default` case, and a `Record` keyed by it no longer compiles. The new `KnownStopReason` schema holds the nine.
|
|
12
|
+
|
|
13
|
+
## 0.2.0
|
|
14
|
+
|
|
15
|
+
`AmazonBedrockClient.layer`, `layerConfig`, and `make` take one of three ways to authenticate: the fixed keys of 0.1.0, a `credentialProvider`, or a Bedrock `apiKey`. Options that mix two ways, or give none, do not compile. Every 0.1.0 call compiles and runs unchanged.
|
|
16
|
+
|
|
17
|
+
- Add the `credentialProvider` option. It takes a function in the shape of the AWS SDK's credential providers, such as `fromNodeProviderChain()` from `@aws-sdk/credential-providers`, or an `Effect`. The package does not depend on the AWS SDK. The client runs the provider when a request needs credentials, runs it once for concurrent requests, and keeps the credentials until five minutes before their `expiration`, or for at least 10 seconds.
|
|
18
|
+
- Keep the last credentials while the provider fails and they have not expired. Ask the provider again after 30 seconds, or when the last credentials expire if that is sooner.
|
|
19
|
+
- Refresh credentials that Bedrock rejects. After an `AuthenticationError` of kind `ExpiredKey`, `InvalidKey`, or `MissingKey`, the next request gets new credentials, and a function provider gets `{ forceRefresh: true }`. The rejected request fails and is not sent again.
|
|
20
|
+
- Fail a request with an `AuthenticationError` of kind `Unknown` when the promise of a function provider rejects, and of kind `MissingKey` when a provider returns an empty key.
|
|
21
|
+
- An `Effect` provider fails with an `AiError`, which the request fails with unchanged, or with an `AiError` reason, which the client puts in an `AiError`. The services that it requires become requirements of the layer through a new type parameter. It runs with the services of the request first, and the services that the layer was built with fill in the rest, so a span that it opens is a child of the request's span.
|
|
22
|
+
- Add the `apiKey` option for Bedrock API keys. The client sends the key as `Authorization: Bearer <key>` in place of a SigV4 signature, and an `AiError` shows the header as `<redacted>`.
|
|
23
|
+
- AWS rejects an API key that it does not accept with `AccessDeniedException`, as it rejects a missing IAM permission, so the request fails with an `AuthenticationError` of kind `InsufficientPermissions`.
|
|
24
|
+
- Add the `Credentials`, `CredentialProvider`, and `ConfigOptions` types. `Options`, `ConfigOptions`, `CredentialProvider`, `make`, `layer`, and `layerConfig` take a type parameter `R` for the services of an `Effect` provider. It defaults to `never`.
|
|
25
|
+
- A retry policy in `transformClient` or `AmazonBedrockConfig.withClientTransform` signs each attempt again with the credentials of the request, and does not retry a provider that fails.
|
|
26
|
+
|
|
3
27
|
## 0.1.0
|
|
4
28
|
|
|
5
29
|
The first release. It adds an Amazon Bedrock provider for `effect/ai`. The provider calls the Converse and ConverseStream APIs, signs requests with SigV4 through `aws4fetch`, and decodes the AWS event-stream framing without another dependency. `AmazonBedrockClient.layer` and `AmazonBedrockClient.layerConfig` take an access key and a secret key, and the optional `sessionToken`, `region`, `apiUrl`, and `transformClient`. The region defaults to `us-east-1`. `AmazonBedrockLanguageModel.Config` takes the Converse request fields other than `messages` and `system`.
|
package/README.md
CHANGED
|
@@ -138,20 +138,88 @@ To run the program, do these steps:
|
|
|
138
138
|
|
|
139
139
|
`AmazonBedrockClient` needs an `HttpClient`. The example above uses `FetchHttpClient.layer` from `effect/http`.
|
|
140
140
|
|
|
141
|
-
The client
|
|
141
|
+
The client authenticates each request in one of three ways:
|
|
142
142
|
|
|
143
|
-
-
|
|
144
|
-
-
|
|
143
|
+
- Fixed keys. `accessKeyId`, `secretAccessKey`, and an optional `sessionToken`. The client signs each request with SigV4.
|
|
144
|
+
- A credential provider. `credentialProvider` is a function or an `Effect` that returns credentials. The client signs each request with SigV4 and asks the provider for new credentials before the old ones expire.
|
|
145
|
+
- A Bedrock API key. `apiKey` is sent as `Authorization: Bearer <key>` in place of a SigV4 signature.
|
|
145
146
|
|
|
146
|
-
|
|
147
|
+
Give exactly one of them. Options that mix two ways, or give none, do not compile. `AmazonBedrockClient.layerConfig` reads each value from a `Config`. `AmazonBedrockClient.layer` takes plain values, with the secrets as `Redacted` values. The client reads no environment variable and no file by itself.
|
|
147
148
|
|
|
148
|
-
|
|
149
|
+
### Use fixed keys
|
|
149
150
|
|
|
150
|
-
|
|
151
|
-
- AWS Lambda sets `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN` for the function's execution role, so the example above runs without changes.
|
|
152
|
-
- On Amazon ECS, Amazon EKS, and Amazon EC2, the role's credentials are not in the environment. Get them yourself, for example with `fromNodeProviderChain()` from `@aws-sdk/credential-providers`, and pass them to `AmazonBedrockClient.layer`.
|
|
151
|
+
The example above reads fixed keys from the environment. `sessionToken` is optional, but `layerConfig` fails with a `ConfigError` if a `Config` that you give it finds no value. For that reason the example gives `AWS_SESSION_TOKEN` an empty default with `Config.withDefault`. The client sends no session token when the token is empty, so the same program runs with temporary and long-lived keys. AWS Lambda sets `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN` for the function's execution role, so the example runs there without changes.
|
|
153
152
|
|
|
154
|
-
The client
|
|
153
|
+
The client reads fixed keys once, when the layer is built. When temporary keys expire, every request fails with an `AuthenticationError` of kind `ExpiredKey`. A program that runs longer than its session needs a credential provider.
|
|
154
|
+
|
|
155
|
+
### Use a credential provider
|
|
156
|
+
|
|
157
|
+
A function in the shape of the AWS SDK's credential providers fits `credentialProvider` without an adapter. `fromNodeProviderChain()` from `@aws-sdk/credential-providers` looks for credentials where the AWS CLI does, in the environment, in the profiles and IAM Identity Center sessions of `~/.aws`, and in the container credentials of Amazon ECS and Amazon EKS and the instance metadata of Amazon EC2. This package does not depend on the AWS SDK, so install `@aws-sdk/credential-providers` yourself.
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
import { fromNodeProviderChain } from "@aws-sdk/credential-providers"
|
|
161
|
+
import { AmazonBedrockClient } from "@wmaurer/effect-ai-amazon-bedrock"
|
|
162
|
+
import { Layer } from "effect"
|
|
163
|
+
import { FetchHttpClient } from "effect/http"
|
|
164
|
+
|
|
165
|
+
const BedrockClient = AmazonBedrockClient.layer({
|
|
166
|
+
region: "eu-west-1",
|
|
167
|
+
credentialProvider: fromNodeProviderChain()
|
|
168
|
+
}).pipe(Layer.provide(FetchHttpClient.layer))
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
The client runs the provider when a request needs credentials, and runs it once for requests that need them at the same time:
|
|
172
|
+
|
|
173
|
+
- It keeps the credentials until five minutes before their `expiration`. It keeps credentials that expire in less than five minutes for 10 seconds, and credentials without an `expiration` until Bedrock rejects them.
|
|
174
|
+
- If the provider fails while the last credentials have not expired, the client signs with the last credentials. It asks the provider again after 30 seconds, or when the last credentials expire if that is sooner.
|
|
175
|
+
- If Bedrock rejects the credentials with an `AuthenticationError` of kind `ExpiredKey`, `InvalidKey`, or `MissingKey`, the request fails, and the next request gets new credentials. The client calls a function provider with `{ forceRefresh: true }` for them. Kind `InsufficientPermissions` keeps the credentials, because new credentials for the same role have the same IAM policy.
|
|
176
|
+
- If the promise of a function provider rejects, the request fails with an `AuthenticationError` of kind `Unknown`. If the provider returns an empty access key ID or secret access key, the request fails with an `AuthenticationError` of kind `MissingKey`.
|
|
177
|
+
|
|
178
|
+
An `Effect` provider can load credentials from a service of your own. The layer then requires that service:
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
import { AmazonBedrockClient } from "@wmaurer/effect-ai-amazon-bedrock"
|
|
182
|
+
import { Context, Effect } from "effect"
|
|
183
|
+
import type { AiError } from "effect/ai"
|
|
184
|
+
|
|
185
|
+
class Vault extends Context.Service<Vault, {
|
|
186
|
+
readonly bedrockCredentials: Effect.Effect<AmazonBedrockClient.Credentials, AiError.AiError>
|
|
187
|
+
}>()("Vault") {}
|
|
188
|
+
|
|
189
|
+
// Layer<AmazonBedrockClient, never, HttpClient | Vault>
|
|
190
|
+
export const BedrockClient = AmazonBedrockClient.layer({
|
|
191
|
+
region: "eu-west-1",
|
|
192
|
+
credentialProvider: Effect.gen(function*() {
|
|
193
|
+
const vault = yield* Vault
|
|
194
|
+
return yield* vault.bedrockCredentials
|
|
195
|
+
})
|
|
196
|
+
})
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
The provider runs with the services of the request first, and the services that the layer was built with fill in the rest. A span that the provider opens is a child of the span of the request that runs the provider.
|
|
200
|
+
|
|
201
|
+
The `Effect` can fail with an `AiError`, which the request fails with unchanged, or with an `AiError` reason such as an `AuthenticationError`, which the client puts in an `AiError`.
|
|
202
|
+
|
|
203
|
+
A retry policy in `transformClient` does not retry a failed provider, because the client gets the credentials before it sends the request. Each retry of a request signs again with the credentials of the first attempt.
|
|
204
|
+
|
|
205
|
+
### Use a Bedrock API key
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
import { AmazonBedrockClient } from "@wmaurer/effect-ai-amazon-bedrock"
|
|
209
|
+
import { Config, Layer } from "effect"
|
|
210
|
+
import { FetchHttpClient } from "effect/http"
|
|
211
|
+
|
|
212
|
+
const BedrockClient = AmazonBedrockClient.layerConfig({
|
|
213
|
+
region: Config.String("AWS_REGION"),
|
|
214
|
+
apiKey: Config.Redacted("AWS_BEARER_TOKEN_BEDROCK")
|
|
215
|
+
}).pipe(Layer.provide(FetchHttpClient.layer))
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
`AWS_BEARER_TOKEN_BEDROCK` is the variable that the AWS SDK for JavaScript reads the key from. The client reads it only through the `Config` that you give it. An `AiError` and an HTTP span that records headers show the `authorization` header as `<redacted>`.
|
|
219
|
+
|
|
220
|
+
AWS rejects an API key that it does not accept, such as an expired or revoked key, with `AccessDeniedException`, as it rejects a request that the IAM policy does not allow. The request then fails with an `AuthenticationError` of kind `InsufficientPermissions`, and the client cannot tell the two causes apart.
|
|
221
|
+
|
|
222
|
+
### Set the other options
|
|
155
223
|
|
|
156
224
|
The other options are these:
|
|
157
225
|
|
|
@@ -167,7 +235,7 @@ To set request defaults, give them as the second argument of `model` or as the `
|
|
|
167
235
|
|
|
168
236
|
- `inferenceConfig`, `additionalModelRequestFields`, and `toolConfig`. The provider sends each one as the Converse request field of the same name.
|
|
169
237
|
- `outputConfig`, which takes only `effort`. The provider sets `outputConfig.textFormat` itself. `effort` is `low`, `medium`, `high`, `xhigh`, or `max`, and a higher level lets the model reason longer before it answers. The Bedrock Runtime API model documents that the level is capped at `high` when extended thinking is off. Not every model takes `effort`. On 2026-10-17 Bedrock rejected it for Claude Sonnet 4.5 and Haiku 4.5 with `This model doesn't support the effort field`.
|
|
170
|
-
- `structuredOutputs` and `forcedToolChoice`, which
|
|
238
|
+
- `structuredOutputs` and `forcedToolChoice`, which override how `generateObject` asks for the object on the model you chose. The provider does not send them to Bedrock. [Get structured output](#get-structured-output) explains them.
|
|
171
239
|
|
|
172
240
|
When `generateObject` asks for the object through a tool, that tool replaces your `toolConfig`. Any other request with tools replaces it with a `toolConfig` built from those tools, unless `toolChoice` is `"none"`. With no tools, or with `toolChoice` set to `"none"`, the provider sends your `toolConfig` unchanged.
|
|
173
241
|
|
|
@@ -216,22 +284,35 @@ export const adaptiveAnswer = LanguageModel.generateText({
|
|
|
216
284
|
|
|
217
285
|
## Get structured output
|
|
218
286
|
|
|
219
|
-
`LanguageModel.generateText`, `LanguageModel.streamText`, and `LanguageModel.generateObject` all work with this provider.
|
|
287
|
+
`LanguageModel.generateText`, `LanguageModel.streamText`, and `LanguageModel.generateObject` all work with this provider. `generateObject` asks for the object in one of three ways, and the provider that the model ID names decides which:
|
|
288
|
+
|
|
289
|
+
- A Claude model gets the schema in the Converse `outputConfig.textFormat` field, and the tools you pass go with it.
|
|
290
|
+
- A Meta or Writer model gets the schema as a tool that it is not forced to call, and the provider adds a system prompt line that tells the model to call it.
|
|
291
|
+
- A model of any other provider, such as Amazon Nova, Mistral, OpenAI, or Qwen, gets the schema as a tool that `toolChoice` `{ any: {} }` forces it to call.
|
|
292
|
+
|
|
293
|
+
The provider is the first part of the model ID, or the second part after a geo prefix: `anthropic` in `eu.anthropic.claude-opus-4-8`, `amazon` in `amazon.nova-pro-v1:0`. A foundation model ARN or an inference profile ARN names its model at the end. The tool replaces the tools you pass, and the tool's input becomes the object. If the model calls the tool more than once, the first call is the object. If the model answers in text instead of calling the tool, `effect/ai` decodes the text as the object. On every path, the provider converts the schema with the rules for Anthropic models.
|
|
294
|
+
|
|
295
|
+
Probes on 2026-10-17 sent one Converse request per model and path through the `eu-west-1` and `us-east-1` endpoints. Of the models outside Anthropic:
|
|
296
|
+
|
|
297
|
+
- The models that answered `outputConfig` with a 400 include Nova, Mistral Large 2402, Pixtral Large, Llama, and Palmyra. gpt-oss-120b accepted it, but wrote text before the JSON in 3 of 4 runs.
|
|
298
|
+
- The tool forced with `any` returned the object on 13 of the 14 models in `eu-west-1`, and on every one of the 17 models in `us-east-1` that accept a forced tool. Mistral Large 2402 and Pixtral Large answer a named tool in `toolChoice` with a 400, and Gemma 3 27B ignores it, but all three accept `any`.
|
|
299
|
+
- Llama 3.1, 3.3, and 4 and Palmyra X4 and X5 answered `any` with a 400. The unforced tool returned the object on Llama 3.1 8B, Llama 4 Scout, Llama 4 Maverick, and Palmyra X5, and a wrong object on Llama 3.1 70B and Llama 3.3 70B.
|
|
300
|
+
- No path returned the object on Magistral Small. Llama 3 70B, Mistral 7B, Mixtral 8x7B, and DeepSeek R1 reject tool use and `outputConfig`, so `generateObject` does not work on them.
|
|
220
301
|
|
|
221
|
-
A probe on
|
|
302
|
+
A probe on the same day sent one request per path to 17 Claude inference profiles through the `eu-west-1` endpoint. Every profile that served the probe's requests, 12 of the 17, accepted `outputConfig.textFormat`: Claude Haiku 4.5 and 5.5, Opus 4.5, 4.6, 4.7, 4.8, 5, and 5.5, and Sonnet 4.5, 4.6, 5, and 5.5. On Opus 4.8, Opus 5.5, and Sonnet 5.5 it also accepted `outputConfig.textFormat` together with `effort`, with adaptive thinking, and next to a strict tool. Fable 5 and 5.1 rejected every request, with or without `outputConfig.textFormat`, with `data retention mode 'default' is not available for this model`, and the other three profiles have reached end of life.
|
|
222
303
|
|
|
223
|
-
The provider keeps a list of models that get the
|
|
304
|
+
The provider keeps a list of Claude models that get the forced tool instead: the Claude 3 models and Claude Sonnet 4 and Opus 4. The list comes from Anthropic's table of models with structured output. The probe could not check it on Bedrock. Claude 3 Haiku, Claude 3 Sonnet, and Sonnet 4 have reached end of life in `eu-west-1`, and the probe did not try the other models on the list.
|
|
224
305
|
|
|
225
|
-
|
|
306
|
+
In the probe, Claude Opus 5.5 and Sonnet 5.5 rejected a forced `toolChoice` with `tool_choice: type "tool" and "any" are not supported for this model`. The provider also treats Fable 5.1 and Mythos 5.1 as rejecting it, which nobody has checked on Bedrock. For these four models the provider leaves the tool unforced and adds the system prompt line. They take the tool path only when `structuredOutputs` is `false`, or when the prompt holds tool calls and no tools go out.
|
|
226
307
|
|
|
227
308
|
When the prompt holds tool calls or tool results and the request offers no tools, `generateObject` uses the tool on every model, even with `structuredOutputs: true`. Converse rejects such a request unless it carries a `toolConfig`, and the object tool is one.
|
|
228
309
|
|
|
229
|
-
|
|
310
|
+
Two config fields override what the model ID decides, and the provider sends neither to Bedrock:
|
|
230
311
|
|
|
231
312
|
- `structuredOutputs` set to `true` sends `outputConfig.textFormat` to any model, except when the prompt holds tool calls and no tools go out. Set to `false`, it sends the tool.
|
|
232
313
|
- `forcedToolChoice` set to `true` forces the tool, and set to `false` leaves it unforced. It has an effect only on the tool path. It does not change a `toolChoice` you pass with your own tools: `"required"` and a named tool go to Bedrock as `any` and `tool`, and the probe's error from Opus 5.5 and Sonnet 5.5 names both as unsupported.
|
|
233
314
|
|
|
234
|
-
A model ID that does not name the model, such as an application inference profile ARN, gets `outputConfig.textFormat`, or a forced tool when `structuredOutputs` is `false`. With tool history and no tools it also gets a forced tool by default. Behind an ARN that wraps Opus 5.5 or Sonnet 5.5, set `forcedToolChoice: false` for that case. To send the unforced tool through such an ARN in every case, set both fields:
|
|
315
|
+
A model ID that does not name the model, such as an application inference profile ARN, gets what a Claude model gets: `outputConfig.textFormat`, or a forced tool when `structuredOutputs` is `false`. With tool history and no tools it also gets a forced tool by default. Behind an ARN that wraps Opus 5.5 or Sonnet 5.5, set `forcedToolChoice: false` for that case. Behind an ARN that wraps a model of another provider, set `structuredOutputs: false`, and also `forcedToolChoice: false` for a Meta or Writer model. To send the unforced tool through such an ARN in every case, set both fields:
|
|
235
316
|
|
|
236
317
|
```ts
|
|
237
318
|
import { AmazonBedrockLanguageModel } from "@wmaurer/effect-ai-amazon-bedrock"
|
|
@@ -1,10 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `AmazonBedrockClient` module defines the low-level Effect service used to
|
|
3
|
+
* call Amazon Bedrock's Converse API. It wraps an `HttpClient` with SigV4
|
|
4
|
+
* request signing (via `aws4fetch`), request defaults, response decoding, and
|
|
5
|
+
* error mapping to the unified `AiError` type.
|
|
6
|
+
*
|
|
7
|
+
* **Mental model**
|
|
8
|
+
*
|
|
9
|
+
* `HttpClient.HttpClient` provides the transport. {@link make} turns explicit
|
|
10
|
+
* {@link Options} into an {@link AmazonBedrockClient} service, while
|
|
11
|
+
* {@link layer} and {@link layerConfig} provide that service as a layer. The
|
|
12
|
+
* service exposes handwritten helpers for the `converse` (non-streaming) and
|
|
13
|
+
* `converse-stream` (streaming) endpoints.
|
|
14
|
+
*
|
|
15
|
+
* @stability unstable
|
|
16
|
+
* @since 0.1.0
|
|
17
|
+
*/
|
|
1
18
|
import type * as AiError from "effect/ai/AiError";
|
|
2
19
|
import type * as Config from "effect/Config";
|
|
3
20
|
import * as Context from "effect/Context";
|
|
4
21
|
import * as Effect from "effect/Effect";
|
|
5
22
|
import * as HttpClient from "effect/http/HttpClient";
|
|
6
23
|
import * as Layer from "effect/Layer";
|
|
7
|
-
import * as Redacted from "effect/Redacted";
|
|
24
|
+
import type * as Redacted from "effect/Redacted";
|
|
8
25
|
import * as Stream from "effect/Stream";
|
|
9
26
|
import type { ConverseRequest } from "./AmazonBedrockSchema.ts";
|
|
10
27
|
import { ConverseResponse, ConverseResponseStreamEvent } from "./AmazonBedrockSchema.ts";
|
|
@@ -14,7 +31,7 @@ import { ConverseResponse, ConverseResponseStreamEvent } from "./AmazonBedrockSc
|
|
|
14
31
|
*
|
|
15
32
|
* @stability unstable
|
|
16
33
|
* @category models
|
|
17
|
-
* @since
|
|
34
|
+
* @since 0.1.0
|
|
18
35
|
*/
|
|
19
36
|
export interface Service {
|
|
20
37
|
/**
|
|
@@ -38,18 +55,59 @@ declare const AmazonBedrockClient_base: Context.ServiceClass<AmazonBedrockClient
|
|
|
38
55
|
*
|
|
39
56
|
* @stability unstable
|
|
40
57
|
* @category services
|
|
41
|
-
* @since
|
|
58
|
+
* @since 0.1.0
|
|
42
59
|
*/
|
|
43
60
|
export declare class AmazonBedrockClient extends AmazonBedrockClient_base {
|
|
44
61
|
}
|
|
45
62
|
/**
|
|
46
|
-
*
|
|
63
|
+
* SigV4 credentials as a {@link CredentialProvider} returns them. The shape is
|
|
64
|
+
* the AWS SDK's `AwsCredentialIdentity`, so the SDK's providers fit without an
|
|
65
|
+
* adapter.
|
|
47
66
|
*
|
|
48
67
|
* @stability unstable
|
|
49
68
|
* @category options
|
|
50
|
-
* @since
|
|
69
|
+
* @since 0.2.0
|
|
51
70
|
*/
|
|
52
|
-
export
|
|
71
|
+
export interface Credentials {
|
|
72
|
+
readonly accessKeyId: string;
|
|
73
|
+
readonly secretAccessKey: string;
|
|
74
|
+
/** An empty token is sent as no token. */
|
|
75
|
+
readonly sessionToken?: string | undefined;
|
|
76
|
+
/** The client asks the provider for new credentials five minutes before this time. */
|
|
77
|
+
readonly expiration?: Date | undefined;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Supplies SigV4 credentials that can change while the program runs.
|
|
81
|
+
*
|
|
82
|
+
* **Details**
|
|
83
|
+
*
|
|
84
|
+
* A provider is one of these:
|
|
85
|
+
*
|
|
86
|
+
* - A function in the shape of the AWS SDK's credential providers, such as
|
|
87
|
+
* `fromNodeProviderChain()` from `@aws-sdk/credential-providers`. A rejected
|
|
88
|
+
* promise fails the request with an `AuthenticationError` of kind
|
|
89
|
+
* `"Unknown"`. After Bedrock rejects the credentials, the client calls the
|
|
90
|
+
* function with `{ forceRefresh: true }`.
|
|
91
|
+
* - An `Effect`. It can fail with an `AiError`, which the request fails with
|
|
92
|
+
* unchanged, or with an `AiError` reason, such as an `AuthenticationError`,
|
|
93
|
+
* which the client wraps in an `AiError`. The services that it requires
|
|
94
|
+
* become requirements of the layer. It runs with the services of the
|
|
95
|
+
* request first, and the services that the layer was built with fill in the
|
|
96
|
+
* rest.
|
|
97
|
+
*
|
|
98
|
+
* The client runs the provider at most once at a time, and keeps the
|
|
99
|
+
* credentials until five minutes before their `expiration`. Credentials with
|
|
100
|
+
* no `expiration` are kept until Bedrock rejects them. Keys that are empty fail
|
|
101
|
+
* the request with an `AuthenticationError` of kind `"MissingKey"`.
|
|
102
|
+
*
|
|
103
|
+
* @stability unstable
|
|
104
|
+
* @category options
|
|
105
|
+
* @since 0.2.0
|
|
106
|
+
*/
|
|
107
|
+
export type CredentialProvider<R = never> = ((options?: {
|
|
108
|
+
readonly forceRefresh?: boolean;
|
|
109
|
+
}) => PromiseLike<Credentials>) | Effect.Effect<Credentials, AiError.AiError | AiError.AiErrorReason, R>;
|
|
110
|
+
interface CommonOptions {
|
|
53
111
|
/**
|
|
54
112
|
* The base URL for the Bedrock runtime API. Override to use a proxy or a
|
|
55
113
|
* different endpoint.
|
|
@@ -57,9 +115,6 @@ export type Options = {
|
|
|
57
115
|
* @default `https://bedrock-runtime.${region}.amazonaws.com`
|
|
58
116
|
*/
|
|
59
117
|
readonly apiUrl?: string | undefined;
|
|
60
|
-
readonly accessKeyId: string;
|
|
61
|
-
readonly secretAccessKey: Redacted.Redacted<string>;
|
|
62
|
-
readonly sessionToken?: Redacted.Redacted<string> | undefined;
|
|
63
118
|
/**
|
|
64
119
|
* The AWS region.
|
|
65
120
|
*
|
|
@@ -67,38 +122,95 @@ export type Options = {
|
|
|
67
122
|
*/
|
|
68
123
|
readonly region?: string | undefined;
|
|
69
124
|
readonly transformClient?: ((client: HttpClient.HttpClient) => HttpClient.HttpClient) | undefined;
|
|
70
|
-
}
|
|
125
|
+
}
|
|
126
|
+
interface StaticKeys {
|
|
127
|
+
readonly accessKeyId: string;
|
|
128
|
+
readonly secretAccessKey: Redacted.Redacted<string>;
|
|
129
|
+
readonly sessionToken?: Redacted.Redacted<string> | undefined;
|
|
130
|
+
readonly credentialProvider?: never;
|
|
131
|
+
readonly apiKey?: never;
|
|
132
|
+
}
|
|
133
|
+
interface ProvidedKeys<R> {
|
|
134
|
+
readonly credentialProvider: CredentialProvider<R>;
|
|
135
|
+
readonly accessKeyId?: never;
|
|
136
|
+
readonly secretAccessKey?: never;
|
|
137
|
+
readonly sessionToken?: never;
|
|
138
|
+
readonly apiKey?: never;
|
|
139
|
+
}
|
|
140
|
+
interface ApiKey {
|
|
141
|
+
/** A Bedrock API key, sent as `Authorization: Bearer <key>` in place of a SigV4 signature. */
|
|
142
|
+
readonly apiKey: Redacted.Redacted<string>;
|
|
143
|
+
readonly accessKeyId?: never;
|
|
144
|
+
readonly secretAccessKey?: never;
|
|
145
|
+
readonly sessionToken?: never;
|
|
146
|
+
readonly credentialProvider?: never;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Configuration for creating an Amazon Bedrock client.
|
|
150
|
+
*
|
|
151
|
+
* **Details**
|
|
152
|
+
*
|
|
153
|
+
* The options take exactly one way to authenticate:
|
|
154
|
+
*
|
|
155
|
+
* - `accessKeyId` and `secretAccessKey`, and an optional `sessionToken`.
|
|
156
|
+
* - `credentialProvider`, a {@link CredentialProvider}.
|
|
157
|
+
* - `apiKey`, a Bedrock API key.
|
|
158
|
+
*
|
|
159
|
+
* @stability unstable
|
|
160
|
+
* @category options
|
|
161
|
+
* @since 0.1.0
|
|
162
|
+
*/
|
|
163
|
+
export type Options<R = never> = CommonOptions & (StaticKeys | ProvidedKeys<R> | ApiKey);
|
|
164
|
+
/**
|
|
165
|
+
* The {@link Options} of {@link layerConfig}, with a `Config` for each value.
|
|
166
|
+
* `credentialProvider` and `transformClient` are not configuration, so they
|
|
167
|
+
* take the same values as in {@link Options}.
|
|
168
|
+
*
|
|
169
|
+
* @stability unstable
|
|
170
|
+
* @category options
|
|
171
|
+
* @since 0.2.0
|
|
172
|
+
*/
|
|
173
|
+
export type ConfigOptions<R = never> = {
|
|
174
|
+
readonly apiUrl?: Config.Config<string> | undefined;
|
|
175
|
+
readonly region?: Config.Config<string> | undefined;
|
|
176
|
+
readonly transformClient?: ((client: HttpClient.HttpClient) => HttpClient.HttpClient) | undefined;
|
|
177
|
+
} & ({
|
|
178
|
+
readonly accessKeyId: Config.Config<string>;
|
|
179
|
+
readonly secretAccessKey: Config.Config<Redacted.Redacted<string>>;
|
|
180
|
+
readonly sessionToken?: Config.Config<Redacted.Redacted<string>> | undefined;
|
|
181
|
+
readonly credentialProvider?: never;
|
|
182
|
+
readonly apiKey?: never;
|
|
183
|
+
} | ProvidedKeys<R> | {
|
|
184
|
+
readonly apiKey: Config.Config<Redacted.Redacted<string>>;
|
|
185
|
+
readonly accessKeyId?: never;
|
|
186
|
+
readonly secretAccessKey?: never;
|
|
187
|
+
readonly sessionToken?: never;
|
|
188
|
+
readonly credentialProvider?: never;
|
|
189
|
+
});
|
|
71
190
|
/**
|
|
72
191
|
* Creates an Amazon Bedrock client service with the given options.
|
|
73
192
|
*
|
|
74
193
|
* @stability unstable
|
|
75
194
|
* @category constructors
|
|
76
|
-
* @since
|
|
195
|
+
* @since 0.1.0
|
|
77
196
|
*/
|
|
78
|
-
export declare const make: (options: Options) => Effect.Effect<Service, never, HttpClient.HttpClient>;
|
|
197
|
+
export declare const make: <R = never>(options: Options<R>) => Effect.Effect<Service, never, HttpClient.HttpClient | R>;
|
|
79
198
|
/**
|
|
80
199
|
* Creates a layer for the Amazon Bedrock client with the given options.
|
|
81
200
|
*
|
|
82
201
|
* @stability unstable
|
|
83
202
|
* @category layers
|
|
84
|
-
* @since
|
|
203
|
+
* @since 0.1.0
|
|
85
204
|
*/
|
|
86
|
-
export declare const layer: (options: Options) => Layer.Layer<AmazonBedrockClient, never, HttpClient.HttpClient>;
|
|
205
|
+
export declare const layer: <R = never>(options: Options<R>) => Layer.Layer<AmazonBedrockClient, never, HttpClient.HttpClient | R>;
|
|
87
206
|
/**
|
|
88
207
|
* Creates a layer for the Amazon Bedrock client, loading credentials and other
|
|
89
208
|
* settings via Effect's `Config` module.
|
|
90
209
|
*
|
|
91
210
|
* @stability unstable
|
|
92
211
|
* @category layers
|
|
93
|
-
* @since
|
|
212
|
+
* @since 0.1.0
|
|
94
213
|
*/
|
|
95
|
-
export declare const layerConfig: (options:
|
|
96
|
-
readonly apiUrl?: Config.Config<string> | undefined;
|
|
97
|
-
readonly accessKeyId: Config.Config<string>;
|
|
98
|
-
readonly secretAccessKey: Config.Config<Redacted.Redacted<string>>;
|
|
99
|
-
readonly sessionToken?: Config.Config<Redacted.Redacted<string>> | undefined;
|
|
100
|
-
readonly region?: Config.Config<string> | undefined;
|
|
101
|
-
readonly transformClient?: ((client: HttpClient.HttpClient) => HttpClient.HttpClient) | undefined;
|
|
102
|
-
}) => Layer.Layer<AmazonBedrockClient, Config.ConfigError, HttpClient.HttpClient>;
|
|
214
|
+
export declare const layerConfig: <R = never>(options: ConfigOptions<R>) => Layer.Layer<AmazonBedrockClient, Config.ConfigError, HttpClient.HttpClient | R>;
|
|
103
215
|
export {};
|
|
104
216
|
//# sourceMappingURL=AmazonBedrockClient.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AmazonBedrockClient.d.ts","sourceRoot":"","sources":["../src/AmazonBedrockClient.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"AmazonBedrockClient.d.ts","sourceRoot":"","sources":["../src/AmazonBedrockClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,KAAK,OAAO,MAAM,mBAAmB,CAAA;AAEjD,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAIvC,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAA;AAGpD,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,KAAK,QAAQ,MAAM,iBAAiB,CAAA;AAChD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAGvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC/D,OAAO,EAAE,gBAAgB,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAA;AAQxF;;;;;;;GAOG;AACH,MAAM,WAAW,OAAO;IACtB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE;QAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,eAAe,CAAC,OAAO,CAAA;KACjD,KAAK,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;IAEtD;;;OAGG;IACH,QAAQ,CAAC,cAAc,EAAE,CAAC,OAAO,EAAE;QACjC,QAAQ,CAAC,OAAO,EAAE,OAAO,eAAe,CAAC,OAAO,CAAA;KACjD,KAAK,MAAM,CAAC,MAAM,CAAC,2BAA2B,EAAE,OAAO,CAAC,OAAO,CAAC,CAAA;CAClE;;AAMD;;;;;;GAMG;AACH,qBAAa,mBAAoB,SAAQ,wBAExC;CAAG;AAMJ;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,0CAA0C;IAC1C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1C,sFAAsF;IACtF,QAAQ,CAAC,UAAU,CAAC,EAAE,IAAI,GAAG,SAAS,CAAA;CACvC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,MAAM,kBAAkB,CAAC,CAAC,GAAG,KAAK,IAGpC,CAAC,CAAC,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,KAAK,WAAW,CAAC,WAAW,CAAC,CAAC,GAC7E,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,CAAA;AAE1E,UAAU,aAAa;IACrB;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACpC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACpC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,UAAU,KAAK,UAAU,CAAC,UAAU,CAAC,GAAG,SAAS,CAAA;CAClG;AAED,UAAU,UAAU;IAClB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,eAAe,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IACnD,QAAQ,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;IAC7D,QAAQ,CAAC,kBAAkB,CAAC,EAAE,KAAK,CAAA;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,CAAA;CACxB;AAED,UAAU,YAAY,CAAC,CAAC;IACtB,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAA;IAClD,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,CAAA;IAC5B,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,CAAA;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,KAAK,CAAA;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,CAAA;CACxB;AAED,UAAU,MAAM;IACd,8FAA8F;IAC9F,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IAC1C,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,CAAA;IAC5B,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,CAAA;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,KAAK,CAAA;IAC7B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,KAAK,CAAA;CACpC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,OAAO,CAAC,CAAC,GAAG,KAAK,IAAI,aAAa,GAAG,CAAC,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAA;AAExF;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,KAAK,IAC/B;IACA,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;IACnD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;IACnD,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,UAAU,KAAK,UAAU,CAAC,UAAU,CAAC,GAAG,SAAS,CAAA;CAClG,GACC,CACE;IACA,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAC3C,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAA;IAClE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,CAAA;IAC5E,QAAQ,CAAC,kBAAkB,CAAC,EAAE,KAAK,CAAA;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,CAAA;CACxB,GACC,YAAY,CAAC,CAAC,CAAC,GACf;IACA,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAA;IACzD,QAAQ,CAAC,WAAW,CAAC,EAAE,KAAK,CAAA;IAC5B,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,CAAA;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,KAAK,CAAA;IAC7B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,KAAK,CAAA;CACpC,CACF,CAAA;AAcH;;;;;;GAMG;AACH,eAAO,MAAM,IAAI,GAAI,CAAC,GAAG,KAAK,WAAW,OAAO,CAAC,CAAC,CAAC,KAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,GAAG,CAAC,CACxF,CAAA;AA8FrB;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,GAAI,CAAC,GAAG,KAAK,WACpB,OAAO,CAAC,CAAC,CAAC,KAClB,KAAK,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,GAAG,CAAC,CAClB,CAAA;AAElD;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,GAAI,CAAC,GAAG,KAAK,WAC1B,aAAa,CAAC,CAAC,CAAC,KACxB,KAAK,CAAC,KAAK,CAAC,mBAAmB,EAAE,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC,UAAU,GAAG,CAAC,CAe9E,CAAA"}
|
|
@@ -1,21 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The `AmazonBedrockClient` module defines the low-level Effect service used to
|
|
3
|
-
* call Amazon Bedrock's Converse API. It wraps an `HttpClient` with SigV4
|
|
4
|
-
* request signing (via `aws4fetch`), request defaults, response decoding, and
|
|
5
|
-
* error mapping to the unified `AiError` type.
|
|
6
|
-
*
|
|
7
|
-
* **Mental model**
|
|
8
|
-
*
|
|
9
|
-
* `HttpClient.HttpClient` provides the transport. {@link make} turns explicit
|
|
10
|
-
* {@link Options} into an {@link AmazonBedrockClient} service, while
|
|
11
|
-
* {@link layer} and {@link layerConfig} provide that service as a layer. The
|
|
12
|
-
* service exposes handwritten helpers for the `converse` (non-streaming) and
|
|
13
|
-
* `converse-stream` (streaming) endpoints.
|
|
14
|
-
*
|
|
15
|
-
* @stability unstable
|
|
16
|
-
* @since 4.0.0
|
|
17
|
-
*/
|
|
18
|
-
import { AwsV4Signer } from "aws4fetch";
|
|
19
1
|
import * as Array from "effect/Array";
|
|
20
2
|
import * as Context from "effect/Context";
|
|
21
3
|
import * as Effect from "effect/Effect";
|
|
@@ -26,12 +8,11 @@ import * as HttpClient from "effect/http/HttpClient";
|
|
|
26
8
|
import * as HttpClientRequest from "effect/http/HttpClientRequest";
|
|
27
9
|
import * as HttpClientResponse from "effect/http/HttpClientResponse";
|
|
28
10
|
import * as Layer from "effect/Layer";
|
|
29
|
-
import * as Predicate from "effect/Predicate";
|
|
30
|
-
import * as Redacted from "effect/Redacted";
|
|
31
11
|
import * as Stream from "effect/Stream";
|
|
32
12
|
import { AmazonBedrockConfig } from "./AmazonBedrockConfig.js";
|
|
33
13
|
import * as EventStream from "./AmazonBedrockEventStream.js";
|
|
34
14
|
import { ConverseResponse, ConverseResponseStreamEvent } from "./AmazonBedrockSchema.js";
|
|
15
|
+
import * as Authentication from "./internal/credentials.js";
|
|
35
16
|
import * as Errors from "./internal/errors.js";
|
|
36
17
|
// =============================================================================
|
|
37
18
|
// Service Identifier
|
|
@@ -41,7 +22,7 @@ import * as Errors from "./internal/errors.js";
|
|
|
41
22
|
*
|
|
42
23
|
* @stability unstable
|
|
43
24
|
* @category services
|
|
44
|
-
* @since
|
|
25
|
+
* @since 0.1.0
|
|
45
26
|
*/
|
|
46
27
|
export class AmazonBedrockClient extends /*#__PURE__*/Context.Service()("@wmaurer/effect-ai-amazon-bedrock/AmazonBedrockClient") {}
|
|
47
28
|
// =============================================================================
|
|
@@ -57,48 +38,35 @@ const withRedactedHeaders = /*#__PURE__*/Effect.updateService(Headers.CurrentRed
|
|
|
57
38
|
*
|
|
58
39
|
* @stability unstable
|
|
59
40
|
* @category constructors
|
|
60
|
-
* @since
|
|
41
|
+
* @since 0.1.0
|
|
61
42
|
*/
|
|
62
|
-
export const make =
|
|
43
|
+
export const make = options => makeUnsafe(options);
|
|
44
|
+
// Takes each authentication field as optional, as `layerConfig` reads them.
|
|
45
|
+
// `Authentication.make` dies on a mix of the ways to authenticate.
|
|
46
|
+
const makeUnsafe = options => Effect.gen(function* () {
|
|
63
47
|
const region = options.region ?? "us-east-1";
|
|
48
|
+
const authenticator = yield* Authentication.make(options);
|
|
64
49
|
const baseClient = yield* HttpClient.HttpClient;
|
|
65
|
-
const httpClient = baseClient.pipe(HttpClient.mapRequest(request => request.pipe(HttpClientRequest.prependUrl(options.apiUrl ?? `https://bedrock-runtime.${region}.amazonaws.com`), HttpClientRequest.acceptJson)), HttpClient.mapRequestEffect(
|
|
66
|
-
const originalHeaders = request.headers;
|
|
67
|
-
const signer = new AwsV4Signer({
|
|
68
|
-
service: "bedrock",
|
|
69
|
-
url: request.url,
|
|
70
|
-
method: request.method,
|
|
71
|
-
headers: Object.entries(originalHeaders),
|
|
72
|
-
body: prepareBody(request.body),
|
|
73
|
-
region,
|
|
74
|
-
accessKeyId: options.accessKeyId,
|
|
75
|
-
secretAccessKey: Redacted.value(options.secretAccessKey),
|
|
76
|
-
...(options.sessionToken ? {
|
|
77
|
-
sessionToken: Redacted.value(options.sessionToken)
|
|
78
|
-
} : {})
|
|
79
|
-
});
|
|
80
|
-
const {
|
|
81
|
-
headers: signedHeaders
|
|
82
|
-
} = yield* Effect.promise(() => signer.sign());
|
|
83
|
-
const headers = Headers.merge(originalHeaders, Headers.fromInput(signedHeaders));
|
|
84
|
-
return HttpClientRequest.setHeaders(request, headers);
|
|
85
|
-
})), options.transformClient ? options.transformClient : identity);
|
|
50
|
+
const httpClient = baseClient.pipe(HttpClient.mapRequest(request => request.pipe(HttpClientRequest.prependUrl(options.apiUrl ?? `https://bedrock-runtime.${region}.amazonaws.com`), HttpClientRequest.acceptJson)), HttpClient.mapRequestEffect(Authentication.authenticateRequest(region)), options.transformClient ? options.transformClient : identity);
|
|
86
51
|
const httpClientOk = HttpClient.filterStatusOk(httpClient);
|
|
87
52
|
const withConfigClient = Effect.fnUntraced(function* () {
|
|
88
53
|
const config = yield* AmazonBedrockConfig.getOrUndefined;
|
|
89
54
|
return config?.transformClient ? config.transformClient(httpClientOk) : httpClientOk;
|
|
90
55
|
});
|
|
56
|
+
const resolveCredentials = method => Effect.mapError(authenticator.resolve, Errors.mapCredentialProviderError(method));
|
|
91
57
|
const converse = ({
|
|
92
58
|
payload: {
|
|
93
59
|
modelId,
|
|
94
60
|
...body
|
|
95
61
|
}
|
|
96
|
-
}) => Effect.
|
|
62
|
+
}) => Effect.gen(function* () {
|
|
63
|
+
const client = yield* withConfigClient();
|
|
64
|
+
const credentials = yield* resolveCredentials("converse");
|
|
97
65
|
const request = HttpClientRequest.post(`/model/${modelId}/converse`, {
|
|
98
66
|
body: HttpBody.jsonUnsafe(body)
|
|
99
67
|
});
|
|
100
|
-
return client.execute(request).pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(ConverseResponse)), Effect.catchTags({
|
|
101
|
-
HttpClientError: error => Errors.mapHttpClientError(error, "converse"),
|
|
68
|
+
return yield* client.execute(request).pipe(Effect.provideService(Authentication.CurrentRequestCredentials, credentials), Effect.flatMap(HttpClientResponse.schemaBodyJson(ConverseResponse)), Effect.catchTags({
|
|
69
|
+
HttpClientError: error => Errors.mapHttpClientError(error, "converse").pipe(Effect.tapError(Authentication.invalidateIfRejected(authenticator, credentials))),
|
|
102
70
|
SchemaError: error => Effect.fail(Errors.mapSchemaError(error, "converse"))
|
|
103
71
|
}), withRedactedHeaders);
|
|
104
72
|
});
|
|
@@ -111,17 +79,21 @@ export const make = /*#__PURE__*/Effect.fnUntraced(function* (options) {
|
|
|
111
79
|
const request = HttpClientRequest.post(`/model/${modelId}/converse-stream`, {
|
|
112
80
|
body: HttpBody.jsonUnsafe(body)
|
|
113
81
|
});
|
|
114
|
-
return Stream.unwrap(Effect.
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
82
|
+
return Stream.unwrap(Effect.gen(function* () {
|
|
83
|
+
const client = yield* withConfigClient();
|
|
84
|
+
const credentials = yield* resolveCredentials("converseStream");
|
|
85
|
+
return client.execute(request).pipe(Effect.provideService(Authentication.CurrentRequestCredentials, credentials), Effect.map(response => response.stream), Stream.unwrap, Stream.pipeThroughChannel(EventStream.makeChannel(ConverseResponseStreamEvent)), Stream.catchTags({
|
|
86
|
+
HttpClientError: error => Stream.fromEffect(Errors.mapHttpClientError(error, "converseStream").pipe(Effect.tapError(Authentication.invalidateIfRejected(authenticator, credentials)))),
|
|
87
|
+
SchemaError: error => Stream.fail(Errors.mapSchemaError(error, "converseStream")),
|
|
88
|
+
EventStreamError: error => Stream.fail(Errors.mapEventStreamError(error, "converseStream"))
|
|
89
|
+
}), Stream.updateService(Headers.CurrentRedactedNames, appendRedactedHeaders));
|
|
90
|
+
}));
|
|
119
91
|
};
|
|
120
92
|
return AmazonBedrockClient.of({
|
|
121
93
|
converse,
|
|
122
94
|
converseStream
|
|
123
95
|
});
|
|
124
|
-
}
|
|
96
|
+
}).pipe(withRedactedHeaders);
|
|
125
97
|
// =============================================================================
|
|
126
98
|
// Layers
|
|
127
99
|
// =============================================================================
|
|
@@ -130,7 +102,7 @@ export const make = /*#__PURE__*/Effect.fnUntraced(function* (options) {
|
|
|
130
102
|
*
|
|
131
103
|
* @stability unstable
|
|
132
104
|
* @category layers
|
|
133
|
-
* @since
|
|
105
|
+
* @since 0.1.0
|
|
134
106
|
*/
|
|
135
107
|
export const layer = options => Layer.effect(AmazonBedrockClient, make(options));
|
|
136
108
|
/**
|
|
@@ -139,47 +111,19 @@ export const layer = options => Layer.effect(AmazonBedrockClient, make(options))
|
|
|
139
111
|
*
|
|
140
112
|
* @stability unstable
|
|
141
113
|
* @category layers
|
|
142
|
-
* @since
|
|
114
|
+
* @since 0.1.0
|
|
143
115
|
*/
|
|
144
116
|
export const layerConfig = options => Layer.effect(AmazonBedrockClient, Effect.gen(function* () {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
secretAccessKey,
|
|
154
|
-
sessionToken,
|
|
155
|
-
region,
|
|
117
|
+
return yield* makeUnsafe({
|
|
118
|
+
apiUrl: yield* readOptional(options.apiUrl),
|
|
119
|
+
region: yield* readOptional(options.region),
|
|
120
|
+
accessKeyId: yield* readOptional(options.accessKeyId),
|
|
121
|
+
secretAccessKey: yield* readOptional(options.secretAccessKey),
|
|
122
|
+
sessionToken: yield* readOptional(options.sessionToken),
|
|
123
|
+
apiKey: yield* readOptional(options.apiKey),
|
|
124
|
+
credentialProvider: options.credentialProvider,
|
|
156
125
|
transformClient: options.transformClient
|
|
157
126
|
});
|
|
158
127
|
}));
|
|
159
|
-
|
|
160
|
-
// Utilities
|
|
161
|
-
// =============================================================================
|
|
162
|
-
const prepareBody = body => {
|
|
163
|
-
switch (body._tag) {
|
|
164
|
-
case "Empty":
|
|
165
|
-
{
|
|
166
|
-
return "";
|
|
167
|
-
}
|
|
168
|
-
case "Raw":
|
|
169
|
-
case "Uint8Array":
|
|
170
|
-
{
|
|
171
|
-
if (typeof body.body === "string") {
|
|
172
|
-
return body.body;
|
|
173
|
-
}
|
|
174
|
-
if (body.body instanceof Uint8Array) {
|
|
175
|
-
return new TextDecoder().decode(body.body);
|
|
176
|
-
}
|
|
177
|
-
if (body.body instanceof ArrayBuffer) {
|
|
178
|
-
return new TextDecoder().decode(body.body);
|
|
179
|
-
}
|
|
180
|
-
return JSON.stringify(body.body);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
throw new Error("Unsupported HttpBody: " + body._tag);
|
|
184
|
-
};
|
|
128
|
+
const readOptional = config => config === undefined ? Effect.undefined : config;
|
|
185
129
|
//# sourceMappingURL=AmazonBedrockClient.js.map
|