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