@jaypie/llm 1.2.36 → 1.2.37

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.
package/dist/esm/index.js CHANGED
@@ -15,7 +15,7 @@ const FIRST_CLASS_PROVIDER = {
15
15
  // https://docs.anthropic.com/en/docs/about-claude/models/overview
16
16
  ANTHROPIC: {
17
17
  DEFAULT: "claude-sonnet-4-6",
18
- LARGE: "claude-opus-4-7",
18
+ LARGE: "claude-opus-4-8",
19
19
  SMALL: "claude-sonnet-4-6",
20
20
  TINY: "claude-haiku-4-5",
21
21
  },
@@ -23,8 +23,8 @@ const FIRST_CLASS_PROVIDER = {
23
23
  GEMINI: {
24
24
  DEFAULT: "gemini-3.1-pro-preview",
25
25
  LARGE: "gemini-3.1-pro-preview",
26
- SMALL: "gemini-3.1-flash-lite-preview",
27
- TINY: "gemini-3.1-flash-lite-preview",
26
+ SMALL: "gemini-3.5-flash",
27
+ TINY: "gemini-3.5-flash",
28
28
  },
29
29
  // https://developers.openai.com/api/docs/models
30
30
  OPENAI: {
@@ -42,6 +42,26 @@ const FIRST_CLASS_PROVIDER = {
42
42
  },
43
43
  };
44
44
  const PROVIDER = {
45
+ // https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html
46
+ BEDROCK: {
47
+ MODEL: {
48
+ DEFAULT: "amazon.nova-lite-v1:0",
49
+ LARGE: "amazon.nova-pro-v1:0",
50
+ SMALL: "amazon.nova-lite-v1:0",
51
+ TINY: "amazon.nova-micro-v1:0",
52
+ },
53
+ MODEL_MATCH_WORDS: [
54
+ "amazon.nova",
55
+ "amazon.titan",
56
+ "anthropic.claude",
57
+ "cohere.command",
58
+ "meta.llama",
59
+ "mistral.mistral",
60
+ "ai21.",
61
+ ],
62
+ NAME: "bedrock",
63
+ REGION: "AWS_REGION",
64
+ },
45
65
  ANTHROPIC: {
46
66
  // https://docs.anthropic.com/en/docs/about-claude/models/overview
47
67
  MAX_TOKENS: {
@@ -210,7 +230,21 @@ function determineModelProvider(input) {
210
230
  provider: PROVIDER.OPENROUTER.NAME,
211
231
  };
212
232
  }
233
+ // Check for explicit bedrock: prefix
234
+ if (input.startsWith("bedrock:")) {
235
+ const model = input.slice("bedrock:".length);
236
+ return {
237
+ model,
238
+ provider: PROVIDER.BEDROCK.NAME,
239
+ };
240
+ }
213
241
  // Check if input is a provider name
242
+ if (input === PROVIDER.BEDROCK.NAME) {
243
+ return {
244
+ model: PROVIDER.BEDROCK.MODEL.DEFAULT,
245
+ provider: PROVIDER.BEDROCK.NAME,
246
+ };
247
+ }
214
248
  if (input === PROVIDER.ANTHROPIC.NAME) {
215
249
  return {
216
250
  model: PROVIDER.ANTHROPIC.MODEL.DEFAULT,
@@ -294,8 +328,17 @@ function determineModelProvider(input) {
294
328
  provider: PROVIDER.OPENROUTER.NAME,
295
329
  };
296
330
  }
297
- // Check Anthropic match words
331
+ // Check Bedrock match words (before Anthropic — "anthropic.claude-*" is a Bedrock model ID)
298
332
  const lowerInput = input.toLowerCase();
333
+ for (const matchWord of PROVIDER.BEDROCK.MODEL_MATCH_WORDS) {
334
+ if (lowerInput.includes(matchWord)) {
335
+ return {
336
+ model: input,
337
+ provider: PROVIDER.BEDROCK.NAME,
338
+ };
339
+ }
340
+ }
341
+ // Check Anthropic match words
299
342
  for (const matchWord of PROVIDER.ANTHROPIC.MODEL_MATCH_WORDS) {
300
343
  if (lowerInput.includes(matchWord)) {
301
344
  return {
@@ -594,7 +637,7 @@ function jsonSchemaToOpenApi3(schema) {
594
637
  return result;
595
638
  }
596
639
 
597
- const getLogger$5 = () => log$1.lib({ lib: JAYPIE.LIB.LLM });
640
+ const getLogger$6 = () => log$1.lib({ lib: JAYPIE.LIB.LLM });
598
641
 
599
642
  // Turn policy constants
600
643
  const MAX_TURNS_ABSOLUTE_LIMIT = 72;
@@ -981,13 +1024,13 @@ function isTransientNetworkError(error) {
981
1024
  //
982
1025
  // Constants
983
1026
  //
984
- const STRUCTURED_OUTPUT_TOOL_NAME$2 = "structured_output";
1027
+ const STRUCTURED_OUTPUT_TOOL_NAME$3 = "structured_output";
985
1028
  const STRUCTURED_OUTPUT_NON_PARSE_STOP_REASONS = new Set([
986
1029
  "refusal",
987
1030
  "max_tokens",
988
1031
  ]);
989
1032
  // Regular expression to parse data URLs: data:mime/type;base64,data
990
- const DATA_URL_REGEX = /^data:([^;]+);base64,(.+)$/;
1033
+ const DATA_URL_REGEX$1 = /^data:([^;]+);base64,(.+)$/;
991
1034
  // String formats accepted by Anthropic's structured-output grammar compiler.
992
1035
  // Other formats are stripped (move to description) so the API does not 400.
993
1036
  const SUPPORTED_STRING_FORMATS = new Set([
@@ -1120,7 +1163,7 @@ function isJsonSchema(value) {
1120
1163
  * Parse a data URL into its components
1121
1164
  */
1122
1165
  function parseDataUrl(dataUrl) {
1123
- const match = dataUrl.match(DATA_URL_REGEX);
1166
+ const match = dataUrl.match(DATA_URL_REGEX$1);
1124
1167
  if (!match)
1125
1168
  return null;
1126
1169
  return { mediaType: match[1], data: match[2] };
@@ -1201,7 +1244,7 @@ const MODELS_WITHOUT_TEMPERATURE$2 = [
1201
1244
  /^claude-opus-4-[789]/,
1202
1245
  /^claude-opus-[5-9]/,
1203
1246
  ];
1204
- function isTemperatureDeprecationError$2(error) {
1247
+ function isTemperatureDeprecationError$3(error) {
1205
1248
  if (!error || typeof error !== "object")
1206
1249
  return false;
1207
1250
  const err = error;
@@ -1351,7 +1394,7 @@ class AnthropicAdapter extends BaseProviderAdapter {
1351
1394
  if (useFallbackStructuredOutput && request.format) {
1352
1395
  log$2.warn(`[AnthropicAdapter] Using legacy structured_output tool fallback for model ${anthropicRequest.model}; native output_config previously rejected for this model.`);
1353
1396
  allTools.push({
1354
- name: STRUCTURED_OUTPUT_TOOL_NAME$2,
1397
+ name: STRUCTURED_OUTPUT_TOOL_NAME$3,
1355
1398
  description: "Output a structured JSON object, " +
1356
1399
  "use this before your final response to give structured outputs to the user",
1357
1400
  parameters: request.format,
@@ -1449,7 +1492,7 @@ class AnthropicAdapter extends BaseProviderAdapter {
1449
1492
  return undefined;
1450
1493
  // If the model rejected `temperature`, cache it and retry without the param
1451
1494
  if (anthropicRequest.temperature !== undefined &&
1452
- isTemperatureDeprecationError$2(error)) {
1495
+ isTemperatureDeprecationError$3(error)) {
1453
1496
  this.rememberModelRejectsTemperature(anthropicRequest.model);
1454
1497
  const retryRequest = { ...anthropicRequest };
1455
1498
  delete retryRequest.temperature;
@@ -1482,7 +1525,7 @@ class AnthropicAdapter extends BaseProviderAdapter {
1482
1525
  return request;
1483
1526
  const fallbackRequest = { ...rest };
1484
1527
  const fakeTool = {
1485
- name: STRUCTURED_OUTPUT_TOOL_NAME$2,
1528
+ name: STRUCTURED_OUTPUT_TOOL_NAME$3,
1486
1529
  description: "Output a structured JSON object, " +
1487
1530
  "use this before your final response to give structured outputs to the user",
1488
1531
  input_schema: {
@@ -1510,7 +1553,7 @@ class AnthropicAdapter extends BaseProviderAdapter {
1510
1553
  }
1511
1554
  catch (error) {
1512
1555
  if (streamRequest.temperature !== undefined &&
1513
- isTemperatureDeprecationError$2(error)) {
1556
+ isTemperatureDeprecationError$3(error)) {
1514
1557
  this.rememberModelRejectsTemperature(streamRequest.model);
1515
1558
  streamRequest = {
1516
1559
  ...streamRequest,
@@ -1768,7 +1811,7 @@ class AnthropicAdapter extends BaseProviderAdapter {
1768
1811
  // runtime has cached as not supporting `output_format`.
1769
1812
  const lastBlock = anthropicResponse.content[anthropicResponse.content.length - 1];
1770
1813
  return (lastBlock?.type === "tool_use" &&
1771
- lastBlock.name === STRUCTURED_OUTPUT_TOOL_NAME$2);
1814
+ lastBlock.name === STRUCTURED_OUTPUT_TOOL_NAME$3);
1772
1815
  }
1773
1816
  extractStructuredOutput(response) {
1774
1817
  const anthropicResponse = response;
@@ -1794,7 +1837,7 @@ class AnthropicAdapter extends BaseProviderAdapter {
1794
1837
  // Fallback path: legacy fake-tool emulation
1795
1838
  const lastBlock = anthropicResponse.content[anthropicResponse.content.length - 1];
1796
1839
  if (lastBlock?.type === "tool_use" &&
1797
- lastBlock.name === STRUCTURED_OUTPUT_TOOL_NAME$2) {
1840
+ lastBlock.name === STRUCTURED_OUTPUT_TOOL_NAME$3) {
1798
1841
  return lastBlock.input;
1799
1842
  }
1800
1843
  return undefined;
@@ -1815,6 +1858,608 @@ class AnthropicAdapter extends BaseProviderAdapter {
1815
1858
  // Export singleton instance
1816
1859
  const anthropicAdapter = new AnthropicAdapter();
1817
1860
 
1861
+ //
1862
+ //
1863
+ // Helpers
1864
+ //
1865
+ // Regular expression to parse data URLs
1866
+ const DATA_URL_REGEX = /^data:([^;]+);base64,(.+)$/;
1867
+ const MIME_TO_DOCUMENT_FORMAT = {
1868
+ "application/pdf": "pdf",
1869
+ "text/csv": "csv",
1870
+ "application/msword": "doc",
1871
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
1872
+ "application/vnd.ms-excel": "xls",
1873
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
1874
+ "text/html": "html",
1875
+ "text/plain": "txt",
1876
+ "text/markdown": "md",
1877
+ };
1878
+ function convertContentToBedrock(content) {
1879
+ if (typeof content === "string") {
1880
+ return [{ text: content }];
1881
+ }
1882
+ return content.map((item) => {
1883
+ if (item.type === LlmMessageType.InputText) {
1884
+ return { text: item.text };
1885
+ }
1886
+ if (item.type === LlmMessageType.InputImage) {
1887
+ const imageUrl = item.image_url || "";
1888
+ const match = imageUrl.match(DATA_URL_REGEX);
1889
+ if (match) {
1890
+ const format = match[1].split("/")[1] || "jpeg";
1891
+ const bytes = Buffer.from(match[2], "base64");
1892
+ return {
1893
+ image: {
1894
+ format,
1895
+ source: { bytes: new Uint8Array(bytes) },
1896
+ },
1897
+ };
1898
+ }
1899
+ return { text: `[Image: ${imageUrl}]` };
1900
+ }
1901
+ if (item.type === LlmMessageType.InputFile) {
1902
+ const fileData = typeof item.file_data === "string" ? item.file_data : "";
1903
+ const match = fileData.match(DATA_URL_REGEX);
1904
+ if (match) {
1905
+ const mimeType = match[1];
1906
+ const documentFormat = MIME_TO_DOCUMENT_FORMAT[mimeType];
1907
+ if (documentFormat) {
1908
+ const bytes = Buffer.from(match[2], "base64");
1909
+ const rawName = item.filename || "document";
1910
+ const name = rawName.replace(/[^a-zA-Z0-9 \-()[\]]/g, "_");
1911
+ return {
1912
+ document: {
1913
+ format: documentFormat,
1914
+ name,
1915
+ source: { bytes: new Uint8Array(bytes) },
1916
+ },
1917
+ };
1918
+ }
1919
+ }
1920
+ return { text: `[File: ${item.filename || "unknown"}]` };
1921
+ }
1922
+ return { text: JSON.stringify(item) };
1923
+ });
1924
+ }
1925
+ //
1926
+ //
1927
+ // Constants / helpers
1928
+ //
1929
+ const STRUCTURED_OUTPUT_TOOL_NAME$2 = "structured_output";
1930
+ function isOutputConfigUnsupportedError(error) {
1931
+ const msg = error?.message ?? "";
1932
+ return /outputConfig|output_config/i.test(msg);
1933
+ }
1934
+ function isTemperatureDeprecationError$2(error) {
1935
+ const msg = error?.message ?? "";
1936
+ return /temperature.*deprecated|deprecated.*temperature/i.test(msg);
1937
+ }
1938
+ function extractJson(text) {
1939
+ // Try direct parse first
1940
+ try {
1941
+ const parsed = JSON.parse(text);
1942
+ if (typeof parsed === "object" && parsed !== null)
1943
+ return parsed;
1944
+ }
1945
+ catch {
1946
+ // fall through
1947
+ }
1948
+ // Try stripping markdown code fences
1949
+ const fenceMatch = text.match(/```(?:json)?\s*([\s\S]*?)```/);
1950
+ if (fenceMatch) {
1951
+ try {
1952
+ const parsed = JSON.parse(fenceMatch[1].trim());
1953
+ if (typeof parsed === "object" && parsed !== null)
1954
+ return parsed;
1955
+ }
1956
+ catch {
1957
+ // fall through
1958
+ }
1959
+ }
1960
+ return undefined;
1961
+ }
1962
+ //
1963
+ //
1964
+ // Main
1965
+ //
1966
+ class BedrockAdapter extends BaseProviderAdapter {
1967
+ constructor() {
1968
+ super(...arguments);
1969
+ this.name = PROVIDER.BEDROCK.NAME;
1970
+ this.defaultModel = PROVIDER.BEDROCK.MODEL.DEFAULT;
1971
+ this._modelsFallbackToStructuredOutputTool = new Set();
1972
+ this._modelsWithoutTemperature = new Set();
1973
+ }
1974
+ rememberModelRejectsOutputConfig(model) {
1975
+ this._modelsFallbackToStructuredOutputTool.add(model);
1976
+ }
1977
+ useFakeToolForStructuredOutput(model) {
1978
+ return this._modelsFallbackToStructuredOutputTool.has(model);
1979
+ }
1980
+ rememberModelRejectsTemperature(model) {
1981
+ this._modelsWithoutTemperature.add(model);
1982
+ }
1983
+ supportsTemperature(model) {
1984
+ return !this._modelsWithoutTemperature.has(model);
1985
+ }
1986
+ //
1987
+ // Request Building
1988
+ //
1989
+ buildRequest(request) {
1990
+ const messages = [];
1991
+ for (const msg of request.messages) {
1992
+ const typedMsg = msg;
1993
+ if (typedMsg.role === "system")
1994
+ continue;
1995
+ if (typedMsg.type === LlmMessageType.FunctionCall) {
1996
+ let parsedInput;
1997
+ try {
1998
+ parsedInput = JSON.parse(typedMsg.arguments || "{}");
1999
+ }
2000
+ catch {
2001
+ parsedInput = {};
2002
+ }
2003
+ messages.push({
2004
+ role: "assistant",
2005
+ content: [
2006
+ {
2007
+ toolUse: {
2008
+ toolUseId: typedMsg.call_id || "",
2009
+ name: typedMsg.name || "",
2010
+ input: parsedInput,
2011
+ },
2012
+ },
2013
+ ],
2014
+ });
2015
+ continue;
2016
+ }
2017
+ if (typedMsg.type === LlmMessageType.FunctionCallOutput) {
2018
+ messages.push({
2019
+ role: "user",
2020
+ content: [
2021
+ {
2022
+ toolResult: {
2023
+ toolUseId: typedMsg.call_id || "",
2024
+ content: [{ text: typedMsg.output || "" }],
2025
+ },
2026
+ },
2027
+ ],
2028
+ });
2029
+ continue;
2030
+ }
2031
+ if (typedMsg.role && typedMsg.content !== undefined) {
2032
+ messages.push({
2033
+ role: typedMsg.role,
2034
+ content: convertContentToBedrock(typedMsg.content),
2035
+ });
2036
+ }
2037
+ }
2038
+ const model = request.model || this.defaultModel;
2039
+ const bedrockRequest = {
2040
+ modelId: model,
2041
+ messages,
2042
+ inferenceConfig: {
2043
+ maxTokens: 4096,
2044
+ },
2045
+ };
2046
+ if (request.system) {
2047
+ bedrockRequest.system = [{ text: request.system }];
2048
+ }
2049
+ if (request.temperature !== undefined &&
2050
+ this.supportsTemperature(model)) {
2051
+ bedrockRequest.inferenceConfig = {
2052
+ ...bedrockRequest.inferenceConfig,
2053
+ temperature: request.temperature,
2054
+ };
2055
+ }
2056
+ if (request.tools && request.tools.length > 0) {
2057
+ bedrockRequest.toolConfig = {
2058
+ tools: request.tools.map((tool) => ({
2059
+ toolSpec: {
2060
+ name: tool.name,
2061
+ description: tool.description,
2062
+ inputSchema: {
2063
+ json: tool.parameters,
2064
+ },
2065
+ },
2066
+ })),
2067
+ };
2068
+ }
2069
+ if (request.instructions && messages.length > 0) {
2070
+ const lastMsg = messages[messages.length - 1];
2071
+ if (lastMsg.content.length > 0) {
2072
+ const firstBlock = lastMsg.content[0];
2073
+ if ("text" in firstBlock) {
2074
+ firstBlock.text = firstBlock.text + "\n\n" + request.instructions;
2075
+ }
2076
+ }
2077
+ }
2078
+ if (request.format) {
2079
+ if (this.useFakeToolForStructuredOutput(model)) {
2080
+ const fakeTool = {
2081
+ toolSpec: {
2082
+ name: STRUCTURED_OUTPUT_TOOL_NAME$2,
2083
+ description: "REQUIRED: You MUST call this tool to provide your final response. " +
2084
+ "After gathering all necessary information (including results from other tools), " +
2085
+ "call this tool with the structured data to complete the request.",
2086
+ inputSchema: { json: request.format },
2087
+ },
2088
+ };
2089
+ bedrockRequest.toolConfig = {
2090
+ tools: [
2091
+ ...(bedrockRequest.toolConfig?.tools ?? []),
2092
+ fakeTool,
2093
+ ],
2094
+ };
2095
+ }
2096
+ else {
2097
+ bedrockRequest.outputConfig = {
2098
+ textFormat: {
2099
+ type: "json_schema",
2100
+ structure: {
2101
+ jsonSchema: {
2102
+ schema: JSON.stringify(request.format),
2103
+ name: "structured_output",
2104
+ },
2105
+ },
2106
+ },
2107
+ };
2108
+ }
2109
+ }
2110
+ if (request.providerOptions) {
2111
+ Object.assign(bedrockRequest, request.providerOptions);
2112
+ }
2113
+ return bedrockRequest;
2114
+ }
2115
+ formatTools(toolkit) {
2116
+ return toolkit.tools.map((tool) => ({
2117
+ name: tool.name,
2118
+ description: tool.description,
2119
+ parameters: {
2120
+ ...tool.parameters,
2121
+ type: "object",
2122
+ },
2123
+ }));
2124
+ }
2125
+ formatOutputSchema(schema) {
2126
+ const zodSchema = schema instanceof z.ZodType
2127
+ ? schema
2128
+ : naturalZodSchema(schema);
2129
+ return z.toJSONSchema(zodSchema);
2130
+ }
2131
+ //
2132
+ // API Execution
2133
+ //
2134
+ async executeRequest(client, request, signal) {
2135
+ const bedrockClient = client;
2136
+ const bedrockRequest = request;
2137
+ const { ConverseCommand } = await import('@aws-sdk/client-bedrock-runtime');
2138
+ const wantsStructuredOutput = Boolean(bedrockRequest.outputConfig);
2139
+ try {
2140
+ const response = (await bedrockClient.send(new ConverseCommand(bedrockRequest), signal ? { abortSignal: signal } : undefined));
2141
+ if (wantsStructuredOutput)
2142
+ response.__jaypieStructuredOutput = true;
2143
+ return response;
2144
+ }
2145
+ catch (error) {
2146
+ if (bedrockRequest.inferenceConfig?.temperature !== undefined &&
2147
+ isTemperatureDeprecationError$2(error)) {
2148
+ this.rememberModelRejectsTemperature(bedrockRequest.modelId || this.defaultModel);
2149
+ const retryRequest = {
2150
+ ...bedrockRequest,
2151
+ inferenceConfig: { ...bedrockRequest.inferenceConfig },
2152
+ };
2153
+ delete retryRequest.inferenceConfig.temperature;
2154
+ const response = (await bedrockClient.send(new ConverseCommand(retryRequest), signal ? { abortSignal: signal } : undefined));
2155
+ if (wantsStructuredOutput)
2156
+ response.__jaypieStructuredOutput = true;
2157
+ return response;
2158
+ }
2159
+ if (wantsStructuredOutput && isOutputConfigUnsupportedError(error)) {
2160
+ const model = bedrockRequest.modelId || this.defaultModel;
2161
+ this.rememberModelRejectsOutputConfig(model);
2162
+ const fallbackRequest = this.toFallbackStructuredOutputRequest(bedrockRequest);
2163
+ return (await bedrockClient.send(new ConverseCommand(fallbackRequest), signal ? { abortSignal: signal } : undefined));
2164
+ }
2165
+ throw error;
2166
+ }
2167
+ }
2168
+ toFallbackStructuredOutputRequest(request) {
2169
+ const { outputConfig, ...rest } = request;
2170
+ if (!outputConfig?.textFormat?.structure)
2171
+ return request;
2172
+ let schema;
2173
+ try {
2174
+ schema = JSON.parse(outputConfig.textFormat.structure.jsonSchema?.schema ?? "{}");
2175
+ }
2176
+ catch {
2177
+ schema = {};
2178
+ }
2179
+ const fakeTool = {
2180
+ toolSpec: {
2181
+ name: STRUCTURED_OUTPUT_TOOL_NAME$2,
2182
+ description: "REQUIRED: You MUST call this tool to provide your final response. " +
2183
+ "After gathering all necessary information (including results from other tools), " +
2184
+ "call this tool with the structured data to complete the request.",
2185
+ inputSchema: { json: schema },
2186
+ },
2187
+ };
2188
+ return {
2189
+ ...rest,
2190
+ toolConfig: {
2191
+ tools: [
2192
+ ...(rest.toolConfig?.tools ?? []),
2193
+ fakeTool,
2194
+ ],
2195
+ },
2196
+ };
2197
+ }
2198
+ async *executeStreamRequest(client, request, signal) {
2199
+ const bedrockClient = client;
2200
+ const bedrockRequest = request;
2201
+ const { ConverseStreamCommand } = await import('@aws-sdk/client-bedrock-runtime');
2202
+ const response = await bedrockClient.send(new ConverseStreamCommand(bedrockRequest), signal ? { abortSignal: signal } : undefined);
2203
+ if (!response.stream)
2204
+ return;
2205
+ let currentToolCall = null;
2206
+ let inputTokens = 0;
2207
+ let outputTokens = 0;
2208
+ const model = bedrockRequest.modelId || this.defaultModel;
2209
+ for await (const event of response.stream) {
2210
+ if (event.contentBlockStart?.start?.toolUse) {
2211
+ const toolUse = event.contentBlockStart.start.toolUse;
2212
+ currentToolCall = {
2213
+ toolUseId: toolUse.toolUseId || "",
2214
+ name: toolUse.name || "",
2215
+ arguments: "",
2216
+ };
2217
+ }
2218
+ else if (event.contentBlockDelta?.delta) {
2219
+ const delta = event.contentBlockDelta.delta;
2220
+ if (delta.text !== undefined) {
2221
+ yield { type: LlmStreamChunkType.Text, content: delta.text };
2222
+ }
2223
+ else if (delta.toolUse?.input && currentToolCall) {
2224
+ currentToolCall.arguments += delta.toolUse.input;
2225
+ }
2226
+ }
2227
+ else if (event.contentBlockStop && currentToolCall) {
2228
+ yield {
2229
+ type: LlmStreamChunkType.ToolCall,
2230
+ toolCall: {
2231
+ id: currentToolCall.toolUseId,
2232
+ name: currentToolCall.name,
2233
+ arguments: currentToolCall.arguments,
2234
+ },
2235
+ };
2236
+ currentToolCall = null;
2237
+ }
2238
+ else if (event.metadata?.usage) {
2239
+ inputTokens = event.metadata.usage.inputTokens ?? 0;
2240
+ outputTokens = event.metadata.usage.outputTokens ?? 0;
2241
+ }
2242
+ else if (event.messageStop) {
2243
+ yield {
2244
+ type: LlmStreamChunkType.Done,
2245
+ usage: [
2246
+ {
2247
+ input: inputTokens,
2248
+ output: outputTokens,
2249
+ reasoning: 0,
2250
+ total: inputTokens + outputTokens,
2251
+ provider: this.name,
2252
+ model,
2253
+ },
2254
+ ],
2255
+ };
2256
+ }
2257
+ }
2258
+ }
2259
+ //
2260
+ // Response Parsing
2261
+ //
2262
+ parseResponse(response, options) {
2263
+ const bedrockResponse = response;
2264
+ const message = bedrockResponse.output?.message;
2265
+ const rawContent = this.extractContentFromMessage(message);
2266
+ let content = rawContent;
2267
+ if (options?.format && typeof rawContent === "string") {
2268
+ content = extractJson(rawContent) ?? rawContent;
2269
+ }
2270
+ // Don't surface structured_output fake tool as a real tool call
2271
+ const allToolUses = (bedrockResponse.output?.message?.content ?? []).filter((b) => "toolUse" in b);
2272
+ const hasOnlyStructuredOutputTool = allToolUses.length > 0 &&
2273
+ allToolUses.every((b) => b.toolUse.name === STRUCTURED_OUTPUT_TOOL_NAME$2);
2274
+ const hasToolCalls = bedrockResponse.stopReason === "tool_use" && !hasOnlyStructuredOutputTool;
2275
+ return {
2276
+ content,
2277
+ hasToolCalls,
2278
+ stopReason: bedrockResponse.stopReason ?? undefined,
2279
+ usage: this.extractUsage(bedrockResponse, bedrockResponse.modelId ||
2280
+ this.defaultModel),
2281
+ raw: bedrockResponse,
2282
+ };
2283
+ }
2284
+ extractToolCalls(response) {
2285
+ const bedrockResponse = response;
2286
+ const content = bedrockResponse.output?.message?.content ?? [];
2287
+ const toolCalls = [];
2288
+ for (const block of content) {
2289
+ const typedBlock = block;
2290
+ if ("toolUse" in typedBlock && typedBlock.toolUse) {
2291
+ const toolUse = typedBlock.toolUse;
2292
+ toolCalls.push({
2293
+ callId: toolUse.toolUseId,
2294
+ name: toolUse.name,
2295
+ arguments: JSON.stringify(toolUse.input),
2296
+ raw: typedBlock,
2297
+ });
2298
+ }
2299
+ }
2300
+ return toolCalls;
2301
+ }
2302
+ extractUsage(response, model) {
2303
+ const bedrockResponse = response;
2304
+ const usage = bedrockResponse.usage;
2305
+ return {
2306
+ input: usage?.inputTokens ?? 0,
2307
+ output: usage?.outputTokens ?? 0,
2308
+ reasoning: 0,
2309
+ total: usage?.totalTokens ??
2310
+ (usage?.inputTokens ?? 0) + (usage?.outputTokens ?? 0),
2311
+ provider: this.name,
2312
+ model,
2313
+ };
2314
+ }
2315
+ //
2316
+ // Tool Result Handling
2317
+ //
2318
+ formatToolResult(toolCall, result) {
2319
+ return {
2320
+ toolResult: {
2321
+ toolUseId: toolCall.callId,
2322
+ content: [{ text: result.output }],
2323
+ },
2324
+ };
2325
+ }
2326
+ appendToolResult(request, toolCall, result) {
2327
+ const bedrockRequest = request;
2328
+ const toolCallRaw = toolCall.raw;
2329
+ bedrockRequest.messages.push({
2330
+ role: "assistant",
2331
+ content: [toolCallRaw],
2332
+ });
2333
+ bedrockRequest.messages.push({
2334
+ role: "user",
2335
+ content: [this.formatToolResult(toolCall, result)],
2336
+ });
2337
+ return bedrockRequest;
2338
+ }
2339
+ //
2340
+ // History Management
2341
+ //
2342
+ responseToHistoryItems(response) {
2343
+ const bedrockResponse = response;
2344
+ const historyItems = [];
2345
+ if (bedrockResponse.stopReason === "tool_use") {
2346
+ return historyItems;
2347
+ }
2348
+ const content = bedrockResponse.output?.message?.content ?? [];
2349
+ const textBlock = content.find((block) => "text" in block);
2350
+ if (textBlock) {
2351
+ historyItems.push({
2352
+ content: textBlock.text,
2353
+ role: "assistant",
2354
+ type: LlmMessageType.Message,
2355
+ });
2356
+ }
2357
+ return historyItems;
2358
+ }
2359
+ //
2360
+ // Error Classification
2361
+ //
2362
+ classifyError(error) {
2363
+ const errorName = error?.constructor?.name;
2364
+ const errorMessage = error?.message ?? "";
2365
+ if (errorName === "ThrottlingException" ||
2366
+ errorMessage.includes("ThrottlingException") ||
2367
+ errorMessage.includes("Too Many Requests")) {
2368
+ return {
2369
+ error,
2370
+ category: ErrorCategory.RateLimit,
2371
+ shouldRetry: false,
2372
+ suggestedDelayMs: 60000,
2373
+ };
2374
+ }
2375
+ if (errorName === "ServiceUnavailableException" ||
2376
+ errorName === "InternalServerException" ||
2377
+ errorMessage.includes("ServiceUnavailableException") ||
2378
+ errorMessage.includes("InternalServerException")) {
2379
+ return {
2380
+ error,
2381
+ category: ErrorCategory.Retryable,
2382
+ shouldRetry: true,
2383
+ };
2384
+ }
2385
+ if (errorName === "AccessDeniedException" ||
2386
+ errorName === "ValidationException" ||
2387
+ errorName === "ResourceNotFoundException" ||
2388
+ errorMessage.includes("AccessDeniedException") ||
2389
+ errorMessage.includes("ValidationException")) {
2390
+ return {
2391
+ error,
2392
+ category: ErrorCategory.Unrecoverable,
2393
+ shouldRetry: false,
2394
+ };
2395
+ }
2396
+ if (isTransientNetworkError(error)) {
2397
+ return {
2398
+ error,
2399
+ category: ErrorCategory.Retryable,
2400
+ shouldRetry: true,
2401
+ };
2402
+ }
2403
+ return {
2404
+ error,
2405
+ category: ErrorCategory.Unknown,
2406
+ shouldRetry: true,
2407
+ };
2408
+ }
2409
+ //
2410
+ // Structured Output
2411
+ //
2412
+ hasStructuredOutput(response) {
2413
+ const bedrockResponse = response;
2414
+ if (bedrockResponse.__jaypieStructuredOutput) {
2415
+ return this.extractStructuredOutput(response) !== undefined;
2416
+ }
2417
+ // Fake-tool path: last content block is a structured_output toolUse
2418
+ const content = (bedrockResponse.output?.message?.content ?? []);
2419
+ const last = content[content.length - 1];
2420
+ return (!!last &&
2421
+ "toolUse" in last &&
2422
+ last.toolUse.name === STRUCTURED_OUTPUT_TOOL_NAME$2);
2423
+ }
2424
+ extractStructuredOutput(response) {
2425
+ const bedrockResponse = response;
2426
+ if (bedrockResponse.__jaypieStructuredOutput) {
2427
+ const content = (bedrockResponse.output?.message?.content ?? []);
2428
+ const textBlock = content.find((b) => "text" in b);
2429
+ if (!textBlock)
2430
+ return undefined;
2431
+ return extractJson(textBlock.text);
2432
+ }
2433
+ // Fake-tool path
2434
+ const content = (bedrockResponse.output?.message?.content ?? []);
2435
+ const last = content[content.length - 1];
2436
+ if (last &&
2437
+ "toolUse" in last &&
2438
+ last.toolUse.name === STRUCTURED_OUTPUT_TOOL_NAME$2) {
2439
+ return last.toolUse.input;
2440
+ }
2441
+ return undefined;
2442
+ }
2443
+ //
2444
+ // Completion Detection
2445
+ //
2446
+ isComplete(response) {
2447
+ const bedrockResponse = response;
2448
+ return bedrockResponse.stopReason !== "tool_use";
2449
+ }
2450
+ //
2451
+ // Private Helpers
2452
+ //
2453
+ extractContentFromMessage(message) {
2454
+ if (!message?.content)
2455
+ return undefined;
2456
+ const content = message.content;
2457
+ const textBlock = content.find((block) => "text" in block);
2458
+ return textBlock?.text;
2459
+ }
2460
+ }
2461
+ const bedrockAdapter = new BedrockAdapter();
2462
+
1818
2463
  //
1819
2464
  //
1820
2465
  // Constants
@@ -4854,7 +5499,7 @@ function matchesCaughtError(reason, caught) {
4854
5499
  * (e.g. undici `TypeError: terminated`) emitted between attempts.
4855
5500
  */
4856
5501
  function createStaleRejectionGuard() {
4857
- const log = getLogger$5();
5502
+ const log = getLogger$6();
4858
5503
  const caughtErrors = new Set();
4859
5504
  let listener;
4860
5505
  return {
@@ -4913,7 +5558,7 @@ class RetryExecutor {
4913
5558
  * @throws BadGatewayError if all retries are exhausted or error is not retryable
4914
5559
  */
4915
5560
  async execute(operation, options) {
4916
- const log = getLogger$5();
5561
+ const log = getLogger$6();
4917
5562
  let attempt = 0;
4918
5563
  // Guard against stale rejections firing on a subsequent microtask after
4919
5564
  // the retry layer has already caught the originating error: undici socket
@@ -5032,7 +5677,7 @@ class OperateLoop {
5032
5677
  * Execute the operate loop for multi-turn conversations with tool calling.
5033
5678
  */
5034
5679
  async execute(input, options = {}) {
5035
- const log = getLogger$5();
5680
+ const log = getLogger$6();
5036
5681
  // Log what was passed to operate
5037
5682
  log.trace("[operate] Starting operate loop");
5038
5683
  log.var({ "operate.input": input });
@@ -5145,7 +5790,7 @@ class OperateLoop {
5145
5790
  };
5146
5791
  }
5147
5792
  async executeOneTurn(request, state, context, options) {
5148
- const log = getLogger$5();
5793
+ const log = getLogger$6();
5149
5794
  // Create error classifier from adapter
5150
5795
  const errorClassifier = createErrorClassifier(this.adapter);
5151
5796
  // Create retry executor for this turn
@@ -5457,7 +6102,7 @@ class StreamLoop {
5457
6102
  * Yields stream chunks as they become available.
5458
6103
  */
5459
6104
  async *execute(input, options = {}) {
5460
- const log = getLogger$5();
6105
+ const log = getLogger$6();
5461
6106
  // Verify adapter supports streaming
5462
6107
  if (!this.adapter.executeStreamRequest) {
5463
6108
  throw new BadGatewayError(`Provider ${this.adapter.name} does not support streaming`);
@@ -5575,7 +6220,7 @@ class StreamLoop {
5575
6220
  };
5576
6221
  }
5577
6222
  async *executeOneStreamingTurn(request, state, context, options) {
5578
- const log = getLogger$5();
6223
+ const log = getLogger$6();
5579
6224
  // Build provider-specific request
5580
6225
  const providerRequest = this.adapter.buildRequest(request);
5581
6226
  // Execute beforeEachModelRequest hook
@@ -5705,7 +6350,7 @@ class StreamLoop {
5705
6350
  return { shouldContinue: false };
5706
6351
  }
5707
6352
  async *processToolCalls(toolCalls, state, context, _options) {
5708
- const log = getLogger$5();
6353
+ const log = getLogger$6();
5709
6354
  for (const toolCall of toolCalls) {
5710
6355
  try {
5711
6356
  // Execute beforeEachTool hook
@@ -5851,28 +6496,28 @@ function createStreamLoop(config) {
5851
6496
  }
5852
6497
 
5853
6498
  // SDK loader with caching
5854
- let cachedSdk$2 = null;
5855
- async function loadSdk$2() {
5856
- if (cachedSdk$2)
5857
- return cachedSdk$2;
6499
+ let cachedSdk$3 = null;
6500
+ async function loadSdk$3() {
6501
+ if (cachedSdk$3)
6502
+ return cachedSdk$3;
5858
6503
  try {
5859
- cachedSdk$2 = await import('@anthropic-ai/sdk');
5860
- return cachedSdk$2;
6504
+ cachedSdk$3 = await import('@anthropic-ai/sdk');
6505
+ return cachedSdk$3;
5861
6506
  }
5862
6507
  catch {
5863
6508
  throw new ConfigurationError("@anthropic-ai/sdk is required but not installed. Run: npm install @anthropic-ai/sdk");
5864
6509
  }
5865
6510
  }
5866
6511
  // Logger
5867
- const getLogger$4 = () => log$1.lib({ lib: JAYPIE.LIB.LLM });
6512
+ const getLogger$5 = () => log$1.lib({ lib: JAYPIE.LIB.LLM });
5868
6513
  // Client initialization
5869
- async function initializeClient$4({ apiKey, } = {}) {
5870
- const logger = getLogger$4();
6514
+ async function initializeClient$5({ apiKey, } = {}) {
6515
+ const logger = getLogger$5();
5871
6516
  const resolvedApiKey = apiKey || (await getEnvSecret("ANTHROPIC_API_KEY"));
5872
6517
  if (!resolvedApiKey) {
5873
6518
  throw new ConfigurationError("The application could not resolve the required API key: ANTHROPIC_API_KEY");
5874
6519
  }
5875
- const sdk = await loadSdk$2();
6520
+ const sdk = await loadSdk$3();
5876
6521
  const client = new sdk.default({ apiKey: resolvedApiKey });
5877
6522
  logger.trace("Initialized Anthropic client");
5878
6523
  return client;
@@ -5893,7 +6538,7 @@ function formatUserMessage$3(message, { data, placeholders: placeholders$1 } = {
5893
6538
  };
5894
6539
  }
5895
6540
  function prepareMessages$3(message, { data, placeholders } = {}) {
5896
- const logger = getLogger$4();
6541
+ const logger = getLogger$5();
5897
6542
  const messages = [];
5898
6543
  // Add user message (necessary for all requests)
5899
6544
  const userMessage = formatUserMessage$3(message, { data, placeholders });
@@ -5977,7 +6622,7 @@ async function createStructuredCompletion$1(client, messages, model, responseSch
5977
6622
  // Main class implementation
5978
6623
  class AnthropicProvider {
5979
6624
  constructor(model = PROVIDER.ANTHROPIC.MODEL.DEFAULT, { apiKey } = {}) {
5980
- this.log = getLogger$4();
6625
+ this.log = getLogger$5();
5981
6626
  this.conversationHistory = [];
5982
6627
  this.model = model;
5983
6628
  this.apiKey = apiKey;
@@ -5986,7 +6631,7 @@ class AnthropicProvider {
5986
6631
  if (this._client) {
5987
6632
  return this._client;
5988
6633
  }
5989
- this._client = await initializeClient$4({ apiKey: this.apiKey });
6634
+ this._client = await initializeClient$5({ apiKey: this.apiKey });
5990
6635
  return this._client;
5991
6636
  }
5992
6637
  async getOperateLoop() {
@@ -6061,6 +6706,87 @@ class AnthropicProvider {
6061
6706
  }
6062
6707
  }
6063
6708
 
6709
+ let cachedSdk$2 = null;
6710
+ async function loadSdk$2() {
6711
+ if (cachedSdk$2)
6712
+ return cachedSdk$2;
6713
+ try {
6714
+ cachedSdk$2 = await import('@aws-sdk/client-bedrock-runtime');
6715
+ return cachedSdk$2;
6716
+ }
6717
+ catch {
6718
+ throw new ConfigurationError("@aws-sdk/client-bedrock-runtime is required but not installed. Run: npm install @aws-sdk/client-bedrock-runtime");
6719
+ }
6720
+ }
6721
+ const getLogger$4 = () => log$1.lib({ lib: JAYPIE.LIB.LLM });
6722
+ async function initializeClient$4({ region, } = {}) {
6723
+ const logger = getLogger$4();
6724
+ const resolvedRegion = region || process.env.AWS_REGION || "us-east-1";
6725
+ const sdk = await loadSdk$2();
6726
+ const client = new sdk.BedrockRuntimeClient({ region: resolvedRegion });
6727
+ logger.trace("Initialized Bedrock client");
6728
+ return client;
6729
+ }
6730
+
6731
+ class BedrockProvider {
6732
+ constructor(model = PROVIDER.BEDROCK.MODEL.DEFAULT, { region } = {}) {
6733
+ this.log = getLogger$4();
6734
+ this.conversationHistory = [];
6735
+ this.model = model;
6736
+ this.region = region;
6737
+ }
6738
+ async getClient() {
6739
+ if (this._client)
6740
+ return this._client;
6741
+ this._client = await initializeClient$4({ region: this.region });
6742
+ return this._client;
6743
+ }
6744
+ async getOperateLoop() {
6745
+ if (this._operateLoop)
6746
+ return this._operateLoop;
6747
+ const client = await this.getClient();
6748
+ this._operateLoop = createOperateLoop({ adapter: bedrockAdapter, client });
6749
+ return this._operateLoop;
6750
+ }
6751
+ async getStreamLoop() {
6752
+ if (this._streamLoop)
6753
+ return this._streamLoop;
6754
+ const client = await this.getClient();
6755
+ this._streamLoop = createStreamLoop({ adapter: bedrockAdapter, client });
6756
+ return this._streamLoop;
6757
+ }
6758
+ async send(message, options) {
6759
+ const operateLoop = await this.getOperateLoop();
6760
+ const mergedOptions = { ...options, model: options?.model ?? this.model };
6761
+ const response = await operateLoop.execute(message, mergedOptions);
6762
+ return response.content ?? "";
6763
+ }
6764
+ async operate(input, options = {}) {
6765
+ const operateLoop = await this.getOperateLoop();
6766
+ const mergedOptions = { ...options, model: options.model ?? this.model };
6767
+ if (this.conversationHistory.length > 0) {
6768
+ mergedOptions.history = options.history
6769
+ ? [...this.conversationHistory, ...options.history]
6770
+ : [...this.conversationHistory];
6771
+ }
6772
+ const response = await operateLoop.execute(input, mergedOptions);
6773
+ if (response.history && response.history.length > 0) {
6774
+ this.conversationHistory = response.history;
6775
+ }
6776
+ return response;
6777
+ }
6778
+ async *stream(input, options = {}) {
6779
+ const streamLoop = await this.getStreamLoop();
6780
+ const mergedOptions = { ...options, model: options.model ?? this.model };
6781
+ if (this.conversationHistory.length > 0) {
6782
+ mergedOptions.history = options.history
6783
+ ? [...this.conversationHistory, ...options.history]
6784
+ : [...this.conversationHistory];
6785
+ }
6786
+ yield* streamLoop.execute(input, mergedOptions);
6787
+ }
6788
+ }
6789
+
6064
6790
  // SDK loader with caching
6065
6791
  let cachedSdk$1 = null;
6066
6792
  async function loadSdk$1() {
@@ -6707,6 +7433,8 @@ class Llm {
6707
7433
  switch (providerName) {
6708
7434
  case PROVIDER.ANTHROPIC.NAME:
6709
7435
  return new AnthropicProvider(model || PROVIDER.ANTHROPIC.MODEL.DEFAULT, { apiKey });
7436
+ case PROVIDER.BEDROCK.NAME:
7437
+ return new BedrockProvider(model || PROVIDER.BEDROCK.MODEL.DEFAULT);
6710
7438
  case PROVIDER.GEMINI.NAME:
6711
7439
  return new GeminiProvider(model || PROVIDER.GEMINI.MODEL.DEFAULT, {
6712
7440
  apiKey,
@@ -6966,7 +7694,7 @@ const roll = {
6966
7694
  },
6967
7695
  type: "function",
6968
7696
  call: ({ number = 1, sides = 6 } = {}) => {
6969
- const log = getLogger$5();
7697
+ const log = getLogger$6();
6970
7698
  const rng = random$1();
6971
7699
  const rolls = [];
6972
7700
  let total = 0;
@@ -7164,5 +7892,5 @@ const toolkit = new JaypieToolkit(tools);
7164
7892
  [LlmMessageRole.Developer]: "user",
7165
7893
  });
7166
7894
 
7167
- export { GeminiProvider, JaypieToolkit, constants as LLM, Llm, LlmMessageRole, LlmMessageType, LlmStreamChunkType, OpenRouterProvider, Toolkit, XaiProvider, extractReasoning, isLlmOperateInput, isLlmOperateInputContent, isLlmOperateInputFile, isLlmOperateInputImage, toolkit, tools };
7895
+ export { BedrockProvider, GeminiProvider, JaypieToolkit, constants as LLM, Llm, LlmMessageRole, LlmMessageType, LlmStreamChunkType, OpenRouterProvider, Toolkit, XaiProvider, extractReasoning, isLlmOperateInput, isLlmOperateInputContent, isLlmOperateInputFile, isLlmOperateInputImage, toolkit, tools };
7168
7896
  //# sourceMappingURL=index.js.map