ai-functions 0.2.19 → 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 (227) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/.turbo/turbo-test.log +105 -0
  3. package/README.md +232 -37
  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 +30 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +54 -0
  76. package/dist/index.js.map +1 -0
  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 +481 -0
  98. package/dist/types.d.ts.map +1 -0
  99. package/dist/types.js +5 -0
  100. package/dist/types.js.map +1 -0
  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 +59 -43
  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 +8 -6
  162. package/vitest.config.ts +42 -0
  163. package/LICENSE +0 -21
  164. package/db/cache.ts +0 -6
  165. package/db/mongo.ts +0 -75
  166. package/dist/mjs/db/cache.d.ts +0 -1
  167. package/dist/mjs/db/cache.js +0 -5
  168. package/dist/mjs/db/mongo.d.ts +0 -31
  169. package/dist/mjs/db/mongo.js +0 -48
  170. package/dist/mjs/examples/data.d.ts +0 -1105
  171. package/dist/mjs/examples/data.js +0 -1105
  172. package/dist/mjs/functions/ai.d.ts +0 -20
  173. package/dist/mjs/functions/ai.js +0 -83
  174. package/dist/mjs/functions/ai.test.d.ts +0 -1
  175. package/dist/mjs/functions/ai.test.js +0 -29
  176. package/dist/mjs/functions/gpt.d.ts +0 -4
  177. package/dist/mjs/functions/gpt.js +0 -10
  178. package/dist/mjs/functions/list.d.ts +0 -7
  179. package/dist/mjs/functions/list.js +0 -72
  180. package/dist/mjs/index.d.ts +0 -3
  181. package/dist/mjs/index.js +0 -3
  182. package/dist/mjs/queue/kafka.d.ts +0 -0
  183. package/dist/mjs/queue/kafka.js +0 -1
  184. package/dist/mjs/queue/memory.d.ts +0 -0
  185. package/dist/mjs/queue/memory.js +0 -1
  186. package/dist/mjs/queue/mongo.d.ts +0 -30
  187. package/dist/mjs/queue/mongo.js +0 -42
  188. package/dist/mjs/streams/kafka.d.ts +0 -0
  189. package/dist/mjs/streams/kafka.js +0 -1
  190. package/dist/mjs/streams/memory.d.ts +0 -0
  191. package/dist/mjs/streams/memory.js +0 -1
  192. package/dist/mjs/streams/mongo.d.ts +0 -0
  193. package/dist/mjs/streams/mongo.js +0 -1
  194. package/dist/mjs/streams/types.d.ts +0 -0
  195. package/dist/mjs/streams/types.js +0 -1
  196. package/dist/mjs/types.d.ts +0 -11
  197. package/dist/mjs/types.js +0 -1
  198. package/dist/mjs/utils/completion.d.ts +0 -9
  199. package/dist/mjs/utils/completion.js +0 -20
  200. package/dist/mjs/utils/schema.d.ts +0 -10
  201. package/dist/mjs/utils/schema.js +0 -72
  202. package/dist/mjs/utils/schema.test.d.ts +0 -1
  203. package/dist/mjs/utils/schema.test.js +0 -60
  204. package/dist/mjs/utils/state.d.ts +0 -1
  205. package/dist/mjs/utils/state.js +0 -19
  206. package/examples/data.ts +0 -1105
  207. package/fixup +0 -11
  208. package/functions/ai.test.ts +0 -41
  209. package/functions/ai.ts +0 -115
  210. package/functions/gpt.ts +0 -12
  211. package/functions/list.ts +0 -84
  212. package/index.ts +0 -3
  213. package/queue/kafka.ts +0 -0
  214. package/queue/memory.ts +0 -0
  215. package/queue/mongo.ts +0 -88
  216. package/streams/kafka.ts +0 -0
  217. package/streams/memory.ts +0 -0
  218. package/streams/mongo.ts +0 -0
  219. package/streams/types.ts +0 -0
  220. package/tsconfig-backup.json +0 -105
  221. package/tsconfig-base.json +0 -26
  222. package/tsconfig-cjs.json +0 -8
  223. package/types.ts +0 -12
  224. package/utils/completion.ts +0 -28
  225. package/utils/schema.test.ts +0 -69
  226. package/utils/schema.ts +0 -74
  227. package/utils/state.ts +0 -23
@@ -0,0 +1,5 @@
1
+
2
+ 
3
+ > ai-functions@0.4.0 build /Users/nathanclevenger/projects/mdx.org.ai/primitives/packages/ai-functions
4
+ > tsc -p tsconfig.json
5
+
@@ -0,0 +1,105 @@
1
+
2
+ > ai-functions@0.0.1 test /Users/nathanclevenger/projects/mdx.org.ai/primitives/packages/ai-functions
3
+ > vitest
4
+
5
+ [dotenv@17.2.3] injecting env (2) from ../../../.env -- tip: 📡 add observability to secrets: https://dotenvx.com/ops
6
+
7
+ DEV v2.1.9 /Users/nathanclevenger/projects/mdx.org.ai/primitives/packages/ai-functions
8
+
9
+ ✓ test/core-functions.test.ts (38 tests) 11ms
10
+ ✓ test/function-types.test.ts (35 tests) 4ms
11
+ ✓ test/browse-read.test.ts (31 tests) 5ms
12
+ ✓ test/batch-background.test.ts (20 tests) 2ms
13
+ ✓ test/decide.test.ts (15 tests) 2ms
14
+ ✓ test/async-iterators.test.ts (13 tests) 336ms
15
+ ✓ test/generate-core.test.ts (18 tests) 2ms
16
+ ✓ test/tagged-templates.test.ts (19 tests) 3ms
17
+ ✓ test/define.test.ts (18 tests) 955ms
18
+ ✓ generative function execution > executes a generative string function 456ms
19
+ ✓ test/embeddings.test.ts (24 tests | 2 skipped) 36ms
20
+ ✓ test/ai-proxy.test.ts (14 tests) 1585ms
21
+ ✓ ai proxy auto-define > uses cached definition on second call 524ms
22
+ ✓ AI() schema functions > generates nested objects 339ms
23
+ ✓ test/generate.test.ts (9 tests) 1702ms
24
+ ✓ generateText > generates simple text response 323ms
25
+ ✓ test/schema.test.ts (12 tests) 2ms
26
+
27
+ Test Files 13 passed (13)
28
+ Tests 264 passed | 2 skipped (266)
29
+ Start at 14:14:37
30
+ Duration 5.46s (transform 171ms, setup 0ms, collect 351ms, tests 4.65s, environment 0ms, prepare 84ms)
31
+
32
+ PASS Waiting for file changes...
33
+ press h to show help, press q to quit
34
+ c RERUN ../language-models/dist/aliases.js
35
+
36
+ ✓ test/generate.test.ts (9 tests) 1916ms
37
+ ✓ generateObject > generates a simple object with string fields 622ms
38
+ ✓ test/ai-proxy.test.ts (14 tests) 1361ms
39
+ ✓ ai proxy auto-define > uses cached definition on second call 540ms
40
+ ✓ test/define.test.ts (18 tests) 349ms
41
+ ✓ test/embeddings.test.ts (24 tests | 2 skipped) 32ms
42
+ ✓ test/schema.test.ts (12 tests) 1ms
43
+
44
+ Test Files 5 passed (5)
45
+ Tests 75 passed | 2 skipped (77)
46
+ Start at 14:22:55
47
+ Duration 3.99s
48
+
49
+ PASS Waiting for file changes...
50
+ press h to show help, press q to quit
51
+ c RERUN ../language-models/dist/aliases.js
52
+
53
+ ✓ test/generate.test.ts (9 tests) 948ms
54
+ ✓ test/ai-proxy.test.ts (14 tests) 610ms
55
+ ✓ test/define.test.ts (18 tests) 289ms
56
+ ✓ test/embeddings.test.ts (24 tests | 2 skipped) 30ms
57
+ ✓ test/schema.test.ts (12 tests) 1ms
58
+
59
+ Test Files 5 passed (5)
60
+ Tests 75 passed | 2 skipped (77)
61
+ Start at 14:31:30
62
+ Duration 2.00s
63
+
64
+ PASS Waiting for file changes...
65
+ press h to show help, press q to quit
66
+ c RERUN src/index.ts
67
+
68
+ ✓ test/generate.test.ts (9 tests) 2001ms
69
+ ✓ generateObject > generates a simple object with string fields 481ms
70
+ ✓ test/ai-proxy.test.ts (14 tests) 1395ms
71
+ ✓ ai proxy auto-define > auto-defines a function on first call 320ms
72
+ ✓ ai proxy auto-define > uses cached definition on second call 541ms
73
+ ✓ test/define.test.ts (18 tests) 844ms
74
+ ✓ test/embeddings.test.ts (24 tests | 2 skipped) 47ms
75
+ ✓ test/schema.test.ts (12 tests) 1ms
76
+
77
+ Test Files 5 passed (5)
78
+ Tests 75 passed | 2 skipped (77)
79
+ Start at 01:20:37
80
+ Duration 4.50s
81
+
82
+ PASS Waiting for file changes...
83
+ press h to show help, press q to quit
84
+ c RERUN test/implicit-batch.test.ts
85
+
86
+ ✓ test/batch-blog-posts.test.ts (15 tests) 411ms
87
+ ✓ test/implicit-batch.test.ts (26 tests) 4ms
88
+ ✓ test/generate.test.ts (9 tests) 1676ms
89
+ ✓ generateObject > generates a simple object with string fields 498ms
90
+ ✓ test/ai-proxy.test.ts (14 tests) 1328ms
91
+ ✓ ai proxy auto-define > auto-defines a function on first call 380ms
92
+ ✓ ai proxy auto-define > uses cached definition on second call 525ms
93
+ ✓ test/define.test.ts (18 tests) 869ms
94
+ ✓ generative function execution > executes a generative string function 315ms
95
+ ✓ test/embeddings.test.ts (24 tests | 2 skipped) 36ms
96
+ ✓ test/schema.test.ts (12 tests) 1ms
97
+
98
+ Test Files 7 passed (7)
99
+ Tests 116 passed | 2 skipped (118)
100
+ Start at 03:35:28
101
+ Duration 4.48s
102
+
103
+ PASS Waiting for file changes...
104
+ press h to show help, press q to quit
105
+  ELIFECYCLE  Test failed. See above for more details.
package/README.md CHANGED
@@ -1,59 +1,254 @@
1
- # AI Functions
1
+ # ai-functions
2
2
 
3
- Library for Developing and Managing AI Functions (including OpenAI GPT4 / GPT3.5)
3
+ Call AI like you'd talk to a colleague. No prompts. No configuration. Just say what you need.
4
4
 
5
- Key Features:
5
+ ```typescript
6
+ import { ai, list, is } from 'ai-functions'
6
7
 
7
- - Enables easy development of AI functions
8
+ // Ask for anything - it reads like English
9
+ const qualified = is`${lead} a good fit for our enterprise plan?`
10
+ const ideas = list`blog posts that would resonate with ${persona}`
11
+ const { summary, nextSteps } = ai`analyze this sales call: ${transcript}`
12
+ ```
8
13
 
9
- ```javascript
10
- import { AI } from 'ai-functions'
14
+ ## Installation
11
15
 
12
- const { ai, gpt, list } = AI({ apiKey: OPENAI_API_KEY })
16
+ ```bash
17
+ pnpm add ai-functions
13
18
  ```
14
19
 
15
- Then you can use magic `ai` functions:
20
+ ## The Magic: Promise Pipelining
16
21
 
17
- ```javascript
18
- const categorizeProduct = ai.categorizeProduct({
19
- productType: 'App | API | Marketplace | Platform | Packaged Service | Professional Service | Website',
20
- customer: 'ideal customer profile in 3-5 words',
21
- solution: 'describe the offer in 4-10 words',
22
- description: 'website meta description',
23
- })
22
+ Chain operations naturally—no `await` needed until you actually need the result:
24
23
 
25
- const product = await categorizeProduct({ domain: name })
26
- ```
24
+ ```typescript
25
+ // Destructure to get exactly what you need
26
+ const { qualified, score, reason } = ai`qualify this lead: ${lead}`
27
27
 
28
- you can also use `list` tagged template as a convienence function:
28
+ // Chain functions together—dependencies resolve automatically
29
+ const followUp = ai`write follow-up email based on: ${reason}`
30
+ const subject = ai`subject line for: ${followUp}`
29
31
 
30
- ```javascript
31
- const things = await list`fun things to do in Miami`
32
- console.log(things)
32
+ // Only await when you need the actual value
33
+ if (await qualified) {
34
+ await sendEmail({ to: lead.email, subject: await subject, body: await followUp })
35
+ }
33
36
  ```
34
37
 
35
- or with Async iterators:
38
+ ## Real-World Examples
36
39
 
37
- ```javascript
38
- for await (const thing of list`fun things to do in Miami`) {
39
- console.log(thing)
40
+ ### Lead Qualification
41
+
42
+ ```typescript
43
+ const { score, qualified, reasoning } = ai`
44
+ qualify ${lead} for our product
45
+ considering: ${idealCustomerProfile}
46
+ `
47
+
48
+ if (await qualified) {
49
+ await assignToSales(lead)
40
50
  }
41
51
  ```
42
52
 
43
- Or in a more complex example:
53
+ ### Content Marketing
44
54
 
45
- ```javascript
46
- const listBlogPosts = (count, topic) => list`${count} blog post titles about ${topic}`
47
- const writeBlogPost = (title) => gpt`write a blog post in markdown starting with "# ${title}"`
55
+ ```typescript
56
+ // Generate topic ideas for your audience
57
+ const topics = list`content ideas for ${persona} in ${industry}`
48
58
 
49
- async function* writeBlog(count, topic) {
50
- for await (const title of listBlogPosts(count, topic)) {
51
- const content = await writeBlogPost(title)
52
- yield { title, content }
53
- }
54
- }
59
+ // Evaluate each in parallel—single LLM call!
60
+ const evaluated = await topics.map(topic => ({
61
+ topic,
62
+ potential: is`${topic} would drive signups?`,
63
+ difficulty: ai`content difficulty for: ${topic}`,
64
+ }))
65
+
66
+ // Pick the best
67
+ const winner = evaluated.find(t => t.potential && t.difficulty === 'easy')
68
+ ```
69
+
70
+ ### Sales Intelligence
71
+
72
+ ```typescript
73
+ const { pros, cons, objections } = lists`
74
+ competitive analysis: ${ourProduct} vs ${competitor}
75
+ `
76
+
77
+ const battleCard = ai`
78
+ sales battlecard addressing: ${objections}
79
+ highlighting: ${pros}
80
+ `
81
+ ```
82
+
83
+ ### Customer Success
55
84
 
56
- for await (const post of writeBlog(25, 'future of car sales')) {
57
- console.log({ post })
85
+ ```typescript
86
+ // Analyze customer health
87
+ const { healthy, churnRisk, opportunities } = ai`
88
+ analyze customer health for ${customer}
89
+ based on: ${usageData}
90
+ `
91
+
92
+ if (await churnRisk) {
93
+ const outreach = ai`retention outreach for ${customer} addressing ${churnRisk}`
94
+ await scheduleCall(customer, await outreach)
58
95
  }
59
96
  ```
97
+
98
+ ### Recruiting
99
+
100
+ ```typescript
101
+ const candidates = list`source ${role} candidates from ${jobBoards}`
102
+
103
+ const evaluated = await candidates.map(candidate => ({
104
+ candidate,
105
+ fit: is`${candidate} matches ${requirements}?`,
106
+ summary: ai`one-line summary of ${candidate}`,
107
+ }))
108
+
109
+ const shortlist = evaluated.filter(c => c.fit)
110
+ ```
111
+
112
+ ## API Reference
113
+
114
+ ### Generation
115
+
116
+ ```typescript
117
+ ai`anything you need` // flexible object/text
118
+ write`blog post about ${topic}` // long-form content
119
+ summarize`${document}` // condense to key points
120
+ list`ideas for ${topic}` // array of items
121
+ lists`pros and cons of ${topic}` // named lists
122
+ extract`emails from ${text}` // structured extraction
123
+ ```
124
+
125
+ ### Classification
126
+
127
+ ```typescript
128
+ is`${email} spam?` // boolean
129
+ decide`which converts better?`(optionA, optionB) // pick best
130
+ ```
131
+
132
+ ### Code & Visuals
133
+
134
+ ```typescript
135
+ code`email validation function` // generate code
136
+ diagram`user flow for ${feature}` // mermaid diagrams
137
+ slides`pitch deck for ${startup}` // presentations
138
+ image`hero image for ${brand}` // image generation
139
+ ```
140
+
141
+ ### Research & Web
142
+
143
+ ```typescript
144
+ research`${competitor} market position` // web research
145
+ read`${url}` // url to markdown
146
+ browse`${url}` // browser automation
147
+ ```
148
+
149
+ ### Human-in-the-Loop
150
+
151
+ ```typescript
152
+ ask`what's the priority for ${feature}?` // free-form input
153
+ approve`deploy ${version} to production?` // yes/no approval
154
+ review`${document}` // detailed feedback
155
+ ```
156
+
157
+ ## The `lists` Function
158
+
159
+ Get exactly what you ask for through destructuring:
160
+
161
+ ```typescript
162
+ // Just name what you want—the schema is inferred!
163
+ const { pros, cons } = lists`pros and cons of ${decision}`
164
+ const { strengths, weaknesses, opportunities, threats } = lists`SWOT for ${company}`
165
+ const { mustHave, niceToHave, outOfScope } = lists`requirements for ${feature}`
166
+ ```
167
+
168
+ ## Batch Processing with `.map()`
169
+
170
+ Process arrays in a single LLM call:
171
+
172
+ ```typescript
173
+ const leads = await list`leads from ${campaign}`
174
+
175
+ // Each field evaluated for each lead—all in ONE call
176
+ const qualified = await leads.map(lead => ({
177
+ lead,
178
+ score: ai`score 1-100: ${lead}`,
179
+ qualified: is`${lead} matches ${icp}?`,
180
+ nextStep: ai`recommended action for ${lead}`,
181
+ }))
182
+
183
+ // Filter and act
184
+ qualified
185
+ .filter(l => l.qualified)
186
+ .forEach(l => createTask(l.nextStep))
187
+ ```
188
+
189
+ ## Typed Schemas with `AI()`
190
+
191
+ For reusable, typed functions:
192
+
193
+ ```typescript
194
+ const ai = AI({
195
+ qualifyLead: {
196
+ score: 'Lead score 1-100 (number)',
197
+ qualified: 'Whether to pursue (boolean)',
198
+ reasoning: 'Explanation of score',
199
+ nextSteps: ['Recommended actions'],
200
+ },
201
+
202
+ analyzeCompetitor: {
203
+ positioning: 'How they position themselves',
204
+ strengths: ['Their advantages'],
205
+ weaknesses: ['Their disadvantages'],
206
+ battleCard: 'Key talking points for sales',
207
+ },
208
+ })
209
+
210
+ // Fully typed!
211
+ const result = await ai.qualifyLead('Enterprise CTO interested in AI automation')
212
+ result.score // number
213
+ result.qualified // boolean
214
+ result.nextSteps // string[]
215
+ ```
216
+
217
+ ## Schema Syntax
218
+
219
+ | Syntax | Type | Example |
220
+ |--------|------|---------|
221
+ | `'description'` | string | `name: 'Company name'` |
222
+ | `'desc (number)'` | number | `score: 'Score 1-100 (number)'` |
223
+ | `'desc (boolean)'` | boolean | `qualified: 'Pursue? (boolean)'` |
224
+ | `'opt1 \| opt2'` | enum | `priority: 'high \| medium \| low'` |
225
+ | `['description']` | array | `steps: ['Action items']` |
226
+ | `{ nested }` | object | `contact: { name, email }` |
227
+
228
+ ## Philosophy
229
+
230
+ **Code should read like conversation.**
231
+
232
+ Compare:
233
+ ```typescript
234
+ // Traditional AI code
235
+ const response = await openai.chat.completions.create({
236
+ model: "gpt-4",
237
+ messages: [{ role: "user", content: `Analyze this lead: ${JSON.stringify(lead)}` }],
238
+ response_format: { type: "json_object" },
239
+ })
240
+ const result = JSON.parse(response.choices[0].message.content)
241
+ ```
242
+
243
+ ```typescript
244
+ // ai-functions
245
+ const { qualified, score, nextStep } = ai`analyze lead: ${lead}`
246
+ ```
247
+
248
+ The second version is what you'd say to a colleague. That's the goal.
249
+
250
+ ## Related Packages
251
+
252
+ - [`ai-database`](../ai-database) — AI-powered database operations
253
+ - [`ai-providers`](../ai-providers) — Model provider abstraction
254
+ - [`language-models`](../language-models) — Model definitions
package/TODO.md ADDED
@@ -0,0 +1,138 @@
1
+ # ai-functions TODO
2
+
3
+ Changes from README that need implementation in tests/code.
4
+
5
+ ## Function Types System
6
+
7
+ - [ ] Implement 4 function types: `Generative`, `Code`, `Agentic`, `Human`
8
+ - [ ] Type inference from function name + argument names + argument values
9
+ - [ ] Subjective judgment (e.g., `processRefund({ amount: 12.99 })` vs `amount: 50000`)
10
+
11
+ ## Core Architecture
12
+
13
+ - [ ] `generate(type, prompt, opts?)` as the core primitive
14
+ - [ ] Types: `json`, `text`, `code`, `list`, `extract`, `summary`, `diagram`, `slides`, `markdown`, `yaml`, `xml`
15
+ - [ ] Schema support for `json` type
16
+ - [ ] All other functions call `generate` under the hood
17
+ - [ ] `define(name, schema)` - foundation function
18
+ - [ ] Infers function type from name + args
19
+ - [ ] Creates appropriate function (Generative, Code, Agentic, Human)
20
+ - [ ] Caches definition for subsequent calls
21
+ - [ ] `AI({ schemas })` factory for typed instances
22
+
23
+ ## Tagged Template Support
24
+
25
+ - [ ] Every function supports tagged template syntax
26
+ - [ ] Objects/arrays in templates auto-stringify to YAML
27
+ - [ ] Template + options chaining: ``fn`prompt`({ model: '...' })``
28
+
29
+ ## Standalone Exports
30
+
31
+ All functions exported directly (not just on `ai` object):
32
+
33
+ - [ ] `ai` - text generation
34
+ - [ ] `summarize` - condense text
35
+ - [ ] `do` - single-pass task executor with tools (not agentic loop)
36
+ - [ ] `is` - boolean classification
37
+ - [ ] `list` - generate list
38
+ - [ ] `lists` - multiple named lists
39
+ - [ ] `extract` - extract from text
40
+ - [ ] `write` - generate content
41
+ - [ ] `generate` - core primitive
42
+ - [ ] `decide` - LLM as judge, picks from options
43
+ - [ ] `code` - generate code
44
+ - [ ] `diagram` - generate diagrams (mermaid, etc.)
45
+ - [ ] `slides` - generate presentations (slidev, marp, reveal.js)
46
+ - [ ] `image` - generate images
47
+ - [ ] `video` - generate videos
48
+ - [ ] `research` - agentic research
49
+ - [ ] `read` - URL to markdown (Firecrawl)
50
+ - [ ] `browse` - browser automation (Stagehand/Browserbase)
51
+ - [ ] `page.extract` - extract data from page
52
+ - [ ] `page.do` - perform action on page
53
+
54
+ ## Magic Proxy (`ai.*`)
55
+
56
+ - [ ] `ai.anyFunctionName(args)` auto-defines on first call
57
+ - [ ] Infers function type from name + args
58
+ - [ ] Examples:
59
+ - [ ] `ai.fizzBuzz()` → CodeFunction
60
+ - [ ] `ai.storyBrand()` → GenerativeFunction with schema
61
+ - [ ] `ai.launchProductHunt()` → AgenticFunction
62
+ - [ ] `ai.approveExpense()` → HumanFunction
63
+
64
+ ## Human Functions
65
+
66
+ - [ ] `ask` - ask human a question
67
+ - [ ] `approve` - request human approval
68
+ - [ ] `review` - request human review
69
+ - [ ] Integration with `human-in-the-loop`, `digital-workers`, `autonomous-agents` packages
70
+
71
+ ## Async Iterators
72
+
73
+ - [ ] `list` returns `AsyncIterable` for streaming
74
+ - [ ] `extract` returns `AsyncIterable` for streaming
75
+ - [ ] `for await (const item of list`...`)` pattern
76
+ - [ ] Early termination with `break`
77
+
78
+ ## `decide` - LLM as Judge
79
+
80
+ - [ ] Syntax: ``decide`criteria`(optionA, optionB, ...)``
81
+ - [ ] Returns the winning option (same type as inputs)
82
+ - [ ] Type-safe: passing `Product` objects returns `Product`
83
+
84
+ ## Options Parameter
85
+
86
+ Every function accepts options as last parameter:
87
+
88
+ - [ ] `model` - model selection
89
+ - [ ] `thinking` - `'low' | 'medium' | 'high' | number` (token budget)
90
+ - [ ] `temperature`
91
+ - [ ] `maxTokens`
92
+
93
+ ## Batch & Background Processing
94
+
95
+ - [ ] Background mode: `{ mode: 'background' }` returns job immediately
96
+ - [ ] `job.result()` to get result later
97
+ - [ ] `job.status` for status
98
+ - [ ] Batch mode: `fn.batch([contexts])`
99
+ - [ ] Better pricing (50% off on OpenAI)
100
+ - [ ] Processes all at once
101
+ - [ ] Batch streaming: `fn.batch.stream([contexts])`
102
+ - [ ] `for await` as results complete
103
+
104
+ ## Integration with Other Packages
105
+
106
+ - [ ] `ai-sandbox` - `evaluate({ code, tests, module, script })` for CodeFunctions
107
+ - [ ] `ai-database` - `embed` moved there, used by `db.search()`
108
+ - [ ] `ai-providers` / `language-models` - model resolution
109
+ - [ ] `human-in-the-loop` - Human function implementation
110
+ - [ ] `autonomous-agents` - Agent loop (vs single-pass `do`)
111
+
112
+ ## Type System
113
+
114
+ - [ ] `AIFunction<TArgs, TReturn>` - callable + tagged template
115
+ - [ ] Schema syntax parsing:
116
+ - [ ] `'description'` → string
117
+ - [ ] `'desc (number)'` → number
118
+ - [ ] `'desc (boolean)'` → boolean
119
+ - [ ] `'opt1 | opt2'` → enum
120
+ - [ ] `['description']` → array
121
+ - [ ] `{ nested }` → object
122
+ - [ ] Type inference for `AI()` factory schemas
123
+
124
+ ## Tests to Write
125
+
126
+ - [ ] Tagged template parsing and YAML conversion
127
+ - [ ] Each function type (Generative, Code, Agentic, Human)
128
+ - [ ] Function type inference from name + args
129
+ - [ ] `generate` with all type options
130
+ - [ ] `define` creating correct function types
131
+ - [ ] Magic proxy auto-definition
132
+ - [ ] Async iterators on `list` and `extract`
133
+ - [ ] `decide` returning correct option
134
+ - [ ] Batch and background modes
135
+ - [ ] Options parameter (model, thinking, etc.)
136
+ - [ ] `browse` with `page.extract` and `page.do`
137
+ - [ ] `read` URL fetching
138
+ - [ ] `research` agentic flow