ai-functions 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (400) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/.turbo/turbo-test.log +105 -0
  3. package/README.md +190 -86
  4. package/TODO.md +138 -0
  5. package/dist/ai-promise.d.ts +219 -0
  6. package/dist/ai-promise.d.ts.map +1 -0
  7. package/dist/ai-promise.js +610 -0
  8. package/dist/ai-promise.js.map +1 -0
  9. package/dist/ai.d.ts +285 -0
  10. package/dist/ai.d.ts.map +1 -0
  11. package/dist/ai.js +842 -0
  12. package/dist/ai.js.map +1 -0
  13. package/dist/batch/anthropic.d.ts +23 -0
  14. package/dist/batch/anthropic.d.ts.map +1 -0
  15. package/dist/batch/anthropic.js +257 -0
  16. package/dist/batch/anthropic.js.map +1 -0
  17. package/dist/batch/bedrock.d.ts +64 -0
  18. package/dist/batch/bedrock.d.ts.map +1 -0
  19. package/dist/batch/bedrock.js +586 -0
  20. package/dist/batch/bedrock.js.map +1 -0
  21. package/dist/batch/cloudflare.d.ts +37 -0
  22. package/dist/batch/cloudflare.d.ts.map +1 -0
  23. package/dist/batch/cloudflare.js +289 -0
  24. package/dist/batch/cloudflare.js.map +1 -0
  25. package/dist/batch/google.d.ts +41 -0
  26. package/dist/batch/google.d.ts.map +1 -0
  27. package/dist/batch/google.js +360 -0
  28. package/dist/batch/google.js.map +1 -0
  29. package/dist/batch/index.d.ts +31 -0
  30. package/dist/batch/index.d.ts.map +1 -0
  31. package/dist/batch/index.js +31 -0
  32. package/dist/batch/index.js.map +1 -0
  33. package/dist/batch/memory.d.ts +44 -0
  34. package/dist/batch/memory.d.ts.map +1 -0
  35. package/dist/batch/memory.js +188 -0
  36. package/dist/batch/memory.js.map +1 -0
  37. package/dist/batch/openai.d.ts +37 -0
  38. package/dist/batch/openai.d.ts.map +1 -0
  39. package/dist/batch/openai.js +403 -0
  40. package/dist/batch/openai.js.map +1 -0
  41. package/dist/batch-map.d.ts +125 -0
  42. package/dist/batch-map.d.ts.map +1 -0
  43. package/dist/batch-map.js +406 -0
  44. package/dist/batch-map.js.map +1 -0
  45. package/dist/batch-queue.d.ts +273 -0
  46. package/dist/batch-queue.d.ts.map +1 -0
  47. package/dist/batch-queue.js +271 -0
  48. package/dist/batch-queue.js.map +1 -0
  49. package/dist/context.d.ts +133 -0
  50. package/dist/context.d.ts.map +1 -0
  51. package/dist/context.js +267 -0
  52. package/dist/context.js.map +1 -0
  53. package/dist/embeddings.d.ts +123 -0
  54. package/dist/embeddings.d.ts.map +1 -0
  55. package/dist/embeddings.js +170 -0
  56. package/dist/embeddings.js.map +1 -0
  57. package/dist/eval/index.d.ts +8 -0
  58. package/dist/eval/index.d.ts.map +1 -0
  59. package/dist/eval/index.js +8 -0
  60. package/dist/eval/index.js.map +1 -0
  61. package/dist/eval/models.d.ts +66 -0
  62. package/dist/eval/models.d.ts.map +1 -0
  63. package/dist/eval/models.js +120 -0
  64. package/dist/eval/models.js.map +1 -0
  65. package/dist/eval/runner.d.ts +64 -0
  66. package/dist/eval/runner.d.ts.map +1 -0
  67. package/dist/eval/runner.js +148 -0
  68. package/dist/eval/runner.js.map +1 -0
  69. package/dist/generate.d.ts +168 -0
  70. package/dist/generate.d.ts.map +1 -0
  71. package/dist/generate.js +174 -0
  72. package/dist/generate.js.map +1 -0
  73. package/dist/index.d.ts +29 -4
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +53 -52
  76. package/dist/index.js.map +1 -1
  77. package/dist/primitives.d.ts +292 -0
  78. package/dist/primitives.d.ts.map +1 -0
  79. package/dist/primitives.js +471 -0
  80. package/dist/primitives.js.map +1 -0
  81. package/dist/providers/cloudflare.d.ts +9 -0
  82. package/dist/providers/cloudflare.d.ts.map +1 -0
  83. package/dist/providers/cloudflare.js +9 -0
  84. package/dist/providers/cloudflare.js.map +1 -0
  85. package/dist/providers/index.d.ts +9 -0
  86. package/dist/providers/index.d.ts.map +1 -0
  87. package/dist/providers/index.js +9 -0
  88. package/dist/providers/index.js.map +1 -0
  89. package/dist/schema.d.ts +54 -0
  90. package/dist/schema.d.ts.map +1 -0
  91. package/dist/schema.js +109 -0
  92. package/dist/schema.js.map +1 -0
  93. package/dist/template.d.ts +73 -0
  94. package/dist/template.d.ts.map +1 -0
  95. package/dist/template.js +129 -0
  96. package/dist/template.js.map +1 -0
  97. package/dist/types.d.ts +474 -106
  98. package/dist/types.d.ts.map +1 -1
  99. package/dist/types.js +4 -8
  100. package/dist/types.js.map +1 -1
  101. package/evalite.config.ts +19 -0
  102. package/evals/README.md +212 -0
  103. package/evals/classification.eval.ts +108 -0
  104. package/evals/marketing.eval.ts +370 -0
  105. package/evals/math.eval.ts +94 -0
  106. package/evals/run-evals.ts +166 -0
  107. package/evals/structured-output.eval.ts +143 -0
  108. package/evals/writing.eval.ts +117 -0
  109. package/examples/batch-blog-posts.ts +160 -0
  110. package/package.json +57 -57
  111. package/src/ai-promise.ts +784 -0
  112. package/src/ai.ts +1183 -0
  113. package/src/batch/anthropic.ts +375 -0
  114. package/src/batch/bedrock.ts +801 -0
  115. package/src/batch/cloudflare.ts +421 -0
  116. package/src/batch/google.ts +491 -0
  117. package/src/batch/index.ts +31 -0
  118. package/src/batch/memory.ts +253 -0
  119. package/src/batch/openai.ts +557 -0
  120. package/src/batch-map.ts +534 -0
  121. package/src/batch-queue.ts +493 -0
  122. package/src/context.ts +332 -0
  123. package/src/embeddings.ts +244 -0
  124. package/src/eval/index.ts +8 -0
  125. package/src/eval/models.ts +158 -0
  126. package/src/eval/runner.ts +217 -0
  127. package/src/generate.ts +245 -0
  128. package/src/index.ts +154 -0
  129. package/src/primitives.ts +612 -0
  130. package/src/providers/cloudflare.ts +15 -0
  131. package/src/providers/index.ts +14 -0
  132. package/src/schema.ts +147 -0
  133. package/src/template.ts +209 -0
  134. package/src/types.ts +540 -0
  135. package/test/README.md +105 -0
  136. package/test/ai-proxy.test.ts +192 -0
  137. package/test/async-iterators.test.ts +327 -0
  138. package/test/batch-background.test.ts +482 -0
  139. package/test/batch-blog-posts.test.ts +387 -0
  140. package/test/blog-generation.test.ts +510 -0
  141. package/test/browse-read.test.ts +611 -0
  142. package/test/core-functions.test.ts +694 -0
  143. package/test/decide.test.ts +393 -0
  144. package/test/define.test.ts +274 -0
  145. package/test/e2e-bedrock-manual.ts +163 -0
  146. package/test/e2e-bedrock.test.ts +191 -0
  147. package/test/e2e-flex-gateway.ts +157 -0
  148. package/test/e2e-flex-manual.ts +183 -0
  149. package/test/e2e-flex.test.ts +209 -0
  150. package/test/e2e-google-manual.ts +178 -0
  151. package/test/e2e-google.test.ts +216 -0
  152. package/test/embeddings.test.ts +284 -0
  153. package/test/evals/define-function.eval.test.ts +379 -0
  154. package/test/evals/primitives.eval.test.ts +384 -0
  155. package/test/function-types.test.ts +492 -0
  156. package/test/generate-core.test.ts +319 -0
  157. package/test/generate.test.ts +163 -0
  158. package/test/implicit-batch.test.ts +422 -0
  159. package/test/schema.test.ts +109 -0
  160. package/test/tagged-templates.test.ts +302 -0
  161. package/tsconfig.json +10 -0
  162. package/vitest.config.ts +42 -0
  163. package/LICENSE +0 -21
  164. package/bin/cli.js +0 -5
  165. package/dist/cli/index.d.ts +0 -10
  166. package/dist/cli/index.d.ts.map +0 -1
  167. package/dist/cli/index.js +0 -38
  168. package/dist/cli/index.js.map +0 -1
  169. package/dist/cli/index.test.d.ts +0 -2
  170. package/dist/cli/index.test.d.ts.map +0 -1
  171. package/dist/cli/index.test.js +0 -35
  172. package/dist/cli/index.test.js.map +0 -1
  173. package/dist/constants/models.d.ts +0 -10
  174. package/dist/constants/models.d.ts.map +0 -1
  175. package/dist/constants/models.js +0 -12
  176. package/dist/constants/models.js.map +0 -1
  177. package/dist/converters/index.d.ts +0 -3
  178. package/dist/converters/index.d.ts.map +0 -1
  179. package/dist/converters/index.js +0 -3
  180. package/dist/converters/index.js.map +0 -1
  181. package/dist/converters/model.d.ts +0 -4
  182. package/dist/converters/model.d.ts.map +0 -1
  183. package/dist/converters/model.js +0 -19
  184. package/dist/converters/model.js.map +0 -1
  185. package/dist/converters/schema.d.ts +0 -4
  186. package/dist/converters/schema.d.ts.map +0 -1
  187. package/dist/converters/schema.js +0 -25
  188. package/dist/converters/schema.js.map +0 -1
  189. package/dist/core/responses.d.ts +0 -5
  190. package/dist/core/responses.d.ts.map +0 -1
  191. package/dist/core/responses.js +0 -16
  192. package/dist/core/responses.js.map +0 -1
  193. package/dist/core/responses.test.d.ts +0 -2
  194. package/dist/core/responses.test.d.ts.map +0 -1
  195. package/dist/core/responses.test.js +0 -31
  196. package/dist/core/responses.test.js.map +0 -1
  197. package/dist/errors.d.ts +0 -6
  198. package/dist/errors.d.ts.map +0 -1
  199. package/dist/errors.js +0 -9
  200. package/dist/errors.js.map +0 -1
  201. package/dist/examples/streaming.test.d.ts +0 -2
  202. package/dist/examples/streaming.test.d.ts.map +0 -1
  203. package/dist/examples/streaming.test.js +0 -176
  204. package/dist/examples/streaming.test.js.map +0 -1
  205. package/dist/factory/__tests__/index.test.d.ts +0 -2
  206. package/dist/factory/__tests__/index.test.d.ts.map +0 -1
  207. package/dist/factory/__tests__/index.test.js +0 -430
  208. package/dist/factory/__tests__/index.test.js.map +0 -1
  209. package/dist/factory/__tests__/list.test.d.ts +0 -2
  210. package/dist/factory/__tests__/list.test.d.ts.map +0 -1
  211. package/dist/factory/__tests__/list.test.js +0 -92
  212. package/dist/factory/__tests__/list.test.js.map +0 -1
  213. package/dist/factory/index.d.ts +0 -20
  214. package/dist/factory/index.d.ts.map +0 -1
  215. package/dist/factory/index.js +0 -287
  216. package/dist/factory/index.js.map +0 -1
  217. package/dist/factory/index.test.d.ts +0 -2
  218. package/dist/factory/index.test.d.ts.map +0 -1
  219. package/dist/factory/index.test.js +0 -287
  220. package/dist/factory/index.test.js.map +0 -1
  221. package/dist/factory/list.d.ts +0 -3
  222. package/dist/factory/list.d.ts.map +0 -1
  223. package/dist/factory/list.js +0 -221
  224. package/dist/factory/list.js.map +0 -1
  225. package/dist/factory/list.test.d.ts +0 -2
  226. package/dist/factory/list.test.d.ts.map +0 -1
  227. package/dist/factory/list.test.js +0 -84
  228. package/dist/factory/list.test.js.map +0 -1
  229. package/dist/generate/index.d.ts +0 -5
  230. package/dist/generate/index.d.ts.map +0 -1
  231. package/dist/generate/index.js +0 -17
  232. package/dist/generate/index.js.map +0 -1
  233. package/dist/index.test.d.ts +0 -2
  234. package/dist/index.test.d.ts.map +0 -1
  235. package/dist/index.test.js +0 -59
  236. package/dist/index.test.js.map +0 -1
  237. package/dist/list/await.d.ts +0 -3
  238. package/dist/list/await.d.ts.map +0 -1
  239. package/dist/list/await.js +0 -28
  240. package/dist/list/await.js.map +0 -1
  241. package/dist/list/constants.d.ts +0 -4
  242. package/dist/list/constants.d.ts.map +0 -1
  243. package/dist/list/constants.js +0 -5
  244. package/dist/list/constants.js.map +0 -1
  245. package/dist/list/create-function.d.ts +0 -3
  246. package/dist/list/create-function.d.ts.map +0 -1
  247. package/dist/list/create-function.js +0 -11
  248. package/dist/list/create-function.js.map +0 -1
  249. package/dist/list/index.d.ts +0 -4
  250. package/dist/list/index.d.ts.map +0 -1
  251. package/dist/list/index.js +0 -5
  252. package/dist/list/index.js.map +0 -1
  253. package/dist/list/prompt.d.ts +0 -3
  254. package/dist/list/prompt.d.ts.map +0 -1
  255. package/dist/list/prompt.js +0 -6
  256. package/dist/list/prompt.js.map +0 -1
  257. package/dist/list/schemas.d.ts +0 -4
  258. package/dist/list/schemas.d.ts.map +0 -1
  259. package/dist/list/schemas.js +0 -8
  260. package/dist/list/schemas.js.map +0 -1
  261. package/dist/list/stream.d.ts +0 -3
  262. package/dist/list/stream.d.ts.map +0 -1
  263. package/dist/list/stream.js +0 -33
  264. package/dist/list/stream.js.map +0 -1
  265. package/dist/list/types.d.ts +0 -11
  266. package/dist/list/types.d.ts.map +0 -1
  267. package/dist/list/types.js +0 -2
  268. package/dist/list/types.js.map +0 -1
  269. package/dist/list/validation.d.ts +0 -3
  270. package/dist/list/validation.d.ts.map +0 -1
  271. package/dist/list/validation.js +0 -12
  272. package/dist/list/validation.js.map +0 -1
  273. package/dist/providers/config.d.ts +0 -4
  274. package/dist/providers/config.d.ts.map +0 -1
  275. package/dist/providers/config.js +0 -21
  276. package/dist/providers/config.js.map +0 -1
  277. package/dist/providers/config.test.d.ts +0 -2
  278. package/dist/providers/config.test.d.ts.map +0 -1
  279. package/dist/providers/config.test.js +0 -37
  280. package/dist/providers/config.test.js.map +0 -1
  281. package/dist/proxy/constants.d.ts +0 -4
  282. package/dist/proxy/constants.d.ts.map +0 -1
  283. package/dist/proxy/constants.js +0 -5
  284. package/dist/proxy/constants.js.map +0 -1
  285. package/dist/proxy/create-function.d.ts +0 -4
  286. package/dist/proxy/create-function.d.ts.map +0 -1
  287. package/dist/proxy/create-function.js +0 -24
  288. package/dist/proxy/create-function.js.map +0 -1
  289. package/dist/proxy/create-proxy.d.ts +0 -2
  290. package/dist/proxy/create-proxy.d.ts.map +0 -1
  291. package/dist/proxy/create-proxy.js +0 -11
  292. package/dist/proxy/create-proxy.js.map +0 -1
  293. package/dist/proxy/function-generator.d.ts +0 -9
  294. package/dist/proxy/function-generator.d.ts.map +0 -1
  295. package/dist/proxy/function-generator.js +0 -29
  296. package/dist/proxy/function-generator.js.map +0 -1
  297. package/dist/proxy/index.d.ts +0 -4
  298. package/dist/proxy/index.d.ts.map +0 -1
  299. package/dist/proxy/index.js +0 -4
  300. package/dist/proxy/index.js.map +0 -1
  301. package/dist/proxy/prompt.d.ts +0 -2
  302. package/dist/proxy/prompt.d.ts.map +0 -1
  303. package/dist/proxy/prompt.js +0 -6
  304. package/dist/proxy/prompt.js.map +0 -1
  305. package/dist/proxy/types.d.ts +0 -7
  306. package/dist/proxy/types.d.ts.map +0 -1
  307. package/dist/proxy/types.js +0 -2
  308. package/dist/proxy/types.js.map +0 -1
  309. package/dist/queue/manager.d.ts +0 -5
  310. package/dist/queue/manager.d.ts.map +0 -1
  311. package/dist/queue/manager.js +0 -37
  312. package/dist/queue/manager.js.map +0 -1
  313. package/dist/queue/manager.test.d.ts +0 -2
  314. package/dist/queue/manager.test.d.ts.map +0 -1
  315. package/dist/queue/manager.test.js +0 -52
  316. package/dist/queue/manager.test.js.map +0 -1
  317. package/dist/schema-converter.d.ts +0 -4
  318. package/dist/schema-converter.d.ts.map +0 -1
  319. package/dist/schema-converter.js +0 -30
  320. package/dist/schema-converter.js.map +0 -1
  321. package/dist/stream/index.d.ts +0 -7
  322. package/dist/stream/index.d.ts.map +0 -1
  323. package/dist/stream/index.js +0 -23
  324. package/dist/stream/index.js.map +0 -1
  325. package/dist/streaming/utils.d.ts +0 -4
  326. package/dist/streaming/utils.d.ts.map +0 -1
  327. package/dist/streaming/utils.js +0 -131
  328. package/dist/streaming/utils.js.map +0 -1
  329. package/dist/streaming/utils.test.d.ts +0 -2
  330. package/dist/streaming/utils.test.d.ts.map +0 -1
  331. package/dist/streaming/utils.test.js +0 -84
  332. package/dist/streaming/utils.test.js.map +0 -1
  333. package/dist/templates/result.d.ts +0 -7
  334. package/dist/templates/result.d.ts.map +0 -1
  335. package/dist/templates/result.js +0 -40
  336. package/dist/templates/result.js.map +0 -1
  337. package/dist/templates/result.test.d.ts +0 -2
  338. package/dist/templates/result.test.d.ts.map +0 -1
  339. package/dist/templates/result.test.js +0 -75
  340. package/dist/templates/result.test.js.map +0 -1
  341. package/dist/test/setup.d.ts +0 -2
  342. package/dist/test/setup.d.ts.map +0 -1
  343. package/dist/test/setup.js +0 -21
  344. package/dist/test/setup.js.map +0 -1
  345. package/dist/test-types.d.ts +0 -13
  346. package/dist/test-types.d.ts.map +0 -1
  347. package/dist/test-types.js +0 -55
  348. package/dist/test-types.js.map +0 -1
  349. package/dist/types/index.d.ts +0 -4
  350. package/dist/types/index.d.ts.map +0 -1
  351. package/dist/types/index.js +0 -4
  352. package/dist/types/index.js.map +0 -1
  353. package/dist/types/list.d.ts +0 -10
  354. package/dist/types/list.d.ts.map +0 -1
  355. package/dist/types/list.js +0 -2
  356. package/dist/types/list.js.map +0 -1
  357. package/dist/types/model.d.ts +0 -7
  358. package/dist/types/model.d.ts.map +0 -1
  359. package/dist/types/model.js +0 -2
  360. package/dist/types/model.js.map +0 -1
  361. package/dist/types/options.d.ts +0 -25
  362. package/dist/types/options.d.ts.map +0 -1
  363. package/dist/types/options.js +0 -2
  364. package/dist/types/options.js.map +0 -1
  365. package/dist/types/schema.d.ts +0 -5
  366. package/dist/types/schema.d.ts.map +0 -1
  367. package/dist/types/schema.js +0 -2
  368. package/dist/types/schema.js.map +0 -1
  369. package/dist/utils/__tests__/request-handler.test.d.ts +0 -2
  370. package/dist/utils/__tests__/request-handler.test.d.ts.map +0 -1
  371. package/dist/utils/__tests__/request-handler.test.js +0 -134
  372. package/dist/utils/__tests__/request-handler.test.js.map +0 -1
  373. package/dist/utils/__tests__/schema.test.d.ts +0 -2
  374. package/dist/utils/__tests__/schema.test.d.ts.map +0 -1
  375. package/dist/utils/__tests__/schema.test.js +0 -49
  376. package/dist/utils/__tests__/schema.test.js.map +0 -1
  377. package/dist/utils/__tests__/stream-progress.test.d.ts +0 -2
  378. package/dist/utils/__tests__/stream-progress.test.d.ts.map +0 -1
  379. package/dist/utils/__tests__/stream-progress.test.js +0 -85
  380. package/dist/utils/__tests__/stream-progress.test.js.map +0 -1
  381. package/dist/utils/index.d.ts +0 -2
  382. package/dist/utils/index.d.ts.map +0 -1
  383. package/dist/utils/index.js +0 -2
  384. package/dist/utils/index.js.map +0 -1
  385. package/dist/utils/request-handler.d.ts +0 -17
  386. package/dist/utils/request-handler.d.ts.map +0 -1
  387. package/dist/utils/request-handler.js +0 -105
  388. package/dist/utils/request-handler.js.map +0 -1
  389. package/dist/utils/schema.d.ts +0 -11
  390. package/dist/utils/schema.d.ts.map +0 -1
  391. package/dist/utils/schema.js +0 -51
  392. package/dist/utils/schema.js.map +0 -1
  393. package/dist/utils/stream-progress.d.ts +0 -17
  394. package/dist/utils/stream-progress.d.ts.map +0 -1
  395. package/dist/utils/stream-progress.js +0 -86
  396. package/dist/utils/stream-progress.js.map +0 -1
  397. package/dist/utils/validation.d.ts +0 -3
  398. package/dist/utils/validation.d.ts.map +0 -1
  399. package/dist/utils/validation.js +0 -30
  400. package/dist/utils/validation.js.map +0 -1
package/src/types.ts ADDED
@@ -0,0 +1,540 @@
1
+ /**
2
+ * Core types for AI functions
3
+ */
4
+
5
+ // Use Promise directly for interface definitions
6
+ // The actual RPC layer handles serialization
7
+ type RpcPromise<T> = Promise<T>
8
+
9
+ /**
10
+ * A function definition that can be called by AI
11
+ */
12
+ export interface AIFunctionDefinition<
13
+ TInput = unknown,
14
+ TOutput = unknown
15
+ > {
16
+ /** Unique name for the function */
17
+ name: string
18
+ /** Human-readable description for the AI */
19
+ description: string
20
+ /** JSON Schema for the input parameters */
21
+ parameters: JSONSchema
22
+ /** The implementation */
23
+ handler: (input: TInput) => TOutput | Promise<TOutput>
24
+ }
25
+
26
+ /**
27
+ * JSON Schema type (simplified)
28
+ */
29
+ export interface JSONSchema {
30
+ type?: string
31
+ properties?: Record<string, JSONSchema>
32
+ items?: JSONSchema
33
+ required?: string[]
34
+ description?: string
35
+ enum?: unknown[]
36
+ default?: unknown
37
+ [key: string]: unknown
38
+ }
39
+
40
+ /**
41
+ * Options for AI generation
42
+ */
43
+ export interface AIGenerateOptions {
44
+ /** The prompt or input */
45
+ prompt?: string
46
+ /** System message */
47
+ system?: string
48
+ /** Model to use */
49
+ model?: string
50
+ /** Temperature (0-1) */
51
+ temperature?: number
52
+ /** Maximum tokens to generate */
53
+ maxTokens?: number
54
+ /** Stop sequences */
55
+ stop?: string[]
56
+ /** Structured output schema */
57
+ schema?: JSONSchema
58
+ /** Available functions */
59
+ functions?: AIFunctionDefinition[]
60
+ }
61
+
62
+ /**
63
+ * Result of AI generation
64
+ */
65
+ export interface AIGenerateResult {
66
+ /** Generated text */
67
+ text: string
68
+ /** Structured output (if schema was provided) */
69
+ object?: unknown
70
+ /** Function calls (if functions were provided) */
71
+ functionCalls?: AIFunctionCall[]
72
+ /** Token usage */
73
+ usage?: {
74
+ promptTokens: number
75
+ completionTokens: number
76
+ totalTokens: number
77
+ }
78
+ }
79
+
80
+ /**
81
+ * A function call made by the AI
82
+ */
83
+ export interface AIFunctionCall {
84
+ /** Name of the function to call */
85
+ name: string
86
+ /** Arguments as JSON */
87
+ arguments: unknown
88
+ }
89
+
90
+ /**
91
+ * AI client interface - all methods return RpcPromise for pipelining
92
+ */
93
+ export interface AIClient {
94
+ /** Generate text or structured output */
95
+ generate(options: AIGenerateOptions): RpcPromise<AIGenerateResult>
96
+
97
+ /** Execute an action */
98
+ do(action: string, context?: unknown): RpcPromise<unknown>
99
+
100
+ /** Type checking / validation */
101
+ is(value: unknown, type: string | JSONSchema): RpcPromise<boolean>
102
+
103
+ /** Generate code */
104
+ code(prompt: string, language?: string): RpcPromise<string>
105
+
106
+ /** Make a decision */
107
+ decide<T extends string>(options: T[], context?: string): RpcPromise<T>
108
+
109
+ /** Generate a diagram */
110
+ diagram(description: string, format?: 'mermaid' | 'svg' | 'ascii'): RpcPromise<string>
111
+
112
+ /** Generate an image */
113
+ image(prompt: string, options?: ImageOptions): RpcPromise<ImageResult>
114
+
115
+ /** Generate a video */
116
+ video(prompt: string, options?: VideoOptions): RpcPromise<VideoResult>
117
+
118
+ /** Write/generate text content */
119
+ write(prompt: string, options?: WriteOptions): RpcPromise<string>
120
+
121
+ /** Generate a list of items with names and descriptions */
122
+ list(prompt: string): RpcPromise<ListResult>
123
+
124
+ /** Generate multiple named lists of items */
125
+ lists(prompt: string): RpcPromise<ListsResult>
126
+ }
127
+
128
+ export interface ImageOptions {
129
+ width?: number
130
+ height?: number
131
+ style?: string
132
+ model?: string
133
+ }
134
+
135
+ export interface ImageResult {
136
+ url: string
137
+ base64?: string
138
+ width: number
139
+ height: number
140
+ }
141
+
142
+ export interface VideoOptions {
143
+ duration?: number
144
+ width?: number
145
+ height?: number
146
+ fps?: number
147
+ model?: string
148
+ }
149
+
150
+ export interface VideoResult {
151
+ url: string
152
+ duration: number
153
+ width: number
154
+ height: number
155
+ }
156
+
157
+ export interface WriteOptions {
158
+ tone?: string
159
+ length?: 'short' | 'medium' | 'long'
160
+ format?: 'text' | 'markdown' | 'html'
161
+ }
162
+
163
+ /**
164
+ * Type for functions that support both regular calls and tagged template literals
165
+ */
166
+ export type TemplateFunction<TArgs extends unknown[], TReturn> =
167
+ & ((prompt: string, ...args: TArgs) => TReturn)
168
+ & ((strings: TemplateStringsArray, ...values: unknown[]) => TReturn)
169
+
170
+ /**
171
+ * A single item in a list
172
+ */
173
+ export interface ListItem {
174
+ name: string
175
+ description: string
176
+ }
177
+
178
+ /**
179
+ * Result of the list() function
180
+ */
181
+ export interface ListResult {
182
+ items: ListItem[]
183
+ }
184
+
185
+ /**
186
+ * A named list containing items
187
+ */
188
+ export interface NamedList {
189
+ name: string
190
+ items: ListItem[]
191
+ }
192
+
193
+ /**
194
+ * Result of the lists() function
195
+ */
196
+ export interface ListsResult {
197
+ lists: NamedList[]
198
+ }
199
+
200
+ // ============================================================================
201
+ // Function Definition Types
202
+ // ============================================================================
203
+
204
+ /**
205
+ * Supported programming languages for code generation
206
+ */
207
+ export type CodeLanguage = 'typescript' | 'javascript' | 'python' | 'go' | 'rust'
208
+
209
+ /**
210
+ * Output types for generative functions
211
+ */
212
+ export type GenerativeOutputType = 'string' | 'object' | 'image' | 'video' | 'audio'
213
+
214
+ /**
215
+ * Human interaction channels
216
+ *
217
+ * - chat: Real-time messaging (WebSocket, in-app)
218
+ * - email: Async email communication
219
+ * - phone: Voice calls
220
+ * - sms: SMS text messages
221
+ * - workspace: Team collaboration platforms (Slack, Teams, Discord)
222
+ * - web: Web-based interface (browser, web app)
223
+ */
224
+ export type HumanChannel = 'chat' | 'email' | 'phone' | 'sms' | 'workspace' | 'web'
225
+
226
+ /**
227
+ * Legacy channel type for backwards compatibility
228
+ * @deprecated Use HumanChannel instead
229
+ */
230
+ export type LegacyHumanChannel = 'slack' | 'email' | 'web' | 'sms' | 'custom'
231
+
232
+ /**
233
+ * Schema limitations that apply across providers
234
+ * These constraints ensure compatibility with OpenAI, Anthropic, and Google
235
+ */
236
+ export interface SchemaLimitations {
237
+ /** OpenAI requires additionalProperties: false on all objects */
238
+ noAdditionalProperties: true
239
+ /** OpenAI requires all properties in 'required' - no optional keys */
240
+ allPropertiesRequired: true
241
+ /** OpenAI doesn't support default values */
242
+ noDefaultValues: true
243
+ /** No recursive schema definitions (all providers) */
244
+ noRecursiveSchemas: true
245
+ /** No external $ref URLs (all providers) */
246
+ noExternalRefs: true
247
+ /** Anthropic doesn't support min/max on numbers */
248
+ noNumericBounds: true
249
+ /** Anthropic doesn't support minLength/maxLength on strings */
250
+ noStringLengthBounds: true
251
+ /** Anthropic only supports minItems of 0 or 1 */
252
+ limitedArrayMinItems: true
253
+ /** Anthropic doesn't support complex types in enums */
254
+ simpleEnumsOnly: true
255
+ /** Anthropic doesn't support lookahead/lookbehind in regex */
256
+ simpleRegexOnly: true
257
+ }
258
+
259
+ /**
260
+ * Base definition shared by all function types
261
+ */
262
+ export interface BaseFunctionDefinition<TArgs = unknown, TReturn = unknown> {
263
+ /** Function name (used as the callable identifier) */
264
+ name: string
265
+ /** Human-readable description of what this function does */
266
+ description?: string
267
+ /** Arguments schema - SimpleSchema or Zod schema */
268
+ args: TArgs
269
+ /** Return type schema - SimpleSchema or Zod schema (optional) */
270
+ returnType?: TReturn
271
+ }
272
+
273
+ /**
274
+ * Code function - generates actual executable code
275
+ *
276
+ * When called, this generates:
277
+ * - Implementation code with JSDoc comments
278
+ * - Vitest test cases
279
+ * - Example usage scripts
280
+ *
281
+ * @example
282
+ * ```ts
283
+ * defineFunction({
284
+ * type: 'code',
285
+ * name: 'calculateTax',
286
+ * args: {
287
+ * amount: 'The amount to calculate tax on (number)',
288
+ * rate: 'Tax rate as decimal (number)',
289
+ * },
290
+ * returnType: 'The calculated tax amount (number)',
291
+ * language: 'typescript',
292
+ * })
293
+ * ```
294
+ */
295
+ export interface CodeFunctionDefinition<TArgs = unknown, TReturn = unknown>
296
+ extends BaseFunctionDefinition<TArgs, TReturn> {
297
+ type: 'code'
298
+ /** Target programming language */
299
+ language?: CodeLanguage
300
+ /** Additional context or requirements for code generation */
301
+ instructions?: string
302
+ /** Whether to include vitest tests (default: true) */
303
+ includeTests?: boolean
304
+ /** Whether to include example usage (default: true) */
305
+ includeExamples?: boolean
306
+ }
307
+
308
+ /**
309
+ * Code function result with generated artifacts
310
+ */
311
+ export interface CodeFunctionResult {
312
+ /** The generated implementation code */
313
+ code: string
314
+ /** Generated vitest test code */
315
+ tests?: string
316
+ /** Generated example usage code */
317
+ examples?: string
318
+ /** The language the code was generated in */
319
+ language: CodeLanguage
320
+ /** JSDoc or equivalent documentation */
321
+ documentation: string
322
+ }
323
+
324
+ /**
325
+ * Generative function - uses AI to generate text, objects, or media
326
+ *
327
+ * @example
328
+ * ```ts
329
+ * defineFunction({
330
+ * type: 'generative',
331
+ * name: 'summarize',
332
+ * args: { text: 'The text to summarize' },
333
+ * output: 'string',
334
+ * system: 'You are an expert summarizer.',
335
+ * promptTemplate: 'Summarize the following text:\n\n{{text}}',
336
+ * })
337
+ * ```
338
+ */
339
+ export interface GenerativeFunctionDefinition<TArgs = unknown, TReturn = unknown>
340
+ extends BaseFunctionDefinition<TArgs, TReturn> {
341
+ type: 'generative'
342
+ /** What type of output this function produces */
343
+ output: GenerativeOutputType
344
+ /** System prompt for the AI */
345
+ system?: string
346
+ /** Prompt template with {{arg}} placeholders */
347
+ promptTemplate?: string
348
+ /** Model to use (defaults to 'sonnet') */
349
+ model?: string
350
+ /** Temperature for generation (0-2) */
351
+ temperature?: number
352
+ }
353
+
354
+ /**
355
+ * Generative function result
356
+ */
357
+ export interface GenerativeFunctionResult<T = unknown> {
358
+ /** Generated text (if output is 'string') */
359
+ text?: string
360
+ /** Generated object (if output is 'object') */
361
+ object?: T
362
+ /** Generated image (if output is 'image') */
363
+ image?: ImageResult
364
+ /** Generated video (if output is 'video') */
365
+ video?: VideoResult
366
+ /** Generated audio URL (if output is 'audio') */
367
+ audio?: { url: string; duration: number }
368
+ }
369
+
370
+ /**
371
+ * Agentic function - runs in a loop with tools until completion
372
+ *
373
+ * @example
374
+ * ```ts
375
+ * defineFunction({
376
+ * type: 'agentic',
377
+ * name: 'researchTopic',
378
+ * args: { topic: 'The topic to research' },
379
+ * returnType: {
380
+ * summary: 'Research summary',
381
+ * sources: ['List of sources'],
382
+ * },
383
+ * instructions: 'Research the topic thoroughly using available tools.',
384
+ * tools: [searchTool, fetchTool],
385
+ * maxIterations: 10,
386
+ * })
387
+ * ```
388
+ */
389
+ export interface AgenticFunctionDefinition<TArgs = unknown, TReturn = unknown>
390
+ extends BaseFunctionDefinition<TArgs, TReturn> {
391
+ type: 'agentic'
392
+ /** Instructions for the agent on how to accomplish the task */
393
+ instructions: string
394
+ /** Prompt template with {{arg}} placeholders */
395
+ promptTemplate?: string
396
+ /** Tools available to the agent */
397
+ tools?: AIFunctionDefinition[]
398
+ /** Maximum number of iterations before stopping (default: 10) */
399
+ maxIterations?: number
400
+ /** Model to use for the agent (defaults to 'sonnet') */
401
+ model?: string
402
+ /** Whether to stream intermediate results */
403
+ stream?: boolean
404
+ }
405
+
406
+ /**
407
+ * Agentic function execution state
408
+ */
409
+ export interface AgenticExecutionState {
410
+ /** Current iteration number */
411
+ iteration: number
412
+ /** Tool calls made so far */
413
+ toolCalls: AIFunctionCall[]
414
+ /** Intermediate results */
415
+ intermediateResults: unknown[]
416
+ /** Whether the agent has completed */
417
+ completed: boolean
418
+ /** Final result (if completed) */
419
+ result?: unknown
420
+ }
421
+
422
+ /**
423
+ * Human function - requires human input/approval
424
+ *
425
+ * Generates appropriate UI/interaction for the specified channel:
426
+ * - slack: Generates Slack BlockKit JSON
427
+ * - email: Generates email template
428
+ * - web: Generates form/UI component
429
+ * - sms: Generates SMS-friendly text
430
+ * - custom: Provides structured data for custom implementation
431
+ *
432
+ * @example
433
+ * ```ts
434
+ * defineFunction({
435
+ * type: 'human',
436
+ * name: 'approveExpense',
437
+ * args: {
438
+ * amount: 'Expense amount (number)',
439
+ * description: 'What the expense is for',
440
+ * submitter: 'Who submitted the expense',
441
+ * },
442
+ * returnType: {
443
+ * approved: 'Whether the expense was approved (boolean)',
444
+ * notes: 'Any notes from the approver',
445
+ * },
446
+ * channel: 'workspace',
447
+ * instructions: 'Review the expense request and approve or reject it.',
448
+ * })
449
+ * ```
450
+ */
451
+ export interface HumanFunctionDefinition<TArgs = unknown, TReturn = unknown>
452
+ extends BaseFunctionDefinition<TArgs, TReturn> {
453
+ type: 'human'
454
+ /** How to interact with the human */
455
+ channel: HumanChannel
456
+ /** Instructions shown to the human */
457
+ instructions: string
458
+ /** Prompt template with {{arg}} placeholders for the request */
459
+ promptTemplate?: string
460
+ /** Timeout in milliseconds (default: none - wait indefinitely) */
461
+ timeout?: number
462
+ /** Who should handle this (e.g., user ID, email, channel ID) */
463
+ assignee?: string
464
+ }
465
+
466
+ /**
467
+ * Human function result with channel-specific artifacts
468
+ */
469
+ export interface HumanFunctionResult<T = unknown> {
470
+ /** The human's response */
471
+ response: T
472
+ /** Who responded */
473
+ respondedBy?: string
474
+ /** When they responded */
475
+ respondedAt?: Date
476
+ /** Channel-specific artifacts */
477
+ artifacts?: {
478
+ /** Slack BlockKit JSON */
479
+ slackBlocks?: unknown[]
480
+ /** Email HTML template */
481
+ emailHtml?: string
482
+ /** Web form component */
483
+ webComponent?: string
484
+ /** SMS message text */
485
+ smsText?: string
486
+ }
487
+ }
488
+
489
+ /**
490
+ * Union of all function definition types
491
+ */
492
+ export type FunctionDefinition<TArgs = unknown, TReturn = unknown> =
493
+ | CodeFunctionDefinition<TArgs, TReturn>
494
+ | GenerativeFunctionDefinition<TArgs, TReturn>
495
+ | AgenticFunctionDefinition<TArgs, TReturn>
496
+ | HumanFunctionDefinition<TArgs, TReturn>
497
+
498
+ /**
499
+ * Result of defineFunction - a callable with metadata
500
+ */
501
+ export interface DefinedFunction<TArgs = unknown, TReturn = unknown> {
502
+ /** The original definition */
503
+ definition: FunctionDefinition<TArgs, TReturn>
504
+ /** Call the function */
505
+ call: (args: TArgs) => Promise<TReturn>
506
+ /** Get the function as a tool definition for AI */
507
+ asTool: () => AIFunctionDefinition<TArgs, TReturn>
508
+ }
509
+
510
+ /**
511
+ * Function registry for storing and retrieving defined functions
512
+ *
513
+ * Note: This is in-memory only. For persistence, use mdxai or mdxdb packages.
514
+ */
515
+ export interface FunctionRegistry {
516
+ /** Get a function by name */
517
+ get(name: string): DefinedFunction | undefined
518
+ /** Set/store a function */
519
+ set(name: string, fn: DefinedFunction): void
520
+ /** Check if a function exists */
521
+ has(name: string): boolean
522
+ /** List all function names */
523
+ list(): string[]
524
+ /** Delete a function */
525
+ delete(name: string): boolean
526
+ /** Clear all functions */
527
+ clear(): void
528
+ }
529
+
530
+ /**
531
+ * Result of auto-defining a function
532
+ */
533
+ export interface AutoDefineResult {
534
+ /** The determined function type */
535
+ type: 'code' | 'generative' | 'agentic' | 'human'
536
+ /** Reasoning for why this type was chosen */
537
+ reasoning: string
538
+ /** The complete function definition */
539
+ definition: FunctionDefinition
540
+ }
package/test/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # ai-functions Tests
2
+
3
+ Integration tests for ai-functions using real AI models via Cloudflare AI Gateway.
4
+
5
+ ## Prerequisites
6
+
7
+ Set environment variables in `.env` at the project root:
8
+
9
+ ```bash
10
+ AI_GATEWAY_URL=https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_name}
11
+ AI_GATEWAY_TOKEN=your-gateway-token
12
+ ```
13
+
14
+ The AI Gateway should have secrets configured for:
15
+ - `anthropic` - Anthropic API key
16
+ - `openai` - OpenAI API key
17
+ - `openrouter` - OpenRouter API key
18
+
19
+ ## Running Tests
20
+
21
+ ```bash
22
+ # Run all tests
23
+ pnpm test
24
+
25
+ # Run specific test file
26
+ npx vitest run test/generate.test.ts
27
+
28
+ # Watch mode
29
+ npx vitest
30
+
31
+ # With verbose output
32
+ npx vitest run --reporter=verbose
33
+ ```
34
+
35
+ ## Test Files
36
+
37
+ | File | Description |
38
+ |------|-------------|
39
+ | `schema.test.ts` | Pure unit tests for schema conversion (no AI calls) |
40
+ | `embeddings.test.ts` | Embedding utility tests (mostly pure, 2 skipped API tests) |
41
+ | `generate.test.ts` | generateObject/generateText with real AI calls |
42
+ | `ai-proxy.test.ts` | AI() proxy and schema functions |
43
+ | `define.test.ts` | Function registry and defineFunction |
44
+
45
+ ## Test Configuration
46
+
47
+ Tests use:
48
+ - **vitest** for test runner
49
+ - **dotenv** for loading env vars from parent directories
50
+ - **Sequential execution** to avoid rate limiting (`singleFork: true`)
51
+ - **60s timeout** for AI calls
52
+
53
+ ## How It Works
54
+
55
+ ### No Mocking
56
+
57
+ Tests call real AI models through Cloudflare AI Gateway. This ensures:
58
+ - Actual API compatibility
59
+ - Real response validation
60
+ - Gateway caching for efficiency
61
+
62
+ ### Gateway Caching
63
+
64
+ Cloudflare AI Gateway caches responses, so:
65
+ - First run may be slower
66
+ - Subsequent runs use cached responses
67
+ - Tests are idempotent with same inputs
68
+
69
+ ### Model Routing
70
+
71
+ All models route through OpenRouter:
72
+ - `'sonnet'` → `openrouter:anthropic/claude-sonnet-4.5`
73
+ - `'gpt-4o'` → `openrouter:openai/gpt-4o`
74
+ - OpenRouter handles model ID translation
75
+
76
+ ## Writing Tests
77
+
78
+ ```typescript
79
+ import { describe, it, expect } from 'vitest'
80
+ import { generateObject } from '../src/generate.js'
81
+
82
+ const hasGateway = !!process.env.AI_GATEWAY_URL
83
+
84
+ describe.skipIf(!hasGateway)('my tests', () => {
85
+ it('generates output', async () => {
86
+ const { object } = await generateObject({
87
+ model: 'sonnet',
88
+ schema: { message: 'A greeting' },
89
+ prompt: 'Say hello',
90
+ })
91
+
92
+ expect(object.message).toBeDefined()
93
+ })
94
+ })
95
+ ```
96
+
97
+ ## Debugging
98
+
99
+ ```bash
100
+ # Check env loading
101
+ node -e "require('dotenv').config({ path: '../../../.env' }); console.log(process.env.AI_GATEWAY_URL)"
102
+
103
+ # Run single test with logs
104
+ npx vitest run test/generate.test.ts -t "generates simple"
105
+ ```