@jecruz/merc-ai 0.1.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.
Files changed (218) hide show
  1. package/README.md +1453 -0
  2. package/dist/api-registry.d.ts +20 -0
  3. package/dist/api-registry.d.ts.map +1 -0
  4. package/dist/api-registry.js +44 -0
  5. package/dist/api-registry.js.map +1 -0
  6. package/dist/bedrock-provider.d.ts +5 -0
  7. package/dist/bedrock-provider.d.ts.map +1 -0
  8. package/dist/bedrock-provider.js +6 -0
  9. package/dist/bedrock-provider.js.map +1 -0
  10. package/dist/cli.d.ts +3 -0
  11. package/dist/cli.d.ts.map +1 -0
  12. package/dist/cli.js +116 -0
  13. package/dist/cli.js.map +1 -0
  14. package/dist/env-api-keys.d.ts +18 -0
  15. package/dist/env-api-keys.d.ts.map +1 -0
  16. package/dist/env-api-keys.js +134 -0
  17. package/dist/env-api-keys.js.map +1 -0
  18. package/dist/image-models.d.ts +10 -0
  19. package/dist/image-models.d.ts.map +1 -0
  20. package/dist/image-models.generated.d.ts +530 -0
  21. package/dist/image-models.generated.d.ts.map +1 -0
  22. package/dist/image-models.generated.js +532 -0
  23. package/dist/image-models.generated.js.map +1 -0
  24. package/dist/image-models.js +23 -0
  25. package/dist/image-models.js.map +1 -0
  26. package/dist/images-api-registry.d.ts +14 -0
  27. package/dist/images-api-registry.d.ts.map +1 -0
  28. package/dist/images-api-registry.js +22 -0
  29. package/dist/images-api-registry.js.map +1 -0
  30. package/dist/images.d.ts +5 -0
  31. package/dist/images.d.ts.map +1 -0
  32. package/dist/images.js +18 -0
  33. package/dist/images.js.map +1 -0
  34. package/dist/index.d.ts +32 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +20 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/models.d.ts +22 -0
  39. package/dist/models.d.ts.map +1 -0
  40. package/dist/models.generated.d.ts +20591 -0
  41. package/dist/models.generated.d.ts.map +1 -0
  42. package/dist/models.generated.js +19123 -0
  43. package/dist/models.generated.js.map +1 -0
  44. package/dist/models.js +80 -0
  45. package/dist/models.js.map +1 -0
  46. package/dist/oauth.d.ts +2 -0
  47. package/dist/oauth.d.ts.map +1 -0
  48. package/dist/oauth.js +2 -0
  49. package/dist/oauth.js.map +1 -0
  50. package/dist/providers/amazon-bedrock.d.ts +38 -0
  51. package/dist/providers/amazon-bedrock.d.ts.map +1 -0
  52. package/dist/providers/amazon-bedrock.js +813 -0
  53. package/dist/providers/amazon-bedrock.js.map +1 -0
  54. package/dist/providers/anthropic.d.ts +54 -0
  55. package/dist/providers/anthropic.d.ts.map +1 -0
  56. package/dist/providers/anthropic.js +1035 -0
  57. package/dist/providers/anthropic.js.map +1 -0
  58. package/dist/providers/azure-openai-responses.d.ts +15 -0
  59. package/dist/providers/azure-openai-responses.d.ts.map +1 -0
  60. package/dist/providers/azure-openai-responses.js +219 -0
  61. package/dist/providers/azure-openai-responses.js.map +1 -0
  62. package/dist/providers/claude-cli.d.ts +4 -0
  63. package/dist/providers/claude-cli.d.ts.map +1 -0
  64. package/dist/providers/claude-cli.js +224 -0
  65. package/dist/providers/claude-cli.js.map +1 -0
  66. package/dist/providers/cloudflare.d.ts +13 -0
  67. package/dist/providers/cloudflare.d.ts.map +1 -0
  68. package/dist/providers/cloudflare.js +26 -0
  69. package/dist/providers/cloudflare.js.map +1 -0
  70. package/dist/providers/faux.d.ts +56 -0
  71. package/dist/providers/faux.d.ts.map +1 -0
  72. package/dist/providers/faux.js +377 -0
  73. package/dist/providers/faux.js.map +1 -0
  74. package/dist/providers/github-copilot-headers.d.ts +8 -0
  75. package/dist/providers/github-copilot-headers.d.ts.map +1 -0
  76. package/dist/providers/github-copilot-headers.js +29 -0
  77. package/dist/providers/github-copilot-headers.js.map +1 -0
  78. package/dist/providers/google-shared.d.ts +70 -0
  79. package/dist/providers/google-shared.d.ts.map +1 -0
  80. package/dist/providers/google-shared.js +329 -0
  81. package/dist/providers/google-shared.js.map +1 -0
  82. package/dist/providers/google-vertex.d.ts +15 -0
  83. package/dist/providers/google-vertex.d.ts.map +1 -0
  84. package/dist/providers/google-vertex.js +446 -0
  85. package/dist/providers/google-vertex.js.map +1 -0
  86. package/dist/providers/google.d.ts +13 -0
  87. package/dist/providers/google.d.ts.map +1 -0
  88. package/dist/providers/google.js +437 -0
  89. package/dist/providers/google.js.map +1 -0
  90. package/dist/providers/mistral.d.ts +25 -0
  91. package/dist/providers/mistral.d.ts.map +1 -0
  92. package/dist/providers/mistral.js +538 -0
  93. package/dist/providers/mistral.js.map +1 -0
  94. package/dist/providers/openai-codex-responses.d.ts +33 -0
  95. package/dist/providers/openai-codex-responses.d.ts.map +1 -0
  96. package/dist/providers/openai-codex-responses.js +1190 -0
  97. package/dist/providers/openai-codex-responses.js.map +1 -0
  98. package/dist/providers/openai-completions.d.ts +19 -0
  99. package/dist/providers/openai-completions.d.ts.map +1 -0
  100. package/dist/providers/openai-completions.js +1126 -0
  101. package/dist/providers/openai-completions.js.map +1 -0
  102. package/dist/providers/openai-responses-shared.d.ts +20 -0
  103. package/dist/providers/openai-responses-shared.d.ts.map +1 -0
  104. package/dist/providers/openai-responses-shared.js +543 -0
  105. package/dist/providers/openai-responses-shared.js.map +1 -0
  106. package/dist/providers/openai-responses.d.ts +14 -0
  107. package/dist/providers/openai-responses.d.ts.map +1 -0
  108. package/dist/providers/openai-responses.js +253 -0
  109. package/dist/providers/openai-responses.js.map +1 -0
  110. package/dist/providers/openrouter-images.d.ts +3 -0
  111. package/dist/providers/openrouter-images.d.ts.map +1 -0
  112. package/dist/providers/openrouter-images.js +139 -0
  113. package/dist/providers/openrouter-images.js.map +1 -0
  114. package/dist/providers/register-builtins.d.ts +37 -0
  115. package/dist/providers/register-builtins.d.ts.map +1 -0
  116. package/dist/providers/register-builtins.js +261 -0
  117. package/dist/providers/register-builtins.js.map +1 -0
  118. package/dist/providers/register-images-builtins.d.ts +4 -0
  119. package/dist/providers/register-images-builtins.d.ts.map +1 -0
  120. package/dist/providers/register-images-builtins.js +48 -0
  121. package/dist/providers/register-images-builtins.js.map +1 -0
  122. package/dist/providers/simple-options.d.ts +8 -0
  123. package/dist/providers/simple-options.d.ts.map +1 -0
  124. package/dist/providers/simple-options.js +47 -0
  125. package/dist/providers/simple-options.js.map +1 -0
  126. package/dist/providers/transform-messages.d.ts +8 -0
  127. package/dist/providers/transform-messages.d.ts.map +1 -0
  128. package/dist/providers/transform-messages.js +193 -0
  129. package/dist/providers/transform-messages.js.map +1 -0
  130. package/dist/session-resources.d.ts +4 -0
  131. package/dist/session-resources.d.ts.map +1 -0
  132. package/dist/session-resources.js +22 -0
  133. package/dist/session-resources.js.map +1 -0
  134. package/dist/stream.d.ts +8 -0
  135. package/dist/stream.d.ts.map +1 -0
  136. package/dist/stream.js +27 -0
  137. package/dist/stream.js.map +1 -0
  138. package/dist/types.d.ts +556 -0
  139. package/dist/types.d.ts.map +1 -0
  140. package/dist/types.js +2 -0
  141. package/dist/types.js.map +1 -0
  142. package/dist/utils/deferred-tools.d.ts +15 -0
  143. package/dist/utils/deferred-tools.d.ts.map +1 -0
  144. package/dist/utils/deferred-tools.js +48 -0
  145. package/dist/utils/deferred-tools.js.map +1 -0
  146. package/dist/utils/diagnostics.d.ts +19 -0
  147. package/dist/utils/diagnostics.d.ts.map +1 -0
  148. package/dist/utils/diagnostics.js +25 -0
  149. package/dist/utils/diagnostics.js.map +1 -0
  150. package/dist/utils/error-body.d.ts +20 -0
  151. package/dist/utils/error-body.d.ts.map +1 -0
  152. package/dist/utils/error-body.js +71 -0
  153. package/dist/utils/error-body.js.map +1 -0
  154. package/dist/utils/event-stream.d.ts +26 -0
  155. package/dist/utils/event-stream.d.ts.map +1 -0
  156. package/dist/utils/event-stream.js +98 -0
  157. package/dist/utils/event-stream.js.map +1 -0
  158. package/dist/utils/hash.d.ts +3 -0
  159. package/dist/utils/hash.d.ts.map +1 -0
  160. package/dist/utils/hash.js +14 -0
  161. package/dist/utils/hash.js.map +1 -0
  162. package/dist/utils/headers.d.ts +2 -0
  163. package/dist/utils/headers.d.ts.map +1 -0
  164. package/dist/utils/headers.js +8 -0
  165. package/dist/utils/headers.js.map +1 -0
  166. package/dist/utils/json-parse.d.ts +16 -0
  167. package/dist/utils/json-parse.d.ts.map +1 -0
  168. package/dist/utils/json-parse.js +113 -0
  169. package/dist/utils/json-parse.js.map +1 -0
  170. package/dist/utils/oauth/anthropic.d.ts +25 -0
  171. package/dist/utils/oauth/anthropic.d.ts.map +1 -0
  172. package/dist/utils/oauth/anthropic.js +335 -0
  173. package/dist/utils/oauth/anthropic.js.map +1 -0
  174. package/dist/utils/oauth/github-copilot.d.ts +30 -0
  175. package/dist/utils/oauth/github-copilot.d.ts.map +1 -0
  176. package/dist/utils/oauth/github-copilot.js +351 -0
  177. package/dist/utils/oauth/github-copilot.js.map +1 -0
  178. package/dist/utils/oauth/index.d.ts +57 -0
  179. package/dist/utils/oauth/index.d.ts.map +1 -0
  180. package/dist/utils/oauth/index.js +121 -0
  181. package/dist/utils/oauth/index.js.map +1 -0
  182. package/dist/utils/oauth/oauth-page.d.ts +3 -0
  183. package/dist/utils/oauth/oauth-page.d.ts.map +1 -0
  184. package/dist/utils/oauth/oauth-page.js +105 -0
  185. package/dist/utils/oauth/oauth-page.js.map +1 -0
  186. package/dist/utils/oauth/openai-codex.d.ts +34 -0
  187. package/dist/utils/oauth/openai-codex.d.ts.map +1 -0
  188. package/dist/utils/oauth/openai-codex.js +374 -0
  189. package/dist/utils/oauth/openai-codex.js.map +1 -0
  190. package/dist/utils/oauth/pkce.d.ts +13 -0
  191. package/dist/utils/oauth/pkce.d.ts.map +1 -0
  192. package/dist/utils/oauth/pkce.js +31 -0
  193. package/dist/utils/oauth/pkce.js.map +1 -0
  194. package/dist/utils/oauth/types.d.ts +57 -0
  195. package/dist/utils/oauth/types.d.ts.map +1 -0
  196. package/dist/utils/oauth/types.js +2 -0
  197. package/dist/utils/oauth/types.js.map +1 -0
  198. package/dist/utils/overflow.d.ts +56 -0
  199. package/dist/utils/overflow.d.ts.map +1 -0
  200. package/dist/utils/overflow.js +152 -0
  201. package/dist/utils/overflow.js.map +1 -0
  202. package/dist/utils/provider-env.d.ts +9 -0
  203. package/dist/utils/provider-env.d.ts.map +1 -0
  204. package/dist/utils/provider-env.js +82 -0
  205. package/dist/utils/provider-env.js.map +1 -0
  206. package/dist/utils/sanitize-unicode.d.ts +22 -0
  207. package/dist/utils/sanitize-unicode.d.ts.map +1 -0
  208. package/dist/utils/sanitize-unicode.js +26 -0
  209. package/dist/utils/sanitize-unicode.js.map +1 -0
  210. package/dist/utils/typebox-helpers.d.ts +17 -0
  211. package/dist/utils/typebox-helpers.d.ts.map +1 -0
  212. package/dist/utils/typebox-helpers.js +21 -0
  213. package/dist/utils/typebox-helpers.js.map +1 -0
  214. package/dist/utils/validation.d.ts +18 -0
  215. package/dist/utils/validation.d.ts.map +1 -0
  216. package/dist/utils/validation.js +281 -0
  217. package/dist/utils/validation.js.map +1 -0
  218. package/package.json +113 -0
@@ -0,0 +1,813 @@
1
+ import { BedrockRuntimeClient, BedrockRuntimeServiceException, StopReason as BedrockStopReason, CachePointType, CacheTTL, ConversationRole, ConverseStreamCommand, ImageFormat, ToolResultStatus, } from "@aws-sdk/client-bedrock-runtime";
2
+ import { calculateCost } from "../models.js";
3
+ import { normalizeProviderError } from "../utils/error-body.js";
4
+ import { AssistantMessageEventStream } from "../utils/event-stream.js";
5
+ import { parseStreamingJson } from "../utils/json-parse.js";
6
+ import { getProviderEnvValue } from "../utils/provider-env.js";
7
+ import { sanitizeSurrogates } from "../utils/sanitize-unicode.js";
8
+ import { adjustMaxTokensForThinking, buildBaseOptions, clampReasoning } from "./simple-options.js";
9
+ import { transformMessages } from "./transform-messages.js";
10
+ function isAmbientAuthMarker(value) {
11
+ return value === "<authenticated>";
12
+ }
13
+ export const streamBedrock = (model, context, options = {}) => {
14
+ const stream = new AssistantMessageEventStream();
15
+ (async () => {
16
+ const output = {
17
+ role: "assistant",
18
+ content: [],
19
+ api: "bedrock-converse-stream",
20
+ provider: model.provider,
21
+ model: model.id,
22
+ usage: {
23
+ input: 0,
24
+ output: 0,
25
+ cacheRead: 0,
26
+ cacheWrite: 0,
27
+ totalTokens: 0,
28
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
29
+ },
30
+ stopReason: "stop",
31
+ timestamp: Date.now(),
32
+ };
33
+ const blocks = output.content;
34
+ const config = {
35
+ profile: options.profile || getProviderEnvValue("AWS_PROFILE", options.env),
36
+ };
37
+ const configuredRegion = getConfiguredBedrockRegion(options);
38
+ const hasConfiguredProfile = hasConfiguredBedrockProfile(options.env);
39
+ const endpointRegion = getStandardBedrockEndpointRegion(model.baseUrl);
40
+ const useExplicitEndpoint = shouldUseExplicitBedrockEndpoint(model.baseUrl, configuredRegion, hasConfiguredProfile);
41
+ // Only pin standard AWS Bedrock runtime endpoints when no region/profile is configured.
42
+ // This preserves custom endpoints (VPC/proxy) from #3402 without forcing built-in
43
+ // catalog defaults such as us-east-1 to override AWS_REGION/AWS_PROFILE.
44
+ if (useExplicitEndpoint) {
45
+ config.endpoint = model.baseUrl;
46
+ }
47
+ // Resolve bearer token for Bedrock API key auth.
48
+ const bearerToken = [
49
+ options.bearerToken,
50
+ options.apiKey,
51
+ getProviderEnvValue("AWS_BEARER_TOKEN_BEDROCK", options.env),
52
+ ].find((value) => !!value && !isAmbientAuthMarker(value));
53
+ const useBearerToken = bearerToken !== undefined && getProviderEnvValue("AWS_BEDROCK_SKIP_AUTH", options.env) !== "1";
54
+ // in Node.js/Bun environment only
55
+ if (typeof process !== "undefined" && (process.versions?.node || process.versions?.bun)) {
56
+ // Region resolution: ARN-embedded > explicit option > env vars > SDK default chain.
57
+ // When the model ID is an inference profile ARN, extract the region from it.
58
+ // This avoids conflicts with AWS_REGION set for other services.
59
+ const arnRegionMatch = model.id.match(/^arn:aws(?:-[a-z0-9-]+)?:bedrock:([a-z0-9-]+):/);
60
+ if (arnRegionMatch) {
61
+ config.region = arnRegionMatch[1];
62
+ }
63
+ else if (configuredRegion) {
64
+ config.region = configuredRegion;
65
+ }
66
+ else if (endpointRegion && useExplicitEndpoint) {
67
+ config.region = endpointRegion;
68
+ }
69
+ else if (!hasConfiguredProfile) {
70
+ config.region = "us-east-1";
71
+ }
72
+ // Support proxies that don't need authentication
73
+ if (getProviderEnvValue("AWS_BEDROCK_SKIP_AUTH", options.env) === "1") {
74
+ config.credentials = {
75
+ accessKeyId: "dummy-access-key",
76
+ secretAccessKey: "dummy-secret-key",
77
+ };
78
+ }
79
+ if (getProviderEnvValue("HTTP_PROXY", options.env) ||
80
+ getProviderEnvValue("HTTPS_PROXY", options.env) ||
81
+ getProviderEnvValue("NO_PROXY", options.env) ||
82
+ getProviderEnvValue("http_proxy", options.env) ||
83
+ getProviderEnvValue("https_proxy", options.env) ||
84
+ getProviderEnvValue("no_proxy", options.env)) {
85
+ const nodeHttpHandler = await import("@smithy/node-http-handler");
86
+ const proxyAgent = await import("proxy-agent");
87
+ const agent = new proxyAgent.ProxyAgent();
88
+ // Bedrock runtime uses NodeHttp2Handler by default since v3.798.0, which is based
89
+ // on `http2` module and has no support for http agent.
90
+ // Use NodeHttpHandler to support http agent.
91
+ config.requestHandler = new nodeHttpHandler.NodeHttpHandler({
92
+ httpAgent: agent,
93
+ httpsAgent: agent,
94
+ });
95
+ }
96
+ else if (getProviderEnvValue("AWS_BEDROCK_FORCE_HTTP1", options.env) === "1") {
97
+ // Some custom endpoints require HTTP/1.1 instead of HTTP/2
98
+ const nodeHttpHandler = await import("@smithy/node-http-handler");
99
+ config.requestHandler = new nodeHttpHandler.NodeHttpHandler();
100
+ }
101
+ }
102
+ else {
103
+ // Non-Node environment (browser): fall back to us-east-1 since
104
+ // there's no config file resolution available.
105
+ config.region =
106
+ configuredRegion || (endpointRegion && useExplicitEndpoint ? endpointRegion : undefined) || "us-east-1";
107
+ }
108
+ if (useBearerToken) {
109
+ config.token = { token: bearerToken };
110
+ config.authSchemePreference = ["httpBearerAuth"];
111
+ }
112
+ try {
113
+ const client = new BedrockRuntimeClient(config);
114
+ const cacheRetention = resolveCacheRetention(options.cacheRetention, options.env);
115
+ const inferenceMaxTokens = options.maxTokens ?? (isAnthropicClaudeModel(model) ? model.maxTokens : undefined);
116
+ let commandInput = {
117
+ modelId: model.id,
118
+ messages: convertMessages(context, model, cacheRetention, options.env),
119
+ system: buildSystemPrompt(context.systemPrompt, model, cacheRetention, options.env),
120
+ inferenceConfig: {
121
+ ...(inferenceMaxTokens !== undefined && { maxTokens: inferenceMaxTokens }),
122
+ ...(options.temperature !== undefined && { temperature: options.temperature }),
123
+ },
124
+ toolConfig: convertToolConfig(context.tools, options.toolChoice),
125
+ additionalModelRequestFields: buildAdditionalModelRequestFields(model, options),
126
+ ...(options.requestMetadata !== undefined && { requestMetadata: options.requestMetadata }),
127
+ };
128
+ const nextCommandInput = await options?.onPayload?.(commandInput, model);
129
+ if (nextCommandInput !== undefined) {
130
+ commandInput = nextCommandInput;
131
+ }
132
+ const command = new ConverseStreamCommand(commandInput);
133
+ const response = await client.send(command, { abortSignal: options.signal });
134
+ if (response.$metadata.httpStatusCode !== undefined) {
135
+ const responseHeaders = {};
136
+ if (response.$metadata.requestId) {
137
+ responseHeaders["x-amzn-requestid"] = response.$metadata.requestId;
138
+ }
139
+ await options?.onResponse?.({ status: response.$metadata.httpStatusCode, headers: responseHeaders }, model);
140
+ }
141
+ for await (const item of response.stream) {
142
+ if (item.messageStart) {
143
+ if (item.messageStart.role !== ConversationRole.ASSISTANT) {
144
+ throw new Error("Unexpected assistant message start but got user message start instead");
145
+ }
146
+ stream.push({ type: "start", partial: output });
147
+ }
148
+ else if (item.contentBlockStart) {
149
+ handleContentBlockStart(item.contentBlockStart, blocks, output, stream);
150
+ }
151
+ else if (item.contentBlockDelta) {
152
+ handleContentBlockDelta(item.contentBlockDelta, blocks, output, stream);
153
+ }
154
+ else if (item.contentBlockStop) {
155
+ handleContentBlockStop(item.contentBlockStop, blocks, output, stream);
156
+ }
157
+ else if (item.messageStop) {
158
+ const { stopReason, errorMessage } = mapStopReason(item.messageStop.stopReason);
159
+ output.stopReason = stopReason;
160
+ if (errorMessage) {
161
+ output.errorMessage = errorMessage;
162
+ }
163
+ }
164
+ else if (item.metadata) {
165
+ handleMetadata(item.metadata, model, output);
166
+ }
167
+ else if (item.internalServerException) {
168
+ throw item.internalServerException;
169
+ }
170
+ else if (item.modelStreamErrorException) {
171
+ throw item.modelStreamErrorException;
172
+ }
173
+ else if (item.validationException) {
174
+ throw item.validationException;
175
+ }
176
+ else if (item.throttlingException) {
177
+ throw item.throttlingException;
178
+ }
179
+ else if (item.serviceUnavailableException) {
180
+ throw item.serviceUnavailableException;
181
+ }
182
+ }
183
+ if (options.signal?.aborted) {
184
+ throw new Error("Request was aborted");
185
+ }
186
+ if (output.stopReason === "error" || output.stopReason === "aborted") {
187
+ throw new Error(output.errorMessage || "An unknown error occurred");
188
+ }
189
+ stream.push({ type: "done", reason: output.stopReason, message: output });
190
+ stream.end();
191
+ }
192
+ catch (error) {
193
+ for (const block of output.content) {
194
+ delete block.index;
195
+ // partialJson is only a streaming scratch buffer; never persist it.
196
+ delete block.partialJson;
197
+ }
198
+ output.stopReason = options.signal?.aborted ? "aborted" : "error";
199
+ output.errorMessage = formatBedrockError(error);
200
+ stream.push({ type: "error", reason: output.stopReason, error: output });
201
+ stream.end();
202
+ }
203
+ })();
204
+ return stream;
205
+ };
206
+ /**
207
+ * Human-readable prefixes for Bedrock SDK exception names.
208
+ * The downstream retry logic in agent-session matches patterns like
209
+ * `server.?error` and `service.?unavailable`, so we preserve the legacy
210
+ * prefix format rather than using the raw SDK exception name.
211
+ */
212
+ const BEDROCK_ERROR_PREFIXES = {
213
+ InternalServerException: "Internal server error",
214
+ ModelStreamErrorException: "Model stream error",
215
+ ValidationException: "Validation error",
216
+ ThrottlingException: "Throttling error",
217
+ ServiceUnavailableException: "Service unavailable",
218
+ };
219
+ /**
220
+ * Some models reject the account/profile's configured Bedrock data retention mode
221
+ * (e.g. "data retention mode 'default' is not available for this model"). Point
222
+ * users at the AWS docs explaining how to configure a supported mode.
223
+ */
224
+ const BEDROCK_DATA_RETENTION_DOCS_URL = "https://docs.aws.amazon.com/bedrock/latest/userguide/data-retention.html";
225
+ /**
226
+ * Format a Bedrock error with a human-readable prefix.
227
+ * AWS SDK exceptions (both from `client.send()` and from stream event items)
228
+ * extend BedrockRuntimeServiceException. We map the `.name` to a stable
229
+ * human-readable prefix so downstream consumers (retry logic, context-overflow
230
+ * detection) can distinguish error categories via simple string matching.
231
+ */
232
+ function formatBedrockError(error) {
233
+ const normalized = normalizeProviderError(error);
234
+ const message = !normalized.messageCarriesBody && normalized.status !== undefined && normalized.body !== undefined
235
+ ? `${normalized.status}: ${normalized.body}`
236
+ : normalized.message;
237
+ const dataRetentionHint = /data retention mode/i.test(message)
238
+ ? ` See ${BEDROCK_DATA_RETENTION_DOCS_URL} for supported data retention modes.`
239
+ : "";
240
+ if (error instanceof BedrockRuntimeServiceException) {
241
+ const prefix = BEDROCK_ERROR_PREFIXES[error.name] ?? error.name;
242
+ return `${prefix}: ${message}${dataRetentionHint}`;
243
+ }
244
+ return `${message}${dataRetentionHint}`;
245
+ }
246
+ export const streamSimpleBedrock = (model, context, options) => {
247
+ const base = buildBaseOptions(model, options, undefined);
248
+ if (!options?.reasoning) {
249
+ return streamBedrock(model, context, { ...base, reasoning: undefined });
250
+ }
251
+ if (isAnthropicClaudeModel(model)) {
252
+ if (supportsAdaptiveThinking(model.id, model.name)) {
253
+ return streamBedrock(model, context, {
254
+ ...base,
255
+ reasoning: options.reasoning,
256
+ thinkingBudgets: options.thinkingBudgets,
257
+ });
258
+ }
259
+ const adjusted = adjustMaxTokensForThinking(base.maxTokens || 0, model.maxTokens, options.reasoning, options.thinkingBudgets);
260
+ return streamBedrock(model, context, {
261
+ ...base,
262
+ maxTokens: adjusted.maxTokens,
263
+ reasoning: options.reasoning,
264
+ thinkingBudgets: {
265
+ ...(options.thinkingBudgets || {}),
266
+ [clampReasoning(options.reasoning)]: adjusted.thinkingBudget,
267
+ },
268
+ });
269
+ }
270
+ return streamBedrock(model, context, {
271
+ ...base,
272
+ reasoning: options.reasoning,
273
+ thinkingBudgets: options.thinkingBudgets,
274
+ });
275
+ };
276
+ function handleContentBlockStart(event, blocks, output, stream) {
277
+ const index = event.contentBlockIndex;
278
+ const start = event.start;
279
+ if (start?.toolUse) {
280
+ const block = {
281
+ type: "toolCall",
282
+ id: start.toolUse.toolUseId || "",
283
+ name: start.toolUse.name || "",
284
+ arguments: {},
285
+ partialJson: "",
286
+ index,
287
+ };
288
+ output.content.push(block);
289
+ stream.push({ type: "toolcall_start", contentIndex: blocks.length - 1, partial: output });
290
+ }
291
+ }
292
+ function handleContentBlockDelta(event, blocks, output, stream) {
293
+ const contentBlockIndex = event.contentBlockIndex;
294
+ const delta = event.delta;
295
+ let index = blocks.findIndex((b) => b.index === contentBlockIndex);
296
+ let block = blocks[index];
297
+ if (delta?.text !== undefined) {
298
+ // If no text block exists yet, create one, as `handleContentBlockStart` is not sent for text blocks
299
+ if (!block) {
300
+ const newBlock = { type: "text", text: "", index: contentBlockIndex };
301
+ output.content.push(newBlock);
302
+ index = blocks.length - 1;
303
+ block = blocks[index];
304
+ stream.push({ type: "text_start", contentIndex: index, partial: output });
305
+ }
306
+ if (block.type === "text") {
307
+ block.text += delta.text;
308
+ stream.push({ type: "text_delta", contentIndex: index, delta: delta.text, partial: output });
309
+ }
310
+ }
311
+ else if (delta?.toolUse && block?.type === "toolCall") {
312
+ block.partialJson = (block.partialJson || "") + (delta.toolUse.input || "");
313
+ block.arguments = parseStreamingJson(block.partialJson);
314
+ stream.push({ type: "toolcall_delta", contentIndex: index, delta: delta.toolUse.input || "", partial: output });
315
+ }
316
+ else if (delta?.reasoningContent) {
317
+ let thinkingBlock = block;
318
+ let thinkingIndex = index;
319
+ if (!thinkingBlock) {
320
+ const newBlock = { type: "thinking", thinking: "", thinkingSignature: "", index: contentBlockIndex };
321
+ output.content.push(newBlock);
322
+ thinkingIndex = blocks.length - 1;
323
+ thinkingBlock = blocks[thinkingIndex];
324
+ stream.push({ type: "thinking_start", contentIndex: thinkingIndex, partial: output });
325
+ }
326
+ if (thinkingBlock?.type === "thinking") {
327
+ if (delta.reasoningContent.text) {
328
+ thinkingBlock.thinking += delta.reasoningContent.text;
329
+ stream.push({
330
+ type: "thinking_delta",
331
+ contentIndex: thinkingIndex,
332
+ delta: delta.reasoningContent.text,
333
+ partial: output,
334
+ });
335
+ }
336
+ if (delta.reasoningContent.signature) {
337
+ thinkingBlock.thinkingSignature =
338
+ (thinkingBlock.thinkingSignature || "") + delta.reasoningContent.signature;
339
+ }
340
+ }
341
+ }
342
+ }
343
+ function handleMetadata(event, model, output) {
344
+ if (event.usage) {
345
+ output.usage.input = event.usage.inputTokens || 0;
346
+ output.usage.output = event.usage.outputTokens || 0;
347
+ output.usage.cacheRead = event.usage.cacheReadInputTokens || 0;
348
+ output.usage.cacheWrite = event.usage.cacheWriteInputTokens || 0;
349
+ output.usage.totalTokens = event.usage.totalTokens || output.usage.input + output.usage.output;
350
+ calculateCost(model, output.usage);
351
+ }
352
+ }
353
+ function handleContentBlockStop(event, blocks, output, stream) {
354
+ const index = blocks.findIndex((b) => b.index === event.contentBlockIndex);
355
+ const block = blocks[index];
356
+ if (!block)
357
+ return;
358
+ delete block.index;
359
+ switch (block.type) {
360
+ case "text":
361
+ stream.push({ type: "text_end", contentIndex: index, content: block.text, partial: output });
362
+ break;
363
+ case "thinking":
364
+ stream.push({ type: "thinking_end", contentIndex: index, content: block.thinking, partial: output });
365
+ break;
366
+ case "toolCall":
367
+ block.arguments = parseStreamingJson(block.partialJson);
368
+ // Finalize in-place and strip the scratch buffer so replay only
369
+ // carries parsed arguments.
370
+ delete block.partialJson;
371
+ stream.push({ type: "toolcall_end", contentIndex: index, toolCall: block, partial: output });
372
+ break;
373
+ }
374
+ }
375
+ /**
376
+ * Check if the model supports adaptive thinking (Opus 4.6+, Sonnet 4.6).
377
+ * Checks both model ID and model name to support application inference profiles
378
+ * whose ARNs don't contain the model name.
379
+ */
380
+ function getModelMatchCandidates(modelId, modelName) {
381
+ const values = modelName ? [modelId, modelName] : [modelId];
382
+ return values.flatMap((value) => {
383
+ const lower = value.toLowerCase();
384
+ return [lower, lower.replace(/[\s_.:]+/g, "-")];
385
+ });
386
+ }
387
+ function supportsAdaptiveThinking(modelId, modelName) {
388
+ const candidates = getModelMatchCandidates(modelId, modelName);
389
+ return candidates.some((s) => s.includes("opus-4-6") ||
390
+ s.includes("opus-4-7") ||
391
+ s.includes("opus-4-8") ||
392
+ s.includes("sonnet-4-6") ||
393
+ s.includes("sonnet-5") ||
394
+ s.includes("fable-5"));
395
+ }
396
+ function supportsNativeXhighEffort(model) {
397
+ const candidates = getModelMatchCandidates(model.id, model.name);
398
+ return candidates.some((s) => s.includes("opus-4-7") || s.includes("opus-4-8") || s.includes("sonnet-5") || s.includes("fable-5"));
399
+ }
400
+ function mapThinkingLevelToEffort(model, level) {
401
+ if (level === "xhigh" && supportsNativeXhighEffort(model))
402
+ return "xhigh";
403
+ if (level === "max" && supportsAdaptiveThinking(model.id, model.name))
404
+ return "max";
405
+ const mapped = level ? model.thinkingLevelMap?.[level] : undefined;
406
+ if (typeof mapped === "string")
407
+ return mapped;
408
+ switch (level) {
409
+ case "minimal":
410
+ case "low":
411
+ return "low";
412
+ case "medium":
413
+ return "medium";
414
+ case "high":
415
+ return "high";
416
+ default:
417
+ return "high";
418
+ }
419
+ }
420
+ /**
421
+ * Resolve cache retention preference.
422
+ * Defaults to "short" and uses PI_CACHE_RETENTION for backward compatibility.
423
+ */
424
+ function resolveCacheRetention(cacheRetention, env) {
425
+ if (cacheRetention) {
426
+ return cacheRetention;
427
+ }
428
+ if (getProviderEnvValue("PI_CACHE_RETENTION", env) === "long") {
429
+ return "long";
430
+ }
431
+ return "short";
432
+ }
433
+ /**
434
+ * Check if the model is an Anthropic Claude model on Bedrock.
435
+ * Checks both model ID and model name to support application inference profiles
436
+ * whose ARNs don't contain the model name.
437
+ */
438
+ function isAnthropicClaudeModel(model) {
439
+ const id = model.id.toLowerCase();
440
+ const name = model.name?.toLowerCase() ?? "";
441
+ return (id.includes("anthropic.claude") ||
442
+ id.includes("anthropic/claude") ||
443
+ name.includes("anthropic.claude") ||
444
+ name.includes("anthropic/claude") ||
445
+ name.includes("claude"));
446
+ }
447
+ /**
448
+ * Check if the model supports prompt caching.
449
+ * Supported: Claude 3.5 Haiku, Claude 3.7 Sonnet, Claude 4.x, and Claude 5 models
450
+ *
451
+ * For base models and system-defined inference profiles the model ID / ARN
452
+ * contains the model name, so we can decide locally.
453
+ *
454
+ * For application inference profiles (whose ARNs don't contain the model name),
455
+ * also checks model.name which is user-controlled via models.json or registerProvider.
456
+ * As a last resort, set AWS_BEDROCK_FORCE_CACHE=1 to enable cache points.
457
+ * Amazon Nova models have automatic caching and don't need explicit cache points.
458
+ */
459
+ function supportsPromptCaching(model, env) {
460
+ const candidates = getModelMatchCandidates(model.id, model.name);
461
+ const hasClaudeRef = candidates.some((s) => s.includes("claude"));
462
+ if (!hasClaudeRef) {
463
+ // Application inference profiles don't contain the model name in the ARN.
464
+ // Allow users to force cache points via environment variable.
465
+ if (getProviderEnvValue("AWS_BEDROCK_FORCE_CACHE", env) === "1")
466
+ return true;
467
+ return false;
468
+ }
469
+ // Claude 4.x models (opus-4, sonnet-4, haiku-4)
470
+ if (candidates.some((s) => s.includes("-4-")))
471
+ return true;
472
+ // Claude 3.7 Sonnet
473
+ if (candidates.some((s) => s.includes("claude-3-7-sonnet")))
474
+ return true;
475
+ // Claude 3.5 Haiku
476
+ if (candidates.some((s) => s.includes("claude-3-5-haiku")))
477
+ return true;
478
+ // Claude 5 models (Fable 5, Sonnet 5)
479
+ if (candidates.some((s) => s.includes("fable-5") || s.includes("sonnet-5")))
480
+ return true;
481
+ return false;
482
+ }
483
+ /**
484
+ * Check if the model supports thinking signatures in reasoningContent.
485
+ * Only Anthropic Claude models support the signature field.
486
+ * Other models (OpenAI, Qwen, Minimax, Moonshot, etc.) reject it with:
487
+ * "This model doesn't support the reasoningContent.reasoningText.signature field"
488
+ *
489
+ * Checks both model ID and model name to support application inference profiles.
490
+ */
491
+ function supportsThinkingSignature(model) {
492
+ return isAnthropicClaudeModel(model);
493
+ }
494
+ function buildSystemPrompt(systemPrompt, model, cacheRetention, env) {
495
+ if (!systemPrompt)
496
+ return undefined;
497
+ const blocks = [{ text: sanitizeSurrogates(systemPrompt) }];
498
+ // Add cache point for supported Claude models when caching is enabled
499
+ if (cacheRetention !== "none" && supportsPromptCaching(model, env)) {
500
+ blocks.push({
501
+ cachePoint: { type: CachePointType.DEFAULT, ...(cacheRetention === "long" ? { ttl: CacheTTL.ONE_HOUR } : {}) },
502
+ });
503
+ }
504
+ return blocks;
505
+ }
506
+ function normalizeToolCallId(id) {
507
+ const sanitized = id.replace(/[^a-zA-Z0-9_-]/g, "_");
508
+ return sanitized.length > 64 ? sanitized.slice(0, 64) : sanitized;
509
+ }
510
+ function convertMessages(context, model, cacheRetention, env) {
511
+ const result = [];
512
+ const transformedMessages = transformMessages(context.messages, model, normalizeToolCallId);
513
+ for (let i = 0; i < transformedMessages.length; i++) {
514
+ const m = transformedMessages[i];
515
+ switch (m.role) {
516
+ case "user": {
517
+ const content = [];
518
+ if (typeof m.content === "string") {
519
+ content.push({ text: sanitizeSurrogates(m.content) });
520
+ }
521
+ else {
522
+ for (const c of m.content) {
523
+ switch (c.type) {
524
+ case "text":
525
+ content.push({ text: sanitizeSurrogates(c.text) });
526
+ break;
527
+ case "image":
528
+ content.push({ image: createImageBlock(c.mimeType, c.data) });
529
+ break;
530
+ default:
531
+ continue;
532
+ }
533
+ }
534
+ }
535
+ if (content.length === 0)
536
+ continue;
537
+ result.push({
538
+ role: ConversationRole.USER,
539
+ content,
540
+ });
541
+ break;
542
+ }
543
+ case "assistant": {
544
+ // Skip assistant messages with empty content (e.g., from aborted requests)
545
+ // Bedrock rejects messages with empty content arrays
546
+ if (m.content.length === 0) {
547
+ continue;
548
+ }
549
+ const contentBlocks = [];
550
+ for (const c of m.content) {
551
+ switch (c.type) {
552
+ case "text":
553
+ // Skip empty text blocks
554
+ if (c.text.trim().length === 0)
555
+ continue;
556
+ contentBlocks.push({ text: sanitizeSurrogates(c.text) });
557
+ break;
558
+ case "toolCall":
559
+ contentBlocks.push({
560
+ toolUse: { toolUseId: c.id, name: c.name, input: c.arguments },
561
+ });
562
+ break;
563
+ case "thinking":
564
+ // Skip empty thinking blocks
565
+ if (c.thinking.trim().length === 0)
566
+ continue;
567
+ // Only Anthropic models support the signature field in reasoningText.
568
+ // For other models, we omit the signature to avoid errors like:
569
+ // "This model doesn't support the reasoningContent.reasoningText.signature field"
570
+ if (supportsThinkingSignature(model)) {
571
+ // Signatures arrive after thinking deltas. If a partial or externally
572
+ // persisted message lacks a signature, Bedrock rejects the replayed
573
+ // reasoning block. Fall back to plain text, matching Anthropic.
574
+ if (!c.thinkingSignature || c.thinkingSignature.trim().length === 0) {
575
+ contentBlocks.push({ text: sanitizeSurrogates(c.thinking) });
576
+ }
577
+ else {
578
+ contentBlocks.push({
579
+ reasoningContent: {
580
+ reasoningText: {
581
+ text: sanitizeSurrogates(c.thinking),
582
+ signature: c.thinkingSignature,
583
+ },
584
+ },
585
+ });
586
+ }
587
+ }
588
+ else {
589
+ contentBlocks.push({
590
+ reasoningContent: {
591
+ reasoningText: { text: sanitizeSurrogates(c.thinking) },
592
+ },
593
+ });
594
+ }
595
+ break;
596
+ default:
597
+ continue;
598
+ }
599
+ }
600
+ // Skip if all content blocks were filtered out
601
+ if (contentBlocks.length === 0) {
602
+ continue;
603
+ }
604
+ result.push({
605
+ role: ConversationRole.ASSISTANT,
606
+ content: contentBlocks,
607
+ });
608
+ break;
609
+ }
610
+ case "toolResult": {
611
+ // Collect all consecutive toolResult messages into a single user message
612
+ // Bedrock requires all tool results to be in one message
613
+ const toolResults = [];
614
+ // Add current tool result with all content blocks combined
615
+ toolResults.push({
616
+ toolResult: {
617
+ toolUseId: m.toolCallId,
618
+ content: m.content.map((c) => c.type === "image"
619
+ ? { image: createImageBlock(c.mimeType, c.data) }
620
+ : { text: sanitizeSurrogates(c.text) }),
621
+ status: m.isError ? ToolResultStatus.ERROR : ToolResultStatus.SUCCESS,
622
+ },
623
+ });
624
+ // Look ahead for consecutive toolResult messages
625
+ let j = i + 1;
626
+ while (j < transformedMessages.length && transformedMessages[j].role === "toolResult") {
627
+ const nextMsg = transformedMessages[j];
628
+ toolResults.push({
629
+ toolResult: {
630
+ toolUseId: nextMsg.toolCallId,
631
+ content: nextMsg.content.map((c) => c.type === "image"
632
+ ? { image: createImageBlock(c.mimeType, c.data) }
633
+ : { text: sanitizeSurrogates(c.text) }),
634
+ status: nextMsg.isError ? ToolResultStatus.ERROR : ToolResultStatus.SUCCESS,
635
+ },
636
+ });
637
+ j++;
638
+ }
639
+ // Skip the messages we've already processed
640
+ i = j - 1;
641
+ result.push({
642
+ role: ConversationRole.USER,
643
+ content: toolResults,
644
+ });
645
+ break;
646
+ }
647
+ default:
648
+ continue;
649
+ }
650
+ }
651
+ // Add cache point to the last user message for supported Claude models when caching is enabled
652
+ if (cacheRetention !== "none" && supportsPromptCaching(model, env) && result.length > 0) {
653
+ const lastMessage = result[result.length - 1];
654
+ if (lastMessage.role === ConversationRole.USER && lastMessage.content) {
655
+ lastMessage.content.push({
656
+ cachePoint: {
657
+ type: CachePointType.DEFAULT,
658
+ ...(cacheRetention === "long" ? { ttl: CacheTTL.ONE_HOUR } : {}),
659
+ },
660
+ });
661
+ }
662
+ }
663
+ return result;
664
+ }
665
+ function convertToolConfig(tools, toolChoice) {
666
+ if (!tools?.length || toolChoice === "none")
667
+ return undefined;
668
+ const bedrockTools = tools.map((tool) => ({
669
+ toolSpec: {
670
+ name: tool.name,
671
+ description: tool.description,
672
+ inputSchema: { json: tool.parameters },
673
+ },
674
+ }));
675
+ let bedrockToolChoice;
676
+ switch (toolChoice) {
677
+ case "auto":
678
+ bedrockToolChoice = { auto: {} };
679
+ break;
680
+ case "any":
681
+ bedrockToolChoice = { any: {} };
682
+ break;
683
+ default:
684
+ if (toolChoice?.type === "tool") {
685
+ bedrockToolChoice = { tool: { name: toolChoice.name } };
686
+ }
687
+ }
688
+ return { tools: bedrockTools, toolChoice: bedrockToolChoice };
689
+ }
690
+ function mapStopReason(reason) {
691
+ switch (reason) {
692
+ case BedrockStopReason.END_TURN:
693
+ case BedrockStopReason.STOP_SEQUENCE:
694
+ return { stopReason: "stop" };
695
+ case BedrockStopReason.MAX_TOKENS:
696
+ case BedrockStopReason.MODEL_CONTEXT_WINDOW_EXCEEDED:
697
+ return { stopReason: "length" };
698
+ case BedrockStopReason.TOOL_USE:
699
+ return { stopReason: "toolUse" };
700
+ default:
701
+ return reason ? { stopReason: "error", errorMessage: reason } : { stopReason: "error" };
702
+ }
703
+ }
704
+ function getConfiguredBedrockRegion(options) {
705
+ if (typeof process === "undefined") {
706
+ return options.region;
707
+ }
708
+ return (options.region ||
709
+ getProviderEnvValue("AWS_REGION", options.env) ||
710
+ getProviderEnvValue("AWS_DEFAULT_REGION", options.env) ||
711
+ undefined);
712
+ }
713
+ function hasConfiguredBedrockProfile(env) {
714
+ if (typeof process === "undefined") {
715
+ return false;
716
+ }
717
+ return Boolean(getProviderEnvValue("AWS_PROFILE", env));
718
+ }
719
+ function getStandardBedrockEndpointRegion(baseUrl) {
720
+ if (!baseUrl) {
721
+ return undefined;
722
+ }
723
+ try {
724
+ const { hostname } = new URL(baseUrl);
725
+ const match = hostname.toLowerCase().match(/^bedrock-runtime(?:-fips)?\.([a-z0-9-]+)\.amazonaws\.com(?:\.cn)?$/);
726
+ return match?.[1];
727
+ }
728
+ catch {
729
+ return undefined;
730
+ }
731
+ }
732
+ function shouldUseExplicitBedrockEndpoint(baseUrl, configuredRegion, hasConfiguredProfile) {
733
+ const endpointRegion = getStandardBedrockEndpointRegion(baseUrl);
734
+ if (!endpointRegion) {
735
+ return true;
736
+ }
737
+ return !configuredRegion && !hasConfiguredProfile;
738
+ }
739
+ function isGovCloudBedrockTarget(model, options) {
740
+ const region = getConfiguredBedrockRegion(options);
741
+ if (region?.toLowerCase().startsWith("us-gov-")) {
742
+ return true;
743
+ }
744
+ const modelId = model.id.toLowerCase();
745
+ return modelId.startsWith("us-gov.") || modelId.startsWith("arn:aws-us-gov:");
746
+ }
747
+ function buildAdditionalModelRequestFields(model, options) {
748
+ if (!options.reasoning || !model.reasoning) {
749
+ return undefined;
750
+ }
751
+ if (isAnthropicClaudeModel(model)) {
752
+ // GovCloud Bedrock currently rejects the Claude thinking.display field.
753
+ // Omit it there until the GovCloud Converse schema catches up.
754
+ const display = isGovCloudBedrockTarget(model, options) ? undefined : (options.thinkingDisplay ?? "summarized");
755
+ const result = supportsAdaptiveThinking(model.id, model.name)
756
+ ? {
757
+ thinking: { type: "adaptive", ...(display !== undefined ? { display } : {}) },
758
+ output_config: { effort: mapThinkingLevelToEffort(model, options.reasoning) },
759
+ }
760
+ : (() => {
761
+ const defaultBudgets = {
762
+ minimal: 1024,
763
+ low: 2048,
764
+ medium: 8192,
765
+ high: 16384,
766
+ xhigh: 16384, // Claude doesn't support xhigh, clamp to high
767
+ max: 16384, // Non-adaptive Claude models do not support max effort
768
+ };
769
+ // Custom budgets override defaults; extended effort levels use the high budget.
770
+ const level = options.reasoning === "xhigh" || options.reasoning === "max" ? "high" : options.reasoning;
771
+ const budget = options.thinkingBudgets?.[level] ?? defaultBudgets[level];
772
+ return {
773
+ thinking: {
774
+ type: "enabled",
775
+ budget_tokens: budget,
776
+ ...(display !== undefined ? { display } : {}),
777
+ },
778
+ };
779
+ })();
780
+ if (!supportsAdaptiveThinking(model.id, model.name) && (options.interleavedThinking ?? true)) {
781
+ result.anthropic_beta = ["interleaved-thinking-2025-05-14"];
782
+ }
783
+ return result;
784
+ }
785
+ return undefined;
786
+ }
787
+ function createImageBlock(mimeType, data) {
788
+ let format;
789
+ switch (mimeType) {
790
+ case "image/jpeg":
791
+ case "image/jpg":
792
+ format = ImageFormat.JPEG;
793
+ break;
794
+ case "image/png":
795
+ format = ImageFormat.PNG;
796
+ break;
797
+ case "image/gif":
798
+ format = ImageFormat.GIF;
799
+ break;
800
+ case "image/webp":
801
+ format = ImageFormat.WEBP;
802
+ break;
803
+ default:
804
+ throw new Error(`Unknown image type: ${mimeType}`);
805
+ }
806
+ const binaryString = atob(data);
807
+ const bytes = new Uint8Array(binaryString.length);
808
+ for (let i = 0; i < binaryString.length; i++) {
809
+ bytes[i] = binaryString.charCodeAt(i);
810
+ }
811
+ return { source: { bytes }, format };
812
+ }
813
+ //# sourceMappingURL=amazon-bedrock.js.map