@handy_wote/pi-ai 0.81.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 (346) hide show
  1. package/README.md +1623 -0
  2. package/dist/api/anthropic-messages.d.ts +71 -0
  3. package/dist/api/anthropic-messages.d.ts.map +1 -0
  4. package/dist/api/anthropic-messages.js +1024 -0
  5. package/dist/api/anthropic-messages.js.map +1 -0
  6. package/dist/api/anthropic-messages.lazy.d.ts +3 -0
  7. package/dist/api/anthropic-messages.lazy.d.ts.map +1 -0
  8. package/dist/api/anthropic-messages.lazy.js +3 -0
  9. package/dist/api/anthropic-messages.lazy.js.map +1 -0
  10. package/dist/api/azure-openai-responses.d.ts +15 -0
  11. package/dist/api/azure-openai-responses.d.ts.map +1 -0
  12. package/dist/api/azure-openai-responses.js +221 -0
  13. package/dist/api/azure-openai-responses.js.map +1 -0
  14. package/dist/api/azure-openai-responses.lazy.d.ts +3 -0
  15. package/dist/api/azure-openai-responses.lazy.d.ts.map +1 -0
  16. package/dist/api/azure-openai-responses.lazy.js +3 -0
  17. package/dist/api/azure-openai-responses.lazy.js.map +1 -0
  18. package/dist/api/bedrock-converse-stream.d.ts +38 -0
  19. package/dist/api/bedrock-converse-stream.d.ts.map +1 -0
  20. package/dist/api/bedrock-converse-stream.js +883 -0
  21. package/dist/api/bedrock-converse-stream.js.map +1 -0
  22. package/dist/api/bedrock-converse-stream.lazy.d.ts +9 -0
  23. package/dist/api/bedrock-converse-stream.lazy.d.ts.map +1 -0
  24. package/dist/api/bedrock-converse-stream.lazy.js +30 -0
  25. package/dist/api/bedrock-converse-stream.lazy.js.map +1 -0
  26. package/dist/api/cloudflare.d.ts +9 -0
  27. package/dist/api/cloudflare.d.ts.map +1 -0
  28. package/dist/api/cloudflare.js +9 -0
  29. package/dist/api/cloudflare.js.map +1 -0
  30. package/dist/api/github-copilot-headers.d.ts +8 -0
  31. package/dist/api/github-copilot-headers.d.ts.map +1 -0
  32. package/dist/api/github-copilot-headers.js +29 -0
  33. package/dist/api/github-copilot-headers.js.map +1 -0
  34. package/dist/api/google-generative-ai.d.ts +13 -0
  35. package/dist/api/google-generative-ai.d.ts.map +1 -0
  36. package/dist/api/google-generative-ai.js +407 -0
  37. package/dist/api/google-generative-ai.js.map +1 -0
  38. package/dist/api/google-generative-ai.lazy.d.ts +3 -0
  39. package/dist/api/google-generative-ai.lazy.d.ts.map +1 -0
  40. package/dist/api/google-generative-ai.lazy.js +3 -0
  41. package/dist/api/google-generative-ai.lazy.js.map +1 -0
  42. package/dist/api/google-shared.d.ts +70 -0
  43. package/dist/api/google-shared.d.ts.map +1 -0
  44. package/dist/api/google-shared.js +329 -0
  45. package/dist/api/google-shared.js.map +1 -0
  46. package/dist/api/google-vertex.d.ts +15 -0
  47. package/dist/api/google-vertex.d.ts.map +1 -0
  48. package/dist/api/google-vertex.js +456 -0
  49. package/dist/api/google-vertex.js.map +1 -0
  50. package/dist/api/google-vertex.lazy.d.ts +3 -0
  51. package/dist/api/google-vertex.lazy.d.ts.map +1 -0
  52. package/dist/api/google-vertex.lazy.js +3 -0
  53. package/dist/api/google-vertex.lazy.js.map +1 -0
  54. package/dist/api/lazy.d.ts +15 -0
  55. package/dist/api/lazy.d.ts.map +1 -0
  56. package/dist/api/lazy.js +58 -0
  57. package/dist/api/lazy.js.map +1 -0
  58. package/dist/api/mistral-conversations.d.ts +25 -0
  59. package/dist/api/mistral-conversations.d.ts.map +1 -0
  60. package/dist/api/mistral-conversations.js +555 -0
  61. package/dist/api/mistral-conversations.js.map +1 -0
  62. package/dist/api/mistral-conversations.lazy.d.ts +3 -0
  63. package/dist/api/mistral-conversations.lazy.d.ts.map +1 -0
  64. package/dist/api/mistral-conversations.lazy.js +3 -0
  65. package/dist/api/mistral-conversations.lazy.js.map +1 -0
  66. package/dist/api/openai-codex-responses.d.ts +31 -0
  67. package/dist/api/openai-codex-responses.d.ts.map +1 -0
  68. package/dist/api/openai-codex-responses.js +1222 -0
  69. package/dist/api/openai-codex-responses.js.map +1 -0
  70. package/dist/api/openai-codex-responses.lazy.d.ts +3 -0
  71. package/dist/api/openai-codex-responses.lazy.d.ts.map +1 -0
  72. package/dist/api/openai-codex-responses.lazy.js +3 -0
  73. package/dist/api/openai-codex-responses.lazy.js.map +1 -0
  74. package/dist/api/openai-completions.d.ts +20 -0
  75. package/dist/api/openai-completions.d.ts.map +1 -0
  76. package/dist/api/openai-completions.js +1120 -0
  77. package/dist/api/openai-completions.js.map +1 -0
  78. package/dist/api/openai-completions.lazy.d.ts +3 -0
  79. package/dist/api/openai-completions.lazy.d.ts.map +1 -0
  80. package/dist/api/openai-completions.lazy.js +3 -0
  81. package/dist/api/openai-completions.lazy.js.map +1 -0
  82. package/dist/api/openai-prompt-cache.d.ts +3 -0
  83. package/dist/api/openai-prompt-cache.d.ts.map +1 -0
  84. package/dist/api/openai-prompt-cache.js +10 -0
  85. package/dist/api/openai-prompt-cache.js.map +1 -0
  86. package/dist/api/openai-responses-shared.d.ts +20 -0
  87. package/dist/api/openai-responses-shared.d.ts.map +1 -0
  88. package/dist/api/openai-responses-shared.js +535 -0
  89. package/dist/api/openai-responses-shared.js.map +1 -0
  90. package/dist/api/openai-responses.d.ts +14 -0
  91. package/dist/api/openai-responses.d.ts.map +1 -0
  92. package/dist/api/openai-responses.js +246 -0
  93. package/dist/api/openai-responses.js.map +1 -0
  94. package/dist/api/openai-responses.lazy.d.ts +3 -0
  95. package/dist/api/openai-responses.lazy.d.ts.map +1 -0
  96. package/dist/api/openai-responses.lazy.js +3 -0
  97. package/dist/api/openai-responses.lazy.js.map +1 -0
  98. package/dist/api/openrouter-images.d.ts +3 -0
  99. package/dist/api/openrouter-images.d.ts.map +1 -0
  100. package/dist/api/openrouter-images.js +126 -0
  101. package/dist/api/openrouter-images.js.map +1 -0
  102. package/dist/api/openrouter-images.lazy.d.ts +3 -0
  103. package/dist/api/openrouter-images.lazy.d.ts.map +1 -0
  104. package/dist/api/openrouter-images.lazy.js +4 -0
  105. package/dist/api/openrouter-images.lazy.js.map +1 -0
  106. package/dist/api/pi-messages.d.ts +97 -0
  107. package/dist/api/pi-messages.d.ts.map +1 -0
  108. package/dist/api/pi-messages.js +307 -0
  109. package/dist/api/pi-messages.js.map +1 -0
  110. package/dist/api/pi-messages.lazy.d.ts +3 -0
  111. package/dist/api/pi-messages.lazy.d.ts.map +1 -0
  112. package/dist/api/pi-messages.lazy.js +3 -0
  113. package/dist/api/pi-messages.lazy.js.map +1 -0
  114. package/dist/api/simple-options.d.ts +9 -0
  115. package/dist/api/simple-options.d.ts.map +1 -0
  116. package/dist/api/simple-options.js +52 -0
  117. package/dist/api/simple-options.js.map +1 -0
  118. package/dist/api/transform-messages.d.ts +8 -0
  119. package/dist/api/transform-messages.d.ts.map +1 -0
  120. package/dist/api/transform-messages.js +187 -0
  121. package/dist/api/transform-messages.js.map +1 -0
  122. package/dist/auth/context.d.ts +7 -0
  123. package/dist/auth/context.d.ts.map +1 -0
  124. package/dist/auth/context.js +42 -0
  125. package/dist/auth/context.js.map +1 -0
  126. package/dist/auth/credential-store.d.ts +17 -0
  127. package/dist/auth/credential-store.d.ts.map +1 -0
  128. package/dist/auth/credential-store.js +40 -0
  129. package/dist/auth/credential-store.js.map +1 -0
  130. package/dist/auth/helpers.d.ts +21 -0
  131. package/dist/auth/helpers.d.ts.map +1 -0
  132. package/dist/auth/helpers.js +48 -0
  133. package/dist/auth/helpers.js.map +1 -0
  134. package/dist/auth/oauth/anthropic.d.ts +9 -0
  135. package/dist/auth/oauth/anthropic.d.ts.map +1 -0
  136. package/dist/auth/oauth/anthropic.js +302 -0
  137. package/dist/auth/oauth/anthropic.js.map +1 -0
  138. package/dist/auth/oauth/device-code.d.ts +23 -0
  139. package/dist/auth/oauth/device-code.d.ts.map +1 -0
  140. package/dist/auth/oauth/device-code.js +69 -0
  141. package/dist/auth/oauth/device-code.js.map +1 -0
  142. package/dist/auth/oauth/github-copilot.d.ts +6 -0
  143. package/dist/auth/oauth/github-copilot.d.ts.map +1 -0
  144. package/dist/auth/oauth/github-copilot.js +313 -0
  145. package/dist/auth/oauth/github-copilot.js.map +1 -0
  146. package/dist/auth/oauth/load.d.ts +23 -0
  147. package/dist/auth/oauth/load.d.ts.map +1 -0
  148. package/dist/auth/oauth/load.js +49 -0
  149. package/dist/auth/oauth/load.js.map +1 -0
  150. package/dist/auth/oauth/oauth-page.d.ts +3 -0
  151. package/dist/auth/oauth/oauth-page.d.ts.map +1 -0
  152. package/dist/auth/oauth/oauth-page.js +105 -0
  153. package/dist/auth/oauth/oauth-page.js.map +1 -0
  154. package/dist/auth/oauth/openai-codex.d.ts +9 -0
  155. package/dist/auth/oauth/openai-codex.d.ts.map +1 -0
  156. package/dist/auth/oauth/openai-codex.js +443 -0
  157. package/dist/auth/oauth/openai-codex.js.map +1 -0
  158. package/dist/auth/oauth/pkce.d.ts +13 -0
  159. package/dist/auth/oauth/pkce.d.ts.map +1 -0
  160. package/dist/auth/oauth/pkce.js +31 -0
  161. package/dist/auth/oauth/pkce.js.map +1 -0
  162. package/dist/auth/oauth/radius.d.ts +16 -0
  163. package/dist/auth/oauth/radius.d.ts.map +1 -0
  164. package/dist/auth/oauth/radius.js +321 -0
  165. package/dist/auth/oauth/radius.js.map +1 -0
  166. package/dist/auth/oauth/xai.d.ts +6 -0
  167. package/dist/auth/oauth/xai.d.ts.map +1 -0
  168. package/dist/auth/oauth/xai.js +189 -0
  169. package/dist/auth/oauth/xai.js.map +1 -0
  170. package/dist/auth/resolve.d.ts +24 -0
  171. package/dist/auth/resolve.d.ts.map +1 -0
  172. package/dist/auth/resolve.js +103 -0
  173. package/dist/auth/resolve.js.map +1 -0
  174. package/dist/auth/types.d.ts +219 -0
  175. package/dist/auth/types.d.ts.map +1 -0
  176. package/dist/auth/types.js +2 -0
  177. package/dist/auth/types.js.map +1 -0
  178. package/dist/bedrock-provider.d.ts +5 -0
  179. package/dist/bedrock-provider.d.ts.map +1 -0
  180. package/dist/bedrock-provider.js +6 -0
  181. package/dist/bedrock-provider.js.map +1 -0
  182. package/dist/bun-oauth.d.ts +3 -0
  183. package/dist/bun-oauth.d.ts.map +1 -0
  184. package/dist/bun-oauth.js +17 -0
  185. package/dist/bun-oauth.js.map +1 -0
  186. package/dist/cli.d.ts +3 -0
  187. package/dist/cli.d.ts.map +1 -0
  188. package/dist/cli.js +115 -0
  189. package/dist/cli.js.map +1 -0
  190. package/dist/compat/extension-oauth-types.d.ts +39 -0
  191. package/dist/compat/extension-oauth-types.d.ts.map +1 -0
  192. package/dist/compat/extension-oauth-types.js +2 -0
  193. package/dist/compat/extension-oauth-types.js.map +1 -0
  194. package/dist/compat.d.ts +70 -0
  195. package/dist/compat.d.ts.map +1 -0
  196. package/dist/compat.js +189 -0
  197. package/dist/compat.js.map +1 -0
  198. package/dist/env-api-keys.d.ts +18 -0
  199. package/dist/env-api-keys.d.ts.map +1 -0
  200. package/dist/env-api-keys.js +148 -0
  201. package/dist/env-api-keys.js.map +1 -0
  202. package/dist/image-models.d.ts +10 -0
  203. package/dist/image-models.d.ts.map +1 -0
  204. package/dist/image-models.js +24 -0
  205. package/dist/image-models.js.map +1 -0
  206. package/dist/images-api-registry.d.ts +14 -0
  207. package/dist/images-api-registry.d.ts.map +1 -0
  208. package/dist/images-api-registry.js +22 -0
  209. package/dist/images-api-registry.js.map +1 -0
  210. package/dist/images-models.d.ts +95 -0
  211. package/dist/images-models.d.ts.map +1 -0
  212. package/dist/images-models.js +142 -0
  213. package/dist/images-models.js.map +1 -0
  214. package/dist/images.d.ts +4 -0
  215. package/dist/images.d.ts.map +1 -0
  216. package/dist/images.js +14 -0
  217. package/dist/images.js.map +1 -0
  218. package/dist/index.d.ts +35 -0
  219. package/dist/index.d.ts.map +1 -0
  220. package/dist/index.js +22 -0
  221. package/dist/index.js.map +1 -0
  222. package/dist/legacy-api-aliases.d.ts +42 -0
  223. package/dist/legacy-api-aliases.d.ts.map +1 -0
  224. package/dist/legacy-api-aliases.js +49 -0
  225. package/dist/legacy-api-aliases.js.map +1 -0
  226. package/dist/models-store.d.ts +27 -0
  227. package/dist/models-store.d.ts.map +1 -0
  228. package/dist/models-store.js +14 -0
  229. package/dist/models-store.js.map +1 -0
  230. package/dist/models.d.ts +178 -0
  231. package/dist/models.d.ts.map +1 -0
  232. package/dist/models.js +432 -0
  233. package/dist/models.js.map +1 -0
  234. package/dist/oauth.d.ts +3 -0
  235. package/dist/oauth.d.ts.map +1 -0
  236. package/dist/oauth.js +2 -0
  237. package/dist/oauth.js.map +1 -0
  238. package/dist/providers/all.d.ts +6 -0
  239. package/dist/providers/all.d.ts.map +1 -0
  240. package/dist/providers/all.js +9 -0
  241. package/dist/providers/all.js.map +1 -0
  242. package/dist/providers/anthropic-compat.d.ts +10 -0
  243. package/dist/providers/anthropic-compat.d.ts.map +1 -0
  244. package/dist/providers/anthropic-compat.js +20 -0
  245. package/dist/providers/anthropic-compat.js.map +1 -0
  246. package/dist/providers/faux.d.ts +97 -0
  247. package/dist/providers/faux.d.ts.map +1 -0
  248. package/dist/providers/faux.js +395 -0
  249. package/dist/providers/faux.js.map +1 -0
  250. package/dist/providers/images/register-builtins.d.ts +4 -0
  251. package/dist/providers/images/register-builtins.d.ts.map +1 -0
  252. package/dist/providers/images/register-builtins.js +34 -0
  253. package/dist/providers/images/register-builtins.js.map +1 -0
  254. package/dist/providers/openai-compat.d.ts +10 -0
  255. package/dist/providers/openai-compat.d.ts.map +1 -0
  256. package/dist/providers/openai-compat.js +24 -0
  257. package/dist/providers/openai-compat.js.map +1 -0
  258. package/dist/providers/openrouter-images.d.ts +3 -0
  259. package/dist/providers/openrouter-images.d.ts.map +1 -0
  260. package/dist/providers/openrouter-images.js +15 -0
  261. package/dist/providers/openrouter-images.js.map +1 -0
  262. package/dist/providers/radius.d.ts +9 -0
  263. package/dist/providers/radius.d.ts.map +1 -0
  264. package/dist/providers/radius.js +70 -0
  265. package/dist/providers/radius.js.map +1 -0
  266. package/dist/session-resources.d.ts +4 -0
  267. package/dist/session-resources.d.ts.map +1 -0
  268. package/dist/session-resources.js +22 -0
  269. package/dist/session-resources.js.map +1 -0
  270. package/dist/types.d.ts +629 -0
  271. package/dist/types.d.ts.map +1 -0
  272. package/dist/types.js +2 -0
  273. package/dist/types.js.map +1 -0
  274. package/dist/utils/abort-signals.d.ts +6 -0
  275. package/dist/utils/abort-signals.d.ts.map +1 -0
  276. package/dist/utils/abort-signals.js +34 -0
  277. package/dist/utils/abort-signals.js.map +1 -0
  278. package/dist/utils/deferred-tools.d.ts +9 -0
  279. package/dist/utils/deferred-tools.d.ts.map +1 -0
  280. package/dist/utils/deferred-tools.js +36 -0
  281. package/dist/utils/deferred-tools.js.map +1 -0
  282. package/dist/utils/diagnostics.d.ts +19 -0
  283. package/dist/utils/diagnostics.d.ts.map +1 -0
  284. package/dist/utils/diagnostics.js +25 -0
  285. package/dist/utils/diagnostics.js.map +1 -0
  286. package/dist/utils/error-body.d.ts +25 -0
  287. package/dist/utils/error-body.d.ts.map +1 -0
  288. package/dist/utils/error-body.js +109 -0
  289. package/dist/utils/error-body.js.map +1 -0
  290. package/dist/utils/estimate.d.ts +17 -0
  291. package/dist/utils/estimate.d.ts.map +1 -0
  292. package/dist/utils/estimate.js +116 -0
  293. package/dist/utils/estimate.js.map +1 -0
  294. package/dist/utils/event-stream.d.ts +21 -0
  295. package/dist/utils/event-stream.d.ts.map +1 -0
  296. package/dist/utils/event-stream.js +81 -0
  297. package/dist/utils/event-stream.js.map +1 -0
  298. package/dist/utils/hash.d.ts +3 -0
  299. package/dist/utils/hash.d.ts.map +1 -0
  300. package/dist/utils/hash.js +14 -0
  301. package/dist/utils/hash.js.map +1 -0
  302. package/dist/utils/headers.d.ts +4 -0
  303. package/dist/utils/headers.d.ts.map +1 -0
  304. package/dist/utils/headers.js +18 -0
  305. package/dist/utils/headers.js.map +1 -0
  306. package/dist/utils/json-parse.d.ts +16 -0
  307. package/dist/utils/json-parse.d.ts.map +1 -0
  308. package/dist/utils/json-parse.js +113 -0
  309. package/dist/utils/json-parse.js.map +1 -0
  310. package/dist/utils/node-http-proxy.d.ts +4 -0
  311. package/dist/utils/node-http-proxy.d.ts.map +1 -0
  312. package/dist/utils/node-http-proxy.js +92 -0
  313. package/dist/utils/node-http-proxy.js.map +1 -0
  314. package/dist/utils/overflow.d.ts +59 -0
  315. package/dist/utils/overflow.d.ts.map +1 -0
  316. package/dist/utils/overflow.js +161 -0
  317. package/dist/utils/overflow.js.map +1 -0
  318. package/dist/utils/provider-env.d.ts +7 -0
  319. package/dist/utils/provider-env.d.ts.map +1 -0
  320. package/dist/utils/provider-env.js +44 -0
  321. package/dist/utils/provider-env.js.map +1 -0
  322. package/dist/utils/retry.d.ts +53 -0
  323. package/dist/utils/retry.d.ts.map +1 -0
  324. package/dist/utils/retry.js +170 -0
  325. package/dist/utils/retry.js.map +1 -0
  326. package/dist/utils/sanitize-unicode.d.ts +22 -0
  327. package/dist/utils/sanitize-unicode.d.ts.map +1 -0
  328. package/dist/utils/sanitize-unicode.js +26 -0
  329. package/dist/utils/sanitize-unicode.js.map +1 -0
  330. package/dist/utils/text.d.ts +6 -0
  331. package/dist/utils/text.d.ts.map +1 -0
  332. package/dist/utils/text.js +10 -0
  333. package/dist/utils/text.js.map +1 -0
  334. package/dist/utils/typebox-helpers.d.ts +17 -0
  335. package/dist/utils/typebox-helpers.d.ts.map +1 -0
  336. package/dist/utils/typebox-helpers.js +21 -0
  337. package/dist/utils/typebox-helpers.js.map +1 -0
  338. package/dist/utils/uuid.d.ts +3 -0
  339. package/dist/utils/uuid.d.ts.map +1 -0
  340. package/dist/utils/uuid.js +46 -0
  341. package/dist/utils/uuid.js.map +1 -0
  342. package/dist/utils/validation.d.ts +18 -0
  343. package/dist/utils/validation.d.ts.map +1 -0
  344. package/dist/utils/validation.js +269 -0
  345. package/dist/utils/validation.js.map +1 -0
  346. package/package.json +95 -0
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Removes unpaired Unicode surrogate characters from a string.
3
+ *
4
+ * Unpaired surrogates (high surrogates 0xD800-0xDBFF without matching low surrogates 0xDC00-0xDFFF,
5
+ * or vice versa) cause JSON serialization errors in many API providers.
6
+ *
7
+ * Valid emoji and other characters outside the Basic Multilingual Plane use properly paired
8
+ * surrogates and will NOT be affected by this function.
9
+ *
10
+ * @param text - The text to sanitize
11
+ * @returns The sanitized text with unpaired surrogates removed
12
+ *
13
+ * @example
14
+ * // Valid emoji (properly paired surrogates) are preserved
15
+ * sanitizeSurrogates("Hello 🙈 World") // => "Hello 🙈 World"
16
+ *
17
+ * // Unpaired high surrogate is removed
18
+ * const unpaired = String.fromCharCode(0xD83D); // high surrogate without low
19
+ * sanitizeSurrogates(`Text ${unpaired} here`) // => "Text here"
20
+ */
21
+ export declare function sanitizeSurrogates(text: string): string;
22
+ //# sourceMappingURL=sanitize-unicode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize-unicode.d.ts","sourceRoot":"","sources":["../../src/utils/sanitize-unicode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIvD","sourcesContent":["/**\n * Removes unpaired Unicode surrogate characters from a string.\n *\n * Unpaired surrogates (high surrogates 0xD800-0xDBFF without matching low surrogates 0xDC00-0xDFFF,\n * or vice versa) cause JSON serialization errors in many API providers.\n *\n * Valid emoji and other characters outside the Basic Multilingual Plane use properly paired\n * surrogates and will NOT be affected by this function.\n *\n * @param text - The text to sanitize\n * @returns The sanitized text with unpaired surrogates removed\n *\n * @example\n * // Valid emoji (properly paired surrogates) are preserved\n * sanitizeSurrogates(\"Hello 🙈 World\") // => \"Hello 🙈 World\"\n *\n * // Unpaired high surrogate is removed\n * const unpaired = String.fromCharCode(0xD83D); // high surrogate without low\n * sanitizeSurrogates(`Text ${unpaired} here`) // => \"Text here\"\n */\nexport function sanitizeSurrogates(text: string): string {\n\t// Replace unpaired high surrogates (0xD800-0xDBFF not followed by low surrogate)\n\t// Replace unpaired low surrogates (0xDC00-0xDFFF not preceded by high surrogate)\n\treturn text.replace(/[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?<![\\uD800-\\uDBFF])[\\uDC00-\\uDFFF]/g, \"\");\n}\n"]}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Removes unpaired Unicode surrogate characters from a string.
3
+ *
4
+ * Unpaired surrogates (high surrogates 0xD800-0xDBFF without matching low surrogates 0xDC00-0xDFFF,
5
+ * or vice versa) cause JSON serialization errors in many API providers.
6
+ *
7
+ * Valid emoji and other characters outside the Basic Multilingual Plane use properly paired
8
+ * surrogates and will NOT be affected by this function.
9
+ *
10
+ * @param text - The text to sanitize
11
+ * @returns The sanitized text with unpaired surrogates removed
12
+ *
13
+ * @example
14
+ * // Valid emoji (properly paired surrogates) are preserved
15
+ * sanitizeSurrogates("Hello 🙈 World") // => "Hello 🙈 World"
16
+ *
17
+ * // Unpaired high surrogate is removed
18
+ * const unpaired = String.fromCharCode(0xD83D); // high surrogate without low
19
+ * sanitizeSurrogates(`Text ${unpaired} here`) // => "Text here"
20
+ */
21
+ export function sanitizeSurrogates(text) {
22
+ // Replace unpaired high surrogates (0xD800-0xDBFF not followed by low surrogate)
23
+ // Replace unpaired low surrogates (0xDC00-0xDFFF not preceded by high surrogate)
24
+ return text.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "");
25
+ }
26
+ //# sourceMappingURL=sanitize-unicode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize-unicode.js","sourceRoot":"","sources":["../../src/utils/sanitize-unicode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAU;IACxD,iFAAiF;IACjF,iFAAiF;IACjF,OAAO,IAAI,CAAC,OAAO,CAAC,yEAAyE,EAAE,EAAE,CAAC,CAAC;AAAA,CACnG","sourcesContent":["/**\n * Removes unpaired Unicode surrogate characters from a string.\n *\n * Unpaired surrogates (high surrogates 0xD800-0xDBFF without matching low surrogates 0xDC00-0xDFFF,\n * or vice versa) cause JSON serialization errors in many API providers.\n *\n * Valid emoji and other characters outside the Basic Multilingual Plane use properly paired\n * surrogates and will NOT be affected by this function.\n *\n * @param text - The text to sanitize\n * @returns The sanitized text with unpaired surrogates removed\n *\n * @example\n * // Valid emoji (properly paired surrogates) are preserved\n * sanitizeSurrogates(\"Hello 🙈 World\") // => \"Hello 🙈 World\"\n *\n * // Unpaired high surrogate is removed\n * const unpaired = String.fromCharCode(0xD83D); // high surrogate without low\n * sanitizeSurrogates(`Text ${unpaired} here`) // => \"Text here\"\n */\nexport function sanitizeSurrogates(text: string): string {\n\t// Replace unpaired high surrogates (0xD800-0xDBFF not followed by low surrogate)\n\t// Replace unpaired low surrogates (0xDC00-0xDFFF not preceded by high surrogate)\n\treturn text.replace(/[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?<![\\uD800-\\uDBFF])[\\uDC00-\\uDFFF]/g, \"\");\n}\n"]}
@@ -0,0 +1,6 @@
1
+ import type { ImageContent, TextContent, ThinkingContent, ToolCall } from "../types.ts";
2
+ type Content = TextContent | ImageContent | ThinkingContent | ToolCall;
3
+ /** Extract and join text from message content. */
4
+ export declare function contentText(content: string | readonly Content[], separator?: string): string;
5
+ export {};
6
+ //# sourceMappingURL=text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/utils/text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAExF,KAAK,OAAO,GAAG,WAAW,GAAG,YAAY,GAAG,eAAe,GAAG,QAAQ,CAAC;AAEvE,kDAAkD;AAClD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,OAAO,EAAE,EAAE,SAAS,SAAO,GAAG,MAAM,CAM1F","sourcesContent":["import type { ImageContent, TextContent, ThinkingContent, ToolCall } from \"../types.ts\";\n\ntype Content = TextContent | ImageContent | ThinkingContent | ToolCall;\n\n/** Extract and join text from message content. */\nexport function contentText(content: string | readonly Content[], separator = \"\\n\"): string {\n\tif (typeof content === \"string\") return content;\n\treturn content\n\t\t.filter((block) => block.type === \"text\")\n\t\t.map((block) => block.text)\n\t\t.join(separator);\n}\n"]}
@@ -0,0 +1,10 @@
1
+ /** Extract and join text from message content. */
2
+ export function contentText(content, separator = "\n") {
3
+ if (typeof content === "string")
4
+ return content;
5
+ return content
6
+ .filter((block) => block.type === "text")
7
+ .map((block) => block.text)
8
+ .join(separator);
9
+ }
10
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/utils/text.ts"],"names":[],"mappings":"AAIA,kDAAkD;AAClD,MAAM,UAAU,WAAW,CAAC,OAAoC,EAAE,SAAS,GAAG,IAAI,EAAU;IAC3F,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,OAAO,OAAO;SACZ,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC;SACxC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;SAC1B,IAAI,CAAC,SAAS,CAAC,CAAC;AAAA,CAClB","sourcesContent":["import type { ImageContent, TextContent, ThinkingContent, ToolCall } from \"../types.ts\";\n\ntype Content = TextContent | ImageContent | ThinkingContent | ToolCall;\n\n/** Extract and join text from message content. */\nexport function contentText(content: string | readonly Content[], separator = \"\\n\"): string {\n\tif (typeof content === \"string\") return content;\n\treturn content\n\t\t.filter((block) => block.type === \"text\")\n\t\t.map((block) => block.text)\n\t\t.join(separator);\n}\n"]}
@@ -0,0 +1,17 @@
1
+ import { type TUnsafe } from "typebox";
2
+ /**
3
+ * Creates a string enum schema compatible with Google's API and other providers
4
+ * that don't support anyOf/const patterns.
5
+ *
6
+ * @example
7
+ * const OperationSchema = StringEnum(["add", "subtract", "multiply", "divide"], {
8
+ * description: "The operation to perform"
9
+ * });
10
+ *
11
+ * type Operation = Static<typeof OperationSchema>; // "add" | "subtract" | "multiply" | "divide"
12
+ */
13
+ export declare function StringEnum<T extends readonly string[]>(values: T, options?: {
14
+ description?: string;
15
+ default?: T[number];
16
+ }): TUnsafe<T[number]>;
17
+ //# sourceMappingURL=typebox-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typebox-helpers.d.ts","sourceRoot":"","sources":["../../src/utils/typebox-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAQ,MAAM,SAAS,CAAC;AAE7C;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,EACrD,MAAM,EAAE,CAAC,EACT,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAA;CAAE,GACrD,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAOpB","sourcesContent":["import { type TUnsafe, Type } from \"typebox\";\n\n/**\n * Creates a string enum schema compatible with Google's API and other providers\n * that don't support anyOf/const patterns.\n *\n * @example\n * const OperationSchema = StringEnum([\"add\", \"subtract\", \"multiply\", \"divide\"], {\n * description: \"The operation to perform\"\n * });\n *\n * type Operation = Static<typeof OperationSchema>; // \"add\" | \"subtract\" | \"multiply\" | \"divide\"\n */\nexport function StringEnum<T extends readonly string[]>(\n\tvalues: T,\n\toptions?: { description?: string; default?: T[number] },\n): TUnsafe<T[number]> {\n\treturn Type.Unsafe<T[number]>({\n\t\ttype: \"string\",\n\t\tenum: values as any,\n\t\t...(options?.description && { description: options.description }),\n\t\t...(options?.default && { default: options.default }),\n\t});\n}\n"]}
@@ -0,0 +1,21 @@
1
+ import { Type } from "typebox";
2
+ /**
3
+ * Creates a string enum schema compatible with Google's API and other providers
4
+ * that don't support anyOf/const patterns.
5
+ *
6
+ * @example
7
+ * const OperationSchema = StringEnum(["add", "subtract", "multiply", "divide"], {
8
+ * description: "The operation to perform"
9
+ * });
10
+ *
11
+ * type Operation = Static<typeof OperationSchema>; // "add" | "subtract" | "multiply" | "divide"
12
+ */
13
+ export function StringEnum(values, options) {
14
+ return Type.Unsafe({
15
+ type: "string",
16
+ enum: values,
17
+ ...(options?.description && { description: options.description }),
18
+ ...(options?.default && { default: options.default }),
19
+ });
20
+ }
21
+ //# sourceMappingURL=typebox-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typebox-helpers.js","sourceRoot":"","sources":["../../src/utils/typebox-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,IAAI,EAAE,MAAM,SAAS,CAAC;AAE7C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CACzB,MAAS,EACT,OAAuD,EAClC;IACrB,OAAO,IAAI,CAAC,MAAM,CAAY;QAC7B,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,MAAa;QACnB,GAAG,CAAC,OAAO,EAAE,WAAW,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;QACjE,GAAG,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;KACrD,CAAC,CAAC;AAAA,CACH","sourcesContent":["import { type TUnsafe, Type } from \"typebox\";\n\n/**\n * Creates a string enum schema compatible with Google's API and other providers\n * that don't support anyOf/const patterns.\n *\n * @example\n * const OperationSchema = StringEnum([\"add\", \"subtract\", \"multiply\", \"divide\"], {\n * description: \"The operation to perform\"\n * });\n *\n * type Operation = Static<typeof OperationSchema>; // \"add\" | \"subtract\" | \"multiply\" | \"divide\"\n */\nexport function StringEnum<T extends readonly string[]>(\n\tvalues: T,\n\toptions?: { description?: string; default?: T[number] },\n): TUnsafe<T[number]> {\n\treturn Type.Unsafe<T[number]>({\n\t\ttype: \"string\",\n\t\tenum: values as any,\n\t\t...(options?.description && { description: options.description }),\n\t\t...(options?.default && { default: options.default }),\n\t});\n}\n"]}
@@ -0,0 +1,3 @@
1
+ /** Generate a time-ordered UUIDv7. */
2
+ export declare function uuidv7(): string;
3
+ //# sourceMappingURL=uuid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../../src/utils/uuid.ts"],"names":[],"mappings":"AAaA,sCAAsC;AACtC,wBAAgB,MAAM,IAAI,MAAM,CAiC/B","sourcesContent":["let lastTimestamp = -Infinity;\nlet sequence = 0;\n\nfunction fillRandomBytes(bytes: Uint8Array<ArrayBuffer>): void {\n\tif (globalThis.crypto?.getRandomValues) {\n\t\tglobalThis.crypto.getRandomValues(bytes);\n\t\treturn;\n\t}\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tbytes[i] = Math.floor(Math.random() * 256);\n\t}\n}\n\n/** Generate a time-ordered UUIDv7. */\nexport function uuidv7(): string {\n\tconst random = new Uint8Array(16);\n\tfillRandomBytes(random);\n\tconst timestamp = Date.now();\n\n\tif (timestamp > lastTimestamp) {\n\t\tsequence = random[6] * 0x1000000 + random[7] * 0x10000 + random[8] * 0x100 + random[9];\n\t\tlastTimestamp = timestamp;\n\t} else {\n\t\tsequence = (sequence + 1) >>> 0;\n\t\tif (sequence === 0) lastTimestamp++;\n\t}\n\n\tconst bytes = new Uint8Array(16);\n\tbytes[0] = (lastTimestamp / 0x10000000000) & 0xff;\n\tbytes[1] = (lastTimestamp / 0x100000000) & 0xff;\n\tbytes[2] = (lastTimestamp / 0x1000000) & 0xff;\n\tbytes[3] = (lastTimestamp / 0x10000) & 0xff;\n\tbytes[4] = (lastTimestamp / 0x100) & 0xff;\n\tbytes[5] = lastTimestamp & 0xff;\n\tbytes[6] = 0x70 | ((sequence >>> 28) & 0x0f);\n\tbytes[7] = (sequence >>> 20) & 0xff;\n\tbytes[8] = 0x80 | ((sequence >>> 14) & 0x3f);\n\tbytes[9] = (sequence >>> 6) & 0xff;\n\tbytes[10] = ((sequence & 0x3f) << 2) | (random[10] & 0x03);\n\tbytes[11] = random[11];\n\tbytes[12] = random[12];\n\tbytes[13] = random[13];\n\tbytes[14] = random[14];\n\tbytes[15] = random[15];\n\n\tconst hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\"));\n\treturn `${hex.slice(0, 4).join(\"\")}-${hex.slice(4, 6).join(\"\")}-${hex.slice(6, 8).join(\"\")}-${hex.slice(8, 10).join(\"\")}-${hex.slice(10, 16).join(\"\")}`;\n}\n"]}
@@ -0,0 +1,46 @@
1
+ let lastTimestamp = -Infinity;
2
+ let sequence = 0;
3
+ function fillRandomBytes(bytes) {
4
+ if (globalThis.crypto?.getRandomValues) {
5
+ globalThis.crypto.getRandomValues(bytes);
6
+ return;
7
+ }
8
+ for (let i = 0; i < bytes.length; i++) {
9
+ bytes[i] = Math.floor(Math.random() * 256);
10
+ }
11
+ }
12
+ /** Generate a time-ordered UUIDv7. */
13
+ export function uuidv7() {
14
+ const random = new Uint8Array(16);
15
+ fillRandomBytes(random);
16
+ const timestamp = Date.now();
17
+ if (timestamp > lastTimestamp) {
18
+ sequence = random[6] * 0x1000000 + random[7] * 0x10000 + random[8] * 0x100 + random[9];
19
+ lastTimestamp = timestamp;
20
+ }
21
+ else {
22
+ sequence = (sequence + 1) >>> 0;
23
+ if (sequence === 0)
24
+ lastTimestamp++;
25
+ }
26
+ const bytes = new Uint8Array(16);
27
+ bytes[0] = (lastTimestamp / 0x10000000000) & 0xff;
28
+ bytes[1] = (lastTimestamp / 0x100000000) & 0xff;
29
+ bytes[2] = (lastTimestamp / 0x1000000) & 0xff;
30
+ bytes[3] = (lastTimestamp / 0x10000) & 0xff;
31
+ bytes[4] = (lastTimestamp / 0x100) & 0xff;
32
+ bytes[5] = lastTimestamp & 0xff;
33
+ bytes[6] = 0x70 | ((sequence >>> 28) & 0x0f);
34
+ bytes[7] = (sequence >>> 20) & 0xff;
35
+ bytes[8] = 0x80 | ((sequence >>> 14) & 0x3f);
36
+ bytes[9] = (sequence >>> 6) & 0xff;
37
+ bytes[10] = ((sequence & 0x3f) << 2) | (random[10] & 0x03);
38
+ bytes[11] = random[11];
39
+ bytes[12] = random[12];
40
+ bytes[13] = random[13];
41
+ bytes[14] = random[14];
42
+ bytes[15] = random[15];
43
+ const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0"));
44
+ return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10, 16).join("")}`;
45
+ }
46
+ //# sourceMappingURL=uuid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uuid.js","sourceRoot":"","sources":["../../src/utils/uuid.ts"],"names":[],"mappings":"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","sourcesContent":["let lastTimestamp = -Infinity;\nlet sequence = 0;\n\nfunction fillRandomBytes(bytes: Uint8Array<ArrayBuffer>): void {\n\tif (globalThis.crypto?.getRandomValues) {\n\t\tglobalThis.crypto.getRandomValues(bytes);\n\t\treturn;\n\t}\n\tfor (let i = 0; i < bytes.length; i++) {\n\t\tbytes[i] = Math.floor(Math.random() * 256);\n\t}\n}\n\n/** Generate a time-ordered UUIDv7. */\nexport function uuidv7(): string {\n\tconst random = new Uint8Array(16);\n\tfillRandomBytes(random);\n\tconst timestamp = Date.now();\n\n\tif (timestamp > lastTimestamp) {\n\t\tsequence = random[6] * 0x1000000 + random[7] * 0x10000 + random[8] * 0x100 + random[9];\n\t\tlastTimestamp = timestamp;\n\t} else {\n\t\tsequence = (sequence + 1) >>> 0;\n\t\tif (sequence === 0) lastTimestamp++;\n\t}\n\n\tconst bytes = new Uint8Array(16);\n\tbytes[0] = (lastTimestamp / 0x10000000000) & 0xff;\n\tbytes[1] = (lastTimestamp / 0x100000000) & 0xff;\n\tbytes[2] = (lastTimestamp / 0x1000000) & 0xff;\n\tbytes[3] = (lastTimestamp / 0x10000) & 0xff;\n\tbytes[4] = (lastTimestamp / 0x100) & 0xff;\n\tbytes[5] = lastTimestamp & 0xff;\n\tbytes[6] = 0x70 | ((sequence >>> 28) & 0x0f);\n\tbytes[7] = (sequence >>> 20) & 0xff;\n\tbytes[8] = 0x80 | ((sequence >>> 14) & 0x3f);\n\tbytes[9] = (sequence >>> 6) & 0xff;\n\tbytes[10] = ((sequence & 0x3f) << 2) | (random[10] & 0x03);\n\tbytes[11] = random[11];\n\tbytes[12] = random[12];\n\tbytes[13] = random[13];\n\tbytes[14] = random[14];\n\tbytes[15] = random[15];\n\n\tconst hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\"));\n\treturn `${hex.slice(0, 4).join(\"\")}-${hex.slice(4, 6).join(\"\")}-${hex.slice(6, 8).join(\"\")}-${hex.slice(8, 10).join(\"\")}-${hex.slice(10, 16).join(\"\")}`;\n}\n"]}
@@ -0,0 +1,18 @@
1
+ import type { Tool, ToolCall } from "../types.ts";
2
+ /**
3
+ * Finds a tool by name and validates the tool call arguments against its TypeBox schema
4
+ * @param tools Array of tool definitions
5
+ * @param toolCall The tool call from the LLM
6
+ * @returns The validated arguments
7
+ * @throws Error if tool is not found or validation fails
8
+ */
9
+ export declare function validateToolCall(tools: Tool[], toolCall: ToolCall): any;
10
+ /**
11
+ * Validates tool call arguments against the tool's TypeBox schema
12
+ * @param tool The tool definition with TypeBox schema
13
+ * @param toolCall The tool call from the LLM
14
+ * @returns The validated (and potentially coerced) arguments
15
+ * @throws Error with formatted message if validation fails
16
+ */
17
+ export declare function validateToolArguments(tool: Tool, toolCall: ToolCall): any;
18
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AA4PlD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,QAAQ,GAAG,GAAG,CAMvE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,GAAG,GAAG,CAgCzE","sourcesContent":["import { Compile } from \"typebox/compile\";\nimport type { TLocalizedValidationError } from \"typebox/error\";\nimport { Value } from \"typebox/value\";\nimport type { Tool, ToolCall } from \"../types.ts\";\n\nconst validatorCache = new WeakMap<object, ReturnType<typeof Compile>>();\nconst TYPEBOX_KIND = Symbol.for(\"TypeBox.Kind\");\n\ninterface JsonSchemaObject {\n\ttype?: string | string[];\n\tproperties?: Record<string, JsonSchemaObject>;\n\titems?: JsonSchemaObject | JsonSchemaObject[];\n\tadditionalProperties?: boolean | JsonSchemaObject;\n\tallOf?: JsonSchemaObject[];\n\tanyOf?: JsonSchemaObject[];\n\toneOf?: JsonSchemaObject[];\n}\n\nfunction getSchemaTypes(schema: JsonSchemaObject): string[] {\n\tif (typeof schema.type === \"string\") {\n\t\treturn [schema.type];\n\t}\n\tif (Array.isArray(schema.type)) {\n\t\treturn schema.type.filter((type): type is string => typeof type === \"string\");\n\t}\n\treturn [];\n}\n\nfunction matchesJsonType(value: unknown, type: string): boolean {\n\tswitch (type) {\n\t\tcase \"number\":\n\t\t\treturn typeof value === \"number\";\n\t\tcase \"integer\":\n\t\t\treturn typeof value === \"number\" && Number.isInteger(value);\n\t\tcase \"boolean\":\n\t\t\treturn typeof value === \"boolean\";\n\t\tcase \"string\":\n\t\t\treturn typeof value === \"string\";\n\t\tcase \"null\":\n\t\t\treturn value === null;\n\t\tcase \"array\":\n\t\t\treturn Array.isArray(value);\n\t\tcase \"object\":\n\t\t\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nfunction getSubSchemaValidator(schema: JsonSchemaObject): ReturnType<typeof Compile> | undefined {\n\ttry {\n\t\treturn getValidator(schema as Tool[\"parameters\"]);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction coercePrimitiveByType(value: unknown, type: string): unknown {\n\tswitch (type) {\n\t\tcase \"number\": {\n\t\t\tif (value === null) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tif (typeof value === \"string\" && value.trim() !== \"\") {\n\t\t\t\tconst parsed = Number(value);\n\t\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\t\treturn parsed;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (typeof value === \"boolean\") {\n\t\t\t\treturn value ? 1 : 0;\n\t\t\t}\n\t\t\treturn value;\n\t\t}\n\t\tcase \"integer\": {\n\t\t\tif (value === null) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tif (typeof value === \"string\" && value.trim() !== \"\") {\n\t\t\t\tconst parsed = Number(value);\n\t\t\t\tif (Number.isInteger(parsed)) {\n\t\t\t\t\treturn parsed;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (typeof value === \"boolean\") {\n\t\t\t\treturn value ? 1 : 0;\n\t\t\t}\n\t\t\treturn value;\n\t\t}\n\t\tcase \"boolean\": {\n\t\t\tif (value === null) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (typeof value === \"string\") {\n\t\t\t\tif (value === \"true\") {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (value === \"false\") {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (typeof value === \"number\") {\n\t\t\t\tif (value === 1) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (value === 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn value;\n\t\t}\n\t\tcase \"string\": {\n\t\t\tif (value === null) {\n\t\t\t\treturn \"\";\n\t\t\t}\n\t\t\tif (typeof value === \"number\" || typeof value === \"boolean\") {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\treturn value;\n\t\t}\n\t\tcase \"null\": {\n\t\t\tif (value === \"\" || value === 0 || value === false) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn value;\n\t\t}\n\t\tdefault:\n\t\t\treturn value;\n\t}\n}\n\nfunction applySchemaObjectCoercion(value: Record<string, unknown>, schema: JsonSchemaObject): void {\n\tconst properties = schema.properties;\n\tconst definedKeys = new Set<string>(properties ? Object.keys(properties) : []);\n\n\tif (properties) {\n\t\tfor (const [key, propertySchema] of Object.entries(properties)) {\n\t\t\tif (!(key in value)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvalue[key] = coerceWithJsonSchema(value[key], propertySchema);\n\t\t}\n\t}\n\n\tif (schema.additionalProperties && typeof schema.additionalProperties === \"object\") {\n\t\tfor (const [key, propertyValue] of Object.entries(value)) {\n\t\t\tif (definedKeys.has(key)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvalue[key] = coerceWithJsonSchema(propertyValue, schema.additionalProperties);\n\t\t}\n\t}\n}\n\nfunction applySchemaArrayCoercion(value: unknown[], schema: JsonSchemaObject): void {\n\tif (Array.isArray(schema.items)) {\n\t\tfor (let index = 0; index < value.length; index++) {\n\t\t\tconst itemSchema = schema.items[index];\n\t\t\tif (!itemSchema) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvalue[index] = coerceWithJsonSchema(value[index], itemSchema);\n\t\t}\n\t\treturn;\n\t}\n\n\tif (schema.items && typeof schema.items === \"object\") {\n\t\tfor (let index = 0; index < value.length; index++) {\n\t\t\tvalue[index] = coerceWithJsonSchema(value[index], schema.items);\n\t\t}\n\t}\n}\n\nfunction coerceWithUnionSchema(value: unknown, schemas: JsonSchemaObject[]): unknown {\n\tfor (const schema of schemas) {\n\t\tconst candidate = structuredClone(value);\n\t\tconst coerced = coerceWithJsonSchema(candidate, schema);\n\t\tconst validator = getSubSchemaValidator(schema);\n\t\tif (validator?.Check(coerced)) {\n\t\t\treturn coerced;\n\t\t}\n\t}\n\treturn value;\n}\n\nfunction coerceWithJsonSchema(value: unknown, schema: JsonSchemaObject): unknown {\n\tlet nextValue = value;\n\n\tif (Array.isArray(schema.allOf)) {\n\t\tfor (const nested of schema.allOf) {\n\t\t\tnextValue = coerceWithJsonSchema(nextValue, nested);\n\t\t}\n\t}\n\n\tif (Array.isArray(schema.anyOf)) {\n\t\tnextValue = coerceWithUnionSchema(nextValue, schema.anyOf);\n\t}\n\n\tif (Array.isArray(schema.oneOf)) {\n\t\tnextValue = coerceWithUnionSchema(nextValue, schema.oneOf);\n\t}\n\n\tconst schemaTypes = getSchemaTypes(schema);\n\tconst matchesUnionMember =\n\t\tschemaTypes.length > 1 && schemaTypes.some((schemaType) => matchesJsonType(nextValue, schemaType));\n\tif (schemaTypes.length > 0 && !matchesUnionMember) {\n\t\tfor (const schemaType of schemaTypes) {\n\t\t\tconst candidate = coercePrimitiveByType(nextValue, schemaType);\n\t\t\tif (candidate !== nextValue) {\n\t\t\t\tnextValue = candidate;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (\n\t\tschemaTypes.includes(\"object\") &&\n\t\ttypeof nextValue === \"object\" &&\n\t\tnextValue !== null &&\n\t\t!Array.isArray(nextValue)\n\t) {\n\t\tapplySchemaObjectCoercion(nextValue as Record<string, unknown>, schema);\n\t}\n\n\tif (schemaTypes.includes(\"array\") && Array.isArray(nextValue)) {\n\t\tapplySchemaArrayCoercion(nextValue, schema);\n\t}\n\n\treturn nextValue;\n}\n\nfunction getValidator(schema: Tool[\"parameters\"]): ReturnType<typeof Compile> {\n\tconst key = schema as object;\n\tconst cached = validatorCache.get(key);\n\tif (cached) {\n\t\treturn cached;\n\t}\n\tconst validator = Compile(schema);\n\tvalidatorCache.set(key, validator);\n\treturn validator;\n}\n\nfunction formatValidationPath(error: TLocalizedValidationError): string {\n\tif (error.keyword === \"required\") {\n\t\tconst requiredProperties = (error.params as { requiredProperties?: string[] }).requiredProperties;\n\t\tconst requiredProperty = requiredProperties?.[0];\n\t\tif (requiredProperty) {\n\t\t\tconst basePath = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\t\t\treturn basePath ? `${basePath}.${requiredProperty}` : requiredProperty;\n\t\t}\n\t}\n\tconst path = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\treturn path || \"root\";\n}\n\n/**\n * Finds a tool by name and validates the tool call arguments against its TypeBox schema\n * @param tools Array of tool definitions\n * @param toolCall The tool call from the LLM\n * @returns The validated arguments\n * @throws Error if tool is not found or validation fails\n */\nexport function validateToolCall(tools: Tool[], toolCall: ToolCall): any {\n\tconst tool = tools.find((t) => t.name === toolCall.name);\n\tif (!tool) {\n\t\tthrow new Error(`Tool \"${toolCall.name}\" not found`);\n\t}\n\treturn validateToolArguments(tool, toolCall);\n}\n\n/**\n * Validates tool call arguments against the tool's TypeBox schema\n * @param tool The tool definition with TypeBox schema\n * @param toolCall The tool call from the LLM\n * @returns The validated (and potentially coerced) arguments\n * @throws Error with formatted message if validation fails\n */\nexport function validateToolArguments(tool: Tool, toolCall: ToolCall): any {\n\tconst args = structuredClone(toolCall.arguments);\n\tValue.Convert(tool.parameters, args);\n\n\tconst validator = getValidator(tool.parameters);\n\tif (!Object.getOwnPropertySymbols(tool.parameters).includes(TYPEBOX_KIND)) {\n\t\tconst coerced = coerceWithJsonSchema(args, tool.parameters as JsonSchemaObject);\n\t\tif (coerced !== args) {\n\t\t\tif (typeof args === \"object\" && args !== null && typeof coerced === \"object\" && coerced !== null) {\n\t\t\t\tfor (const key of Object.keys(args)) {\n\t\t\t\t\tdelete args[key];\n\t\t\t\t}\n\t\t\t\tObject.assign(args, coerced);\n\t\t\t} else {\n\t\t\t\treturn validator.Check(coerced) ? coerced : args;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (validator.Check(args)) {\n\t\treturn args;\n\t}\n\n\tconst errors =\n\t\tvalidator\n\t\t\t.Errors(args)\n\t\t\t.map((error) => ` - ${formatValidationPath(error)}: ${error.message}`)\n\t\t\t.join(\"\\n\") || \"Unknown validation error\";\n\n\tconst errorMessage = `Validation failed for tool \"${toolCall.name}\":\\n${errors}\\n\\nReceived arguments:\\n${JSON.stringify(toolCall.arguments, null, 2)}`;\n\n\tthrow new Error(errorMessage);\n}\n"]}
@@ -0,0 +1,269 @@
1
+ import { Compile } from "typebox/compile";
2
+ import { Value } from "typebox/value";
3
+ const validatorCache = new WeakMap();
4
+ const TYPEBOX_KIND = Symbol.for("TypeBox.Kind");
5
+ function getSchemaTypes(schema) {
6
+ if (typeof schema.type === "string") {
7
+ return [schema.type];
8
+ }
9
+ if (Array.isArray(schema.type)) {
10
+ return schema.type.filter((type) => typeof type === "string");
11
+ }
12
+ return [];
13
+ }
14
+ function matchesJsonType(value, type) {
15
+ switch (type) {
16
+ case "number":
17
+ return typeof value === "number";
18
+ case "integer":
19
+ return typeof value === "number" && Number.isInteger(value);
20
+ case "boolean":
21
+ return typeof value === "boolean";
22
+ case "string":
23
+ return typeof value === "string";
24
+ case "null":
25
+ return value === null;
26
+ case "array":
27
+ return Array.isArray(value);
28
+ case "object":
29
+ return typeof value === "object" && value !== null && !Array.isArray(value);
30
+ default:
31
+ return false;
32
+ }
33
+ }
34
+ function getSubSchemaValidator(schema) {
35
+ try {
36
+ return getValidator(schema);
37
+ }
38
+ catch {
39
+ return undefined;
40
+ }
41
+ }
42
+ function coercePrimitiveByType(value, type) {
43
+ switch (type) {
44
+ case "number": {
45
+ if (value === null) {
46
+ return 0;
47
+ }
48
+ if (typeof value === "string" && value.trim() !== "") {
49
+ const parsed = Number(value);
50
+ if (Number.isFinite(parsed)) {
51
+ return parsed;
52
+ }
53
+ }
54
+ if (typeof value === "boolean") {
55
+ return value ? 1 : 0;
56
+ }
57
+ return value;
58
+ }
59
+ case "integer": {
60
+ if (value === null) {
61
+ return 0;
62
+ }
63
+ if (typeof value === "string" && value.trim() !== "") {
64
+ const parsed = Number(value);
65
+ if (Number.isInteger(parsed)) {
66
+ return parsed;
67
+ }
68
+ }
69
+ if (typeof value === "boolean") {
70
+ return value ? 1 : 0;
71
+ }
72
+ return value;
73
+ }
74
+ case "boolean": {
75
+ if (value === null) {
76
+ return false;
77
+ }
78
+ if (typeof value === "string") {
79
+ if (value === "true") {
80
+ return true;
81
+ }
82
+ if (value === "false") {
83
+ return false;
84
+ }
85
+ }
86
+ if (typeof value === "number") {
87
+ if (value === 1) {
88
+ return true;
89
+ }
90
+ if (value === 0) {
91
+ return false;
92
+ }
93
+ }
94
+ return value;
95
+ }
96
+ case "string": {
97
+ if (value === null) {
98
+ return "";
99
+ }
100
+ if (typeof value === "number" || typeof value === "boolean") {
101
+ return String(value);
102
+ }
103
+ return value;
104
+ }
105
+ case "null": {
106
+ if (value === "" || value === 0 || value === false) {
107
+ return null;
108
+ }
109
+ return value;
110
+ }
111
+ default:
112
+ return value;
113
+ }
114
+ }
115
+ function applySchemaObjectCoercion(value, schema) {
116
+ const properties = schema.properties;
117
+ const definedKeys = new Set(properties ? Object.keys(properties) : []);
118
+ if (properties) {
119
+ for (const [key, propertySchema] of Object.entries(properties)) {
120
+ if (!(key in value)) {
121
+ continue;
122
+ }
123
+ value[key] = coerceWithJsonSchema(value[key], propertySchema);
124
+ }
125
+ }
126
+ if (schema.additionalProperties && typeof schema.additionalProperties === "object") {
127
+ for (const [key, propertyValue] of Object.entries(value)) {
128
+ if (definedKeys.has(key)) {
129
+ continue;
130
+ }
131
+ value[key] = coerceWithJsonSchema(propertyValue, schema.additionalProperties);
132
+ }
133
+ }
134
+ }
135
+ function applySchemaArrayCoercion(value, schema) {
136
+ if (Array.isArray(schema.items)) {
137
+ for (let index = 0; index < value.length; index++) {
138
+ const itemSchema = schema.items[index];
139
+ if (!itemSchema) {
140
+ continue;
141
+ }
142
+ value[index] = coerceWithJsonSchema(value[index], itemSchema);
143
+ }
144
+ return;
145
+ }
146
+ if (schema.items && typeof schema.items === "object") {
147
+ for (let index = 0; index < value.length; index++) {
148
+ value[index] = coerceWithJsonSchema(value[index], schema.items);
149
+ }
150
+ }
151
+ }
152
+ function coerceWithUnionSchema(value, schemas) {
153
+ for (const schema of schemas) {
154
+ const candidate = structuredClone(value);
155
+ const coerced = coerceWithJsonSchema(candidate, schema);
156
+ const validator = getSubSchemaValidator(schema);
157
+ if (validator?.Check(coerced)) {
158
+ return coerced;
159
+ }
160
+ }
161
+ return value;
162
+ }
163
+ function coerceWithJsonSchema(value, schema) {
164
+ let nextValue = value;
165
+ if (Array.isArray(schema.allOf)) {
166
+ for (const nested of schema.allOf) {
167
+ nextValue = coerceWithJsonSchema(nextValue, nested);
168
+ }
169
+ }
170
+ if (Array.isArray(schema.anyOf)) {
171
+ nextValue = coerceWithUnionSchema(nextValue, schema.anyOf);
172
+ }
173
+ if (Array.isArray(schema.oneOf)) {
174
+ nextValue = coerceWithUnionSchema(nextValue, schema.oneOf);
175
+ }
176
+ const schemaTypes = getSchemaTypes(schema);
177
+ const matchesUnionMember = schemaTypes.length > 1 && schemaTypes.some((schemaType) => matchesJsonType(nextValue, schemaType));
178
+ if (schemaTypes.length > 0 && !matchesUnionMember) {
179
+ for (const schemaType of schemaTypes) {
180
+ const candidate = coercePrimitiveByType(nextValue, schemaType);
181
+ if (candidate !== nextValue) {
182
+ nextValue = candidate;
183
+ break;
184
+ }
185
+ }
186
+ }
187
+ if (schemaTypes.includes("object") &&
188
+ typeof nextValue === "object" &&
189
+ nextValue !== null &&
190
+ !Array.isArray(nextValue)) {
191
+ applySchemaObjectCoercion(nextValue, schema);
192
+ }
193
+ if (schemaTypes.includes("array") && Array.isArray(nextValue)) {
194
+ applySchemaArrayCoercion(nextValue, schema);
195
+ }
196
+ return nextValue;
197
+ }
198
+ function getValidator(schema) {
199
+ const key = schema;
200
+ const cached = validatorCache.get(key);
201
+ if (cached) {
202
+ return cached;
203
+ }
204
+ const validator = Compile(schema);
205
+ validatorCache.set(key, validator);
206
+ return validator;
207
+ }
208
+ function formatValidationPath(error) {
209
+ if (error.keyword === "required") {
210
+ const requiredProperties = error.params.requiredProperties;
211
+ const requiredProperty = requiredProperties?.[0];
212
+ if (requiredProperty) {
213
+ const basePath = error.instancePath.replace(/^\//, "").replace(/\//g, ".");
214
+ return basePath ? `${basePath}.${requiredProperty}` : requiredProperty;
215
+ }
216
+ }
217
+ const path = error.instancePath.replace(/^\//, "").replace(/\//g, ".");
218
+ return path || "root";
219
+ }
220
+ /**
221
+ * Finds a tool by name and validates the tool call arguments against its TypeBox schema
222
+ * @param tools Array of tool definitions
223
+ * @param toolCall The tool call from the LLM
224
+ * @returns The validated arguments
225
+ * @throws Error if tool is not found or validation fails
226
+ */
227
+ export function validateToolCall(tools, toolCall) {
228
+ const tool = tools.find((t) => t.name === toolCall.name);
229
+ if (!tool) {
230
+ throw new Error(`Tool "${toolCall.name}" not found`);
231
+ }
232
+ return validateToolArguments(tool, toolCall);
233
+ }
234
+ /**
235
+ * Validates tool call arguments against the tool's TypeBox schema
236
+ * @param tool The tool definition with TypeBox schema
237
+ * @param toolCall The tool call from the LLM
238
+ * @returns The validated (and potentially coerced) arguments
239
+ * @throws Error with formatted message if validation fails
240
+ */
241
+ export function validateToolArguments(tool, toolCall) {
242
+ const args = structuredClone(toolCall.arguments);
243
+ Value.Convert(tool.parameters, args);
244
+ const validator = getValidator(tool.parameters);
245
+ if (!Object.getOwnPropertySymbols(tool.parameters).includes(TYPEBOX_KIND)) {
246
+ const coerced = coerceWithJsonSchema(args, tool.parameters);
247
+ if (coerced !== args) {
248
+ if (typeof args === "object" && args !== null && typeof coerced === "object" && coerced !== null) {
249
+ for (const key of Object.keys(args)) {
250
+ delete args[key];
251
+ }
252
+ Object.assign(args, coerced);
253
+ }
254
+ else {
255
+ return validator.Check(coerced) ? coerced : args;
256
+ }
257
+ }
258
+ }
259
+ if (validator.Check(args)) {
260
+ return args;
261
+ }
262
+ const errors = validator
263
+ .Errors(args)
264
+ .map((error) => ` - ${formatValidationPath(error)}: ${error.message}`)
265
+ .join("\n") || "Unknown validation error";
266
+ const errorMessage = `Validation failed for tool "${toolCall.name}":\n${errors}\n\nReceived arguments:\n${JSON.stringify(toolCall.arguments, null, 2)}`;
267
+ throw new Error(errorMessage);
268
+ }
269
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Compile } from \"typebox/compile\";\nimport type { TLocalizedValidationError } from \"typebox/error\";\nimport { Value } from \"typebox/value\";\nimport type { Tool, ToolCall } from \"../types.ts\";\n\nconst validatorCache = new WeakMap<object, ReturnType<typeof Compile>>();\nconst TYPEBOX_KIND = Symbol.for(\"TypeBox.Kind\");\n\ninterface JsonSchemaObject {\n\ttype?: string | string[];\n\tproperties?: Record<string, JsonSchemaObject>;\n\titems?: JsonSchemaObject | JsonSchemaObject[];\n\tadditionalProperties?: boolean | JsonSchemaObject;\n\tallOf?: JsonSchemaObject[];\n\tanyOf?: JsonSchemaObject[];\n\toneOf?: JsonSchemaObject[];\n}\n\nfunction getSchemaTypes(schema: JsonSchemaObject): string[] {\n\tif (typeof schema.type === \"string\") {\n\t\treturn [schema.type];\n\t}\n\tif (Array.isArray(schema.type)) {\n\t\treturn schema.type.filter((type): type is string => typeof type === \"string\");\n\t}\n\treturn [];\n}\n\nfunction matchesJsonType(value: unknown, type: string): boolean {\n\tswitch (type) {\n\t\tcase \"number\":\n\t\t\treturn typeof value === \"number\";\n\t\tcase \"integer\":\n\t\t\treturn typeof value === \"number\" && Number.isInteger(value);\n\t\tcase \"boolean\":\n\t\t\treturn typeof value === \"boolean\";\n\t\tcase \"string\":\n\t\t\treturn typeof value === \"string\";\n\t\tcase \"null\":\n\t\t\treturn value === null;\n\t\tcase \"array\":\n\t\t\treturn Array.isArray(value);\n\t\tcase \"object\":\n\t\t\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\nfunction getSubSchemaValidator(schema: JsonSchemaObject): ReturnType<typeof Compile> | undefined {\n\ttry {\n\t\treturn getValidator(schema as Tool[\"parameters\"]);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction coercePrimitiveByType(value: unknown, type: string): unknown {\n\tswitch (type) {\n\t\tcase \"number\": {\n\t\t\tif (value === null) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tif (typeof value === \"string\" && value.trim() !== \"\") {\n\t\t\t\tconst parsed = Number(value);\n\t\t\t\tif (Number.isFinite(parsed)) {\n\t\t\t\t\treturn parsed;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (typeof value === \"boolean\") {\n\t\t\t\treturn value ? 1 : 0;\n\t\t\t}\n\t\t\treturn value;\n\t\t}\n\t\tcase \"integer\": {\n\t\t\tif (value === null) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\tif (typeof value === \"string\" && value.trim() !== \"\") {\n\t\t\t\tconst parsed = Number(value);\n\t\t\t\tif (Number.isInteger(parsed)) {\n\t\t\t\t\treturn parsed;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (typeof value === \"boolean\") {\n\t\t\t\treturn value ? 1 : 0;\n\t\t\t}\n\t\t\treturn value;\n\t\t}\n\t\tcase \"boolean\": {\n\t\t\tif (value === null) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (typeof value === \"string\") {\n\t\t\t\tif (value === \"true\") {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (value === \"false\") {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (typeof value === \"number\") {\n\t\t\t\tif (value === 1) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tif (value === 0) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn value;\n\t\t}\n\t\tcase \"string\": {\n\t\t\tif (value === null) {\n\t\t\t\treturn \"\";\n\t\t\t}\n\t\t\tif (typeof value === \"number\" || typeof value === \"boolean\") {\n\t\t\t\treturn String(value);\n\t\t\t}\n\t\t\treturn value;\n\t\t}\n\t\tcase \"null\": {\n\t\t\tif (value === \"\" || value === 0 || value === false) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn value;\n\t\t}\n\t\tdefault:\n\t\t\treturn value;\n\t}\n}\n\nfunction applySchemaObjectCoercion(value: Record<string, unknown>, schema: JsonSchemaObject): void {\n\tconst properties = schema.properties;\n\tconst definedKeys = new Set<string>(properties ? Object.keys(properties) : []);\n\n\tif (properties) {\n\t\tfor (const [key, propertySchema] of Object.entries(properties)) {\n\t\t\tif (!(key in value)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvalue[key] = coerceWithJsonSchema(value[key], propertySchema);\n\t\t}\n\t}\n\n\tif (schema.additionalProperties && typeof schema.additionalProperties === \"object\") {\n\t\tfor (const [key, propertyValue] of Object.entries(value)) {\n\t\t\tif (definedKeys.has(key)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvalue[key] = coerceWithJsonSchema(propertyValue, schema.additionalProperties);\n\t\t}\n\t}\n}\n\nfunction applySchemaArrayCoercion(value: unknown[], schema: JsonSchemaObject): void {\n\tif (Array.isArray(schema.items)) {\n\t\tfor (let index = 0; index < value.length; index++) {\n\t\t\tconst itemSchema = schema.items[index];\n\t\t\tif (!itemSchema) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvalue[index] = coerceWithJsonSchema(value[index], itemSchema);\n\t\t}\n\t\treturn;\n\t}\n\n\tif (schema.items && typeof schema.items === \"object\") {\n\t\tfor (let index = 0; index < value.length; index++) {\n\t\t\tvalue[index] = coerceWithJsonSchema(value[index], schema.items);\n\t\t}\n\t}\n}\n\nfunction coerceWithUnionSchema(value: unknown, schemas: JsonSchemaObject[]): unknown {\n\tfor (const schema of schemas) {\n\t\tconst candidate = structuredClone(value);\n\t\tconst coerced = coerceWithJsonSchema(candidate, schema);\n\t\tconst validator = getSubSchemaValidator(schema);\n\t\tif (validator?.Check(coerced)) {\n\t\t\treturn coerced;\n\t\t}\n\t}\n\treturn value;\n}\n\nfunction coerceWithJsonSchema(value: unknown, schema: JsonSchemaObject): unknown {\n\tlet nextValue = value;\n\n\tif (Array.isArray(schema.allOf)) {\n\t\tfor (const nested of schema.allOf) {\n\t\t\tnextValue = coerceWithJsonSchema(nextValue, nested);\n\t\t}\n\t}\n\n\tif (Array.isArray(schema.anyOf)) {\n\t\tnextValue = coerceWithUnionSchema(nextValue, schema.anyOf);\n\t}\n\n\tif (Array.isArray(schema.oneOf)) {\n\t\tnextValue = coerceWithUnionSchema(nextValue, schema.oneOf);\n\t}\n\n\tconst schemaTypes = getSchemaTypes(schema);\n\tconst matchesUnionMember =\n\t\tschemaTypes.length > 1 && schemaTypes.some((schemaType) => matchesJsonType(nextValue, schemaType));\n\tif (schemaTypes.length > 0 && !matchesUnionMember) {\n\t\tfor (const schemaType of schemaTypes) {\n\t\t\tconst candidate = coercePrimitiveByType(nextValue, schemaType);\n\t\t\tif (candidate !== nextValue) {\n\t\t\t\tnextValue = candidate;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (\n\t\tschemaTypes.includes(\"object\") &&\n\t\ttypeof nextValue === \"object\" &&\n\t\tnextValue !== null &&\n\t\t!Array.isArray(nextValue)\n\t) {\n\t\tapplySchemaObjectCoercion(nextValue as Record<string, unknown>, schema);\n\t}\n\n\tif (schemaTypes.includes(\"array\") && Array.isArray(nextValue)) {\n\t\tapplySchemaArrayCoercion(nextValue, schema);\n\t}\n\n\treturn nextValue;\n}\n\nfunction getValidator(schema: Tool[\"parameters\"]): ReturnType<typeof Compile> {\n\tconst key = schema as object;\n\tconst cached = validatorCache.get(key);\n\tif (cached) {\n\t\treturn cached;\n\t}\n\tconst validator = Compile(schema);\n\tvalidatorCache.set(key, validator);\n\treturn validator;\n}\n\nfunction formatValidationPath(error: TLocalizedValidationError): string {\n\tif (error.keyword === \"required\") {\n\t\tconst requiredProperties = (error.params as { requiredProperties?: string[] }).requiredProperties;\n\t\tconst requiredProperty = requiredProperties?.[0];\n\t\tif (requiredProperty) {\n\t\t\tconst basePath = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\t\t\treturn basePath ? `${basePath}.${requiredProperty}` : requiredProperty;\n\t\t}\n\t}\n\tconst path = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\treturn path || \"root\";\n}\n\n/**\n * Finds a tool by name and validates the tool call arguments against its TypeBox schema\n * @param tools Array of tool definitions\n * @param toolCall The tool call from the LLM\n * @returns The validated arguments\n * @throws Error if tool is not found or validation fails\n */\nexport function validateToolCall(tools: Tool[], toolCall: ToolCall): any {\n\tconst tool = tools.find((t) => t.name === toolCall.name);\n\tif (!tool) {\n\t\tthrow new Error(`Tool \"${toolCall.name}\" not found`);\n\t}\n\treturn validateToolArguments(tool, toolCall);\n}\n\n/**\n * Validates tool call arguments against the tool's TypeBox schema\n * @param tool The tool definition with TypeBox schema\n * @param toolCall The tool call from the LLM\n * @returns The validated (and potentially coerced) arguments\n * @throws Error with formatted message if validation fails\n */\nexport function validateToolArguments(tool: Tool, toolCall: ToolCall): any {\n\tconst args = structuredClone(toolCall.arguments);\n\tValue.Convert(tool.parameters, args);\n\n\tconst validator = getValidator(tool.parameters);\n\tif (!Object.getOwnPropertySymbols(tool.parameters).includes(TYPEBOX_KIND)) {\n\t\tconst coerced = coerceWithJsonSchema(args, tool.parameters as JsonSchemaObject);\n\t\tif (coerced !== args) {\n\t\t\tif (typeof args === \"object\" && args !== null && typeof coerced === \"object\" && coerced !== null) {\n\t\t\t\tfor (const key of Object.keys(args)) {\n\t\t\t\t\tdelete args[key];\n\t\t\t\t}\n\t\t\t\tObject.assign(args, coerced);\n\t\t\t} else {\n\t\t\t\treturn validator.Check(coerced) ? coerced : args;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (validator.Check(args)) {\n\t\treturn args;\n\t}\n\n\tconst errors =\n\t\tvalidator\n\t\t\t.Errors(args)\n\t\t\t.map((error) => ` - ${formatValidationPath(error)}: ${error.message}`)\n\t\t\t.join(\"\\n\") || \"Unknown validation error\";\n\n\tconst errorMessage = `Validation failed for tool \"${toolCall.name}\":\\n${errors}\\n\\nReceived arguments:\\n${JSON.stringify(toolCall.arguments, null, 2)}`;\n\n\tthrow new Error(errorMessage);\n}\n"]}