@node-llm/core 1.7.0 → 1.9.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 (132) hide show
  1. package/README.md +9 -8
  2. package/dist/aliases.d.ts +216 -0
  3. package/dist/aliases.d.ts.map +1 -1
  4. package/dist/aliases.js +241 -25
  5. package/dist/chat/Chat.d.ts +8 -4
  6. package/dist/chat/Chat.d.ts.map +1 -1
  7. package/dist/chat/Chat.js +33 -5
  8. package/dist/chat/ChatResponse.d.ts +28 -3
  9. package/dist/chat/ChatResponse.d.ts.map +1 -1
  10. package/dist/chat/ChatResponse.js +79 -6
  11. package/dist/chat/ChatStream.d.ts.map +1 -1
  12. package/dist/chat/ChatStream.js +13 -1
  13. package/dist/chat/Content.d.ts +7 -0
  14. package/dist/chat/Content.d.ts.map +1 -1
  15. package/dist/config.d.ts +28 -0
  16. package/dist/config.d.ts.map +1 -1
  17. package/dist/config.js +58 -6
  18. package/dist/constants.d.ts +6 -0
  19. package/dist/constants.d.ts.map +1 -1
  20. package/dist/constants.js +6 -0
  21. package/dist/errors/index.d.ts +20 -2
  22. package/dist/errors/index.d.ts.map +1 -1
  23. package/dist/errors/index.js +31 -3
  24. package/dist/index.d.ts +2 -2
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/llm.d.ts.map +1 -1
  27. package/dist/llm.js +3 -2
  28. package/dist/models/ModelRegistry.d.ts.map +1 -1
  29. package/dist/models/ModelRegistry.js +4 -2
  30. package/dist/models/PricingRegistry.js +3 -3
  31. package/dist/models/models.json +16696 -0
  32. package/dist/providers/Provider.d.ts +5 -0
  33. package/dist/providers/Provider.d.ts.map +1 -1
  34. package/dist/providers/anthropic/AnthropicProvider.d.ts.map +1 -1
  35. package/dist/providers/anthropic/AnthropicProvider.js +2 -1
  36. package/dist/providers/anthropic/Capabilities.d.ts +1 -0
  37. package/dist/providers/anthropic/Capabilities.d.ts.map +1 -1
  38. package/dist/providers/anthropic/Capabilities.js +8 -5
  39. package/dist/providers/anthropic/Chat.d.ts.map +1 -1
  40. package/dist/providers/anthropic/Chat.js +2 -1
  41. package/dist/providers/anthropic/Errors.d.ts.map +1 -1
  42. package/dist/providers/anthropic/Errors.js +15 -1
  43. package/dist/providers/anthropic/Streaming.d.ts.map +1 -1
  44. package/dist/providers/anthropic/Streaming.js +19 -3
  45. package/dist/providers/bedrock/BedrockProvider.d.ts +53 -0
  46. package/dist/providers/bedrock/BedrockProvider.d.ts.map +1 -0
  47. package/dist/providers/bedrock/BedrockProvider.js +107 -0
  48. package/dist/providers/bedrock/Capabilities.d.ts +50 -0
  49. package/dist/providers/bedrock/Capabilities.d.ts.map +1 -0
  50. package/dist/providers/bedrock/Capabilities.js +233 -0
  51. package/dist/providers/bedrock/Chat.d.ts +26 -0
  52. package/dist/providers/bedrock/Chat.d.ts.map +1 -0
  53. package/dist/providers/bedrock/Chat.js +152 -0
  54. package/dist/providers/bedrock/Embeddings.d.ts +22 -0
  55. package/dist/providers/bedrock/Embeddings.d.ts.map +1 -0
  56. package/dist/providers/bedrock/Embeddings.js +100 -0
  57. package/dist/providers/bedrock/Errors.d.ts +2 -0
  58. package/dist/providers/bedrock/Errors.d.ts.map +1 -0
  59. package/dist/providers/bedrock/Errors.js +51 -0
  60. package/dist/providers/bedrock/Image.d.ts +33 -0
  61. package/dist/providers/bedrock/Image.d.ts.map +1 -0
  62. package/dist/providers/bedrock/Image.js +154 -0
  63. package/dist/providers/bedrock/Models.d.ts +34 -0
  64. package/dist/providers/bedrock/Models.d.ts.map +1 -0
  65. package/dist/providers/bedrock/Models.js +131 -0
  66. package/dist/providers/bedrock/Moderation.d.ts +23 -0
  67. package/dist/providers/bedrock/Moderation.d.ts.map +1 -0
  68. package/dist/providers/bedrock/Moderation.js +138 -0
  69. package/dist/providers/bedrock/Streaming.d.ts +21 -0
  70. package/dist/providers/bedrock/Streaming.d.ts.map +1 -0
  71. package/dist/providers/bedrock/Streaming.js +239 -0
  72. package/dist/providers/bedrock/config.d.ts +57 -0
  73. package/dist/providers/bedrock/config.d.ts.map +1 -0
  74. package/dist/providers/bedrock/config.js +33 -0
  75. package/dist/providers/bedrock/index.d.ts +8 -0
  76. package/dist/providers/bedrock/index.d.ts.map +1 -0
  77. package/dist/providers/bedrock/index.js +30 -0
  78. package/dist/providers/bedrock/mapper.d.ts +37 -0
  79. package/dist/providers/bedrock/mapper.d.ts.map +1 -0
  80. package/dist/providers/bedrock/mapper.js +204 -0
  81. package/dist/providers/bedrock/types.d.ts +179 -0
  82. package/dist/providers/bedrock/types.d.ts.map +1 -0
  83. package/dist/providers/bedrock/types.js +7 -0
  84. package/dist/providers/deepseek/Capabilities.d.ts +3 -2
  85. package/dist/providers/deepseek/Capabilities.d.ts.map +1 -1
  86. package/dist/providers/deepseek/Capabilities.js +19 -5
  87. package/dist/providers/deepseek/Chat.d.ts.map +1 -1
  88. package/dist/providers/deepseek/Chat.js +2 -2
  89. package/dist/providers/deepseek/DeepSeekProvider.d.ts.map +1 -1
  90. package/dist/providers/deepseek/DeepSeekProvider.js +2 -1
  91. package/dist/providers/deepseek/Errors.d.ts +2 -0
  92. package/dist/providers/deepseek/Errors.d.ts.map +1 -0
  93. package/dist/providers/deepseek/Errors.js +45 -0
  94. package/dist/providers/deepseek/Streaming.d.ts.map +1 -1
  95. package/dist/providers/deepseek/Streaming.js +13 -2
  96. package/dist/providers/gemini/Capabilities.d.ts +1 -0
  97. package/dist/providers/gemini/Capabilities.d.ts.map +1 -1
  98. package/dist/providers/gemini/Capabilities.js +9 -6
  99. package/dist/providers/gemini/Chat.d.ts.map +1 -1
  100. package/dist/providers/gemini/Chat.js +6 -23
  101. package/dist/providers/gemini/Errors.d.ts.map +1 -1
  102. package/dist/providers/gemini/Errors.js +13 -1
  103. package/dist/providers/gemini/GeminiProvider.d.ts.map +1 -1
  104. package/dist/providers/gemini/GeminiProvider.js +2 -1
  105. package/dist/providers/ollama/Capabilities.d.ts.map +1 -1
  106. package/dist/providers/ollama/Capabilities.js +4 -1
  107. package/dist/providers/ollama/OllamaProvider.d.ts.map +1 -1
  108. package/dist/providers/ollama/OllamaProvider.js +2 -2
  109. package/dist/providers/openai/Capabilities.d.ts +1 -0
  110. package/dist/providers/openai/Capabilities.d.ts.map +1 -1
  111. package/dist/providers/openai/Capabilities.js +14 -11
  112. package/dist/providers/openai/Errors.d.ts.map +1 -1
  113. package/dist/providers/openai/Errors.js +31 -5
  114. package/dist/providers/openai/OpenAIProvider.d.ts.map +1 -1
  115. package/dist/providers/openai/OpenAIProvider.js +2 -1
  116. package/dist/providers/openai/Streaming.d.ts.map +1 -1
  117. package/dist/providers/openai/Streaming.js +10 -0
  118. package/dist/providers/openrouter/OpenRouterProvider.d.ts.map +1 -1
  119. package/dist/providers/openrouter/OpenRouterProvider.js +2 -1
  120. package/dist/providers/registry.d.ts +5 -1
  121. package/dist/providers/registry.d.ts.map +1 -1
  122. package/dist/providers/registry.js +12 -3
  123. package/dist/utils/AwsSigV4.d.ts +51 -0
  124. package/dist/utils/AwsSigV4.d.ts.map +1 -0
  125. package/dist/utils/AwsSigV4.js +209 -0
  126. package/dist/utils/json.d.ts +6 -0
  127. package/dist/utils/json.d.ts.map +1 -0
  128. package/dist/utils/json.js +43 -0
  129. package/package.json +1 -1
  130. package/dist/models/models.d.ts +0 -327
  131. package/dist/models/models.d.ts.map +0 -1
  132. package/dist/models/models.js +0 -11138
@@ -0,0 +1,233 @@
1
+ /**
2
+ * Maps Bedrock model IDs to their capabilities.
3
+ */
4
+ import { ModelRegistry } from "../../models/ModelRegistry.js";
5
+ import { PricingRegistry } from "../../models/PricingRegistry.js";
6
+ const MODEL_FAMILIES = [
7
+ [/anthropic\.claude-3-opus/, "claude3_opus"],
8
+ [/anthropic\.claude-3-sonnet/, "claude3_sonnet"],
9
+ [/anthropic\.claude-3-5-sonnet/, "claude3_sonnet"],
10
+ [/anthropic\.claude-3-7-sonnet/, "claude3_sonnet"],
11
+ [/anthropic\.claude-3-haiku/, "claude3_haiku"],
12
+ [/anthropic\.claude-3-5-haiku/, "claude3_5_haiku"],
13
+ [/anthropic\.claude-v2/, "claude2"],
14
+ [/anthropic\.claude-2/, "claude2"],
15
+ [/anthropic\.claude-instant/, "claude_instant"],
16
+ [/anthropic\.claude-(opus|sonnet|haiku)-4/, "claude4"],
17
+ [/amazon\.nova-2/, "nova2"],
18
+ [/amazon\.nova/, "nova"]
19
+ ];
20
+ // ─────────────────────────────────────────────────────────────────────────────
21
+ // Pricing (per million tokens)
22
+ // ─────────────────────────────────────────────────────────────────────────────
23
+ const PRICES = {
24
+ claude3_opus: { input: 15.0, output: 75.0 },
25
+ claude3_sonnet: { input: 3.0, output: 15.0 },
26
+ claude3_haiku: { input: 0.25, output: 1.25 },
27
+ claude3_5_haiku: { input: 0.8, output: 4.0 },
28
+ claude2: { input: 8.0, output: 24.0 },
29
+ claude_instant: { input: 0.8, output: 2.4 },
30
+ claude4: { input: 3.0, output: 15.0 }, // Assuming Sonnet 4 as baseline for the family
31
+ nova: { input: 0.06, output: 0.24 },
32
+ nova2: { input: 0.03, output: 0.12 }, // Assuming Nova 2 is cheaper as per trend
33
+ other: { input: 0.1, output: 0.2 }
34
+ };
35
+ // ─────────────────────────────────────────────────────────────────────────────
36
+ // Capabilities Class
37
+ // ─────────────────────────────────────────────────────────────────────────────
38
+ export class Capabilities {
39
+ static getModelFamily(modelId) {
40
+ for (const [pattern, family] of MODEL_FAMILIES) {
41
+ if (pattern.test(modelId))
42
+ return family;
43
+ }
44
+ return "other";
45
+ }
46
+ static getContextWindow(modelId) {
47
+ const val = ModelRegistry.getContextWindow(modelId, "bedrock");
48
+ if (val)
49
+ return val;
50
+ // Claude 2 has 100k, others have 200k
51
+ if (/anthropic\.claude-2/.test(modelId))
52
+ return 100_000;
53
+ if (/anthropic\.claude/.test(modelId))
54
+ return 200_000;
55
+ // DeepSeek
56
+ if (/deepseek/.test(modelId))
57
+ return 128_000;
58
+ // Mistral
59
+ if (/mistral-large/.test(modelId))
60
+ return 128_000;
61
+ if (/mistral/.test(modelId))
62
+ return 32_000;
63
+ // Llama
64
+ if (/llama/.test(modelId))
65
+ return 128_000;
66
+ // Titan
67
+ if (/titan/.test(modelId))
68
+ return 32_000;
69
+ // Nova
70
+ if (/nova/.test(modelId))
71
+ return 300_000;
72
+ return null;
73
+ }
74
+ static getMaxOutputTokens(modelId) {
75
+ const val = ModelRegistry.getMaxOutputTokens(modelId, "bedrock");
76
+ if (val)
77
+ return val;
78
+ return 4_096;
79
+ }
80
+ static supportsChat(modelId) {
81
+ const model = this.findModel(modelId);
82
+ if (model?.capabilities?.includes("chat"))
83
+ return true;
84
+ return (/anthropic\.claude/.test(modelId) ||
85
+ /amazon\.nova/.test(modelId) ||
86
+ /mistral\.mistral/.test(modelId) ||
87
+ /meta\.llama/.test(modelId) ||
88
+ /deepseek/.test(modelId));
89
+ }
90
+ static supportsStreaming(modelId) {
91
+ const model = this.findModel(modelId);
92
+ if (model?.capabilities?.includes("streaming"))
93
+ return true;
94
+ return (/anthropic\.claude/.test(modelId) ||
95
+ /amazon\.nova/.test(modelId) ||
96
+ /mistral\.mistral/.test(modelId) ||
97
+ /meta\.llama/.test(modelId) ||
98
+ /deepseek/.test(modelId));
99
+ }
100
+ static supportsVision(modelId) {
101
+ const model = this.findModel(modelId);
102
+ if (model?.modalities?.input?.includes("image"))
103
+ return true;
104
+ if (model?.capabilities?.includes("vision"))
105
+ return true;
106
+ return /anthropic\.claude-3|anthropic\.claude-4|amazon\.nova/.test(modelId);
107
+ }
108
+ static supportsTools(modelId) {
109
+ const model = this.findModel(modelId);
110
+ if (model?.capabilities?.includes("tools") || model?.capabilities?.includes("function_calling"))
111
+ return true;
112
+ return /anthropic\.claude|amazon\.nova|deepseek-chat/.test(modelId);
113
+ }
114
+ static supportsJsonMode(modelId) {
115
+ const model = this.findModel(modelId);
116
+ if (model?.capabilities?.includes("json_mode") ||
117
+ model?.capabilities?.includes("structured_output"))
118
+ return true;
119
+ return /anthropic\.claude|amazon\.nova/.test(modelId);
120
+ }
121
+ static supportsExtendedThinking(modelId) {
122
+ const model = this.findModel(modelId);
123
+ if (model?.capabilities?.includes("reasoning"))
124
+ return true;
125
+ return /claude-3-7|deepseek-reasoner|deepseek\.r1/.test(modelId);
126
+ }
127
+ static supportsEmbeddings(modelId) {
128
+ const model = this.findModel(modelId);
129
+ if (model?.capabilities?.includes("embeddings"))
130
+ return true;
131
+ return /amazon\.titan-embed/.test(modelId);
132
+ }
133
+ static supportsImageGeneration(modelId) {
134
+ const model = this.findModel(modelId);
135
+ if (model?.capabilities?.includes("image_generation"))
136
+ return true;
137
+ return /amazon\.titan-image-generator|stability\.stable-diffusion/.test(modelId);
138
+ }
139
+ /**
140
+ * Check if a model supports audio input.
141
+ */
142
+ static supportsAudio(_modelId) {
143
+ return false;
144
+ }
145
+ /**
146
+ * Get input modalities for a model.
147
+ */
148
+ static getInputModalities(modelId) {
149
+ const modalities = ["text"];
150
+ if ((/anthropic\.claude/.test(modelId) || /amazon\.nova/.test(modelId)) &&
151
+ this.supportsVision(modelId)) {
152
+ modalities.push("image");
153
+ modalities.push("pdf");
154
+ }
155
+ return modalities;
156
+ }
157
+ /**
158
+ * Get output modalities for a model.
159
+ */
160
+ static getOutputModalities(_modelId) {
161
+ return ["text"];
162
+ }
163
+ /**
164
+ * Get all capabilities for a model.
165
+ */
166
+ static getCapabilities(modelId) {
167
+ const capabilities = [];
168
+ if (/anthropic\.claude/.test(modelId)) {
169
+ capabilities.push("streaming");
170
+ }
171
+ if (this.supportsTools(modelId)) {
172
+ capabilities.push("function_calling");
173
+ }
174
+ if (/claude-3-7|nova/.test(modelId)) {
175
+ capabilities.push("reasoning");
176
+ }
177
+ if (/claude-3\.5|claude-3-7|nova/.test(modelId)) {
178
+ capabilities.push("batch");
179
+ capabilities.push("citations");
180
+ }
181
+ return capabilities;
182
+ }
183
+ static getPricing(modelId) {
184
+ // Try registry first
185
+ const registryPricing = PricingRegistry.getPricing(modelId, "bedrock");
186
+ if (registryPricing)
187
+ return registryPricing;
188
+ // Fallback to built-in pricing
189
+ const family = this.getModelFamily(modelId);
190
+ const prices = PRICES[family];
191
+ return {
192
+ text_tokens: {
193
+ standard: {
194
+ input_per_million: prices.input,
195
+ output_per_million: prices.output
196
+ },
197
+ batch: {
198
+ input_per_million: prices.input * 0.5,
199
+ output_per_million: prices.output * 0.5
200
+ }
201
+ }
202
+ };
203
+ }
204
+ /**
205
+ * Get input price per million tokens.
206
+ */
207
+ static getInputPrice(modelId) {
208
+ const family = this.getModelFamily(modelId);
209
+ return PRICES[family].input;
210
+ }
211
+ /**
212
+ * Get output price per million tokens.
213
+ */
214
+ static getOutputPrice(modelId) {
215
+ const family = this.getModelFamily(modelId);
216
+ return PRICES[family].output;
217
+ }
218
+ /**
219
+ * Format model ID as display name.
220
+ */
221
+ static formatDisplayName(modelId) {
222
+ return modelId
223
+ .replace(/-/g, " ")
224
+ .split(".")
225
+ .pop()
226
+ .split(" ")
227
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
228
+ .join(" ");
229
+ }
230
+ static findModel(modelId) {
231
+ return ModelRegistry.find(modelId, "bedrock");
232
+ }
233
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Bedrock Chat Handler
3
+ *
4
+ * Executes chat requests against the Bedrock Converse API.
5
+ */
6
+ import { ChatRequest, ChatResponse } from "../Provider.js";
7
+ import { BedrockConfig } from "./config.js";
8
+ export declare class BedrockChat {
9
+ private readonly config;
10
+ private readonly authMode;
11
+ private readonly baseUrl;
12
+ constructor(config: BedrockConfig);
13
+ /**
14
+ * Execute a chat request against Bedrock Converse API.
15
+ */
16
+ execute(request: ChatRequest): Promise<ChatResponse>;
17
+ /**
18
+ * Build request headers based on auth mode.
19
+ */
20
+ private buildHeaders;
21
+ /**
22
+ * Parse Bedrock response to NodeLLM format.
23
+ */
24
+ private parseResponse;
25
+ }
26
+ //# sourceMappingURL=Chat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../../src/providers/bedrock/Chat.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAS,MAAM,gBAAgB,CAAC;AAElE,OAAO,EAAE,aAAa,EAA6C,MAAM,aAAa,CAAC;AAavF,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,EAAE,aAAa;IAMjC;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAwD1D;;OAEG;IACH,OAAO,CAAC,YAAY;IA6CpB;;OAEG;IACH,OAAO,CAAC,aAAa;CAiDtB"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Bedrock Chat Handler
3
+ *
4
+ * Executes chat requests against the Bedrock Converse API.
5
+ */
6
+ import { validateBedrockConfig, getBedrockEndpoint } from "./config.js";
7
+ import { buildConverseRequest } from "./mapper.js";
8
+ import { signRequest } from "../../utils/AwsSigV4.js";
9
+ import { handleBedrockError } from "./Errors.js";
10
+ import { ModelRegistry } from "../../models/ModelRegistry.js";
11
+ import { fetchWithTimeout } from "../../utils/fetch.js";
12
+ import { logger } from "../../utils/logger.js";
13
+ // ─────────────────────────────────────────────────────────────────────────────
14
+ // Chat Handler
15
+ // ─────────────────────────────────────────────────────────────────────────────
16
+ export class BedrockChat {
17
+ config;
18
+ authMode;
19
+ baseUrl;
20
+ constructor(config) {
21
+ this.config = config;
22
+ this.authMode = validateBedrockConfig(config);
23
+ this.baseUrl = getBedrockEndpoint(config.region);
24
+ }
25
+ /**
26
+ * Execute a chat request against Bedrock Converse API.
27
+ */
28
+ async execute(request) {
29
+ const modelId = request.model;
30
+ const url = `${this.baseUrl}/model/${modelId}/converse`;
31
+ // Build the Bedrock request body
32
+ const guardrail = this.config.guardrailIdentifier && this.config.guardrailVersion
33
+ ? {
34
+ guardrailIdentifier: this.config.guardrailIdentifier,
35
+ guardrailVersion: this.config.guardrailVersion
36
+ }
37
+ : undefined;
38
+ const body = buildConverseRequest(request.messages, request.tools, {
39
+ maxTokens: request.max_tokens,
40
+ temperature: request.temperature,
41
+ thinking: request.thinking,
42
+ guardrail,
43
+ additionalModelRequestFields: request.additionalModelRequestFields
44
+ });
45
+ const bodyJson = JSON.stringify(body);
46
+ // Build headers based on auth mode
47
+ const headers = this.buildHeaders(url, bodyJson, request.headers);
48
+ logger.logRequest("Bedrock", "POST", url, body);
49
+ // Make the request
50
+ const response = await fetchWithTimeout(url, {
51
+ method: "POST",
52
+ headers,
53
+ body: bodyJson
54
+ }, request.requestTimeout ?? this.config.requestTimeout);
55
+ if (!response.ok) {
56
+ await handleBedrockError(response, modelId);
57
+ }
58
+ const json = (await response.json());
59
+ logger.logResponse("Bedrock", response.status, response.statusText, json);
60
+ const result = this.parseResponse(json);
61
+ if (result.usage) {
62
+ result.usage = ModelRegistry.calculateCost(result.usage, modelId, "bedrock");
63
+ }
64
+ return result;
65
+ }
66
+ /**
67
+ * Build request headers based on auth mode.
68
+ */
69
+ buildHeaders(url, body, additionalHeaders) {
70
+ const headers = {
71
+ "Content-Type": "application/json",
72
+ Accept: "application/json",
73
+ ...additionalHeaders
74
+ };
75
+ if (this.authMode === "apiKey") {
76
+ // Simple Bearer token auth
77
+ headers["Authorization"] = `Bearer ${this.config.apiKey}`;
78
+ }
79
+ else {
80
+ // SigV4 signing
81
+ const credentials = {
82
+ accessKeyId: this.config.accessKeyId,
83
+ secretAccessKey: this.config.secretAccessKey,
84
+ sessionToken: this.config.sessionToken
85
+ };
86
+ const signedHeaders = signRequest({
87
+ method: "POST",
88
+ url,
89
+ body,
90
+ credentials,
91
+ region: this.config.region,
92
+ service: "bedrock"
93
+ });
94
+ // Merge signed headers
95
+ headers["host"] = signedHeaders.host;
96
+ headers["x-amz-date"] = signedHeaders["x-amz-date"];
97
+ headers["x-amz-content-sha256"] = signedHeaders["x-amz-content-sha256"];
98
+ headers["Authorization"] = signedHeaders.authorization;
99
+ if (signedHeaders["x-amz-security-token"]) {
100
+ headers["x-amz-security-token"] = signedHeaders["x-amz-security-token"];
101
+ }
102
+ }
103
+ return headers;
104
+ }
105
+ /**
106
+ * Parse Bedrock response to NodeLLM format.
107
+ */
108
+ parseResponse(response) {
109
+ const message = response.output.message;
110
+ let content = null;
111
+ let thinkingText = null;
112
+ const toolCalls = [];
113
+ // Process content blocks
114
+ for (const block of message.content) {
115
+ if (block.text) {
116
+ content = content ? content + block.text : block.text;
117
+ }
118
+ if (block.reasoningContent?.text) {
119
+ thinkingText = thinkingText
120
+ ? thinkingText + block.reasoningContent.text
121
+ : block.reasoningContent.text;
122
+ }
123
+ if (block.toolUse) {
124
+ toolCalls.push({
125
+ id: block.toolUse.toolUseId,
126
+ type: "function",
127
+ function: {
128
+ name: block.toolUse.name,
129
+ arguments: JSON.stringify(block.toolUse.input)
130
+ }
131
+ });
132
+ }
133
+ }
134
+ // Build usage info
135
+ const usage = {
136
+ input_tokens: response.usage.inputTokens,
137
+ output_tokens: response.usage.outputTokens,
138
+ total_tokens: response.usage.totalTokens,
139
+ cached_tokens: response.usage.cacheReadInputTokens,
140
+ cache_creation_tokens: response.usage.cacheWriteInputTokens
141
+ };
142
+ return {
143
+ content,
144
+ thinking: thinkingText ? { text: thinkingText } : undefined,
145
+ reasoning: thinkingText || undefined, // Keep deprecated field for compat
146
+ tool_calls: toolCalls.length > 0 ? toolCalls : undefined,
147
+ usage,
148
+ finish_reason: response.stopReason,
149
+ metadata: response.trace ? { trace: response.trace } : undefined
150
+ };
151
+ }
152
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Bedrock Embeddings Handler
3
+ *
4
+ * Executes embedding requests against the Bedrock InvokeModel API.
5
+ */
6
+ import { EmbeddingRequest, EmbeddingResponse } from "../Provider.js";
7
+ import { BedrockConfig } from "./config.js";
8
+ export declare class BedrockEmbeddings {
9
+ private readonly config;
10
+ private readonly authMode;
11
+ private readonly baseUrl;
12
+ constructor(config: BedrockConfig);
13
+ /**
14
+ * Execute an embedding request against Bedrock InvokeModel API.
15
+ */
16
+ execute(request: EmbeddingRequest): Promise<EmbeddingResponse>;
17
+ /**
18
+ * Build request headers based on auth mode.
19
+ */
20
+ private buildHeaders;
21
+ }
22
+ //# sourceMappingURL=Embeddings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Embeddings.d.ts","sourceRoot":"","sources":["../../../src/providers/bedrock/Embeddings.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,EAAE,aAAa,EAA6C,MAAM,aAAa,CAAC;AAwBvF,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,EAAE,aAAa;IAMjC;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAqDpE;;OAEG;IACH,OAAO,CAAC,YAAY;CAoCrB"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Bedrock Embeddings Handler
3
+ *
4
+ * Executes embedding requests against the Bedrock InvokeModel API.
5
+ */
6
+ import { validateBedrockConfig, getBedrockEndpoint } from "./config.js";
7
+ import { signRequest } from "../../utils/AwsSigV4.js";
8
+ import { fetchWithTimeout } from "../../utils/fetch.js";
9
+ import { logger } from "../../utils/logger.js";
10
+ // ─────────────────────────────────────────────────────────────────────────────
11
+ // Embeddings Handler
12
+ // ─────────────────────────────────────────────────────────────────────────────
13
+ export class BedrockEmbeddings {
14
+ config;
15
+ authMode;
16
+ baseUrl;
17
+ constructor(config) {
18
+ this.config = config;
19
+ this.authMode = validateBedrockConfig(config);
20
+ this.baseUrl = getBedrockEndpoint(config.region);
21
+ }
22
+ /**
23
+ * Execute an embedding request against Bedrock InvokeModel API.
24
+ */
25
+ async execute(request) {
26
+ const modelId = request.model ?? "amazon.titan-embed-text-v2:0";
27
+ const url = `${this.baseUrl}/model/${modelId}/invoke`;
28
+ // Handle single vs multiple inputs (Titan only supports one at a time via InvokeModel)
29
+ const inputs = Array.isArray(request.input) ? request.input : [request.input];
30
+ const results = [];
31
+ let totalTokens = 0;
32
+ // Bedrock InvokeModel API for Titan embeddings processes one text at a time.
33
+ // We iterate through inputs and collect embeddings.
34
+ for (const text of inputs) {
35
+ const body = {
36
+ inputText: text,
37
+ // Titan V2 supports 256, 512, 1024 dimensions. NodeLLM doesn't have a standardized field for this yet,
38
+ // so we use the model's default (typically 1024 for V2) unless passed in headers/custom.
39
+ normalize: true
40
+ };
41
+ const bodyJson = JSON.stringify(body);
42
+ const headers = this.buildHeaders(url, bodyJson);
43
+ logger.logRequest("BedrockEmbeddings", "POST", url, body);
44
+ const response = await fetchWithTimeout(url, {
45
+ method: "POST",
46
+ headers,
47
+ body: bodyJson
48
+ }, request.requestTimeout ?? this.config.requestTimeout);
49
+ if (!response.ok) {
50
+ const errorText = await response.text();
51
+ logger.logResponse("BedrockEmbeddings", response.status, response.statusText, errorText);
52
+ throw new Error(`Bedrock Embeddings error (${response.status}): ${errorText}`);
53
+ }
54
+ const json = (await response.json());
55
+ results.push(json.embedding);
56
+ totalTokens += json.inputTextTokenCount;
57
+ }
58
+ return {
59
+ vectors: results,
60
+ model: modelId,
61
+ input_tokens: totalTokens,
62
+ dimensions: results[0]?.length || 0
63
+ };
64
+ }
65
+ /**
66
+ * Build request headers based on auth mode.
67
+ */
68
+ buildHeaders(url, body) {
69
+ const headers = {
70
+ "Content-Type": "application/json",
71
+ Accept: "application/json"
72
+ };
73
+ if (this.authMode === "apiKey") {
74
+ headers["Authorization"] = `Bearer ${this.config.apiKey}`;
75
+ }
76
+ else {
77
+ const credentials = {
78
+ accessKeyId: this.config.accessKeyId,
79
+ secretAccessKey: this.config.secretAccessKey,
80
+ sessionToken: this.config.sessionToken
81
+ };
82
+ const signedHeaders = signRequest({
83
+ method: "POST",
84
+ url,
85
+ body: body,
86
+ credentials,
87
+ region: this.config.region,
88
+ service: "bedrock"
89
+ });
90
+ headers["host"] = signedHeaders.host;
91
+ headers["x-amz-date"] = signedHeaders["x-amz-date"];
92
+ headers["x-amz-content-sha256"] = signedHeaders["x-amz-content-sha256"];
93
+ headers["Authorization"] = signedHeaders.authorization;
94
+ if (signedHeaders["x-amz-security-token"]) {
95
+ headers["x-amz-security-token"] = signedHeaders["x-amz-security-token"];
96
+ }
97
+ }
98
+ return headers;
99
+ }
100
+ }
@@ -0,0 +1,2 @@
1
+ export declare function handleBedrockError(response: Response, modelId: string): Promise<never>;
2
+ //# sourceMappingURL=Errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Errors.d.ts","sourceRoot":"","sources":["../../../src/providers/bedrock/Errors.ts"],"names":[],"mappings":"AAcA,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAmE5F"}
@@ -0,0 +1,51 @@
1
+ import { BadRequestError, ContextWindowExceededError, InsufficientQuotaError, InvalidModelError, AuthenticationError, RateLimitError, ServerError, ServiceUnavailableError, APIError, ForbiddenError } from "../../errors/index.js";
2
+ export async function handleBedrockError(response, modelId) {
3
+ const status = response.status;
4
+ const errorText = await response.text();
5
+ let message = errorText;
6
+ let body;
7
+ try {
8
+ body = JSON.parse(errorText);
9
+ message = body.message || errorText;
10
+ }
11
+ catch {
12
+ body = errorText;
13
+ }
14
+ const provider = "bedrock";
15
+ // Throttling
16
+ if (status === 429 || message.includes("ThrottlingException")) {
17
+ throw new RateLimitError(message, body, provider, modelId);
18
+ }
19
+ // Auth / Access
20
+ if (status === 401) {
21
+ throw new AuthenticationError(message, status, body, provider);
22
+ }
23
+ if (status === 403 || message.includes("AccessDeniedException")) {
24
+ if (message.includes("model access")) {
25
+ throw new ForbiddenError(`Access denied for model ${modelId}. Ensure you have requested access in the AWS Bedrock console.`, body, provider);
26
+ }
27
+ throw new ForbiddenError(message, body, provider);
28
+ }
29
+ // Not Found
30
+ if (status === 404 || message.includes("ResourceNotFoundException")) {
31
+ throw new InvalidModelError(message, body, provider, modelId);
32
+ }
33
+ // Bad Request
34
+ if (status === 400 || message.includes("ValidationException")) {
35
+ if (message.includes("context length") || message.includes("too many tokens")) {
36
+ throw new ContextWindowExceededError(message, body, provider, modelId);
37
+ }
38
+ throw new BadRequestError(message, body, provider, modelId);
39
+ }
40
+ // Payment
41
+ if (message.includes("INVALID_PAYMENT_INSTRUMENT")) {
42
+ throw new InsufficientQuotaError("Billing setup incomplete for AWS Marketplace models. Ensure a credit card is set as default payment method.", body, provider, modelId);
43
+ }
44
+ if (status >= 500) {
45
+ if (status === 502 || status === 503) {
46
+ throw new ServiceUnavailableError(message, status, body, provider, modelId);
47
+ }
48
+ throw new ServerError(message, status, body, provider, modelId);
49
+ }
50
+ throw new APIError(message, status, body, provider, modelId);
51
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Bedrock Image Generation Handler
3
+ *
4
+ * Supports Amazon Titan Image Generator and Stability.ai Stable Diffusion models.
5
+ */
6
+ import { ImageRequest, ImageResponse } from "../Provider.js";
7
+ import { BedrockConfig } from "./config.js";
8
+ export declare class BedrockImage {
9
+ private readonly config;
10
+ private readonly baseUrl;
11
+ constructor(config: BedrockConfig);
12
+ /**
13
+ * Execute an image generation request.
14
+ */
15
+ execute(request: ImageRequest): Promise<ImageResponse>;
16
+ /**
17
+ * Build model-specific request body.
18
+ */
19
+ private buildRequestBody;
20
+ /**
21
+ * Parse model-specific response.
22
+ */
23
+ private parseResponse;
24
+ /**
25
+ * Parse size string (e.g. "1024x1024") into height and width.
26
+ */
27
+ private parseSize;
28
+ /**
29
+ * Build headers with SigV4 signing.
30
+ */
31
+ private buildHeaders;
32
+ }
33
+ //# sourceMappingURL=Image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Image.d.ts","sourceRoot":"","sources":["../../../src/providers/bedrock/Image.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAsB,MAAM,aAAa,CAAC;AAKhE,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,EAAE,aAAa;IAKjC;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;IA8B5D;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAuCxB;;OAEG;IACH,OAAO,CAAC,aAAa;IAwBrB;;OAEG;IACH,OAAO,CAAC,SAAS;IAejB;;OAEG;IACH,OAAO,CAAC,YAAY;CAsCrB"}