@nodetool-ai/runtime 0.8.2 → 0.8.4-a13.1

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 (295) hide show
  1. package/dist/.nodetool-build-stamp +1 -1
  2. package/dist/canvas-codec.d.ts +3 -0
  3. package/dist/canvas-codec.d.ts.map +1 -0
  4. package/dist/canvas-codec.js +12 -0
  5. package/dist/canvas-codec.js.map +1 -0
  6. package/dist/context-packer.d.ts +1 -1
  7. package/dist/context-packer.js +1 -1
  8. package/dist/context.d.ts +3 -0
  9. package/dist/context.d.ts.map +1 -1
  10. package/dist/context.js +16 -5
  11. package/dist/context.js.map +1 -1
  12. package/dist/host-binaries.d.ts.map +1 -1
  13. package/dist/host-binaries.js +4 -3
  14. package/dist/host-binaries.js.map +1 -1
  15. package/dist/http-client-spans.d.ts +9 -0
  16. package/dist/http-client-spans.d.ts.map +1 -0
  17. package/dist/http-client-spans.js +88 -0
  18. package/dist/http-client-spans.js.map +1 -0
  19. package/dist/image-codec.d.ts +6 -3
  20. package/dist/image-codec.d.ts.map +1 -1
  21. package/dist/image-codec.js +17 -17
  22. package/dist/image-codec.js.map +1 -1
  23. package/dist/image-model-tasks.d.ts +20 -0
  24. package/dist/image-model-tasks.d.ts.map +1 -1
  25. package/dist/image-model-tasks.js +44 -1
  26. package/dist/image-model-tasks.js.map +1 -1
  27. package/dist/index.d.ts +4 -3
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +4 -3
  30. package/dist/index.js.map +1 -1
  31. package/dist/media-ref-bytes.d.ts.map +1 -1
  32. package/dist/media-ref-bytes.js +31 -6
  33. package/dist/media-ref-bytes.js.map +1 -1
  34. package/dist/otlp-json-trace-exporter.d.ts +89 -0
  35. package/dist/otlp-json-trace-exporter.d.ts.map +1 -0
  36. package/dist/otlp-json-trace-exporter.js +155 -0
  37. package/dist/otlp-json-trace-exporter.js.map +1 -0
  38. package/dist/prompt-asset-refs.d.ts +12 -1
  39. package/dist/prompt-asset-refs.d.ts.map +1 -1
  40. package/dist/prompt-asset-refs.js +9 -4
  41. package/dist/prompt-asset-refs.js.map +1 -1
  42. package/dist/providers/antigravity-provider.d.ts +113 -0
  43. package/dist/providers/antigravity-provider.d.ts.map +1 -0
  44. package/dist/providers/antigravity-provider.js +527 -0
  45. package/dist/providers/antigravity-provider.js.map +1 -0
  46. package/dist/providers/api-route-provider.d.ts +22 -0
  47. package/dist/providers/api-route-provider.d.ts.map +1 -0
  48. package/dist/providers/api-route-provider.js +56 -0
  49. package/dist/providers/api-route-provider.js.map +1 -0
  50. package/dist/providers/azure-openai-provider.d.ts +69 -0
  51. package/dist/providers/azure-openai-provider.d.ts.map +1 -0
  52. package/dist/providers/azure-openai-provider.js +233 -0
  53. package/dist/providers/azure-openai-provider.js.map +1 -0
  54. package/dist/providers/base-provider.d.ts.map +1 -1
  55. package/dist/providers/base-provider.js +41 -4
  56. package/dist/providers/base-provider.js.map +1 -1
  57. package/dist/providers/bedrock-provider.d.ts +52 -0
  58. package/dist/providers/bedrock-provider.d.ts.map +1 -0
  59. package/dist/providers/bedrock-provider.js +648 -0
  60. package/dist/providers/bedrock-provider.js.map +1 -0
  61. package/dist/providers/bedrock-transport.d.ts +37 -0
  62. package/dist/providers/bedrock-transport.d.ts.map +1 -0
  63. package/dist/providers/bedrock-transport.js +186 -0
  64. package/dist/providers/bedrock-transport.js.map +1 -0
  65. package/dist/providers/chatgpt-provider.d.ts +48 -0
  66. package/dist/providers/chatgpt-provider.d.ts.map +1 -0
  67. package/dist/providers/chatgpt-provider.js +551 -0
  68. package/dist/providers/chatgpt-provider.js.map +1 -0
  69. package/dist/providers/claude-agent-provider.d.ts +29 -51
  70. package/dist/providers/claude-agent-provider.d.ts.map +1 -1
  71. package/dist/providers/claude-agent-provider.js +144 -202
  72. package/dist/providers/claude-agent-provider.js.map +1 -1
  73. package/dist/providers/claude-cli.d.ts +265 -0
  74. package/dist/providers/claude-cli.d.ts.map +1 -0
  75. package/dist/providers/claude-cli.js +488 -0
  76. package/dist/providers/claude-cli.js.map +1 -0
  77. package/dist/providers/codex-provider.d.ts +9 -2
  78. package/dist/providers/codex-provider.d.ts.map +1 -1
  79. package/dist/providers/codex-provider.js +25 -11
  80. package/dist/providers/codex-provider.js.map +1 -1
  81. package/dist/providers/context-window.d.ts.map +1 -1
  82. package/dist/providers/context-window.js +1 -0
  83. package/dist/providers/context-window.js.map +1 -1
  84. package/dist/providers/core-tools.d.ts +4 -1
  85. package/dist/providers/core-tools.d.ts.map +1 -1
  86. package/dist/providers/core-tools.js +5 -3
  87. package/dist/providers/core-tools.js.map +1 -1
  88. package/dist/providers/cost-calculator.d.ts.map +1 -1
  89. package/dist/providers/cost-calculator.js +9 -0
  90. package/dist/providers/cost-calculator.js.map +1 -1
  91. package/dist/providers/credential-check.d.ts +8 -0
  92. package/dist/providers/credential-check.d.ts.map +1 -1
  93. package/dist/providers/credential-check.js +22 -0
  94. package/dist/providers/credential-check.js.map +1 -1
  95. package/dist/providers/custom-openai-provider.d.ts.map +1 -1
  96. package/dist/providers/custom-openai-provider.js +19 -1
  97. package/dist/providers/custom-openai-provider.js.map +1 -1
  98. package/dist/providers/dreamina-pending.d.ts +22 -0
  99. package/dist/providers/dreamina-pending.d.ts.map +1 -0
  100. package/dist/providers/dreamina-pending.js +86 -0
  101. package/dist/providers/dreamina-pending.js.map +1 -0
  102. package/dist/providers/dreamina-provider.d.ts +10 -3
  103. package/dist/providers/dreamina-provider.d.ts.map +1 -1
  104. package/dist/providers/dreamina-provider.js +325 -45
  105. package/dist/providers/dreamina-provider.js.map +1 -1
  106. package/dist/providers/extension-tab.d.ts +42 -0
  107. package/dist/providers/extension-tab.d.ts.map +1 -0
  108. package/dist/providers/extension-tab.js +200 -0
  109. package/dist/providers/extension-tab.js.map +1 -0
  110. package/dist/providers/fake-provider.d.ts +3 -1
  111. package/dist/providers/fake-provider.d.ts.map +1 -1
  112. package/dist/providers/fake-provider.js +63 -9
  113. package/dist/providers/fake-provider.js.map +1 -1
  114. package/dist/providers/fake-schema-answer.d.ts +10 -0
  115. package/dist/providers/fake-schema-answer.d.ts.map +1 -0
  116. package/dist/providers/fake-schema-answer.js +64 -0
  117. package/dist/providers/fake-schema-answer.js.map +1 -0
  118. package/dist/providers/fal-provider.d.ts.map +1 -1
  119. package/dist/providers/fal-provider.js +5 -2
  120. package/dist/providers/fal-provider.js.map +1 -1
  121. package/dist/providers/gemini-web-provider.d.ts +76 -0
  122. package/dist/providers/gemini-web-provider.d.ts.map +1 -0
  123. package/dist/providers/gemini-web-provider.js +827 -0
  124. package/dist/providers/gemini-web-provider.js.map +1 -0
  125. package/dist/providers/http-transport.d.ts.map +1 -1
  126. package/dist/providers/http-transport.js +2 -0
  127. package/dist/providers/http-transport.js.map +1 -1
  128. package/dist/providers/huggingface-provider.d.ts.map +1 -1
  129. package/dist/providers/huggingface-provider.js +17 -1
  130. package/dist/providers/huggingface-provider.js.map +1 -1
  131. package/dist/providers/index.d.ts +18 -2
  132. package/dist/providers/index.d.ts.map +1 -1
  133. package/dist/providers/index.js +66 -15
  134. package/dist/providers/index.js.map +1 -1
  135. package/dist/providers/llama-provider.d.ts +8 -0
  136. package/dist/providers/llama-provider.d.ts.map +1 -1
  137. package/dist/providers/llama-provider.js +23 -5
  138. package/dist/providers/llama-provider.js.map +1 -1
  139. package/dist/providers/lmstudio-provider.js +2 -2
  140. package/dist/providers/lmstudio-provider.js.map +1 -1
  141. package/dist/providers/manifest-models.d.ts +2 -12
  142. package/dist/providers/manifest-models.d.ts.map +1 -1
  143. package/dist/providers/manifest-models.js +45 -3
  144. package/dist/providers/manifest-models.js.map +1 -1
  145. package/dist/providers/meta-provider.d.ts +53 -6
  146. package/dist/providers/meta-provider.d.ts.map +1 -1
  147. package/dist/providers/meta-provider.js +289 -6
  148. package/dist/providers/meta-provider.js.map +1 -1
  149. package/dist/providers/meta-segmentation.d.ts +27 -0
  150. package/dist/providers/meta-segmentation.d.ts.map +1 -0
  151. package/dist/providers/meta-segmentation.js +141 -0
  152. package/dist/providers/meta-segmentation.js.map +1 -0
  153. package/dist/providers/meta-transcription.d.ts +31 -0
  154. package/dist/providers/meta-transcription.d.ts.map +1 -0
  155. package/dist/providers/meta-transcription.js +187 -0
  156. package/dist/providers/meta-transcription.js.map +1 -0
  157. package/dist/providers/node-llama-cpp-provider.d.ts +6 -3
  158. package/dist/providers/node-llama-cpp-provider.d.ts.map +1 -1
  159. package/dist/providers/node-llama-cpp-provider.js +77 -62
  160. package/dist/providers/node-llama-cpp-provider.js.map +1 -1
  161. package/dist/providers/ollama-provider.d.ts +23 -0
  162. package/dist/providers/ollama-provider.d.ts.map +1 -1
  163. package/dist/providers/ollama-provider.js +140 -27
  164. package/dist/providers/ollama-provider.js.map +1 -1
  165. package/dist/providers/openai-compat/client.d.ts +10 -1
  166. package/dist/providers/openai-compat/client.d.ts.map +1 -1
  167. package/dist/providers/openai-compat/client.js +21 -3
  168. package/dist/providers/openai-compat/client.js.map +1 -1
  169. package/dist/providers/openai-compat/index.d.ts +1 -1
  170. package/dist/providers/openai-compat/index.d.ts.map +1 -1
  171. package/dist/providers/openai-compat/index.js +1 -1
  172. package/dist/providers/openai-compat/index.js.map +1 -1
  173. package/dist/providers/openai-compat/types.d.ts +4 -0
  174. package/dist/providers/openai-compat/types.d.ts.map +1 -1
  175. package/dist/providers/openai-compat-provider.d.ts +11 -0
  176. package/dist/providers/openai-compat-provider.d.ts.map +1 -1
  177. package/dist/providers/openai-compat-provider.js +47 -2
  178. package/dist/providers/openai-compat-provider.js.map +1 -1
  179. package/dist/providers/openai-provider.d.ts +15 -0
  180. package/dist/providers/openai-provider.d.ts.map +1 -1
  181. package/dist/providers/openai-provider.js +50 -12
  182. package/dist/providers/openai-provider.js.map +1 -1
  183. package/dist/providers/opper-provider.d.ts +31 -0
  184. package/dist/providers/opper-provider.d.ts.map +1 -0
  185. package/dist/providers/opper-provider.js +91 -0
  186. package/dist/providers/opper-provider.js.map +1 -0
  187. package/dist/providers/provider-request-log.d.ts.map +1 -1
  188. package/dist/providers/provider-request-log.js +3 -2
  189. package/dist/providers/provider-request-log.js.map +1 -1
  190. package/dist/providers/python-provider.d.ts.map +1 -1
  191. package/dist/providers/python-provider.js +5 -3
  192. package/dist/providers/python-provider.js.map +1 -1
  193. package/dist/providers/responses-api.d.ts +12 -2
  194. package/dist/providers/responses-api.d.ts.map +1 -1
  195. package/dist/providers/responses-api.js +54 -3
  196. package/dist/providers/responses-api.js.map +1 -1
  197. package/dist/providers/safe-url.d.ts.map +1 -1
  198. package/dist/providers/safe-url.js +8 -0
  199. package/dist/providers/safe-url.js.map +1 -1
  200. package/dist/providers/scripted-provider.d.ts.map +1 -1
  201. package/dist/providers/scripted-provider.js +6 -1
  202. package/dist/providers/scripted-provider.js.map +1 -1
  203. package/dist/providers/types.d.ts +16 -0
  204. package/dist/providers/types.d.ts.map +1 -1
  205. package/dist/providers/types.js.map +1 -1
  206. package/dist/providers/vgenv-provider.d.ts +33 -0
  207. package/dist/providers/vgenv-provider.d.ts.map +1 -0
  208. package/dist/providers/vgenv-provider.js +261 -0
  209. package/dist/providers/vgenv-provider.js.map +1 -0
  210. package/dist/providers/vllm-provider.d.ts +7 -0
  211. package/dist/providers/vllm-provider.d.ts.map +1 -1
  212. package/dist/providers/vllm-provider.js +15 -3
  213. package/dist/providers/vllm-provider.js.map +1 -1
  214. package/dist/python-bridge-base.d.ts +16 -6
  215. package/dist/python-bridge-base.d.ts.map +1 -1
  216. package/dist/python-bridge-base.js +117 -40
  217. package/dist/python-bridge-base.js.map +1 -1
  218. package/dist/python-bridge-codec.d.ts +16 -1
  219. package/dist/python-bridge-codec.d.ts.map +1 -1
  220. package/dist/python-bridge-codec.js +60 -2
  221. package/dist/python-bridge-codec.js.map +1 -1
  222. package/dist/python-bridge-framing.d.ts +10 -1
  223. package/dist/python-bridge-framing.d.ts.map +1 -1
  224. package/dist/python-bridge-framing.js +33 -8
  225. package/dist/python-bridge-framing.js.map +1 -1
  226. package/dist/python-bridge-types.d.ts +26 -5
  227. package/dist/python-bridge-types.d.ts.map +1 -1
  228. package/dist/python-bridge-types.js.map +1 -1
  229. package/dist/python-graph-resolver.d.ts.map +1 -1
  230. package/dist/python-graph-resolver.js +12 -2
  231. package/dist/python-graph-resolver.js.map +1 -1
  232. package/dist/python-node-executor.d.ts +14 -3
  233. package/dist/python-node-executor.d.ts.map +1 -1
  234. package/dist/python-node-executor.js +185 -3
  235. package/dist/python-node-executor.js.map +1 -1
  236. package/dist/python-stdio-bridge.d.ts +6 -0
  237. package/dist/python-stdio-bridge.d.ts.map +1 -1
  238. package/dist/python-stdio-bridge.js +58 -12
  239. package/dist/python-stdio-bridge.js.map +1 -1
  240. package/dist/run-trace-context.d.ts +2 -27
  241. package/dist/run-trace-context.d.ts.map +1 -1
  242. package/dist/run-trace-context.js +4 -51
  243. package/dist/run-trace-context.js.map +1 -1
  244. package/dist/run-trace-processor.d.ts +3 -0
  245. package/dist/run-trace-processor.d.ts.map +1 -1
  246. package/dist/run-trace-processor.js +63 -46
  247. package/dist/run-trace-processor.js.map +1 -1
  248. package/dist/run-trace-scope.d.ts +28 -0
  249. package/dist/run-trace-scope.d.ts.map +1 -0
  250. package/dist/run-trace-scope.js +51 -0
  251. package/dist/run-trace-scope.js.map +1 -0
  252. package/dist/run-trace-serialization.d.ts.map +1 -1
  253. package/dist/run-trace-serialization.js +4 -3
  254. package/dist/run-trace-serialization.js.map +1 -1
  255. package/dist/span-record.d.ts +4 -0
  256. package/dist/span-record.d.ts.map +1 -0
  257. package/dist/span-record.js +48 -0
  258. package/dist/span-record.js.map +1 -0
  259. package/dist/swappable-python-bridge.d.ts +6 -6
  260. package/dist/swappable-python-bridge.d.ts.map +1 -1
  261. package/dist/swappable-python-bridge.js +10 -10
  262. package/dist/swappable-python-bridge.js.map +1 -1
  263. package/dist/telemetry.d.ts +2 -2
  264. package/dist/telemetry.d.ts.map +1 -1
  265. package/dist/telemetry.js +33 -34
  266. package/dist/telemetry.js.map +1 -1
  267. package/dist/testing.d.ts +1 -1
  268. package/dist/testing.d.ts.map +1 -1
  269. package/dist/testing.js +55 -3
  270. package/dist/testing.js.map +1 -1
  271. package/dist/token-counter.d.ts +4 -13
  272. package/dist/token-counter.d.ts.map +1 -1
  273. package/dist/token-counter.js +68 -18
  274. package/dist/token-counter.js.map +1 -1
  275. package/dist/trace-context-manager.d.ts +12 -0
  276. package/dist/trace-context-manager.d.ts.map +1 -0
  277. package/dist/trace-context-manager.js +30 -0
  278. package/dist/trace-context-manager.js.map +1 -0
  279. package/dist/trace-exporters.d.ts +2 -3
  280. package/dist/trace-exporters.d.ts.map +1 -1
  281. package/dist/trace-exporters.js +5 -52
  282. package/dist/trace-exporters.js.map +1 -1
  283. package/dist/trace-semantic-conventions.d.ts +2 -0
  284. package/dist/trace-semantic-conventions.d.ts.map +1 -0
  285. package/dist/trace-semantic-conventions.js +2 -0
  286. package/dist/trace-semantic-conventions.js.map +1 -0
  287. package/dist/traced-storage.d.ts +17 -0
  288. package/dist/traced-storage.d.ts.map +1 -0
  289. package/dist/traced-storage.js +41 -0
  290. package/dist/traced-storage.js.map +1 -0
  291. package/dist/tracing-module.d.ts +3 -0
  292. package/dist/tracing-module.d.ts.map +1 -0
  293. package/dist/tracing-module.js +12 -0
  294. package/dist/tracing-module.js.map +1 -0
  295. package/package.json +37 -18
@@ -0,0 +1,648 @@
1
+ import { PROVIDER_IDS, isRecord, isString } from "@nodetool-ai/protocol";
2
+ import { BaseProvider } from "./base-provider.js";
3
+ import { decodeEventStream, signAwsRequest } from "./bedrock-transport.js";
4
+ import { sniffImageMime } from "./image-mime.js";
5
+ import { safeFetch } from "./safe-url.js";
6
+ const DEFAULT_REGION = "us-east-1";
7
+ const REGION_PATTERN = /^[a-z]{2}(-[a-z]+)+-\d+$/;
8
+ const SERVICE = "bedrock";
9
+ const DEFAULT_MAX_TOKENS = 4096;
10
+ const IMAGE_FORMATS = {
11
+ "image/png": "png",
12
+ "image/jpeg": "jpeg",
13
+ "image/gif": "gif",
14
+ "image/webp": "webp"
15
+ };
16
+ const DOCUMENT_FORMATS = {
17
+ "application/pdf": "pdf",
18
+ "text/csv": "csv",
19
+ "application/msword": "doc",
20
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
21
+ "application/vnd.ms-excel": "xls",
22
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
23
+ "text/html": "html",
24
+ "text/plain": "txt",
25
+ "text/markdown": "md"
26
+ };
27
+ /** Event-stream exception types and the HTTP status Bedrock documents for each. */
28
+ const STREAM_EXCEPTION_STATUS = {
29
+ throttlingException: 429,
30
+ validationException: 400,
31
+ accessDeniedException: 403,
32
+ modelStreamErrorException: 424,
33
+ modelTimeoutException: 408,
34
+ serviceUnavailableException: 503,
35
+ internalServerException: 500
36
+ };
37
+ function imageFamily(modelId) {
38
+ const id = modelId.toLowerCase();
39
+ if (/amazon\.(nova-canvas|titan-image)/.test(id))
40
+ return "amazon";
41
+ if (/stability\./.test(id))
42
+ return "stability";
43
+ return null;
44
+ }
45
+ function toBytes(data) {
46
+ if (data instanceof Uint8Array)
47
+ return { bytes: data };
48
+ const match = /^data:([^;,]+)?(;base64)?,(.*)$/s.exec(data);
49
+ if (match) {
50
+ const payload = match[2]
51
+ ? Buffer.from(match[3], "base64")
52
+ : Buffer.from(decodeURIComponent(match[3]), "utf8");
53
+ return { bytes: new Uint8Array(payload), mime: match[1] };
54
+ }
55
+ return { bytes: new Uint8Array(Buffer.from(data, "base64")) };
56
+ }
57
+ function textOf(content) {
58
+ if (content == null)
59
+ return "";
60
+ if (isString(content))
61
+ return content;
62
+ return content
63
+ .filter((part) => part.type === "text")
64
+ .map((part) => part.text)
65
+ .join("\n");
66
+ }
67
+ /** Bedrock document names allow letters, digits, spaces, hyphens, parentheses and brackets. */
68
+ function documentName(title, index) {
69
+ const cleaned = (title ?? "")
70
+ .replace(/[^A-Za-z0-9\s\-()[\]]/g, " ")
71
+ .replace(/\s+/g, " ")
72
+ .trim();
73
+ return cleaned || `document ${index + 1}`;
74
+ }
75
+ function thinkingFields(model, thinking) {
76
+ if (!thinking || thinking.type === "disabled")
77
+ return undefined;
78
+ if (!model.toLowerCase().includes("anthropic."))
79
+ return undefined;
80
+ if (thinking.type === "adaptive")
81
+ return { thinking: { type: "adaptive" } };
82
+ return { thinking: { type: "enabled", budget_tokens: thinking.budgetTokens } };
83
+ }
84
+ function reasoningBlocks(blocks) {
85
+ return (blocks ?? []).map((block) => block.type === "thinking"
86
+ ? { reasoningContent: { reasoningText: { text: block.thinking, signature: block.signature } } }
87
+ : { reasoningContent: { redactedContent: block.data } });
88
+ }
89
+ /** Read a Converse response's reasoning blocks back into the shape the agent loop carries between turns. */
90
+ function thinkingBlocksOf(content) {
91
+ const blocks = [];
92
+ for (const block of content) {
93
+ const reasoning = block.reasoningContent;
94
+ if (!isRecord(reasoning))
95
+ continue;
96
+ const text = reasoning.reasoningText;
97
+ if (isRecord(text) && isString(text.text)) {
98
+ blocks.push({
99
+ type: "thinking",
100
+ thinking: text.text,
101
+ signature: isString(text.signature) ? text.signature : ""
102
+ });
103
+ }
104
+ else if (isString(reasoning.redactedContent)) {
105
+ blocks.push({ type: "redacted_thinking", data: reasoning.redactedContent });
106
+ }
107
+ }
108
+ return blocks;
109
+ }
110
+ /**
111
+ * Amazon Bedrock. Chat runs through the Converse API, which speaks one request
112
+ * shape for every Bedrock chat model: Claude, Llama, Mistral, Nova and the
113
+ * rest. Image generation runs through InvokeModel for Amazon Nova Canvas,
114
+ * Titan Image and Stability models.
115
+ *
116
+ * Requests are signed with SigV4 from an IAM access key. Models are listed
117
+ * from the region's foundation models and cross-region inference profiles
118
+ * (`eu.anthropic.claude-…`), or from `BEDROCK_MODEL_IDS` when set.
119
+ */
120
+ export class BedrockProvider extends BaseProvider {
121
+ static requiredSecrets() {
122
+ return ["BEDROCK_ACCESS_KEY_ID", "BEDROCK_SECRET_ACCESS_KEY"];
123
+ }
124
+ region;
125
+ credentials;
126
+ modelIds;
127
+ _fetch;
128
+ now;
129
+ listing = null;
130
+ constructor(secrets, options = {}) {
131
+ super(PROVIDER_IDS.BEDROCK);
132
+ const accessKeyId = secrets.BEDROCK_ACCESS_KEY_ID?.trim();
133
+ const secretAccessKey = secrets.BEDROCK_SECRET_ACCESS_KEY?.trim();
134
+ if (!accessKeyId || !secretAccessKey) {
135
+ throw new Error("BEDROCK_ACCESS_KEY_ID and BEDROCK_SECRET_ACCESS_KEY are required");
136
+ }
137
+ this.region = secrets.BEDROCK_REGION?.trim() || DEFAULT_REGION;
138
+ this.credentials = {
139
+ accessKeyId,
140
+ secretAccessKey,
141
+ sessionToken: secrets.BEDROCK_SESSION_TOKEN?.trim() || undefined
142
+ };
143
+ this.modelIds = (secrets.BEDROCK_MODEL_IDS ?? "")
144
+ .split(",")
145
+ .map((id) => id.trim())
146
+ .filter((id) => id.length > 0);
147
+ this._fetch = options.fetchFn ?? globalThis.fetch.bind(globalThis);
148
+ this.now = options.now ?? (() => new Date());
149
+ }
150
+ getContainerEnv() {
151
+ const env = {
152
+ BEDROCK_ACCESS_KEY_ID: this.credentials.accessKeyId,
153
+ BEDROCK_SECRET_ACCESS_KEY: this.credentials.secretAccessKey,
154
+ BEDROCK_REGION: this.region
155
+ };
156
+ if (this.credentials.sessionToken) {
157
+ env.BEDROCK_SESSION_TOKEN = this.credentials.sessionToken;
158
+ }
159
+ return env;
160
+ }
161
+ declaredCapabilities() {
162
+ return ["text_to_image"];
163
+ }
164
+ async hasToolSupport(_model) {
165
+ return true;
166
+ }
167
+ async request(host, method, path, body, signal) {
168
+ // The region becomes part of the host name, so it must be a region and
169
+ // nothing else.
170
+ if (!REGION_PATTERN.test(this.region)) {
171
+ throw new Error(`BEDROCK_REGION is not an AWS region: ${this.region}`);
172
+ }
173
+ const url = new URL(`https://${host}.${this.region}.amazonaws.com${path}`);
174
+ const payload = body === undefined ? "" : JSON.stringify(body);
175
+ const headers = signAwsRequest({
176
+ method,
177
+ url,
178
+ body: payload,
179
+ region: this.region,
180
+ service: SERVICE,
181
+ credentials: this.credentials,
182
+ headers: body === undefined ? { accept: "application/json" } : { "content-type": "application/json", accept: "application/json" },
183
+ now: this.now()
184
+ });
185
+ const response = await this._fetch(url.toString(), {
186
+ method,
187
+ headers,
188
+ body: body === undefined ? undefined : payload,
189
+ signal
190
+ });
191
+ if (!response.ok) {
192
+ const text = await response.text().catch(() => "");
193
+ let message = text;
194
+ try {
195
+ const parsed = JSON.parse(text);
196
+ if (isRecord(parsed) && isString(parsed.message))
197
+ message = parsed.message;
198
+ else if (isRecord(parsed) && isString(parsed.Message))
199
+ message = parsed.Message;
200
+ }
201
+ catch {
202
+ // Not JSON: keep the raw body as the message.
203
+ }
204
+ throw new Error(`Bedrock error ${response.status}: ${message || response.statusText}`);
205
+ }
206
+ return response;
207
+ }
208
+ modelPath(model, action) {
209
+ return `/model/${encodeURIComponent(model)}/${action}`;
210
+ }
211
+ // ── Model discovery ────────────────────────────────────────────────
212
+ async listModels() {
213
+ if (this.modelIds.length > 0) {
214
+ return {
215
+ language: this.modelIds
216
+ .filter((id) => !imageFamily(id))
217
+ .map((id) => ({ id, name: id, provider: this.provider })),
218
+ image: this.modelIds
219
+ .filter((id) => imageFamily(id))
220
+ .map((id) => ({ id, name: id, provider: this.provider, supportedTasks: ["text_to_image"] }))
221
+ };
222
+ }
223
+ this.listing ??= this.fetchModelListing().catch((error) => {
224
+ this.listing = null;
225
+ throw error;
226
+ });
227
+ return this.listing;
228
+ }
229
+ async fetchModelListing() {
230
+ const foundation = await (await this.request("bedrock", "GET", "/foundation-models")).json();
231
+ const summaries = (foundation.modelSummaries ?? []).filter((m) => isString(m.modelId) && m.modelLifecycle?.status !== "LEGACY");
232
+ const textModels = new Set(summaries.filter((m) => m.outputModalities?.includes("TEXT")).map((m) => m.modelId));
233
+ const label = (m) => [m.providerName, m.modelName].filter(Boolean).join(" ") || m.modelId;
234
+ const language = summaries
235
+ .filter((m) => textModels.has(m.modelId) && m.inferenceTypesSupported?.includes("ON_DEMAND"))
236
+ .map((m) => ({ id: m.modelId, name: label(m), provider: this.provider }));
237
+ const image = summaries
238
+ .filter((m) => m.outputModalities?.includes("IMAGE") &&
239
+ m.inferenceTypesSupported?.includes("ON_DEMAND") &&
240
+ imageFamily(m.modelId))
241
+ .map((m) => ({
242
+ id: m.modelId,
243
+ name: label(m),
244
+ provider: this.provider,
245
+ supportedTasks: ["text_to_image"]
246
+ }));
247
+ let nextToken;
248
+ do {
249
+ const query = new URLSearchParams({ typeEquals: "SYSTEM_DEFINED", maxResults: "1000" });
250
+ if (nextToken)
251
+ query.set("nextToken", nextToken);
252
+ const page = await (await this.request("bedrock", "GET", `/inference-profiles?${query}`)).json();
253
+ for (const profile of page.inferenceProfileSummaries ?? []) {
254
+ if (!isString(profile.inferenceProfileId) || profile.status === "INACTIVE")
255
+ continue;
256
+ const servesText = (profile.models ?? []).some((m) => textModels.has(String(m.modelArn ?? "").split("/").pop() ?? ""));
257
+ if (!servesText)
258
+ continue;
259
+ language.push({
260
+ id: profile.inferenceProfileId,
261
+ name: profile.inferenceProfileName || profile.inferenceProfileId,
262
+ provider: this.provider
263
+ });
264
+ }
265
+ nextToken = page.nextToken || undefined;
266
+ } while (nextToken);
267
+ return { language, image };
268
+ }
269
+ async getAvailableLanguageModels() {
270
+ try {
271
+ return (await this.listModels()).language;
272
+ }
273
+ catch {
274
+ // A failed listing (bad key, missing bedrock:ListFoundationModels
275
+ // permission, offline) leaves the picker empty instead of failing discovery.
276
+ return [];
277
+ }
278
+ }
279
+ async getAvailableImageModels() {
280
+ try {
281
+ return (await this.listModels()).image;
282
+ }
283
+ catch {
284
+ // Same as the language listing: discovery never throws.
285
+ return [];
286
+ }
287
+ }
288
+ // ── Converse request building ──────────────────────────────────────
289
+ async mediaBytes(source, signal) {
290
+ const hasData = source.data !== undefined &&
291
+ (source.data instanceof Uint8Array ? source.data.length > 0 : source.data.length > 0);
292
+ if (hasData) {
293
+ const decoded = toBytes(source.data);
294
+ return { bytes: decoded.bytes, mime: source.mimeType ?? decoded.mime };
295
+ }
296
+ const uri = source.uri ?? "";
297
+ if (uri.startsWith("data:")) {
298
+ const decoded = toBytes(uri);
299
+ return { bytes: decoded.bytes, mime: source.mimeType ?? decoded.mime };
300
+ }
301
+ if (/^https?:\/\//i.test(uri)) {
302
+ const response = await safeFetch(uri, signal ? { signal } : undefined, 5, this._fetch);
303
+ if (!response.ok)
304
+ throw new Error(`Failed to fetch ${uri}: ${response.status}`);
305
+ return {
306
+ bytes: new Uint8Array(await response.arrayBuffer()),
307
+ mime: source.mimeType ?? response.headers.get("content-type")?.split(";")[0] ?? undefined
308
+ };
309
+ }
310
+ throw new Error("Bedrock media content needs inline data, a data: URI, or an https URL");
311
+ }
312
+ async convertParts(content, signal) {
313
+ if (content == null)
314
+ return [];
315
+ if (isString(content))
316
+ return content ? [{ text: content }] : [];
317
+ const blocks = [];
318
+ let documents = 0;
319
+ for (const part of content) {
320
+ if (part.type === "text") {
321
+ if (part.text)
322
+ blocks.push({ text: part.text });
323
+ }
324
+ else if (part.type === "image_url") {
325
+ const { bytes, mime } = await this.mediaBytes(part.image, signal);
326
+ const format = IMAGE_FORMATS[sniffImageMime(bytes) ?? mime ?? ""];
327
+ if (!format)
328
+ throw new Error("Bedrock accepts PNG, JPEG, GIF or WebP images");
329
+ blocks.push({ image: { format, source: { bytes: Buffer.from(bytes).toString("base64") } } });
330
+ }
331
+ else if (part.type === "document") {
332
+ const { bytes, mime } = await this.mediaBytes(part.document, signal);
333
+ const format = DOCUMENT_FORMATS[mime ?? ""];
334
+ if (!format)
335
+ throw new Error(`Bedrock does not accept documents of type ${mime ?? "unknown"}`);
336
+ blocks.push({
337
+ document: {
338
+ format,
339
+ name: documentName(part.document.title, documents++),
340
+ source: { bytes: Buffer.from(bytes).toString("base64") }
341
+ }
342
+ });
343
+ }
344
+ else {
345
+ throw new Error(`Bedrock chat does not accept ${part.type} content`);
346
+ }
347
+ }
348
+ return blocks;
349
+ }
350
+ async buildMessages(messages, signal) {
351
+ const system = [];
352
+ const out = [];
353
+ const push = (role, content) => {
354
+ if (content.length === 0)
355
+ return;
356
+ const last = out.at(-1);
357
+ // Converse requires alternating roles: parallel tool results and
358
+ // back-to-back user turns merge into one message.
359
+ if (last?.role === role)
360
+ last.content.push(...content);
361
+ else
362
+ out.push({ role, content });
363
+ };
364
+ for (const message of messages) {
365
+ if (message.role === "system") {
366
+ const text = textOf(message.content);
367
+ if (text)
368
+ system.push({ text });
369
+ }
370
+ else if (message.role === "user") {
371
+ push("user", await this.convertParts(message.content, signal));
372
+ }
373
+ else if (message.role === "assistant") {
374
+ const blocks = [];
375
+ if (message.toolCalls?.length) {
376
+ blocks.push(...reasoningBlocks(message._anthropicThinkingBlocks));
377
+ }
378
+ const text = textOf(message.content);
379
+ if (text)
380
+ blocks.push({ text });
381
+ for (const call of message.toolCalls ?? []) {
382
+ blocks.push({ toolUse: { toolUseId: call.id, name: call.name, input: call.args } });
383
+ }
384
+ push("assistant", blocks);
385
+ }
386
+ else if (message.role === "tool") {
387
+ const parts = isString(message.content)
388
+ ? [{ text: message.content || "(empty)" }]
389
+ : await this.convertParts(message.content, signal);
390
+ push("user", [
391
+ {
392
+ toolResult: {
393
+ toolUseId: message.toolCallId ?? "",
394
+ content: parts.length > 0 ? parts : [{ text: "(empty)" }],
395
+ status: message.isError ? "error" : "success"
396
+ }
397
+ }
398
+ ]);
399
+ }
400
+ }
401
+ return { system, messages: out };
402
+ }
403
+ toolConfig(tools, toolChoice) {
404
+ const specs = (tools ?? []).filter((tool) => tool.type !== "code_interpreter");
405
+ if (specs.length === 0)
406
+ return undefined;
407
+ let choice = { auto: {} };
408
+ if (toolChoice === "any")
409
+ choice = { any: {} };
410
+ else if (toolChoice && specs.some((tool) => tool.name === toolChoice)) {
411
+ choice = { tool: { name: toolChoice } };
412
+ }
413
+ return {
414
+ tools: specs.map((tool) => ({
415
+ toolSpec: {
416
+ name: tool.name,
417
+ description: tool.description || tool.name,
418
+ inputSchema: { json: tool.inputSchema ?? { type: "object", properties: {} } }
419
+ }
420
+ })),
421
+ toolChoice: choice
422
+ };
423
+ }
424
+ async buildRequest(args) {
425
+ const { system, messages } = await this.buildMessages(args.messages, args.signal);
426
+ const inferenceConfig = {
427
+ maxTokens: args.maxTokens ?? DEFAULT_MAX_TOKENS
428
+ };
429
+ const additional = thinkingFields(args.model, args.thinking);
430
+ if (additional) {
431
+ if (args.toolChoice && args.toolChoice !== "auto" && args.tools?.some((tool) => tool.type !== "code_interpreter" && (args.toolChoice === "any" || args.toolChoice === tool.name))) {
432
+ throw new Error("Bedrock thinking does not support forced tool selection");
433
+ }
434
+ if (args.thinking?.type === "manual") {
435
+ inferenceConfig.maxTokens = Math.max(args.maxTokens ?? DEFAULT_MAX_TOKENS, args.thinking.budgetTokens + 1);
436
+ }
437
+ }
438
+ else {
439
+ if (args.temperature !== undefined)
440
+ inferenceConfig.temperature = args.temperature;
441
+ if (args.topP !== undefined)
442
+ inferenceConfig.topP = args.topP;
443
+ }
444
+ const request = { messages, inferenceConfig };
445
+ if (system.length > 0)
446
+ request.system = system;
447
+ const toolConfig = this.toolConfig(args.tools, args.toolChoice);
448
+ if (toolConfig)
449
+ request.toolConfig = toolConfig;
450
+ if (additional)
451
+ request.additionalModelRequestFields = additional;
452
+ this.recordRequestPayload(request);
453
+ return request;
454
+ }
455
+ recordUsage(model, usage) {
456
+ if (!usage)
457
+ return;
458
+ const cachedTokens = usage.cacheReadInputTokens ?? 0;
459
+ const cacheWriteTokens = usage.cacheWriteInputTokens ?? 0;
460
+ // Converse reports cache reads and writes apart from inputTokens; the
461
+ // cost calculator expects inputTokens to include them.
462
+ this.trackUsage(model, {
463
+ inputTokens: (usage.inputTokens ?? 0) + cachedTokens + cacheWriteTokens,
464
+ outputTokens: usage.outputTokens ?? 0,
465
+ cachedTokens,
466
+ cacheWriteTokens
467
+ });
468
+ }
469
+ // ── Chat ───────────────────────────────────────────────────────────
470
+ async generateMessage(args) {
471
+ const request = await this.buildRequest(args);
472
+ const response = await this.request("bedrock-runtime", "POST", this.modelPath(args.model, "converse"), request, args.signal);
473
+ const body = (await response.json());
474
+ this.recordUsage(args.model, body.usage);
475
+ const content = body.output?.message?.content ?? [];
476
+ const text = content
477
+ .map((block) => (isString(block.text) ? block.text : ""))
478
+ .join("");
479
+ const thinking = thinkingBlocksOf(content);
480
+ const toolCalls = [];
481
+ for (const block of content) {
482
+ const use = block.toolUse;
483
+ if (!isRecord(use))
484
+ continue;
485
+ toolCalls.push({
486
+ id: String(use.toolUseId ?? ""),
487
+ name: String(use.name ?? ""),
488
+ args: isRecord(use.input) ? use.input : {},
489
+ _anthropicThinkingBlocks: thinking.length > 0 ? thinking : undefined
490
+ });
491
+ }
492
+ const message = { role: "assistant", content: text };
493
+ if (toolCalls.length > 0)
494
+ message.toolCalls = toolCalls;
495
+ if (thinking.length > 0)
496
+ message._anthropicThinkingBlocks = thinking;
497
+ return message;
498
+ }
499
+ async *generateMessages(args) {
500
+ const request = await this.buildRequest(args);
501
+ const response = await this.request("bedrock-runtime", "POST", this.modelPath(args.model, "converse-stream"), request, args.signal);
502
+ if (!response.body)
503
+ throw new Error("Bedrock returned an empty stream");
504
+ const tools = new Map();
505
+ const thinkingByIndex = new Map();
506
+ const toolCalls = [];
507
+ for await (const event of decodeEventStream(response.body)) {
508
+ const payload = event.payload.length > 0
509
+ ? JSON.parse(new TextDecoder().decode(event.payload))
510
+ : {};
511
+ if (event.headers[":message-type"] === "exception") {
512
+ const type = event.headers[":exception-type"] ?? "exception";
513
+ const message = isRecord(payload) && isString(payload.message) ? payload.message : type;
514
+ throw new Error(`Bedrock error ${STREAM_EXCEPTION_STATUS[type] ?? 500}: ${message}`);
515
+ }
516
+ if (!isRecord(payload))
517
+ continue;
518
+ const index = Number(payload.contentBlockIndex ?? 0);
519
+ switch (event.headers[":event-type"]) {
520
+ case "contentBlockStart": {
521
+ const start = payload.start;
522
+ if (isRecord(start) && isRecord(start.toolUse)) {
523
+ tools.set(index, {
524
+ id: String(start.toolUse.toolUseId ?? ""),
525
+ name: String(start.toolUse.name ?? ""),
526
+ input: ""
527
+ });
528
+ }
529
+ break;
530
+ }
531
+ case "contentBlockDelta": {
532
+ const delta = payload.delta;
533
+ if (!isRecord(delta))
534
+ break;
535
+ if (isString(delta.text)) {
536
+ if (delta.text)
537
+ yield { type: "chunk", content: delta.text, done: false };
538
+ }
539
+ else if (isRecord(delta.toolUse) && isString(delta.toolUse.input)) {
540
+ const tool = tools.get(index);
541
+ if (tool)
542
+ tool.input += delta.toolUse.input;
543
+ }
544
+ else if (isRecord(delta.reasoningContent)) {
545
+ const reasoning = delta.reasoningContent;
546
+ let last = thinkingByIndex.get(index);
547
+ if (isString(reasoning.text)) {
548
+ if (last?.type !== "thinking") {
549
+ last = { type: "thinking", thinking: "", signature: "" };
550
+ thinkingByIndex.set(index, last);
551
+ }
552
+ last.thinking += reasoning.text;
553
+ yield { type: "chunk", content: reasoning.text, done: false, thinking: true };
554
+ }
555
+ else if (isString(reasoning.signature) && last?.type === "thinking") {
556
+ last.signature += reasoning.signature;
557
+ }
558
+ else if (isString(reasoning.redactedContent)) {
559
+ thinkingByIndex.set(index, { type: "redacted_thinking", data: reasoning.redactedContent });
560
+ }
561
+ }
562
+ break;
563
+ }
564
+ case "contentBlockStop": {
565
+ const tool = tools.get(index);
566
+ if (!tool)
567
+ break;
568
+ tools.delete(index);
569
+ let input;
570
+ try {
571
+ input = tool.input ? JSON.parse(tool.input) : {};
572
+ }
573
+ catch {
574
+ throw new Error("Bedrock returned incomplete tool input JSON");
575
+ }
576
+ toolCalls.push({
577
+ id: tool.id,
578
+ name: tool.name,
579
+ args: isRecord(input) ? input : {}
580
+ });
581
+ break;
582
+ }
583
+ case "metadata":
584
+ this.recordUsage(args.model, payload.usage);
585
+ break;
586
+ default:
587
+ break;
588
+ }
589
+ }
590
+ const thinking = [...thinkingByIndex.values()];
591
+ for (const call of toolCalls) {
592
+ if (thinking.length > 0)
593
+ call._anthropicThinkingBlocks = [...thinking];
594
+ yield call;
595
+ }
596
+ yield { type: "chunk", content: "", done: true };
597
+ }
598
+ // ── Image generation ───────────────────────────────────────────────
599
+ async textToImage(params) {
600
+ if (!params.prompt)
601
+ throw new Error("The input prompt cannot be empty.");
602
+ const modelId = params.model.id;
603
+ const family = imageFamily(modelId);
604
+ if (!family)
605
+ throw new Error(`Bedrock image generation does not support ${modelId}`);
606
+ let body;
607
+ if (family === "amazon") {
608
+ const config = { numberOfImages: 1 };
609
+ if (params.width && params.height) {
610
+ config.width = Math.round(params.width / 16) * 16;
611
+ config.height = Math.round(params.height / 16) * 16;
612
+ }
613
+ if (params.guidanceScale != null)
614
+ config.cfgScale = params.guidanceScale;
615
+ if (params.seed != null && params.seed >= 0)
616
+ config.seed = params.seed;
617
+ if (params.quality === "premium" || params.quality === "standard") {
618
+ config.quality = params.quality;
619
+ }
620
+ const textParams = { text: params.prompt };
621
+ if (params.negativePrompt)
622
+ textParams.negativeText = params.negativePrompt;
623
+ body = { taskType: "TEXT_IMAGE", textToImageParams: textParams, imageGenerationConfig: config };
624
+ }
625
+ else {
626
+ body = { prompt: params.prompt, output_format: "png" };
627
+ if (params.negativePrompt)
628
+ body.negative_prompt = params.negativePrompt;
629
+ if (params.aspectRatio)
630
+ body.aspect_ratio = params.aspectRatio;
631
+ if (params.seed != null && params.seed >= 0)
632
+ body.seed = params.seed;
633
+ }
634
+ const response = await this.request("bedrock-runtime", "POST", this.modelPath(modelId, "invoke"), body, params.signal);
635
+ const result = (await response.json());
636
+ if (result.error)
637
+ throw new Error(`Bedrock image generation failed: ${result.error}`);
638
+ const filtered = result.finish_reasons?.find((reason) => reason);
639
+ if (filtered)
640
+ throw new Error(`Bedrock image generation was filtered: ${filtered}`);
641
+ const image = result.images?.[0];
642
+ if (!image)
643
+ throw new Error("Bedrock image generation returned no image data.");
644
+ this.trackUsage(modelId, { imageCount: 1 });
645
+ return new Uint8Array(Buffer.from(image, "base64"));
646
+ }
647
+ }
648
+ //# sourceMappingURL=bedrock-provider.js.map