@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,154 @@
1
+ /**
2
+ * Bedrock Image Generation Handler
3
+ *
4
+ * Supports Amazon Titan Image Generator and Stability.ai Stable Diffusion models.
5
+ */
6
+ import { 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
+ export class BedrockImage {
11
+ config;
12
+ baseUrl;
13
+ constructor(config) {
14
+ this.config = config;
15
+ this.baseUrl = getBedrockEndpoint(config.region);
16
+ }
17
+ /**
18
+ * Execute an image generation request.
19
+ */
20
+ async execute(request) {
21
+ const modelId = request.model ?? "amazon.titan-image-generator-v2:0";
22
+ const url = `${this.baseUrl}/model/${modelId}/invoke`;
23
+ const body = this.buildRequestBody(modelId, request);
24
+ const bodyJson = JSON.stringify(body);
25
+ const headers = this.buildHeaders(url, bodyJson, request.headers);
26
+ logger.logRequest("BedrockImage", "POST", url, body);
27
+ const response = await fetchWithTimeout(url, {
28
+ method: "POST",
29
+ headers,
30
+ body: bodyJson
31
+ }, request.requestTimeout ?? this.config.requestTimeout ?? 120000);
32
+ if (!response.ok) {
33
+ const errorText = await response.text();
34
+ logger.logResponse("BedrockImage", response.status, response.statusText, errorText);
35
+ throw new Error(`Bedrock Image Generation error (${response.status}): ${errorText}`);
36
+ }
37
+ const data = await response.json();
38
+ return this.parseResponse(modelId, data);
39
+ }
40
+ /**
41
+ * Build model-specific request body.
42
+ */
43
+ buildRequestBody(modelId, request) {
44
+ const prompt = request.prompt;
45
+ // Amazon Titan
46
+ if (modelId.includes("amazon.titan-image")) {
47
+ return {
48
+ taskType: "TEXT_IMAGE",
49
+ textToImageParams: {
50
+ text: prompt
51
+ },
52
+ imageGenerationConfig: {
53
+ numberOfImages: request.n ?? 1,
54
+ height: this.parseSize(request.size)?.height ?? 1024,
55
+ width: this.parseSize(request.size)?.width ?? 1024,
56
+ cfgScale: 8.0
57
+ }
58
+ };
59
+ }
60
+ // Stability AI (Stable Diffusion)
61
+ if (modelId.includes("stability.stable-diffusion")) {
62
+ return {
63
+ text_prompts: [
64
+ {
65
+ text: prompt,
66
+ weight: 1
67
+ }
68
+ ],
69
+ cfg_scale: 7,
70
+ steps: 30,
71
+ samples: request.n ?? 1,
72
+ width: this.parseSize(request.size)?.width ?? 1024,
73
+ height: this.parseSize(request.size)?.height ?? 1024
74
+ };
75
+ }
76
+ throw new Error(`Unsupported image generation model: ${modelId}`);
77
+ }
78
+ /**
79
+ * Parse model-specific response.
80
+ */
81
+ parseResponse(modelId, data) {
82
+ // Amazon Titan returns { images: ["base64", ...] }
83
+ if (modelId.includes("amazon.titan-image")) {
84
+ const base64 = data.images?.[0];
85
+ if (!base64)
86
+ throw new Error("No image data returned from Titan");
87
+ return {
88
+ data: base64,
89
+ mime_type: "image/png"
90
+ };
91
+ }
92
+ // Stability AI returns { artifacts: [ { base64: "...", ... } ] }
93
+ if (modelId.includes("stability.stable-diffusion")) {
94
+ const base64 = data.artifacts?.[0]?.base64;
95
+ if (!base64)
96
+ throw new Error("No image data returned from Stable Diffusion");
97
+ return {
98
+ data: base64,
99
+ mime_type: "image/png"
100
+ };
101
+ }
102
+ throw new Error(`Unsupported model response format: ${modelId}`);
103
+ }
104
+ /**
105
+ * Parse size string (e.g. "1024x1024") into height and width.
106
+ */
107
+ parseSize(size) {
108
+ if (!size)
109
+ return null;
110
+ const parts = size.toLowerCase().split("x");
111
+ const width = parts[0];
112
+ const height = parts[1];
113
+ if (width && height) {
114
+ return {
115
+ width: parseInt(width, 10),
116
+ height: parseInt(height, 10)
117
+ };
118
+ }
119
+ return null;
120
+ }
121
+ /**
122
+ * Build headers with SigV4 signing.
123
+ */
124
+ buildHeaders(url, body, additionalHeaders) {
125
+ const headers = {
126
+ "Content-Type": "application/json",
127
+ Accept: "application/json",
128
+ ...additionalHeaders
129
+ };
130
+ if (this.config.apiKey) {
131
+ headers["Authorization"] = `Bearer ${this.config.apiKey}`;
132
+ }
133
+ else if (this.config.accessKeyId && this.config.secretAccessKey && this.config.region) {
134
+ const accessKeyId = this.config.accessKeyId;
135
+ const secretAccessKey = this.config.secretAccessKey;
136
+ const region = this.config.region;
137
+ const credentials = {
138
+ accessKeyId,
139
+ secretAccessKey,
140
+ sessionToken: this.config.sessionToken
141
+ };
142
+ const signedHeaders = signRequest({
143
+ method: "POST",
144
+ url,
145
+ body,
146
+ credentials,
147
+ region,
148
+ service: "bedrock"
149
+ });
150
+ return { ...headers, ...signedHeaders };
151
+ }
152
+ return headers;
153
+ }
154
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Bedrock Models Handler
3
+ *
4
+ * Lists and normalizes models from the Bedrock management API.
5
+ */
6
+ import { BedrockConfig } from "./config.js";
7
+ import { ModelInfo } from "../Provider.js";
8
+ export declare class BedrockModels {
9
+ private readonly config;
10
+ private readonly baseUrl;
11
+ constructor(config: BedrockConfig);
12
+ /**
13
+ * List and normalize foundation models.
14
+ */
15
+ execute(): Promise<ModelInfo[]>;
16
+ /**
17
+ * Parse Bedrock model list into NodeLLM format.
18
+ */
19
+ private parseResponse;
20
+ /**
21
+ * Determine if a model should be included in the NodeLLM models list.
22
+ */
23
+ private shouldIncludeModel;
24
+ /**
25
+ * Map summary to Model info.
26
+ */
27
+ private mapToModel;
28
+ /**
29
+ * Normalize model ID for inference profiles if supported.
30
+ * Handles regional prefixes for Cross-Region Inference.
31
+ */
32
+ private normalizeModelId;
33
+ }
34
+ //# sourceMappingURL=Models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Models.d.ts","sourceRoot":"","sources":["../../../src/providers/bedrock/Models.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAyB,MAAM,aAAa,CAAC;AAGnE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAK3C,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,EAAE,aAAa;IAOjC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAyCrC;;OAEG;IACH,OAAO,CAAC,aAAa;IAQrB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAiB1B;;OAEG;IACH,OAAO,CAAC,UAAU;IA+BlB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;CAkBzB"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Bedrock Models Handler
3
+ *
4
+ * Lists and normalizes models from the Bedrock management API.
5
+ */
6
+ import { validateBedrockConfig } from "./config.js";
7
+ import { Capabilities } from "./Capabilities.js";
8
+ import { signRequest } from "../../utils/AwsSigV4.js";
9
+ import { fetchWithTimeout } from "../../utils/fetch.js";
10
+ import { logger } from "../../utils/logger.js";
11
+ export class BedrockModels {
12
+ config;
13
+ baseUrl;
14
+ constructor(config) {
15
+ this.config = config;
16
+ validateBedrockConfig(config);
17
+ // Management API uses a different subdomain than the runtime API
18
+ this.baseUrl = `https://bedrock.${config.region}.amazonaws.com`;
19
+ }
20
+ /**
21
+ * List and normalize foundation models.
22
+ */
23
+ async execute() {
24
+ const url = `${this.baseUrl}/foundation-models`;
25
+ const body = ""; // GET request
26
+ const credentials = {
27
+ accessKeyId: this.config.accessKeyId,
28
+ secretAccessKey: this.config.secretAccessKey,
29
+ sessionToken: this.config.sessionToken
30
+ };
31
+ const signedHeaders = signRequest({
32
+ method: "GET",
33
+ url,
34
+ body,
35
+ credentials,
36
+ region: this.config.region,
37
+ service: "bedrock"
38
+ });
39
+ logger.logRequest("Bedrock", "GET", url);
40
+ const response = await fetchWithTimeout(url, {
41
+ method: "GET",
42
+ headers: {
43
+ ...signedHeaders,
44
+ Accept: "application/json"
45
+ }
46
+ });
47
+ if (!response.ok) {
48
+ const errorText = await response.text();
49
+ logger.logResponse("Bedrock", response.status, response.statusText, errorText);
50
+ throw new Error(`Bedrock Models API error (${response.status}): ${errorText}`);
51
+ }
52
+ const json = (await response.json());
53
+ logger.logResponse("Bedrock", response.status, response.statusText, json);
54
+ return this.parseResponse(json);
55
+ }
56
+ /**
57
+ * Parse Bedrock model list into NodeLLM format.
58
+ */
59
+ parseResponse(response) {
60
+ const summaries = response.modelSummaries || [];
61
+ // Filter and map models
62
+ // We primarily focus on models that support text conversation (Converse API)
63
+ return summaries.filter((m) => this.shouldIncludeModel(m)).map((m) => this.mapToModel(m));
64
+ }
65
+ /**
66
+ * Determine if a model should be included in the NodeLLM models list.
67
+ */
68
+ shouldIncludeModel(summary) {
69
+ const modelId = summary.modelId;
70
+ // We only support Claude, DeepSeek, Mistral, Llama, and Titan for now.
71
+ // Exclude embedding models and image models unless we strictly want to list them.
72
+ const isSupportedFamily = modelId.includes("anthropic.claude") ||
73
+ modelId.includes("deepseek") ||
74
+ modelId.includes("mistral") ||
75
+ modelId.includes("meta.llama") ||
76
+ modelId.includes("amazon.nova") ||
77
+ modelId.includes("amazon.titan-text") ||
78
+ modelId.includes("amazon.titan-embed");
79
+ return isSupportedFamily;
80
+ }
81
+ /**
82
+ * Map summary to Model info.
83
+ */
84
+ mapToModel(summary) {
85
+ const modelId = summary.modelId;
86
+ const normalizedId = this.normalizeModelId(summary);
87
+ const capabilities = Capabilities.getCapabilities(modelId);
88
+ const pricing = Capabilities.getPricing(modelId);
89
+ const contextWindow = Capabilities.getContextWindow(modelId);
90
+ const maxTokens = Capabilities.getMaxOutputTokens(modelId);
91
+ return {
92
+ id: normalizedId,
93
+ name: summary.modelName || Capabilities.formatDisplayName(modelId),
94
+ provider: "bedrock",
95
+ family: Capabilities.getModelFamily(modelId),
96
+ context_window: contextWindow,
97
+ max_output_tokens: maxTokens,
98
+ modalities: {
99
+ input: summary.inputModalities || ["text"],
100
+ output: summary.outputModalities || ["text"]
101
+ },
102
+ capabilities,
103
+ pricing,
104
+ metadata: {
105
+ bedrock_model_id: modelId,
106
+ provider_name: summary.providerName,
107
+ inference_types: summary.inferenceTypesSupported || [],
108
+ streaming_supported: summary.responseStreamingSupported || false
109
+ }
110
+ };
111
+ }
112
+ /**
113
+ * Normalize model ID for inference profiles if supported.
114
+ * Handles regional prefixes for Cross-Region Inference.
115
+ */
116
+ normalizeModelId(summary) {
117
+ const modelId = summary.modelId;
118
+ const types = summary.inferenceTypesSupported || [];
119
+ // If it supports INFERENCE_PROFILE but NOT ON_DEMAND directly,
120
+ // it likely requires the regional prefix.
121
+ const needsPrefix = types.includes("INFERENCE_PROFILE") && !types.includes("ON_DEMAND");
122
+ if (needsPrefix) {
123
+ const region = this.config.region;
124
+ const prefix = region.split("-")[0]; // 'us', 'eu', 'ap'
125
+ if (prefix && !/^[a-z]{2}\./.test(modelId)) {
126
+ return `${prefix}.${modelId}`;
127
+ }
128
+ }
129
+ return modelId;
130
+ }
131
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Bedrock Moderation Handler
3
+ *
4
+ * Implements the standalone moderation endpoint using Bedrock Guardrails.
5
+ * Use this to check content for safety before sending it to an LLM.
6
+ */
7
+ import { ModerationRequest, ModerationResponse } from "../Provider.js";
8
+ import { BedrockConfig } from "./config.js";
9
+ export declare class BedrockModeration {
10
+ private readonly config;
11
+ private readonly authMode;
12
+ private readonly baseUrl;
13
+ constructor(config: BedrockConfig);
14
+ /**
15
+ * Execute a moderation request against Bedrock Guardrails.
16
+ */
17
+ execute(request: ModerationRequest): Promise<ModerationResponse>;
18
+ private applyGuardrail;
19
+ private mapToModerationResult;
20
+ private mapConfidence;
21
+ private buildHeaders;
22
+ }
23
+ //# sourceMappingURL=Moderation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Moderation.d.ts","sourceRoot":"","sources":["../../../src/providers/bedrock/Moderation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAoB,MAAM,gBAAgB,CAAC;AACzF,OAAO,EAAE,aAAa,EAA6C,MAAM,aAAa,CAAC;AAKvF,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,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;YAgCxD,cAAc;IAuC5B,OAAO,CAAC,qBAAqB;IAoC7B,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,YAAY;CA6BrB"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Bedrock Moderation Handler
3
+ *
4
+ * Implements the standalone moderation endpoint using Bedrock Guardrails.
5
+ * Use this to check content for safety before sending it to an LLM.
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
+ export class BedrockModeration {
12
+ config;
13
+ authMode;
14
+ baseUrl;
15
+ constructor(config) {
16
+ this.config = config;
17
+ this.authMode = validateBedrockConfig(config);
18
+ this.baseUrl = getBedrockEndpoint(config.region);
19
+ }
20
+ /**
21
+ * Execute a moderation request against Bedrock Guardrails.
22
+ */
23
+ async execute(request) {
24
+ const { guardrailIdentifier, guardrailVersion } = this.config;
25
+ if (!guardrailIdentifier || !guardrailVersion) {
26
+ throw new Error("Bedrock moderation requires 'bedrockGuardrailIdentifier' and 'bedrockGuardrailVersion' to be configured.");
27
+ }
28
+ const inputs = Array.isArray(request.input) ? request.input : [request.input];
29
+ const results = [];
30
+ // Process each input against the guardrail
31
+ // Note: Bedrock ApplyGuardrail accepts a list of content blocks,
32
+ // but usually we want to moderate individual strings to get back granular results.
33
+ for (const text of inputs) {
34
+ const result = await this.applyGuardrail(text, guardrailIdentifier, guardrailVersion, request.requestTimeout);
35
+ results.push(result);
36
+ }
37
+ return {
38
+ id: `bedrock-mod-${Date.now()}`,
39
+ model: `guardrail:${guardrailIdentifier}:${guardrailVersion}`,
40
+ results
41
+ };
42
+ }
43
+ async applyGuardrail(text, id, version, timeout) {
44
+ const encodedId = encodeURIComponent(id);
45
+ const encodedVersion = encodeURIComponent(version);
46
+ const url = `${this.baseUrl}/guardrail/${encodedId}/version/${encodedVersion}/apply`;
47
+ const body = JSON.stringify({
48
+ content: [{ text: { text } }],
49
+ source: "INPUT"
50
+ });
51
+ const headers = this.buildHeaders(url, body);
52
+ logger.logRequest("Bedrock Moderation", "POST", url, { text });
53
+ const response = await fetchWithTimeout(url, {
54
+ method: "POST",
55
+ headers,
56
+ body
57
+ }, timeout ?? this.config.requestTimeout);
58
+ if (!response.ok) {
59
+ const errorText = await response.text();
60
+ throw new Error(`Bedrock Moderation API error (${response.status}): ${errorText}`);
61
+ }
62
+ const json = await response.json();
63
+ logger.logResponse("Bedrock Moderation", response.status, response.statusText, json);
64
+ return this.mapToModerationResult(json);
65
+ }
66
+ mapToModerationResult(response) {
67
+ const flagged = response.action === "BLOCK";
68
+ const categories = {};
69
+ const category_scores = {};
70
+ // Map Bedrock assessments to standard categories
71
+ if (response.assessments) {
72
+ for (const assessment of response.assessments) {
73
+ // Content Policy Filters (Hate, Violence, etc.)
74
+ if (assessment.contentPolicy?.filters) {
75
+ for (const filter of assessment.contentPolicy.filters) {
76
+ const key = filter.type.toLowerCase();
77
+ const isBlocked = filter.action === "BLOCK";
78
+ categories[key] = isBlocked;
79
+ // Map confidence to a 0-1 score
80
+ category_scores[key] = this.mapConfidence(filter.confidence);
81
+ }
82
+ }
83
+ // Topic Policy
84
+ if (assessment.topicPolicy?.topics) {
85
+ for (const topic of assessment.topicPolicy.topics) {
86
+ categories[`topic_${topic.name.toLowerCase()}`] = topic.action === "BLOCK";
87
+ category_scores[`topic_${topic.name.toLowerCase()}`] = 1.0;
88
+ }
89
+ }
90
+ }
91
+ }
92
+ return {
93
+ flagged,
94
+ categories,
95
+ category_scores
96
+ };
97
+ }
98
+ mapConfidence(confidence) {
99
+ switch (confidence) {
100
+ case "HIGH":
101
+ return 0.9;
102
+ case "MEDIUM":
103
+ return 0.5;
104
+ case "LOW":
105
+ return 0.1;
106
+ case "NONE":
107
+ return 0.0;
108
+ default:
109
+ return 0.0;
110
+ }
111
+ }
112
+ buildHeaders(url, body) {
113
+ const headers = {
114
+ "Content-Type": "application/json",
115
+ Accept: "application/json"
116
+ };
117
+ if (this.authMode === "apiKey") {
118
+ headers["Authorization"] = `Bearer ${this.config.apiKey}`;
119
+ }
120
+ else {
121
+ const credentials = {
122
+ accessKeyId: this.config.accessKeyId,
123
+ secretAccessKey: this.config.secretAccessKey,
124
+ sessionToken: this.config.sessionToken
125
+ };
126
+ const signedHeaders = signRequest({
127
+ method: "POST",
128
+ url,
129
+ body,
130
+ credentials,
131
+ region: this.config.region,
132
+ service: "bedrock"
133
+ });
134
+ Object.assign(headers, signedHeaders);
135
+ }
136
+ return headers;
137
+ }
138
+ }
@@ -0,0 +1,21 @@
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 { ChatRequest, ChatChunk } from "../Provider.js";
8
+ import { BedrockConfig } from "./config.js";
9
+ export declare class BedrockStreaming {
10
+ private readonly config;
11
+ private readonly authMode;
12
+ private readonly baseUrl;
13
+ constructor(config: BedrockConfig);
14
+ execute(request: ChatRequest, controller?: AbortController): AsyncGenerator<ChatChunk>;
15
+ /**
16
+ * Parse a Bedrock ConverseStream event into a NodeLLM ChatChunk.
17
+ */
18
+ private parseEvent;
19
+ private buildHeaders;
20
+ }
21
+ //# sourceMappingURL=Streaming.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Streaming.d.ts","sourceRoot":"","sources":["../../../src/providers/bedrock/Streaming.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAS,MAAM,gBAAgB,CAAC;AAC/D,OAAO,EAAE,aAAa,EAA6C,MAAM,aAAa,CAAC;AAQvF,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,MAAM,EAAE,aAAa;IAM1B,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,eAAe,GAAG,cAAc,CAAC,SAAS,CAAC;IA4H7F;;OAEG;IACH,OAAO,CAAC,UAAU;IAyGlB,OAAO,CAAC,YAAY;CAsCrB"}