ai-functions 2.1.3 → 2.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 (284) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +90 -1
  3. package/README.md +38 -0
  4. package/dist/ai-promise.d.ts +3 -3
  5. package/dist/ai-promise.d.ts.map +1 -1
  6. package/dist/ai-promise.js +135 -64
  7. package/dist/ai-promise.js.map +1 -1
  8. package/dist/ai-schemas.d.ts +56 -0
  9. package/dist/ai-schemas.d.ts.map +1 -0
  10. package/dist/ai-schemas.js +53 -0
  11. package/dist/ai-schemas.js.map +1 -0
  12. package/dist/ai.d.ts +16 -242
  13. package/dist/ai.d.ts.map +1 -1
  14. package/dist/ai.js +51 -858
  15. package/dist/ai.js.map +1 -1
  16. package/dist/batch/anthropic.d.ts +6 -4
  17. package/dist/batch/anthropic.d.ts.map +1 -1
  18. package/dist/batch/anthropic.js +83 -145
  19. package/dist/batch/anthropic.js.map +1 -1
  20. package/dist/batch/bedrock.d.ts +8 -30
  21. package/dist/batch/bedrock.d.ts.map +1 -1
  22. package/dist/batch/bedrock.js +155 -338
  23. package/dist/batch/bedrock.js.map +1 -1
  24. package/dist/batch/cloudflare.d.ts +8 -20
  25. package/dist/batch/cloudflare.d.ts.map +1 -1
  26. package/dist/batch/cloudflare.js +68 -189
  27. package/dist/batch/cloudflare.js.map +1 -1
  28. package/dist/batch/google.d.ts +6 -20
  29. package/dist/batch/google.d.ts.map +1 -1
  30. package/dist/batch/google.js +70 -238
  31. package/dist/batch/google.js.map +1 -1
  32. package/dist/batch/index.d.ts +4 -1
  33. package/dist/batch/index.d.ts.map +1 -1
  34. package/dist/batch/index.js +4 -1
  35. package/dist/batch/index.js.map +1 -1
  36. package/dist/batch/memory.d.ts +1 -1
  37. package/dist/batch/memory.d.ts.map +1 -1
  38. package/dist/batch/memory.js +14 -10
  39. package/dist/batch/memory.js.map +1 -1
  40. package/dist/batch/openai.d.ts +11 -14
  41. package/dist/batch/openai.d.ts.map +1 -1
  42. package/dist/batch/openai.js +52 -156
  43. package/dist/batch/openai.js.map +1 -1
  44. package/dist/batch/provider.d.ts +111 -0
  45. package/dist/batch/provider.d.ts.map +1 -0
  46. package/dist/batch/provider.js +233 -0
  47. package/dist/batch/provider.js.map +1 -0
  48. package/dist/batch-map.d.ts.map +1 -1
  49. package/dist/batch-map.js +23 -17
  50. package/dist/batch-map.js.map +1 -1
  51. package/dist/batch-queue.d.ts +65 -0
  52. package/dist/batch-queue.d.ts.map +1 -1
  53. package/dist/batch-queue.js +169 -14
  54. package/dist/batch-queue.js.map +1 -1
  55. package/dist/budget.d.ts.map +1 -1
  56. package/dist/budget.js +27 -14
  57. package/dist/budget.js.map +1 -1
  58. package/dist/cache.d.ts +23 -0
  59. package/dist/cache.d.ts.map +1 -1
  60. package/dist/cache.js +36 -15
  61. package/dist/cache.js.map +1 -1
  62. package/dist/context.d.ts +26 -8
  63. package/dist/context.d.ts.map +1 -1
  64. package/dist/context.js +64 -62
  65. package/dist/context.js.map +1 -1
  66. package/dist/digital-objects-registry.d.ts +229 -0
  67. package/dist/digital-objects-registry.d.ts.map +1 -0
  68. package/dist/digital-objects-registry.js +617 -0
  69. package/dist/digital-objects-registry.js.map +1 -0
  70. package/dist/embeddings.d.ts +2 -2
  71. package/dist/embeddings.d.ts.map +1 -1
  72. package/dist/errors.d.ts +22 -0
  73. package/dist/errors.d.ts.map +1 -0
  74. package/dist/errors.js +35 -0
  75. package/dist/errors.js.map +1 -0
  76. package/dist/eval/runner.d.ts +8 -0
  77. package/dist/eval/runner.d.ts.map +1 -1
  78. package/dist/eval/runner.js +41 -35
  79. package/dist/eval/runner.js.map +1 -1
  80. package/dist/eval-log/in-memory.d.ts +34 -0
  81. package/dist/eval-log/in-memory.d.ts.map +1 -0
  82. package/dist/eval-log/in-memory.js +84 -0
  83. package/dist/eval-log/in-memory.js.map +1 -0
  84. package/dist/eval-log/index.d.ts +29 -0
  85. package/dist/eval-log/index.d.ts.map +1 -0
  86. package/dist/eval-log/index.js +39 -0
  87. package/dist/eval-log/index.js.map +1 -0
  88. package/dist/eval-log/types.d.ts +101 -0
  89. package/dist/eval-log/types.d.ts.map +1 -0
  90. package/dist/eval-log/types.js +16 -0
  91. package/dist/eval-log/types.js.map +1 -0
  92. package/dist/function-registry.d.ts +176 -0
  93. package/dist/function-registry.d.ts.map +1 -0
  94. package/dist/function-registry.js +685 -0
  95. package/dist/function-registry.js.map +1 -0
  96. package/dist/generate.d.ts +9 -3
  97. package/dist/generate.d.ts.map +1 -1
  98. package/dist/generate.js +18 -18
  99. package/dist/generate.js.map +1 -1
  100. package/dist/index.d.ts +18 -11
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/index.js +35 -18
  103. package/dist/index.js.map +1 -1
  104. package/dist/logger.d.ts +118 -0
  105. package/dist/logger.d.ts.map +1 -0
  106. package/dist/logger.js +187 -0
  107. package/dist/logger.js.map +1 -0
  108. package/dist/middleware/budget.d.ts +84 -0
  109. package/dist/middleware/budget.d.ts.map +1 -0
  110. package/dist/middleware/budget.js +110 -0
  111. package/dist/middleware/budget.js.map +1 -0
  112. package/dist/middleware/cache.d.ts +103 -0
  113. package/dist/middleware/cache.d.ts.map +1 -0
  114. package/dist/middleware/cache.js +228 -0
  115. package/dist/middleware/cache.js.map +1 -0
  116. package/dist/middleware/embed-cache.d.ts +99 -0
  117. package/dist/middleware/embed-cache.d.ts.map +1 -0
  118. package/dist/middleware/embed-cache.js +128 -0
  119. package/dist/middleware/embed-cache.js.map +1 -0
  120. package/dist/middleware/index.d.ts +11 -0
  121. package/dist/middleware/index.d.ts.map +1 -0
  122. package/dist/middleware/index.js +11 -0
  123. package/dist/middleware/index.js.map +1 -0
  124. package/dist/middleware/trace.d.ts +103 -0
  125. package/dist/middleware/trace.d.ts.map +1 -0
  126. package/dist/middleware/trace.js +176 -0
  127. package/dist/middleware/trace.js.map +1 -0
  128. package/dist/primitives.d.ts +120 -1
  129. package/dist/primitives.d.ts.map +1 -1
  130. package/dist/primitives.js +398 -26
  131. package/dist/primitives.js.map +1 -1
  132. package/dist/retry.d.ts +66 -1
  133. package/dist/retry.d.ts.map +1 -1
  134. package/dist/retry.js +115 -8
  135. package/dist/retry.js.map +1 -1
  136. package/dist/sandbox.d.ts +36 -0
  137. package/dist/sandbox.d.ts.map +1 -0
  138. package/dist/sandbox.js +44 -0
  139. package/dist/sandbox.js.map +1 -0
  140. package/dist/schema.js +2 -2
  141. package/dist/schema.js.map +1 -1
  142. package/dist/telemetry.d.ts +128 -0
  143. package/dist/telemetry.d.ts.map +1 -0
  144. package/dist/telemetry.js +285 -0
  145. package/dist/telemetry.js.map +1 -0
  146. package/dist/template.d.ts.map +1 -1
  147. package/dist/template.js +6 -1
  148. package/dist/template.js.map +1 -1
  149. package/dist/tool-orchestration.d.ts +66 -4
  150. package/dist/tool-orchestration.d.ts.map +1 -1
  151. package/dist/tool-orchestration.js +123 -23
  152. package/dist/tool-orchestration.js.map +1 -1
  153. package/dist/type-guards.d.ts +28 -0
  154. package/dist/type-guards.d.ts.map +1 -0
  155. package/dist/type-guards.js +29 -0
  156. package/dist/type-guards.js.map +1 -0
  157. package/dist/types.d.ts +155 -19
  158. package/dist/types.d.ts.map +1 -1
  159. package/dist/types.js +36 -1
  160. package/dist/types.js.map +1 -1
  161. package/dist/wrap-for-v3.d.ts +80 -0
  162. package/dist/wrap-for-v3.d.ts.map +1 -0
  163. package/dist/wrap-for-v3.js +89 -0
  164. package/dist/wrap-for-v3.js.map +1 -0
  165. package/examples/00-quickstart.ts +232 -0
  166. package/examples/01-rag-chatbot.ts +212 -0
  167. package/examples/02-multi-agent-research.ts +290 -0
  168. package/examples/03-email-classification.ts +379 -0
  169. package/examples/04-content-moderation.ts +400 -0
  170. package/examples/05-document-extraction.ts +455 -0
  171. package/examples/06-streaming-chat-nextjs.ts +437 -0
  172. package/examples/07-cloudflare-worker.ts +483 -0
  173. package/examples/08-batch-processing.ts +491 -0
  174. package/examples/09-budget-constrained.ts +527 -0
  175. package/examples/10-tool-orchestration.ts +565 -0
  176. package/examples/11-retry-resilience.ts +403 -0
  177. package/examples/12-caching-strategies.ts +422 -0
  178. package/examples/README.md +145 -0
  179. package/package.json +29 -25
  180. package/src/ai-promise.ts +226 -140
  181. package/src/ai-schemas.ts +122 -0
  182. package/src/ai.ts +71 -1176
  183. package/src/batch/anthropic.ts +96 -161
  184. package/src/batch/bedrock.ts +203 -454
  185. package/src/batch/cloudflare.ts +99 -282
  186. package/src/batch/google.ts +91 -297
  187. package/src/batch/index.ts +4 -1
  188. package/src/batch/memory.ts +15 -10
  189. package/src/batch/openai.ts +65 -193
  190. package/src/batch/provider.ts +336 -0
  191. package/src/batch-map.ts +29 -24
  192. package/src/batch-queue.ts +200 -11
  193. package/src/budget.ts +31 -18
  194. package/src/cache.ts +45 -17
  195. package/src/context.ts +106 -77
  196. package/src/digital-objects-registry.ts +750 -0
  197. package/src/errors.ts +37 -0
  198. package/src/eval/runner.ts +60 -36
  199. package/src/eval-log/in-memory.ts +90 -0
  200. package/src/eval-log/index.ts +46 -0
  201. package/src/eval-log/types.ts +110 -0
  202. package/src/function-registry.ts +874 -0
  203. package/src/generate.ts +33 -28
  204. package/src/index.ts +122 -21
  205. package/src/logger.ts +232 -0
  206. package/src/middleware/budget.ts +171 -0
  207. package/src/middleware/cache.ts +299 -0
  208. package/src/middleware/embed-cache.ts +195 -0
  209. package/src/middleware/index.ts +23 -0
  210. package/src/middleware/trace.ts +248 -0
  211. package/src/primitives.ts +589 -62
  212. package/src/retry.ts +144 -18
  213. package/src/sandbox.ts +52 -0
  214. package/src/schema.ts +8 -8
  215. package/src/telemetry.ts +403 -0
  216. package/src/template.ts +8 -4
  217. package/src/tool-orchestration.ts +213 -48
  218. package/src/type-guards.ts +31 -0
  219. package/src/types.ts +186 -27
  220. package/src/wrap-for-v3.ts +105 -0
  221. package/test/ai-promise.test.ts +1080 -0
  222. package/test/ai-proxy.test.ts +1 -1
  223. package/test/batch-autosubmit-errors.test.ts +49 -37
  224. package/test/batch-blog-posts.test.ts +87 -129
  225. package/test/core-functions.test.ts +183 -579
  226. package/test/decide.test.ts +154 -322
  227. package/test/define.test.ts +211 -8
  228. package/test/digital-objects-registry.test.ts +760 -0
  229. package/test/embedding-cache-middleware.test.ts +140 -0
  230. package/test/fill-template.test.ts +89 -0
  231. package/test/generate-core.test.ts +140 -229
  232. package/test/implicit-batch.test.ts +22 -65
  233. package/test/retry-policy-integration.test.ts +117 -0
  234. package/test/sandbox-execution.test.ts +155 -0
  235. package/test/schema.test.ts +55 -19
  236. package/test/template.test.ts +1164 -0
  237. package/test/tool-orchestration.test.ts +270 -0
  238. package/test/wrap-for-v3.test.ts +612 -0
  239. package/vitest.config.js +6 -0
  240. package/vitest.config.ts +20 -0
  241. package/LICENSE +0 -21
  242. package/dist/rpc/auth.d.ts +0 -69
  243. package/dist/rpc/auth.d.ts.map +0 -1
  244. package/dist/rpc/auth.js +0 -136
  245. package/dist/rpc/auth.js.map +0 -1
  246. package/dist/rpc/client.d.ts +0 -62
  247. package/dist/rpc/client.d.ts.map +0 -1
  248. package/dist/rpc/client.js +0 -103
  249. package/dist/rpc/client.js.map +0 -1
  250. package/dist/rpc/deferred.d.ts +0 -60
  251. package/dist/rpc/deferred.d.ts.map +0 -1
  252. package/dist/rpc/deferred.js +0 -96
  253. package/dist/rpc/deferred.js.map +0 -1
  254. package/dist/rpc/index.d.ts +0 -22
  255. package/dist/rpc/index.d.ts.map +0 -1
  256. package/dist/rpc/index.js +0 -38
  257. package/dist/rpc/index.js.map +0 -1
  258. package/dist/rpc/local.d.ts +0 -42
  259. package/dist/rpc/local.d.ts.map +0 -1
  260. package/dist/rpc/local.js +0 -50
  261. package/dist/rpc/local.js.map +0 -1
  262. package/dist/rpc/server.d.ts +0 -165
  263. package/dist/rpc/server.d.ts.map +0 -1
  264. package/dist/rpc/server.js +0 -405
  265. package/dist/rpc/server.js.map +0 -1
  266. package/dist/rpc/session.d.ts +0 -32
  267. package/dist/rpc/session.d.ts.map +0 -1
  268. package/dist/rpc/session.js +0 -43
  269. package/dist/rpc/session.js.map +0 -1
  270. package/dist/rpc/transport.d.ts +0 -306
  271. package/dist/rpc/transport.d.ts.map +0 -1
  272. package/dist/rpc/transport.js +0 -731
  273. package/dist/rpc/transport.js.map +0 -1
  274. package/src/batch/anthropic.js +0 -256
  275. package/src/batch/bedrock.js +0 -584
  276. package/src/batch/cloudflare.js +0 -287
  277. package/src/batch/google.js +0 -359
  278. package/src/batch/index.js +0 -30
  279. package/src/batch/memory.js +0 -187
  280. package/src/batch/openai.js +0 -402
  281. package/src/eval/index.js +0 -7
  282. package/src/eval/models.js +0 -119
  283. package/src/eval/runner.js +0 -147
  284. package/test/schema.test.js +0 -96
@@ -0,0 +1,379 @@
1
+ /**
2
+ * Email Classification and Routing Example
3
+ *
4
+ * This example demonstrates building an email classification and routing system
5
+ * using ai-functions. It shows how to:
6
+ * - Classify emails into categories
7
+ * - Extract key information from emails
8
+ * - Route to appropriate handlers
9
+ * - Handle priority and urgency
10
+ *
11
+ * @example
12
+ * ```bash
13
+ * ANTHROPIC_API_KEY=sk-... npx tsx examples/03-email-classification.ts
14
+ * ```
15
+ */
16
+
17
+ import { ai, is, list, extract, configure, decide } from '../src/index.js'
18
+
19
+ // ============================================================================
20
+ // Types
21
+ // ============================================================================
22
+
23
+ interface Email {
24
+ id: string
25
+ from: string
26
+ to: string
27
+ subject: string
28
+ body: string
29
+ timestamp: Date
30
+ }
31
+
32
+ interface ClassificationResult {
33
+ category: string
34
+ subcategory: string
35
+ priority: 'low' | 'medium' | 'high' | 'urgent'
36
+ sentiment: 'positive' | 'neutral' | 'negative'
37
+ requiresResponse: boolean
38
+ suggestedTeam: string
39
+ }
40
+
41
+ interface ExtractedInfo {
42
+ senderIntent: string
43
+ keyEntities: string[]
44
+ actionItems: string[]
45
+ deadlines: string[]
46
+ attachmentReferences: string[]
47
+ }
48
+
49
+ interface RoutingDecision {
50
+ team: string
51
+ handler: string
52
+ autoResponse: boolean
53
+ escalate: boolean
54
+ suggestedResponse?: string
55
+ }
56
+
57
+ // ============================================================================
58
+ // Sample Emails
59
+ // ============================================================================
60
+
61
+ const sampleEmails: Email[] = [
62
+ {
63
+ id: 'email-1',
64
+ from: 'john.smith@bigcorp.com',
65
+ to: 'sales@ourcompany.com',
66
+ subject: 'Enterprise License Inquiry - 500 seats',
67
+ body: `Hi,
68
+
69
+ We are interested in your enterprise solution for our organization.
70
+ We have approximately 500 developers who would need access.
71
+
72
+ Could you please provide:
73
+ 1. Enterprise pricing for 500 seats
74
+ 2. Volume discount options
75
+ 3. Security compliance certifications (SOC2, HIPAA)
76
+ 4. On-premise deployment options
77
+
78
+ We're looking to make a decision within the next 2 weeks.
79
+
80
+ Best regards,
81
+ John Smith
82
+ VP of Engineering, BigCorp Inc.`,
83
+ timestamp: new Date(),
84
+ },
85
+ {
86
+ id: 'email-2',
87
+ from: 'frustrated.user@example.com',
88
+ to: 'support@ourcompany.com',
89
+ subject: 'URGENT: System down - Production blocked!',
90
+ body: `Our production system has been down for 3 hours!!!
91
+
92
+ Error: "Connection timeout to API endpoint"
93
+
94
+ We're losing thousands of dollars per hour. We need immediate assistance.
95
+ Our contract includes 24/7 premium support.
96
+
97
+ Account ID: ENT-12345
98
+ Contact: 555-123-4567
99
+
100
+ This needs to be fixed NOW.`,
101
+ timestamp: new Date(),
102
+ },
103
+ {
104
+ id: 'email-3',
105
+ from: 'newsletter@techblog.com',
106
+ to: 'team@ourcompany.com',
107
+ subject: 'Weekly AI Newsletter - Top Stories',
108
+ body: `This week in AI:
109
+
110
+ - GPT-5 rumors continue to swirl
111
+ - New open-source models released
112
+ - Industry adoption trends
113
+
114
+ Click to read more...
115
+
116
+ Unsubscribe: techblog.com/unsubscribe`,
117
+ timestamp: new Date(),
118
+ },
119
+ {
120
+ id: 'email-4',
121
+ from: 'hr@ourcompany.com',
122
+ to: 'team@ourcompany.com',
123
+ subject: 'Company All-Hands Meeting - Friday 3pm',
124
+ body: `Hi everyone,
125
+
126
+ Reminder: Our monthly all-hands meeting is this Friday at 3pm.
127
+
128
+ Agenda:
129
+ - Q4 Results Review
130
+ - 2025 Planning
131
+ - Team Awards
132
+
133
+ Please submit any questions beforehand.
134
+
135
+ Best,
136
+ HR Team`,
137
+ timestamp: new Date(),
138
+ },
139
+ ]
140
+
141
+ // ============================================================================
142
+ // Email Classifier
143
+ // ============================================================================
144
+
145
+ async function classifyEmail(email: Email): Promise<ClassificationResult> {
146
+ console.log(`\nClassifying: "${email.subject}"`)
147
+
148
+ const { category, subcategory, priority, sentiment, requiresResponse, suggestedTeam } =
149
+ await ai`Classify this email:
150
+
151
+ From: ${email.from}
152
+ Subject: ${email.subject}
153
+ Body: ${email.body}
154
+
155
+ Provide:
156
+ - category: one of [sales, support, marketing, internal, spam, other]
157
+ - subcategory: more specific classification
158
+ - priority: one of [low, medium, high, urgent]
159
+ - sentiment: one of [positive, neutral, negative]
160
+ - requiresResponse: boolean - does this need a reply?
161
+ - suggestedTeam: which team should handle this`
162
+
163
+ return {
164
+ category: category as string,
165
+ subcategory: subcategory as string,
166
+ priority: priority as 'low' | 'medium' | 'high' | 'urgent',
167
+ sentiment: sentiment as 'positive' | 'neutral' | 'negative',
168
+ requiresResponse: requiresResponse as boolean,
169
+ suggestedTeam: suggestedTeam as string,
170
+ }
171
+ }
172
+
173
+ // ============================================================================
174
+ // Information Extractor
175
+ // ============================================================================
176
+
177
+ async function extractInfo(email: Email): Promise<ExtractedInfo> {
178
+ console.log(` Extracting key information...`)
179
+
180
+ const { senderIntent, keyEntities, actionItems, deadlines, attachmentReferences } =
181
+ await ai`Extract key information from this email:
182
+
183
+ Subject: ${email.subject}
184
+ Body: ${email.body}
185
+
186
+ Provide:
187
+ - senderIntent: what the sender wants (1 sentence)
188
+ - keyEntities: array of important entities (names, companies, products, account IDs)
189
+ - actionItems: array of action items or requests
190
+ - deadlines: array of mentioned deadlines or timeframes
191
+ - attachmentReferences: any references to attachments or documents`
192
+
193
+ return {
194
+ senderIntent: senderIntent as string,
195
+ keyEntities: keyEntities as string[],
196
+ actionItems: actionItems as string[],
197
+ deadlines: deadlines as string[],
198
+ attachmentReferences: attachmentReferences as string[],
199
+ }
200
+ }
201
+
202
+ // ============================================================================
203
+ // Router
204
+ // ============================================================================
205
+
206
+ async function routeEmail(
207
+ email: Email,
208
+ classification: ClassificationResult,
209
+ info: ExtractedInfo
210
+ ): Promise<RoutingDecision> {
211
+ console.log(` Determining routing...`)
212
+
213
+ // Check if escalation is needed
214
+ const needsEscalation = await is`This email requires immediate escalation to management:
215
+ Category: ${classification.category}
216
+ Priority: ${classification.priority}
217
+ Sentiment: ${classification.sentiment}
218
+ Intent: ${info.senderIntent}`
219
+
220
+ // Determine if auto-response is appropriate
221
+ const canAutoRespond = await is`This email can be handled with an automated response:
222
+ Category: ${classification.category}
223
+ Intent: ${info.senderIntent}
224
+ Action Items: ${info.actionItems.join(', ')}`
225
+
226
+ // Route based on category
227
+ const routingMap: Record<string, { team: string; handler: string }> = {
228
+ sales: { team: 'Sales', handler: 'sales-queue' },
229
+ support: {
230
+ team: 'Support',
231
+ handler: classification.priority === 'urgent' ? 'urgent-queue' : 'support-queue',
232
+ },
233
+ marketing: { team: 'Marketing', handler: 'marketing-inbox' },
234
+ internal: { team: 'Internal', handler: 'internal-comms' },
235
+ spam: { team: 'None', handler: 'spam-filter' },
236
+ other: { team: 'Triage', handler: 'general-queue' },
237
+ }
238
+
239
+ const route = routingMap[classification.category] || routingMap.other
240
+
241
+ let suggestedResponse: string | undefined
242
+ if (canAutoRespond) {
243
+ suggestedResponse = await generateAutoResponse(email, classification, info)
244
+ }
245
+
246
+ return {
247
+ team: route.team,
248
+ handler: route.handler,
249
+ autoResponse: canAutoRespond,
250
+ escalate: needsEscalation,
251
+ suggestedResponse,
252
+ }
253
+ }
254
+
255
+ // ============================================================================
256
+ // Auto-Response Generator
257
+ // ============================================================================
258
+
259
+ async function generateAutoResponse(
260
+ email: Email,
261
+ classification: ClassificationResult,
262
+ info: ExtractedInfo
263
+ ): Promise<string> {
264
+ console.log(` Generating auto-response...`)
265
+
266
+ const response = await ai`Generate a brief, professional auto-response for this email:
267
+
268
+ Original Subject: ${email.subject}
269
+ Category: ${classification.category}
270
+ Sender Intent: ${info.senderIntent}
271
+
272
+ The response should:
273
+ - Acknowledge receipt
274
+ - Set expectations for response time
275
+ - Provide any immediately helpful information
276
+ - Be concise (3-4 sentences max)
277
+
278
+ Return just the response text.`
279
+
280
+ return response as string
281
+ }
282
+
283
+ // ============================================================================
284
+ // Batch Classification
285
+ // ============================================================================
286
+
287
+ async function batchClassifyEmails(emails: Email[]): Promise<void> {
288
+ console.log(`\n${'='.repeat(60)}`)
289
+ console.log('Batch Email Classification Results')
290
+ console.log('='.repeat(60))
291
+
292
+ for (const email of emails) {
293
+ const classification = await classifyEmail(email)
294
+ const info = await extractInfo(email)
295
+ const routing = await routeEmail(email, classification, info)
296
+
297
+ console.log(`
298
+ ID: ${email.id}
299
+ Subject: ${email.subject}
300
+ ---
301
+ Classification:
302
+ Category: ${classification.category} / ${classification.subcategory}
303
+ Priority: ${classification.priority}
304
+ Sentiment: ${classification.sentiment}
305
+ Requires Response: ${classification.requiresResponse}
306
+
307
+ Extracted Info:
308
+ Intent: ${info.senderIntent}
309
+ Entities: ${info.keyEntities.join(', ') || 'none'}
310
+ Action Items: ${info.actionItems.length}
311
+ Deadlines: ${info.deadlines.join(', ') || 'none'}
312
+
313
+ Routing:
314
+ Team: ${routing.team}
315
+ Handler: ${routing.handler}
316
+ Auto-Response: ${routing.autoResponse}
317
+ Escalate: ${routing.escalate}
318
+ ${
319
+ routing.suggestedResponse
320
+ ? `\nSuggested Response:\n "${routing.suggestedResponse.substring(0, 100)}..."`
321
+ : ''
322
+ }
323
+ ${'='.repeat(60)}`)
324
+ }
325
+ }
326
+
327
+ // ============================================================================
328
+ // Priority Comparison
329
+ // ============================================================================
330
+
331
+ async function prioritizeEmails(emails: Email[]): Promise<Email[]> {
332
+ console.log('\n--- Prioritizing Emails ---')
333
+
334
+ // Use decide to compare email urgency
335
+ if (emails.length < 2) return emails
336
+
337
+ // For demo, just compare first two
338
+ const moreUrgent = await decide`which email is more urgent and should be handled first`(
339
+ { subject: emails[0].subject, body: emails[0].body.substring(0, 100) },
340
+ { subject: emails[1].subject, body: emails[1].body.substring(0, 100) }
341
+ )
342
+
343
+ console.log(`Most urgent: "${(moreUrgent as Email).subject}"`)
344
+ return emails
345
+ }
346
+
347
+ // ============================================================================
348
+ // Main Example
349
+ // ============================================================================
350
+
351
+ async function main() {
352
+ console.log('\n=== Email Classification & Routing Example ===\n')
353
+
354
+ // Configure the AI provider
355
+ configure({
356
+ model: 'sonnet',
357
+ provider: 'anthropic',
358
+ })
359
+
360
+ // Process all sample emails
361
+ await batchClassifyEmails(sampleEmails)
362
+
363
+ // Prioritize emails
364
+ await prioritizeEmails(sampleEmails.slice(0, 2))
365
+
366
+ // Show statistics
367
+ console.log('\n--- Processing Statistics ---')
368
+ console.log(`Total emails processed: ${sampleEmails.length}`)
369
+ }
370
+
371
+ main()
372
+ .then(() => {
373
+ console.log('\n=== Example Complete ===\n')
374
+ process.exit(0)
375
+ })
376
+ .catch((error) => {
377
+ console.error('\nError:', error.message)
378
+ process.exit(1)
379
+ })