@llumiverse/drivers 1.0.0-dev.20260202.145450Z → 1.0.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 (240) hide show
  1. package/lib/cjs/adobe/firefly.js +120 -0
  2. package/lib/cjs/adobe/firefly.js.map +1 -0
  3. package/lib/cjs/azure/azure_foundry.js +432 -0
  4. package/lib/cjs/azure/azure_foundry.js.map +1 -0
  5. package/lib/cjs/bedrock/converse.js +359 -0
  6. package/lib/cjs/bedrock/converse.js.map +1 -0
  7. package/lib/cjs/bedrock/index.js +1441 -0
  8. package/lib/cjs/bedrock/index.js.map +1 -0
  9. package/lib/cjs/bedrock/nova-image-payload.js +207 -0
  10. package/lib/cjs/bedrock/nova-image-payload.js.map +1 -0
  11. package/lib/cjs/bedrock/payloads.js +3 -0
  12. package/lib/cjs/bedrock/payloads.js.map +1 -0
  13. package/lib/cjs/bedrock/s3.js +107 -0
  14. package/lib/cjs/bedrock/s3.js.map +1 -0
  15. package/lib/cjs/bedrock/twelvelabs.js +87 -0
  16. package/lib/cjs/bedrock/twelvelabs.js.map +1 -0
  17. package/lib/cjs/groq/index.js +326 -0
  18. package/lib/cjs/groq/index.js.map +1 -0
  19. package/lib/cjs/huggingface_ie.js +201 -0
  20. package/lib/cjs/huggingface_ie.js.map +1 -0
  21. package/lib/cjs/index.js +31 -0
  22. package/lib/cjs/index.js.map +1 -0
  23. package/lib/cjs/mistral/index.js +176 -0
  24. package/lib/cjs/mistral/index.js.map +1 -0
  25. package/lib/cjs/mistral/types.js +83 -0
  26. package/lib/cjs/mistral/types.js.map +1 -0
  27. package/lib/cjs/openai/azure_openai.js +72 -0
  28. package/lib/cjs/openai/azure_openai.js.map +1 -0
  29. package/lib/cjs/openai/index.js +1100 -0
  30. package/lib/cjs/openai/index.js.map +1 -0
  31. package/lib/cjs/openai/openai.js +21 -0
  32. package/lib/cjs/openai/openai.js.map +1 -0
  33. package/lib/cjs/openai/openai_compatible.js +63 -0
  34. package/lib/cjs/openai/openai_compatible.js.map +1 -0
  35. package/lib/cjs/openai/openai_format.js +131 -0
  36. package/lib/cjs/openai/openai_format.js.map +1 -0
  37. package/lib/cjs/package.json +3 -0
  38. package/lib/cjs/replicate.js +275 -0
  39. package/lib/cjs/replicate.js.map +1 -0
  40. package/lib/cjs/test-driver/TestErrorCompletionStream.js +20 -0
  41. package/lib/cjs/test-driver/TestErrorCompletionStream.js.map +1 -0
  42. package/lib/cjs/test-driver/TestValidationErrorCompletionStream.js +24 -0
  43. package/lib/cjs/test-driver/TestValidationErrorCompletionStream.js.map +1 -0
  44. package/lib/cjs/test-driver/index.js +109 -0
  45. package/lib/cjs/test-driver/index.js.map +1 -0
  46. package/lib/cjs/test-driver/utils.js +30 -0
  47. package/lib/cjs/test-driver/utils.js.map +1 -0
  48. package/lib/cjs/togetherai/index.js +126 -0
  49. package/lib/cjs/togetherai/index.js.map +1 -0
  50. package/lib/cjs/togetherai/interfaces.js +3 -0
  51. package/lib/cjs/togetherai/interfaces.js.map +1 -0
  52. package/lib/cjs/vertexai/debug.js +12 -0
  53. package/lib/cjs/vertexai/debug.js.map +1 -0
  54. package/lib/cjs/vertexai/embeddings/embeddings-image.js +27 -0
  55. package/lib/cjs/vertexai/embeddings/embeddings-image.js.map +1 -0
  56. package/lib/cjs/vertexai/embeddings/embeddings-text.js +23 -0
  57. package/lib/cjs/vertexai/embeddings/embeddings-text.js.map +1 -0
  58. package/lib/cjs/vertexai/index.js +635 -0
  59. package/lib/cjs/vertexai/index.js.map +1 -0
  60. package/lib/cjs/vertexai/models/claude.js +842 -0
  61. package/lib/cjs/vertexai/models/claude.js.map +1 -0
  62. package/lib/cjs/vertexai/models/gemini.js +1110 -0
  63. package/lib/cjs/vertexai/models/gemini.js.map +1 -0
  64. package/lib/cjs/vertexai/models/imagen.js +303 -0
  65. package/lib/cjs/vertexai/models/imagen.js.map +1 -0
  66. package/lib/cjs/vertexai/models/llama.js +183 -0
  67. package/lib/cjs/vertexai/models/llama.js.map +1 -0
  68. package/lib/cjs/vertexai/models.js +35 -0
  69. package/lib/cjs/vertexai/models.js.map +1 -0
  70. package/lib/cjs/watsonx/index.js +161 -0
  71. package/lib/cjs/watsonx/index.js.map +1 -0
  72. package/lib/cjs/watsonx/interfaces.js +3 -0
  73. package/lib/cjs/watsonx/interfaces.js.map +1 -0
  74. package/lib/cjs/xai/index.js +65 -0
  75. package/lib/cjs/xai/index.js.map +1 -0
  76. package/lib/esm/adobe/firefly.js +116 -0
  77. package/lib/esm/adobe/firefly.js.map +1 -0
  78. package/lib/esm/azure/azure_foundry.js +426 -0
  79. package/lib/esm/azure/azure_foundry.js.map +1 -0
  80. package/lib/esm/bedrock/converse.js +352 -0
  81. package/lib/esm/bedrock/converse.js.map +1 -0
  82. package/lib/esm/bedrock/index.js +1434 -0
  83. package/lib/esm/bedrock/index.js.map +1 -0
  84. package/lib/esm/bedrock/nova-image-payload.js +203 -0
  85. package/lib/esm/bedrock/nova-image-payload.js.map +1 -0
  86. package/lib/esm/bedrock/payloads.js +2 -0
  87. package/lib/esm/bedrock/payloads.js.map +1 -0
  88. package/lib/esm/bedrock/s3.js +99 -0
  89. package/lib/esm/bedrock/s3.js.map +1 -0
  90. package/lib/esm/bedrock/twelvelabs.js +84 -0
  91. package/lib/esm/bedrock/twelvelabs.js.map +1 -0
  92. package/lib/esm/groq/index.js +319 -0
  93. package/lib/esm/groq/index.js.map +1 -0
  94. package/lib/esm/huggingface_ie.js +197 -0
  95. package/lib/esm/huggingface_ie.js.map +1 -0
  96. package/lib/esm/index.js +15 -0
  97. package/lib/esm/index.js.map +1 -0
  98. package/lib/esm/mistral/index.js +172 -0
  99. package/lib/esm/mistral/index.js.map +1 -0
  100. package/lib/esm/mistral/types.js +80 -0
  101. package/lib/esm/mistral/types.js.map +1 -0
  102. package/lib/esm/openai/azure_openai.js +68 -0
  103. package/lib/esm/openai/azure_openai.js.map +1 -0
  104. package/lib/esm/openai/index.js +1093 -0
  105. package/lib/esm/openai/index.js.map +1 -0
  106. package/lib/esm/openai/openai.js +14 -0
  107. package/lib/esm/openai/openai.js.map +1 -0
  108. package/lib/esm/openai/openai_compatible.js +56 -0
  109. package/lib/esm/openai/openai_compatible.js.map +1 -0
  110. package/lib/esm/openai/openai_format.js +127 -0
  111. package/lib/esm/openai/openai_format.js.map +1 -0
  112. package/lib/esm/replicate.js +268 -0
  113. package/lib/esm/replicate.js.map +1 -0
  114. package/lib/esm/test-driver/TestErrorCompletionStream.js +16 -0
  115. package/lib/esm/test-driver/TestErrorCompletionStream.js.map +1 -0
  116. package/lib/esm/test-driver/TestValidationErrorCompletionStream.js +20 -0
  117. package/lib/esm/test-driver/TestValidationErrorCompletionStream.js.map +1 -0
  118. package/lib/esm/test-driver/index.js +91 -0
  119. package/lib/esm/test-driver/index.js.map +1 -0
  120. package/lib/esm/test-driver/utils.js +25 -0
  121. package/lib/esm/test-driver/utils.js.map +1 -0
  122. package/lib/esm/togetherai/index.js +122 -0
  123. package/lib/esm/togetherai/index.js.map +1 -0
  124. package/lib/esm/togetherai/interfaces.js +2 -0
  125. package/lib/esm/togetherai/interfaces.js.map +1 -0
  126. package/lib/esm/vertexai/debug.js +6 -0
  127. package/lib/esm/vertexai/debug.js.map +1 -0
  128. package/lib/esm/vertexai/embeddings/embeddings-image.js +24 -0
  129. package/lib/esm/vertexai/embeddings/embeddings-image.js.map +1 -0
  130. package/lib/esm/vertexai/embeddings/embeddings-text.js +20 -0
  131. package/lib/esm/vertexai/embeddings/embeddings-text.js.map +1 -0
  132. package/lib/esm/vertexai/index.js +630 -0
  133. package/lib/esm/vertexai/index.js.map +1 -0
  134. package/lib/esm/vertexai/models/claude.js +833 -0
  135. package/lib/esm/vertexai/models/claude.js.map +1 -0
  136. package/lib/esm/vertexai/models/gemini.js +1104 -0
  137. package/lib/esm/vertexai/models/gemini.js.map +1 -0
  138. package/lib/esm/vertexai/models/imagen.js +299 -0
  139. package/lib/esm/vertexai/models/imagen.js.map +1 -0
  140. package/lib/esm/vertexai/models/llama.js +179 -0
  141. package/lib/esm/vertexai/models/llama.js.map +1 -0
  142. package/lib/esm/vertexai/models.js +32 -0
  143. package/lib/esm/vertexai/models.js.map +1 -0
  144. package/lib/esm/watsonx/index.js +157 -0
  145. package/lib/esm/watsonx/index.js.map +1 -0
  146. package/lib/esm/watsonx/interfaces.js +2 -0
  147. package/lib/esm/watsonx/interfaces.js.map +1 -0
  148. package/lib/esm/xai/index.js +58 -0
  149. package/lib/esm/xai/index.js.map +1 -0
  150. package/lib/types/adobe/firefly.d.ts +30 -0
  151. package/lib/types/adobe/firefly.d.ts.map +1 -0
  152. package/lib/types/azure/azure_foundry.d.ts +52 -0
  153. package/lib/types/azure/azure_foundry.d.ts.map +1 -0
  154. package/lib/types/bedrock/converse.d.ts +8 -0
  155. package/lib/types/bedrock/converse.d.ts.map +1 -0
  156. package/lib/types/bedrock/index.d.ts +135 -0
  157. package/lib/types/bedrock/index.d.ts.map +1 -0
  158. package/lib/types/bedrock/nova-image-payload.d.ts +74 -0
  159. package/lib/types/bedrock/nova-image-payload.d.ts.map +1 -0
  160. package/lib/types/bedrock/payloads.d.ts +12 -0
  161. package/lib/types/bedrock/payloads.d.ts.map +1 -0
  162. package/lib/types/bedrock/s3.d.ts +23 -0
  163. package/lib/types/bedrock/s3.d.ts.map +1 -0
  164. package/lib/types/bedrock/twelvelabs.d.ts +50 -0
  165. package/lib/types/bedrock/twelvelabs.d.ts.map +1 -0
  166. package/lib/types/groq/index.d.ts +27 -0
  167. package/lib/types/groq/index.d.ts.map +1 -0
  168. package/lib/types/huggingface_ie.d.ts +35 -0
  169. package/lib/types/huggingface_ie.d.ts.map +1 -0
  170. package/lib/types/index.d.ts +15 -0
  171. package/lib/types/index.d.ts.map +1 -0
  172. package/lib/types/mistral/index.d.ts +25 -0
  173. package/lib/types/mistral/index.d.ts.map +1 -0
  174. package/lib/types/mistral/types.d.ts +127 -0
  175. package/lib/types/mistral/types.d.ts.map +1 -0
  176. package/lib/types/openai/azure_openai.d.ts +25 -0
  177. package/lib/types/openai/azure_openai.d.ts.map +1 -0
  178. package/lib/types/openai/index.d.ts +126 -0
  179. package/lib/types/openai/index.d.ts.map +1 -0
  180. package/lib/types/openai/openai.d.ts +15 -0
  181. package/lib/types/openai/openai.d.ts.map +1 -0
  182. package/lib/types/openai/openai_compatible.d.ts +31 -0
  183. package/lib/types/openai/openai_compatible.d.ts.map +1 -0
  184. package/lib/types/openai/openai_format.d.ts +21 -0
  185. package/lib/types/openai/openai_format.d.ts.map +1 -0
  186. package/lib/types/replicate.d.ts +48 -0
  187. package/lib/types/replicate.d.ts.map +1 -0
  188. package/lib/types/test-driver/TestErrorCompletionStream.d.ts +9 -0
  189. package/lib/types/test-driver/TestErrorCompletionStream.d.ts.map +1 -0
  190. package/lib/types/test-driver/TestValidationErrorCompletionStream.d.ts +9 -0
  191. package/lib/types/test-driver/TestValidationErrorCompletionStream.d.ts.map +1 -0
  192. package/lib/types/test-driver/index.d.ts +24 -0
  193. package/lib/types/test-driver/index.d.ts.map +1 -0
  194. package/lib/types/test-driver/utils.d.ts +5 -0
  195. package/lib/types/test-driver/utils.d.ts.map +1 -0
  196. package/lib/types/togetherai/index.d.ts +23 -0
  197. package/lib/types/togetherai/index.d.ts.map +1 -0
  198. package/lib/types/togetherai/interfaces.d.ts +96 -0
  199. package/lib/types/togetherai/interfaces.d.ts.map +1 -0
  200. package/lib/types/vertexai/debug.d.ts +2 -0
  201. package/lib/types/vertexai/debug.d.ts.map +1 -0
  202. package/lib/types/vertexai/embeddings/embeddings-image.d.ts +11 -0
  203. package/lib/types/vertexai/embeddings/embeddings-image.d.ts.map +1 -0
  204. package/lib/types/vertexai/embeddings/embeddings-text.d.ts +10 -0
  205. package/lib/types/vertexai/embeddings/embeddings-text.d.ts.map +1 -0
  206. package/lib/types/vertexai/index.d.ts +79 -0
  207. package/lib/types/vertexai/index.d.ts.map +1 -0
  208. package/lib/types/vertexai/models/claude.d.ts +103 -0
  209. package/lib/types/vertexai/models/claude.d.ts.map +1 -0
  210. package/lib/types/vertexai/models/gemini.d.ts +78 -0
  211. package/lib/types/vertexai/models/gemini.d.ts.map +1 -0
  212. package/lib/types/vertexai/models/imagen.d.ts +75 -0
  213. package/lib/types/vertexai/models/imagen.d.ts.map +1 -0
  214. package/lib/types/vertexai/models/llama.d.ts +20 -0
  215. package/lib/types/vertexai/models/llama.d.ts.map +1 -0
  216. package/lib/types/vertexai/models.d.ts +20 -0
  217. package/lib/types/vertexai/models.d.ts.map +1 -0
  218. package/lib/types/watsonx/index.d.ts +27 -0
  219. package/lib/types/watsonx/index.d.ts.map +1 -0
  220. package/lib/types/watsonx/interfaces.d.ts +65 -0
  221. package/lib/types/watsonx/interfaces.d.ts.map +1 -0
  222. package/lib/types/xai/index.d.ts +18 -0
  223. package/lib/types/xai/index.d.ts.map +1 -0
  224. package/package.json +18 -18
  225. package/src/bedrock/converse.ts +85 -10
  226. package/src/bedrock/error-handling.test.ts +352 -0
  227. package/src/bedrock/index.ts +293 -16
  228. package/src/groq/index.ts +9 -4
  229. package/src/mistral/index.ts +25 -22
  230. package/src/mistral/types.ts +0 -5
  231. package/src/openai/error-handling.test.ts +567 -0
  232. package/src/openai/index.ts +513 -33
  233. package/src/openai/openai_compatible.ts +7 -0
  234. package/src/openai/openai_format.ts +1 -1
  235. package/src/vertexai/index.ts +61 -13
  236. package/src/vertexai/models/claude-error-handling.test.ts +432 -0
  237. package/src/vertexai/models/claude.ts +287 -10
  238. package/src/vertexai/models/gemini-error-handling.test.ts +353 -0
  239. package/src/vertexai/models/gemini.ts +329 -52
  240. package/src/vertexai/models.ts +7 -2
@@ -10,22 +10,26 @@ import {
10
10
  BedrockClaudeOptions,
11
11
  BedrockGptOssOptions,
12
12
  BedrockPalmyraOptions,
13
- Completion, CompletionChunkObject, DataSource, DriverOptions, EmbeddingsOptions, EmbeddingsResult,
13
+ Completion, CompletionChunkObject,
14
+ CompletionResult,
15
+ DataSource,
16
+ deserializeBinaryFromStorage,
17
+ DriverOptions, EmbeddingsOptions, EmbeddingsResult,
14
18
  ExecutionOptions, ExecutionTokenUsage,
19
+ getConversationMeta,
15
20
  getMaxTokensLimitBedrock,
16
21
  getModelCapabilities,
22
+ incrementConversationTurn,
23
+ LlumiverseError, LlumiverseErrorContext,
17
24
  modelModalitiesToArray,
18
25
  ModelOptions,
19
26
  NovaCanvasOptions,
20
27
  PromptSegment,
21
28
  StatelessExecutionOptions,
22
29
  stripBinaryFromConversation,
23
- truncateLargeTextInConversation,
24
- deserializeBinaryFromStorage,
25
- getConversationMeta,
26
- incrementConversationTurn,
30
+ stripHeartbeatsFromConversation,
27
31
  TextFallbackOptions, ToolDefinition, ToolUse, TrainingJob, TrainingJobStatus, TrainingOptions,
28
- CompletionResult
32
+ truncateLargeTextInConversation
29
33
  } from "@llumiverse/core";
30
34
  import { transformAsyncIterator } from "@llumiverse/core/async";
31
35
  import { formatNovaPrompt, NovaMessagesPrompt } from "@llumiverse/core/formatters";
@@ -93,14 +97,49 @@ function maxTokenFallbackClaude(option: StatelessExecutionOptions): number {
93
97
  if (modelOptions && typeof modelOptions.max_tokens === "number") {
94
98
  return modelOptions.max_tokens;
95
99
  } else {
96
- const thinking_budget = modelOptions?.thinking_budget_tokens ?? 0;
97
100
  let maxSupportedTokens = getMaxTokensLimitBedrock(option.model) ?? 8192; // Should always return a number for claude, 8192 is to satisfy the TypeScript type checker;
98
101
  // Fallback to the default max tokens limit for the model
99
102
  if (option.model.includes('claude-3-7-sonnet') && (modelOptions?.thinking_budget_tokens ?? 0) < 48000) {
100
103
  maxSupportedTokens = 64000; // Claude 3.7 can go up to 128k with a beta header, but when no max tokens is specified, we default to 64k.
101
104
  }
102
- return Math.min(16000 + thinking_budget, maxSupportedTokens); // Cap to 16k, to avoid taking up too much context window and quota.
105
+ return maxSupportedTokens;
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Parse Claude model version from model string.
111
+ * @param modelString - The model identifier string
112
+ * @returns An object with major and minor version numbers, or null if not parseable
113
+ */
114
+ function parseClaudeVersion(modelString: string): { major: number; minor: number } | null {
115
+ // Match pattern: claude-[optional variant]-{major}-[optional 1-2 digit minor]
116
+ // The minor version is limited to 1-2 digits to avoid matching dates (YYYYMMDD format)
117
+ const match = modelString.match(/claude-(?:[a-z]+-)?(\d+)(?:-(\d{1,2}))?(?:-|\b)/);
118
+ if (match) {
119
+ return {
120
+ major: parseInt(match[1], 10),
121
+ minor: match[2] ? parseInt(match[2], 10) : 0
122
+ };
103
123
  }
124
+ return null;
125
+ }
126
+
127
+ /**
128
+ * Check if a Claude model version is greater than or equal to a target version.
129
+ * @returns true if the model version is >= target version, false otherwise
130
+ */
131
+ function isClaudeVersionGTE(modelString: string, targetMajor: number, targetMinor: number): boolean {
132
+ const version = parseClaudeVersion(modelString);
133
+ if (!version) {
134
+ return false;
135
+ }
136
+ if (version.major > targetMajor) {
137
+ return true;
138
+ }
139
+ if (version.major === targetMajor && version.minor >= targetMinor) {
140
+ return true;
141
+ }
142
+ return false;
104
143
  }
105
144
 
106
145
  export type BedrockPrompt = NovaMessagesPrompt | ConverseRequest | TwelvelabsPegasusRequest;
@@ -153,6 +192,143 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
153
192
  return await formatConversePrompt(segments, opts);
154
193
  }
155
194
 
195
+ /**
196
+ * Format AWS Bedrock errors into LlumiverseError with proper status codes and retryability.
197
+ *
198
+ * AWS SDK errors provide:
199
+ * - error.name: The exception type (e.g., "ThrottlingException")
200
+ * - error.$metadata.httpStatusCode: The HTTP status code
201
+ * - error.$metadata.requestId: The AWS request ID for tracking
202
+ * - error.$fault: "client" or "server" indicating error category
203
+ *
204
+ * @param error - The AWS SDK error
205
+ * @param context - Context about where the error occurred
206
+ * @returns A standardized LlumiverseError
207
+ */
208
+ public formatLlumiverseError(
209
+ error: unknown,
210
+ context: LlumiverseErrorContext
211
+ ): LlumiverseError {
212
+ // Check if it's an AWS SDK error with $metadata
213
+ const awsError = error as any;
214
+ const hasMetadata = awsError?.$metadata !== undefined;
215
+
216
+ if (!hasMetadata) {
217
+ // Not an AWS SDK error, use default handling
218
+ return super.formatLlumiverseError(error, context);
219
+ }
220
+
221
+ // Extract AWS-specific fields
222
+ const errorName = awsError.name || 'UnknownError';
223
+ const httpStatusCode = awsError.$metadata?.httpStatusCode;
224
+ const requestId = awsError.$metadata?.requestId;
225
+ const fault = awsError.$fault; // "client" or "server"
226
+
227
+ // Extract error message - handle both Error instances and plain objects
228
+ let message: string;
229
+ if (error instanceof Error) {
230
+ message = error.message;
231
+ } else if (typeof awsError.message === 'string') {
232
+ message = awsError.message;
233
+ } else {
234
+ message = String(error);
235
+ }
236
+
237
+ // Build user-facing message with error name and status code
238
+ let userMessage = message;
239
+
240
+ // Include status code in message if available (for end-user visibility)
241
+ if (httpStatusCode) {
242
+ userMessage = `[${httpStatusCode}] ${userMessage}`;
243
+ }
244
+
245
+ // Prefix with error name if it's meaningful (not just "Error")
246
+ if (errorName && errorName !== 'Error' && errorName !== 'UnknownError') {
247
+ userMessage = `${errorName}: ${userMessage}`;
248
+ }
249
+
250
+ // Add request ID if available (useful for AWS support)
251
+ if (requestId) {
252
+ userMessage += ` (Request ID: ${requestId})`;
253
+ }
254
+
255
+ // Determine retryability based on AWS error types
256
+ const retryable = this.isBedrockErrorRetryable(errorName, httpStatusCode, fault);
257
+
258
+ return new LlumiverseError(
259
+ `[${this.provider}] ${userMessage}`,
260
+ retryable,
261
+ context,
262
+ error,
263
+ httpStatusCode, // Only set code if we have numeric status code
264
+ errorName // Preserve AWS error name
265
+ );
266
+ }
267
+
268
+ /**
269
+ * Determine if a Bedrock error is retryable based on error type and status.
270
+ *
271
+ * Retryable errors:
272
+ * - ThrottlingException: Rate limit exceeded, retry with backoff
273
+ * - ServiceUnavailableException: Service temporarily down
274
+ * - InternalServerException: Server-side error
275
+ * - ServiceQuotaExceededException: Quota exhausted, may recover
276
+ * - 5xx status codes: Server errors
277
+ * - 429, 408 status codes: Rate limit, timeout
278
+ *
279
+ * Non-retryable errors:
280
+ * - ValidationException: Invalid request parameters
281
+ * - AccessDeniedException: Authentication/authorization failure
282
+ * - ResourceNotFoundException: Resource doesn't exist
283
+ * - ConflictException: Resource state conflict
284
+ * - ResourceInUseException: Resource locked by another operation
285
+ * - 4xx status codes (except 429, 408): Client errors
286
+ *
287
+ * @param errorName - The AWS error name (e.g., "ThrottlingException")
288
+ * @param httpStatusCode - The HTTP status code if available
289
+ * @param fault - The fault type ("client" or "server")
290
+ * @returns True if retryable, false if not retryable, undefined if unknown
291
+ */
292
+ private isBedrockErrorRetryable(
293
+ errorName: string,
294
+ httpStatusCode: number | undefined,
295
+ fault: string | undefined
296
+ ): boolean | undefined {
297
+ // Check specific AWS error types first
298
+ switch (errorName) {
299
+ // Retryable errors
300
+ case 'ThrottlingException':
301
+ case 'ServiceUnavailableException':
302
+ case 'InternalServerException':
303
+ case 'ServiceQuotaExceededException':
304
+ return true;
305
+
306
+ // Non-retryable errors
307
+ case 'ValidationException':
308
+ case 'AccessDeniedException':
309
+ case 'ResourceNotFoundException':
310
+ case 'ConflictException':
311
+ case 'ResourceInUseException':
312
+ case 'TooManyTagsException':
313
+ return false;
314
+ }
315
+
316
+ // If we have HTTP status code, use it
317
+ if (httpStatusCode !== undefined) {
318
+ if (httpStatusCode === 429 || httpStatusCode === 408) return true; // Rate limit, timeout
319
+ if (httpStatusCode === 529) return true; // Overloaded
320
+ if (httpStatusCode >= 500 && httpStatusCode < 600) return true; // Server errors
321
+ if (httpStatusCode >= 400 && httpStatusCode < 500) return false; // Client errors
322
+ }
323
+
324
+ // Fall back to fault type
325
+ if (fault === 'server') return true;
326
+ if (fault === 'client') return false;
327
+
328
+ // Unknown error type - let consumer decide retry strategy
329
+ return undefined;
330
+ }
331
+
156
332
  getExtractedExecution(result: ConverseResponse, _prompt?: BedrockPrompt, options?: ExecutionOptions): CompletionChunkObject {
157
333
  let resultText = "";
158
334
  let reasoning = "";
@@ -163,9 +339,11 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
163
339
  if (content.text) {
164
340
  resultText += content.text;
165
341
  } else if (content.reasoningContent) {
166
- // Get reasoning content only if include_thoughts is true
342
+ // Extract reasoning content if include_thoughts is true, or if it's a
343
+ // reasoning-only model (e.g. DeepSeek R1) that returns no text blocks
167
344
  const claudeOptions = options?.model_options as BedrockClaudeOptions;
168
- if (claudeOptions?.include_thoughts) {
345
+ const isReasoningModel = options?.model?.includes('deepseek') && options?.model?.includes('r1');
346
+ if (claudeOptions?.include_thoughts || isReasoningModel) {
169
347
  if (content.reasoningContent.reasoningText) {
170
348
  reasoning += content.reasoningContent.reasoningText.text;
171
349
  } else if (content.reasoningContent.redactedContent) {
@@ -210,8 +388,9 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
210
388
  let stop_reason = "";
211
389
  let token_usage: ExecutionTokenUsage | undefined;
212
390
 
213
- // Check if we should include thoughts
214
- const shouldIncludeThoughts = options && (options.model_options as BedrockClaudeOptions)?.include_thoughts;
391
+ // Check if we should include thoughts (always true for reasoning-only models like DeepSeek R1)
392
+ const isReasoningModel = options?.model?.includes('deepseek') && options?.model?.includes('r1');
393
+ const shouldIncludeThoughts = isReasoningModel || (options && (options.model_options as BedrockClaudeOptions)?.include_thoughts);
215
394
 
216
395
  // Handle content block start events (for reasoning blocks)
217
396
  if (result.contentBlockStart) {
@@ -443,6 +622,10 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
443
622
  };
444
623
  let processedConversation = stripBinaryFromConversation(conversation, stripOptions);
445
624
  processedConversation = truncateLargeTextInConversation(processedConversation, stripOptions);
625
+ processedConversation = stripHeartbeatsFromConversation(processedConversation, {
626
+ keepForTurns: options.stripHeartbeatsAfterTurns ?? 1,
627
+ currentTurn,
628
+ });
446
629
 
447
630
  return processedConversation as ConverseRequest;
448
631
  }
@@ -467,8 +650,15 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
467
650
  ...payload,
468
651
  });
469
652
 
653
+ // Strip reasoningContent from assistant messages before storing in conversation
654
+ // (DeepSeek R1 returns reasoning blocks but rejects them in subsequent user turns)
655
+ const assistantMsg = res.output?.message ?? { content: [{ text: "" }], role: "assistant" };
656
+ if (assistantMsg.content) {
657
+ assistantMsg.content = assistantMsg.content.filter((c: any) => !c.reasoningContent);
658
+ }
659
+
470
660
  conversation = updateConversation(conversation, {
471
- messages: [res.output?.message ?? { content: [{ text: "" }], role: "assistant" }],
661
+ messages: [assistantMsg],
472
662
  modelId: conversePrompt.modelId,
473
663
  });
474
664
 
@@ -504,6 +694,12 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
504
694
  // Truncate large text content if configured
505
695
  processedConversation = truncateLargeTextInConversation(processedConversation, stripOptions);
506
696
 
697
+ // Strip old heartbeat status messages
698
+ processedConversation = stripHeartbeatsFromConversation(processedConversation, {
699
+ keepForTurns: options.stripHeartbeatsAfterTurns ?? 1,
700
+ currentTurn,
701
+ });
702
+
507
703
  const completion = {
508
704
  ...this.getExtractedExecution(res, conversePrompt, options),
509
705
  original_response: options.include_original_response ? res : undefined,
@@ -671,6 +867,10 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
671
867
  };
672
868
  }
673
869
  }
870
+ // Claude 4.6 and later versions don't support JSON prefill
871
+ if (isClaudeVersionGTE(options.model, 4, 6)) {
872
+ supportsJSONPrefill = false;
873
+ }
674
874
  //Needs max_tokens to be set
675
875
  if (!model_options.max_tokens) {
676
876
  model_options.max_tokens = maxTokenFallbackClaude(options);
@@ -735,7 +935,9 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
735
935
  min_tokens: palmyraOptions?.min_tokens,
736
936
  }
737
937
  } else if (options.model.includes("deepseek")) {
738
- //DeepSeek models support no additional options
938
+ // DeepSeek models: no additional options, no stopSequences, only one of temperature/top_p
939
+ model_options.stop_sequence = undefined;
940
+ model_options.top_p = undefined;
739
941
  } else if (options.model.includes("gpt-oss")) {
740
942
  const gptOssOptions = model_options as ModelOptions as BedrockGptOssOptions;
741
943
  additionalField = {
@@ -769,7 +971,7 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
769
971
  const cleanedModelOptions = removeUndefinedValues({
770
972
  maxTokens: model_options.max_tokens,
771
973
  temperature: model_options.temperature,
772
- topP: model_options.top_p,
974
+ topP: model_options.temperature != null ? undefined : model_options.top_p,
773
975
  stopSequences: model_options.stop_sequence,
774
976
  } satisfies InferenceConfiguration);
775
977
 
@@ -799,6 +1001,12 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
799
1001
  request.toolConfig = {
800
1002
  tools: tool_defs,
801
1003
  }
1004
+ } else if (request.messages && messagesContainToolBlocks(request.messages)) {
1005
+ // Bedrock requires toolConfig when conversation contains toolUse/toolResult blocks.
1006
+ // When no tools are provided (e.g. checkpoint summary calls), convert tool blocks
1007
+ // to text representations so the conversation data is preserved while satisfying
1008
+ // Bedrock's API requirements without making tools callable.
1009
+ request.messages = convertToolBlocksToText(request.messages);
802
1010
  }
803
1011
 
804
1012
  return request;
@@ -1142,7 +1350,7 @@ export class BedrockDriver extends AbstractDriver<BedrockDriverOptions, BedrockP
1142
1350
  const executor = this.getExecutor();
1143
1351
 
1144
1352
  // Prepare the request payload for TwelveLabs Marengo
1145
- let invokeBody: TwelvelabsMarengoRequest = {
1353
+ const invokeBody: TwelvelabsMarengoRequest = {
1146
1354
  inputType: "text"
1147
1355
  };
1148
1356
 
@@ -1232,6 +1440,75 @@ function getToolDefinition(tool: ToolDefinition): Tool.ToolSpecMember {
1232
1440
  }
1233
1441
  }
1234
1442
 
1443
+ /**
1444
+ * Checks whether any message contains toolUse or toolResult content blocks.
1445
+ */
1446
+ export function messagesContainToolBlocks(messages: Message[]): boolean {
1447
+ for (const msg of messages) {
1448
+ if (!msg.content) continue;
1449
+ for (const block of msg.content) {
1450
+ if ((block as ContentBlock.ToolUseMember).toolUse ||
1451
+ (block as ContentBlock.ToolResultMember).toolResult) {
1452
+ return true;
1453
+ }
1454
+ }
1455
+ }
1456
+ return false;
1457
+ }
1458
+
1459
+ /**
1460
+ * Converts toolUse and toolResult content blocks to text representations.
1461
+ * This preserves the tool call information in the conversation while removing
1462
+ * the structured tool blocks that require Bedrock's toolConfig to be set.
1463
+ *
1464
+ * Used when no tools are provided (e.g. checkpoint summary calls) but the
1465
+ * conversation history contains tool interactions from prior turns.
1466
+ */
1467
+ export function convertToolBlocksToText(messages: Message[]): Message[] {
1468
+ return messages.map(msg => {
1469
+ if (!msg.content) return msg;
1470
+ let hasToolBlocks = false;
1471
+ for (const block of msg.content) {
1472
+ if ((block as ContentBlock.ToolUseMember).toolUse ||
1473
+ (block as ContentBlock.ToolResultMember).toolResult) {
1474
+ hasToolBlocks = true;
1475
+ break;
1476
+ }
1477
+ }
1478
+ if (!hasToolBlocks) return msg;
1479
+
1480
+ const newContent: ContentBlock[] = [];
1481
+ for (const block of msg.content) {
1482
+ const toolUse = (block as ContentBlock.ToolUseMember).toolUse;
1483
+ const toolResult = (block as ContentBlock.ToolResultMember).toolResult;
1484
+ if (toolUse) {
1485
+ const inputStr = toolUse.input ? JSON.stringify(toolUse.input) : '';
1486
+ const truncatedInput = inputStr.length > 500 ? inputStr.substring(0, 500) + '...' : inputStr;
1487
+ newContent.push({
1488
+ text: `[Tool call: ${toolUse.name}(${truncatedInput})]`,
1489
+ } as ContentBlock.TextMember);
1490
+ } else if (toolResult) {
1491
+ const resultTexts: string[] = [];
1492
+ if (toolResult.content) {
1493
+ for (const c of toolResult.content) {
1494
+ if ((c as any).text) {
1495
+ const text = (c as any).text as string;
1496
+ resultTexts.push(text.length > 500 ? text.substring(0, 500) + '...' : text);
1497
+ }
1498
+ }
1499
+ }
1500
+ const resultStr = resultTexts.length > 0 ? resultTexts.join('\n') : 'No text content';
1501
+ newContent.push({
1502
+ text: `[Tool result: ${resultStr}]`,
1503
+ } as ContentBlock.TextMember);
1504
+ } else {
1505
+ newContent.push(block);
1506
+ }
1507
+ }
1508
+ return { ...msg, content: newContent };
1509
+ });
1510
+ }
1511
+
1235
1512
  /**
1236
1513
  * Recursively removes undefined values from an object.
1237
1514
  * AWS Bedrock's additionalModelRequestFields must be valid JSON, and undefined is not valid JSON.
package/src/groq/index.ts CHANGED
@@ -299,12 +299,17 @@ function convertResponseItemsToGroqMessages(items: ResponseInputItem[]): ChatCom
299
299
  } else if (part.type === 'input_image') {
300
300
  const imgPart = part as OpenAI.Responses.ResponseInputImage;
301
301
  if (imgPart.image_url) {
302
+ const image_url: { url: string; detail?: 'auto' | 'low' | 'high' } = {
303
+ url: imgPart.image_url
304
+ };
305
+
306
+ if (imgPart.detail) {
307
+ image_url.detail = imgPart.detail as 'auto' | 'low' | 'high';
308
+ }
309
+
302
310
  parts.push({
303
311
  type: 'image_url',
304
- image_url: {
305
- url: imgPart.image_url,
306
- ...(imgPart.detail && { detail: imgPart.detail })
307
- }
312
+ image_url
308
313
  });
309
314
  }
310
315
  }
@@ -68,14 +68,17 @@ export class MistralAIDriver extends AbstractDriver<MistralAIDriverOptions, Open
68
68
  }
69
69
  options.model_options = options.model_options as TextFallbackOptions;
70
70
 
71
+ const requestPayload = _makeChatCompletionRequest({
72
+ model: options.model,
73
+ messages: messages,
74
+ maxTokens: options.model_options?.max_tokens,
75
+ temperature: options.model_options?.temperature,
76
+ responseFormat: this.getResponseFormat(options),
77
+ });
78
+ this.logger.debug({ payload: JSON.stringify(requestPayload) }, "Mistral request payload");
79
+
71
80
  const res = await this.client.post('/v1/chat/completions', {
72
- payload: _makeChatCompletionRequest({
73
- model: options.model,
74
- messages: messages,
75
- maxTokens: options.model_options?.max_tokens,
76
- temperature: options.model_options?.temperature,
77
- responseFormat: this.getResponseFormat(options),
78
- })
81
+ payload: requestPayload,
79
82
  }) as ChatCompletionResponse;
80
83
 
81
84
  const choice = res.choices[0];
@@ -99,17 +102,20 @@ export class MistralAIDriver extends AbstractDriver<MistralAIDriverOptions, Open
99
102
  }
100
103
  options.model_options = options.model_options as TextFallbackOptions;
101
104
 
105
+ const streamPayload = _makeChatCompletionRequest({
106
+ model: options.model,
107
+ messages: messages,
108
+ maxTokens: options.model_options?.max_tokens,
109
+ temperature: options.model_options?.temperature,
110
+ topP: options.model_options?.top_p,
111
+ responseFormat: this.getResponseFormat(options),
112
+ stream: true,
113
+ stopSequences: options.model_options?.stop_sequence,
114
+ });
115
+ this.logger.debug({ payload: JSON.stringify(streamPayload) }, "Mistral stream request payload");
116
+
102
117
  const stream = await this.client.post('/v1/chat/completions', {
103
- payload: _makeChatCompletionRequest({
104
- model: options.model,
105
- messages: messages,
106
- maxTokens: options.model_options?.max_tokens,
107
- temperature: options.model_options?.temperature,
108
- topP: options.model_options?.top_p,
109
- responseFormat: this.getResponseFormat(options),
110
- stream: true,
111
- stopSequences: options.model_options?.stop_sequence,
112
- }),
118
+ payload: streamPayload,
113
119
  reader: 'sse'
114
120
  });
115
121
 
@@ -191,22 +197,19 @@ function _makeChatCompletionRequest({
191
197
  topP,
192
198
  randomSeed,
193
199
  stream,
194
- safeMode,
195
- safePrompt,
196
200
  toolChoice,
197
201
  responseFormat,
198
202
  stopSequences,
199
203
  }: CompletionRequestParams) {
200
204
  return {
201
- model: model,
202
- messages: messages,
205
+ model,
206
+ messages,
203
207
  tools: tools ?? undefined,
204
208
  temperature: temperature ?? undefined,
205
209
  max_tokens: maxTokens ?? undefined,
206
210
  top_p: topP ?? undefined,
207
211
  random_seed: randomSeed ?? undefined,
208
212
  stream: stream ?? undefined,
209
- safe_prompt: (safeMode || safePrompt) ?? undefined,
210
213
  tool_choice: toolChoice ?? undefined,
211
214
  response_format: responseFormat ?? undefined,
212
215
  stop: stopSequences ?? undefined,
@@ -132,11 +132,6 @@ export interface CompletionRequestParams {
132
132
  topP?: number,
133
133
  randomSeed?: number,
134
134
  stream?: boolean,
135
- /**
136
- * @deprecated use safePrompt instead
137
- */
138
- safeMode?: boolean,
139
- safePrompt?: boolean,
140
135
  toolChoice?: ToolChoice,
141
136
  responseFormat?: ResponseFormat,
142
137
  stopSequences?: string[],