@node-llm/core 1.6.2 → 1.8.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 (105) hide show
  1. package/README.md +9 -8
  2. package/dist/aliases.d.ts +215 -0
  3. package/dist/aliases.d.ts.map +1 -1
  4. package/dist/aliases.js +241 -26
  5. package/dist/chat/Chat.d.ts +12 -3
  6. package/dist/chat/Chat.d.ts.map +1 -1
  7. package/dist/chat/Chat.js +35 -5
  8. package/dist/chat/ChatOptions.d.ts +2 -1
  9. package/dist/chat/ChatOptions.d.ts.map +1 -1
  10. package/dist/chat/ChatResponse.d.ts +9 -2
  11. package/dist/chat/ChatResponse.d.ts.map +1 -1
  12. package/dist/chat/ChatResponse.js +12 -3
  13. package/dist/chat/ChatStream.d.ts.map +1 -1
  14. package/dist/chat/ChatStream.js +15 -1
  15. package/dist/chat/Content.d.ts +7 -0
  16. package/dist/chat/Content.d.ts.map +1 -1
  17. package/dist/config.d.ts +28 -0
  18. package/dist/config.d.ts.map +1 -1
  19. package/dist/config.js +50 -0
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/llm.d.ts.map +1 -1
  23. package/dist/llm.js +3 -2
  24. package/dist/models/models.d.ts +321 -76
  25. package/dist/models/models.d.ts.map +1 -1
  26. package/dist/models/models.js +7804 -2885
  27. package/dist/providers/Provider.d.ts +37 -0
  28. package/dist/providers/Provider.d.ts.map +1 -1
  29. package/dist/providers/anthropic/Capabilities.d.ts +1 -0
  30. package/dist/providers/anthropic/Capabilities.d.ts.map +1 -1
  31. package/dist/providers/anthropic/Capabilities.js +8 -5
  32. package/dist/providers/anthropic/Chat.d.ts.map +1 -1
  33. package/dist/providers/anthropic/Chat.js +23 -1
  34. package/dist/providers/anthropic/Streaming.d.ts.map +1 -1
  35. package/dist/providers/anthropic/Streaming.js +15 -0
  36. package/dist/providers/anthropic/types.d.ts +7 -1
  37. package/dist/providers/anthropic/types.d.ts.map +1 -1
  38. package/dist/providers/bedrock/BedrockProvider.d.ts +53 -0
  39. package/dist/providers/bedrock/BedrockProvider.d.ts.map +1 -0
  40. package/dist/providers/bedrock/BedrockProvider.js +107 -0
  41. package/dist/providers/bedrock/Capabilities.d.ts +50 -0
  42. package/dist/providers/bedrock/Capabilities.d.ts.map +1 -0
  43. package/dist/providers/bedrock/Capabilities.js +233 -0
  44. package/dist/providers/bedrock/Chat.d.ts +26 -0
  45. package/dist/providers/bedrock/Chat.d.ts.map +1 -0
  46. package/dist/providers/bedrock/Chat.js +170 -0
  47. package/dist/providers/bedrock/Embeddings.d.ts +22 -0
  48. package/dist/providers/bedrock/Embeddings.d.ts.map +1 -0
  49. package/dist/providers/bedrock/Embeddings.js +100 -0
  50. package/dist/providers/bedrock/Image.d.ts +33 -0
  51. package/dist/providers/bedrock/Image.d.ts.map +1 -0
  52. package/dist/providers/bedrock/Image.js +154 -0
  53. package/dist/providers/bedrock/Models.d.ts +34 -0
  54. package/dist/providers/bedrock/Models.d.ts.map +1 -0
  55. package/dist/providers/bedrock/Models.js +131 -0
  56. package/dist/providers/bedrock/Moderation.d.ts +23 -0
  57. package/dist/providers/bedrock/Moderation.d.ts.map +1 -0
  58. package/dist/providers/bedrock/Moderation.js +138 -0
  59. package/dist/providers/bedrock/Streaming.d.ts +21 -0
  60. package/dist/providers/bedrock/Streaming.d.ts.map +1 -0
  61. package/dist/providers/bedrock/Streaming.js +240 -0
  62. package/dist/providers/bedrock/config.d.ts +57 -0
  63. package/dist/providers/bedrock/config.d.ts.map +1 -0
  64. package/dist/providers/bedrock/config.js +33 -0
  65. package/dist/providers/bedrock/index.d.ts +8 -0
  66. package/dist/providers/bedrock/index.d.ts.map +1 -0
  67. package/dist/providers/bedrock/index.js +30 -0
  68. package/dist/providers/bedrock/mapper.d.ts +37 -0
  69. package/dist/providers/bedrock/mapper.d.ts.map +1 -0
  70. package/dist/providers/bedrock/mapper.js +204 -0
  71. package/dist/providers/bedrock/types.d.ts +179 -0
  72. package/dist/providers/bedrock/types.d.ts.map +1 -0
  73. package/dist/providers/bedrock/types.js +7 -0
  74. package/dist/providers/deepseek/Capabilities.d.ts +3 -2
  75. package/dist/providers/deepseek/Capabilities.d.ts.map +1 -1
  76. package/dist/providers/deepseek/Capabilities.js +19 -5
  77. package/dist/providers/deepseek/Chat.d.ts.map +1 -1
  78. package/dist/providers/deepseek/Chat.js +9 -2
  79. package/dist/providers/deepseek/Streaming.d.ts.map +1 -1
  80. package/dist/providers/deepseek/Streaming.js +3 -2
  81. package/dist/providers/gemini/Capabilities.d.ts +1 -0
  82. package/dist/providers/gemini/Capabilities.d.ts.map +1 -1
  83. package/dist/providers/gemini/Capabilities.js +9 -6
  84. package/dist/providers/gemini/Chat.d.ts.map +1 -1
  85. package/dist/providers/gemini/Chat.js +4 -5
  86. package/dist/providers/gemini/Streaming.d.ts.map +1 -1
  87. package/dist/providers/gemini/Streaming.js +17 -2
  88. package/dist/providers/gemini/types.d.ts +4 -0
  89. package/dist/providers/gemini/types.d.ts.map +1 -1
  90. package/dist/providers/ollama/Capabilities.d.ts.map +1 -1
  91. package/dist/providers/ollama/Capabilities.js +4 -1
  92. package/dist/providers/openai/Capabilities.d.ts +1 -0
  93. package/dist/providers/openai/Capabilities.d.ts.map +1 -1
  94. package/dist/providers/openai/Capabilities.js +14 -11
  95. package/dist/providers/openai/Chat.d.ts.map +1 -1
  96. package/dist/providers/openai/Chat.js +18 -3
  97. package/dist/providers/openai/Streaming.d.ts.map +1 -1
  98. package/dist/providers/openai/Streaming.js +11 -3
  99. package/dist/providers/registry.d.ts +2 -1
  100. package/dist/providers/registry.d.ts.map +1 -1
  101. package/dist/providers/registry.js +2 -1
  102. package/dist/utils/AwsSigV4.d.ts +51 -0
  103. package/dist/utils/AwsSigV4.d.ts.map +1 -0
  104. package/dist/utils/AwsSigV4.js +209 -0
  105. package/package.json +1 -1
@@ -0,0 +1,240 @@
1
+ /**
2
+ * Bedrock Streaming Handler
3
+ *
4
+ * Handles streaming responses from Bedrock ConverseStream API.
5
+ * Parses the AWS EventStream binary format to extract JSON chunks.
6
+ */
7
+ import { validateBedrockConfig, getBedrockEndpoint } from "./config.js";
8
+ import { signRequest } from "../../utils/AwsSigV4.js";
9
+ import { fetchWithTimeout } from "../../utils/fetch.js";
10
+ import { logger } from "../../utils/logger.js";
11
+ import { buildConverseRequest } from "./mapper.js";
12
+ import { ModelRegistry } from "../../models/ModelRegistry.js";
13
+ export class BedrockStreaming {
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
+ async *execute(request, controller) {
23
+ const internalController = new AbortController();
24
+ const abortController = controller || internalController;
25
+ const signal = request.signal ? request.signal : abortController.signal;
26
+ const currentToolCalls = new Map();
27
+ let currentReasoning = "";
28
+ const modelId = request.model;
29
+ const url = `${this.baseUrl}/model/${modelId}/converse-stream`;
30
+ const guardrail = this.config.guardrailIdentifier && this.config.guardrailVersion
31
+ ? {
32
+ guardrailIdentifier: this.config.guardrailIdentifier,
33
+ guardrailVersion: this.config.guardrailVersion
34
+ }
35
+ : undefined;
36
+ const body = buildConverseRequest(request.messages, request.tools, {
37
+ maxTokens: request.max_tokens,
38
+ temperature: request.temperature,
39
+ thinking: request.thinking,
40
+ guardrail,
41
+ additionalModelRequestFields: request.additionalModelRequestFields
42
+ });
43
+ const bodyJson = JSON.stringify(body);
44
+ const headers = this.buildHeaders(url, bodyJson, request.headers);
45
+ logger.logRequest("Bedrock", "POST", url, body);
46
+ const response = await fetchWithTimeout(url, {
47
+ method: "POST",
48
+ headers,
49
+ body: bodyJson,
50
+ signal
51
+ }, request.requestTimeout ?? this.config.requestTimeout);
52
+ if (!response.ok) {
53
+ const errorText = await response.text();
54
+ logger.logResponse("Bedrock", response.status, response.statusText, errorText);
55
+ throw new Error(`Bedrock Streaming Error (${response.status}): ${errorText}`);
56
+ }
57
+ if (!response.body) {
58
+ throw new Error("No response body from Bedrock streaming");
59
+ }
60
+ const reader = response.body.getReader();
61
+ const decoder = new TextDecoder();
62
+ let buffer = new Uint8Array(0);
63
+ try {
64
+ while (true) {
65
+ const { value, done } = await reader.read();
66
+ if (done)
67
+ break;
68
+ // Append new data to buffer
69
+ const newBuffer = new Uint8Array(buffer.length + value.length);
70
+ newBuffer.set(buffer);
71
+ newBuffer.set(value, buffer.length);
72
+ buffer = newBuffer;
73
+ // Parse messages from buffer
74
+ while (buffer.length >= 12) {
75
+ const totalLength = new DataView(buffer.buffer, buffer.byteOffset, 4).getUint32(0);
76
+ if (totalLength < 16 || totalLength > 1024 * 1024) {
77
+ // Safety check: skip if total length is unreasonable
78
+ logger.error(`Bedrock stream: invalid total length ${totalLength}`);
79
+ buffer = buffer.slice(4);
80
+ continue;
81
+ }
82
+ if (buffer.length < totalLength) {
83
+ break; // Wait for more data
84
+ }
85
+ const headersLength = new DataView(buffer.buffer, buffer.byteOffset + 4, 4).getUint32(0);
86
+ if (headersLength + 16 > totalLength) {
87
+ logger.error(`Bedrock stream: invalid headers length ${headersLength} for total length ${totalLength}`);
88
+ buffer = buffer.slice(totalLength);
89
+ continue;
90
+ }
91
+ const payloadLength = totalLength - headersLength - 16;
92
+ const payloadOffset = 12 + headersLength;
93
+ const payload = buffer.slice(payloadOffset, payloadOffset + payloadLength);
94
+ const chunkJson = decoder.decode(payload);
95
+ try {
96
+ const event = JSON.parse(chunkJson);
97
+ const chatChunk = this.parseEvent(event, currentToolCalls, (text) => {
98
+ currentReasoning += text;
99
+ }, modelId);
100
+ if (chatChunk) {
101
+ yield chatChunk;
102
+ }
103
+ }
104
+ catch (e) {
105
+ // Might be a binary event or malformed JSON (though Bedrock uses JSON in payload)
106
+ logger.debug("Failed to parse Bedrock event payload", { chunkJson, error: e });
107
+ }
108
+ // Advance buffer
109
+ buffer = buffer.slice(totalLength);
110
+ }
111
+ }
112
+ }
113
+ finally {
114
+ reader.releaseLock();
115
+ }
116
+ }
117
+ /**
118
+ * Parse a Bedrock ConverseStream event into a NodeLLM ChatChunk.
119
+ */
120
+ parseEvent(event, toolCalls, onReasoning, modelId) {
121
+ // Bedrock ConverseStream events can be wrapped or unwrapped depending on model/service version
122
+ const contentBlockStart = event.contentBlockStart;
123
+ const contentBlockDelta = event.contentBlockDelta || (event.delta ? event : null);
124
+ const contentBlockStop = event.contentBlockStop;
125
+ const messageStop = event.messageStop || (event.stopReason ? event : null);
126
+ const metadata = event.metadata || (event.usage ? event : null);
127
+ // 1. Content Block Start (Initialize tools or reasoning)
128
+ if (contentBlockStart) {
129
+ const { contentBlockIndex, start } = contentBlockStart;
130
+ if (start?.toolUse) {
131
+ toolCalls.set(contentBlockIndex, {
132
+ id: start.toolUse.toolUseId,
133
+ name: start.toolUse.name,
134
+ input: ""
135
+ });
136
+ }
137
+ if (start?.reasoningContent) {
138
+ return { content: "", thinking: { text: "" }, reasoning: "" };
139
+ }
140
+ }
141
+ // 2. Content Block Delta (Accumulate text, tools, or reasoning)
142
+ if (contentBlockDelta) {
143
+ const delta = contentBlockDelta.delta || contentBlockDelta;
144
+ const contentBlockIndex = contentBlockDelta.contentBlockIndex ?? 0;
145
+ if (delta.text) {
146
+ return { content: delta.text };
147
+ }
148
+ if (delta.reasoningContent?.text) {
149
+ onReasoning(delta.reasoningContent.text);
150
+ return {
151
+ content: "",
152
+ thinking: { text: delta.reasoningContent.text },
153
+ reasoning: delta.reasoningContent.text
154
+ };
155
+ }
156
+ if (delta.toolUse) {
157
+ const toolCall = toolCalls.get(contentBlockIndex);
158
+ if (toolCall) {
159
+ toolCall.input += delta.toolUse.input;
160
+ return null;
161
+ }
162
+ }
163
+ }
164
+ // 3. Content Block Stop (Finalize tool calls)
165
+ if (contentBlockStop) {
166
+ const { contentBlockIndex } = contentBlockStop;
167
+ const toolCall = toolCalls.get(contentBlockIndex);
168
+ if (toolCall) {
169
+ toolCalls.delete(contentBlockIndex);
170
+ return {
171
+ content: "",
172
+ tool_calls: [
173
+ {
174
+ id: toolCall.id,
175
+ type: "function",
176
+ function: {
177
+ name: toolCall.name,
178
+ arguments: toolCall.input
179
+ }
180
+ }
181
+ ]
182
+ };
183
+ }
184
+ }
185
+ // 4. Message Stop
186
+ if (event.messageStop) {
187
+ return {
188
+ content: "",
189
+ done: true,
190
+ finish_reason: event.messageStop.stopReason
191
+ };
192
+ }
193
+ // 5. Metadata (Usage)
194
+ if (event.metadata && event.metadata.usage) {
195
+ const rawUsage = {
196
+ input_tokens: event.metadata.usage.inputTokens,
197
+ output_tokens: event.metadata.usage.outputTokens,
198
+ total_tokens: event.metadata.usage.totalTokens,
199
+ cached_tokens: event.metadata.usage.cacheReadInputTokens,
200
+ cache_creation_tokens: event.metadata.usage.cacheWriteInputTokens
201
+ };
202
+ const usage = ModelRegistry.calculateCost(rawUsage, modelId, "bedrock");
203
+ const metadata = event.metadata.trace ? { trace: event.metadata.trace } : undefined;
204
+ return { content: "", usage, done: true, metadata };
205
+ }
206
+ return null;
207
+ }
208
+ buildHeaders(url, body, additionalHeaders) {
209
+ const headers = {
210
+ "Content-Type": "application/json",
211
+ Accept: "application/json",
212
+ ...additionalHeaders
213
+ };
214
+ if (this.authMode === "apiKey") {
215
+ headers["Authorization"] = `Bearer ${this.config.apiKey}`;
216
+ }
217
+ else {
218
+ const signedHeaders = signRequest({
219
+ method: "POST",
220
+ url,
221
+ body,
222
+ credentials: {
223
+ accessKeyId: this.config.accessKeyId,
224
+ secretAccessKey: this.config.secretAccessKey,
225
+ sessionToken: this.config.sessionToken
226
+ },
227
+ region: this.config.region,
228
+ service: "bedrock"
229
+ });
230
+ headers["host"] = signedHeaders.host;
231
+ headers["x-amz-date"] = signedHeaders["x-amz-date"];
232
+ headers["x-amz-content-sha256"] = signedHeaders["x-amz-content-sha256"];
233
+ headers["Authorization"] = signedHeaders.authorization;
234
+ if (signedHeaders["x-amz-security-token"]) {
235
+ headers["x-amz-security-token"] = signedHeaders["x-amz-security-token"];
236
+ }
237
+ }
238
+ return headers;
239
+ }
240
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * AWS Bedrock Provider Configuration
3
+ *
4
+ * Supports two authentication modes:
5
+ * 1. API Key (Bearer token) - Simplest, for long-term API keys
6
+ * 2. SigV4 (IAM credentials) - For EC2/ECS/Lambda with IAM roles
7
+ */
8
+ export interface BedrockConfig {
9
+ /**
10
+ * AWS Region where Bedrock is enabled.
11
+ * Example: "us-east-1", "us-west-2"
12
+ */
13
+ region: string;
14
+ /**
15
+ * Long-term API key generated from AWS Bedrock console.
16
+ * When provided, uses simple Bearer token authentication.
17
+ * Mutually exclusive with accessKeyId/secretAccessKey.
18
+ */
19
+ apiKey?: string;
20
+ /**
21
+ * AWS Access Key ID.
22
+ * Required when using SigV4 authentication (no apiKey).
23
+ */
24
+ accessKeyId?: string;
25
+ /**
26
+ * AWS Secret Access Key.
27
+ * Required when using SigV4 authentication (no apiKey).
28
+ */
29
+ secretAccessKey?: string;
30
+ /**
31
+ * AWS Session Token (optional).
32
+ * Required for temporary credentials from STS, SSO, or assumed roles.
33
+ */
34
+ sessionToken?: string;
35
+ /**
36
+ * Request timeout in milliseconds.
37
+ * Default: 120000 (2 minutes)
38
+ */
39
+ requestTimeout?: number;
40
+ /**
41
+ * Default Bedrock Guardrail identifier (ID or ARN).
42
+ */
43
+ guardrailIdentifier?: string;
44
+ /**
45
+ * Default Bedrock Guardrail version (e.g., "1", "DRAFT").
46
+ */
47
+ guardrailVersion?: string;
48
+ }
49
+ /**
50
+ * Validates the configuration and determines the auth mode.
51
+ */
52
+ export declare function validateBedrockConfig(config: BedrockConfig): "apiKey" | "sigv4";
53
+ /**
54
+ * Build the Bedrock Runtime endpoint URL for a given region.
55
+ */
56
+ export declare function getBedrockEndpoint(region: string): string;
57
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/providers/bedrock/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IAKf;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAKhB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAKtB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,QAAQ,GAAG,OAAO,CAuB/E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEzD"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * AWS Bedrock Provider Configuration
3
+ *
4
+ * Supports two authentication modes:
5
+ * 1. API Key (Bearer token) - Simplest, for long-term API keys
6
+ * 2. SigV4 (IAM credentials) - For EC2/ECS/Lambda with IAM roles
7
+ */
8
+ /**
9
+ * Validates the configuration and determines the auth mode.
10
+ */
11
+ export function validateBedrockConfig(config) {
12
+ if (!config.region) {
13
+ throw new Error("BedrockConfig: region is required");
14
+ }
15
+ const hasApiKey = !!config.apiKey;
16
+ const hasSigV4 = !!(config.accessKeyId && config.secretAccessKey);
17
+ if (hasApiKey && hasSigV4) {
18
+ throw new Error("BedrockConfig: provide either apiKey OR accessKeyId/secretAccessKey, not both");
19
+ }
20
+ if (hasApiKey) {
21
+ return "apiKey";
22
+ }
23
+ if (hasSigV4) {
24
+ return "sigv4";
25
+ }
26
+ throw new Error("BedrockConfig: provide either apiKey OR accessKeyId/secretAccessKey");
27
+ }
28
+ /**
29
+ * Build the Bedrock Runtime endpoint URL for a given region.
30
+ */
31
+ export function getBedrockEndpoint(region) {
32
+ return `https://bedrock-runtime.${region}.amazonaws.com`;
33
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Bedrock Provider - Public Exports
3
+ */
4
+ export declare function registerBedrockProvider(): void;
5
+ export { BedrockProvider, BedrockConfig } from "./BedrockProvider.js";
6
+ export { BedrockChat } from "./Chat.js";
7
+ export * from "./types.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/providers/bedrock/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,wBAAgB,uBAAuB,SAuBtC;AAED,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,cAAc,YAAY,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Bedrock Provider - Public Exports
3
+ */
4
+ import { config as globalConfig } from "../../config.js";
5
+ import { providerRegistry } from "../registry.js";
6
+ import { BedrockProvider } from "./BedrockProvider.js";
7
+ export function registerBedrockProvider() {
8
+ providerRegistry.register("bedrock", (config) => {
9
+ const cfg = config || globalConfig;
10
+ const region = cfg.bedrockRegion;
11
+ if (!region) {
12
+ throw new Error("bedrockRegion is not set in config or AWS_REGION environment variable");
13
+ }
14
+ // Pass all available credentials to the provider.
15
+ // BedrockProvider.validateBedrockConfig will ensure they are mutually exclusive.
16
+ const bedrockConfig = {
17
+ region,
18
+ apiKey: cfg.bedrockApiKey,
19
+ accessKeyId: cfg.bedrockAccessKeyId,
20
+ secretAccessKey: cfg.bedrockSecretAccessKey,
21
+ sessionToken: cfg.bedrockSessionToken,
22
+ guardrailIdentifier: cfg.bedrockGuardrailIdentifier,
23
+ guardrailVersion: cfg.bedrockGuardrailVersion
24
+ };
25
+ return new BedrockProvider(bedrockConfig);
26
+ });
27
+ }
28
+ export { BedrockProvider } from "./BedrockProvider.js";
29
+ export { BedrockChat } from "./Chat.js";
30
+ export * from "./types.js";
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Bedrock Message Mapper
3
+ *
4
+ * Converts NodeLLM messages to Bedrock Converse API format.
5
+ * Handles system messages, tool calls, and content blocks.
6
+ */
7
+ import { Message } from "../../chat/Message.js";
8
+ import { ToolDefinition } from "../../chat/Tool.js";
9
+ import { BedrockMessage, BedrockContentBlock, BedrockConverseRequest, BedrockToolConfig } from "./types.js";
10
+ import { ThinkingConfig } from "../../providers/Provider.js";
11
+ /**
12
+ * Convert NodeLLM messages to Bedrock Converse format.
13
+ * Extracts system messages to the top-level system field.
14
+ */
15
+ export declare function convertMessages(messages: Message[]): {
16
+ messages: BedrockMessage[];
17
+ system?: BedrockContentBlock[];
18
+ };
19
+ /**
20
+ * Convert NodeLLM tool definitions to Bedrock tool config.
21
+ */
22
+ export declare function convertTools(tools?: ToolDefinition[]): BedrockToolConfig | undefined;
23
+ /**
24
+ * Build a complete Bedrock Converse request from NodeLLM ChatRequest.
25
+ */
26
+ export declare function buildConverseRequest(messages: Message[], tools?: ToolDefinition[], options?: {
27
+ maxTokens?: number;
28
+ temperature?: number;
29
+ thinking?: ThinkingConfig;
30
+ guardrail?: {
31
+ guardrailIdentifier: string;
32
+ guardrailVersion: string;
33
+ trace?: "enabled" | "disabled";
34
+ };
35
+ additionalModelRequestFields?: Record<string, any>;
36
+ }): BedrockConverseRequest;
37
+ //# sourceMappingURL=mapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.d.ts","sourceRoot":"","sources":["../../../src/providers/bedrock/mapper.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAiD7D;;;GAGG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG;IACpD,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,mBAAmB,EAAE,CAAC;CAChC,CAuFA;AAMD;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE,cAAc,EAAE,GAAG,iBAAiB,GAAG,SAAS,CAgBpF;AAMD;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,OAAO,EAAE,EACnB,KAAK,CAAC,EAAE,cAAc,EAAE,EACxB,OAAO,CAAC,EAAE;IACR,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,SAAS,CAAC,EAAE;QACV,mBAAmB,EAAE,MAAM,CAAC;QAC5B,gBAAgB,EAAE,MAAM,CAAC;QACzB,KAAK,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;KAChC,CAAC;IACF,4BAA4B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACpD,GACA,sBAAsB,CAmDxB"}
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Bedrock Message Mapper
3
+ *
4
+ * Converts NodeLLM messages to Bedrock Converse API format.
5
+ * Handles system messages, tool calls, and content blocks.
6
+ */
7
+ // ─────────────────────────────────────────────────────────────────────────────
8
+ // Message Conversion
9
+ // ─────────────────────────────────────────────────────────────────────────────
10
+ /**
11
+ * Convert a NodeLLM message to Bedrock content blocks.
12
+ */
13
+ function messageContentToBlocks(content) {
14
+ if (typeof content === "string") {
15
+ return content ? [{ text: content }] : [];
16
+ }
17
+ if (Array.isArray(content)) {
18
+ const blocks = [];
19
+ for (const part of content) {
20
+ if (part.type === "text") {
21
+ const block = { text: part.text };
22
+ blocks.push(block);
23
+ if (part.cache_control?.type === "ephemeral") {
24
+ blocks.push({ cachePoint: { type: "default" } });
25
+ }
26
+ }
27
+ else if (part.type === "image_url" && part.image_url) {
28
+ // Extract base64 data from data URL
29
+ const match = part.image_url.url.match(/^data:image\/(\w+);base64,(.+)$/);
30
+ if (match && match[1] && match[2]) {
31
+ blocks.push({
32
+ image: {
33
+ format: match[1].replace("jpg", "jpeg"),
34
+ source: { bytes: match[2] }
35
+ }
36
+ });
37
+ }
38
+ else {
39
+ // Fallback if not a data URL or missing base64
40
+ blocks.push({ text: `[Image: ${part.image_url.url}]` });
41
+ }
42
+ }
43
+ else {
44
+ // Default to empty text for unsupported types
45
+ blocks.push({ text: "" });
46
+ }
47
+ }
48
+ return blocks.filter((b) => b.text !== "");
49
+ }
50
+ return [];
51
+ }
52
+ /**
53
+ * Convert NodeLLM messages to Bedrock Converse format.
54
+ * Extracts system messages to the top-level system field.
55
+ */
56
+ export function convertMessages(messages) {
57
+ const systemBlocks = [];
58
+ const bedrockMessages = [];
59
+ let currentToolResults = [];
60
+ const flushToolResults = () => {
61
+ if (currentToolResults.length > 0) {
62
+ bedrockMessages.push({
63
+ role: "user",
64
+ content: currentToolResults
65
+ });
66
+ currentToolResults = [];
67
+ }
68
+ };
69
+ for (const msg of messages) {
70
+ if (msg.role !== "tool") {
71
+ flushToolResults();
72
+ }
73
+ // System messages go to the top-level system field
74
+ if (msg.role === "system") {
75
+ const blocks = messageContentToBlocks(msg.content);
76
+ systemBlocks.push(...blocks);
77
+ continue;
78
+ }
79
+ // User messages
80
+ if (msg.role === "user") {
81
+ bedrockMessages.push({
82
+ role: "user",
83
+ content: messageContentToBlocks(msg.content)
84
+ });
85
+ continue;
86
+ }
87
+ // Assistant messages (may include tool calls and reasoning)
88
+ if (msg.role === "assistant") {
89
+ const contentBlocks = messageContentToBlocks(msg.content);
90
+ // Add reasoning content if present
91
+ if (msg.reasoning) {
92
+ contentBlocks.unshift({
93
+ reasoningContent: {
94
+ text: msg.reasoning
95
+ }
96
+ });
97
+ }
98
+ // Add tool use blocks if present
99
+ if (msg.tool_calls) {
100
+ for (const toolCall of msg.tool_calls) {
101
+ contentBlocks.push({
102
+ toolUse: {
103
+ toolUseId: toolCall.id,
104
+ name: toolCall.function.name,
105
+ input: JSON.parse(toolCall.function.arguments || "{}")
106
+ }
107
+ });
108
+ }
109
+ }
110
+ bedrockMessages.push({
111
+ role: "assistant",
112
+ content: contentBlocks
113
+ });
114
+ continue;
115
+ }
116
+ // Tool result messages
117
+ if (msg.role === "tool") {
118
+ currentToolResults.push({
119
+ toolResult: {
120
+ toolUseId: msg.tool_call_id || "",
121
+ content: [{ text: typeof msg.content === "string" ? msg.content : "" }],
122
+ status: msg.isError ? "error" : "success"
123
+ }
124
+ });
125
+ }
126
+ }
127
+ flushToolResults();
128
+ return {
129
+ messages: bedrockMessages,
130
+ system: systemBlocks.length > 0 ? systemBlocks : undefined
131
+ };
132
+ }
133
+ // ─────────────────────────────────────────────────────────────────────────────
134
+ // Tool Conversion
135
+ // ─────────────────────────────────────────────────────────────────────────────
136
+ /**
137
+ * Convert NodeLLM tool definitions to Bedrock tool config.
138
+ */
139
+ export function convertTools(tools) {
140
+ if (!tools || tools.length === 0) {
141
+ return undefined;
142
+ }
143
+ return {
144
+ tools: tools.map((tool) => ({
145
+ toolSpec: {
146
+ name: tool.function.name,
147
+ description: tool.function.description,
148
+ inputSchema: {
149
+ json: tool.function.parameters || {}
150
+ }
151
+ }
152
+ }))
153
+ };
154
+ }
155
+ // ─────────────────────────────────────────────────────────────────────────────
156
+ // Request Builder
157
+ // ─────────────────────────────────────────────────────────────────────────────
158
+ /**
159
+ * Build a complete Bedrock Converse request from NodeLLM ChatRequest.
160
+ */
161
+ export function buildConverseRequest(messages, tools, options) {
162
+ const { messages: bedrockMessages, system } = convertMessages(messages);
163
+ const request = {
164
+ messages: bedrockMessages
165
+ };
166
+ if (system) {
167
+ request.system = system;
168
+ }
169
+ const toolConfig = convertTools(tools);
170
+ if (toolConfig) {
171
+ request.toolConfig = toolConfig;
172
+ }
173
+ if (options?.guardrail) {
174
+ request.guardrailConfig = options.guardrail;
175
+ }
176
+ // Inference config (only add if we have values)
177
+ if (options?.maxTokens || options?.temperature !== undefined) {
178
+ request.inferenceConfig = {};
179
+ if (options.maxTokens) {
180
+ request.inferenceConfig.maxTokens = options.maxTokens;
181
+ }
182
+ if (options.temperature !== undefined) {
183
+ request.inferenceConfig.temperature = options.temperature;
184
+ }
185
+ }
186
+ // Thinking config for Claude 3.7+
187
+ if (options?.thinking?.budget) {
188
+ request.additionalModelRequestFields = {
189
+ ...request.additionalModelRequestFields,
190
+ thinking: {
191
+ type: "enabled",
192
+ budget_tokens: options.thinking.budget
193
+ }
194
+ };
195
+ }
196
+ // Merge any other additional fields
197
+ if (options?.additionalModelRequestFields) {
198
+ request.additionalModelRequestFields = {
199
+ ...request.additionalModelRequestFields,
200
+ ...options.additionalModelRequestFields
201
+ };
202
+ }
203
+ return request;
204
+ }