@od-oneapp/analytics 2026.1.1301

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 (184) hide show
  1. package/README.md +509 -0
  2. package/dist/ai-YMnynb-t.mjs +3347 -0
  3. package/dist/ai-YMnynb-t.mjs.map +1 -0
  4. package/dist/chunk-DQk6qfdC.mjs +18 -0
  5. package/dist/client-CTzJVFU5.mjs +9 -0
  6. package/dist/client-CTzJVFU5.mjs.map +1 -0
  7. package/dist/client-CcFTauAh.mjs +54 -0
  8. package/dist/client-CcFTauAh.mjs.map +1 -0
  9. package/dist/client-CeOLjbac.mjs +281 -0
  10. package/dist/client-CeOLjbac.mjs.map +1 -0
  11. package/dist/client-D339NFJS.mjs +267 -0
  12. package/dist/client-D339NFJS.mjs.map +1 -0
  13. package/dist/client-next.d.mts +62 -0
  14. package/dist/client-next.d.mts.map +1 -0
  15. package/dist/client-next.mjs +525 -0
  16. package/dist/client-next.mjs.map +1 -0
  17. package/dist/client.d.mts +30 -0
  18. package/dist/client.d.mts.map +1 -0
  19. package/dist/client.mjs +186 -0
  20. package/dist/client.mjs.map +1 -0
  21. package/dist/config-DPS6bSYo.d.mts +34 -0
  22. package/dist/config-DPS6bSYo.d.mts.map +1 -0
  23. package/dist/config-P6P5adJg.mjs +287 -0
  24. package/dist/config-P6P5adJg.mjs.map +1 -0
  25. package/dist/console-8bND3mMU.mjs +128 -0
  26. package/dist/console-8bND3mMU.mjs.map +1 -0
  27. package/dist/ecommerce-Cgu4wlux.mjs +993 -0
  28. package/dist/ecommerce-Cgu4wlux.mjs.map +1 -0
  29. package/dist/emitters-6-nKo8i-.mjs +208 -0
  30. package/dist/emitters-6-nKo8i-.mjs.map +1 -0
  31. package/dist/emitters-DldkVSPp.d.mts +12 -0
  32. package/dist/emitters-DldkVSPp.d.mts.map +1 -0
  33. package/dist/index-BfNWgfa5.d.mts +1494 -0
  34. package/dist/index-BfNWgfa5.d.mts.map +1 -0
  35. package/dist/index-BkIWe--N.d.mts +953 -0
  36. package/dist/index-BkIWe--N.d.mts.map +1 -0
  37. package/dist/index-jPzXRn52.d.mts +184 -0
  38. package/dist/index-jPzXRn52.d.mts.map +1 -0
  39. package/dist/manager-DvRRjza6.d.mts +76 -0
  40. package/dist/manager-DvRRjza6.d.mts.map +1 -0
  41. package/dist/posthog-bootstrap-CYfIy_WS.mjs +1769 -0
  42. package/dist/posthog-bootstrap-CYfIy_WS.mjs.map +1 -0
  43. package/dist/posthog-bootstrap-DWxFrxlt.d.mts +81 -0
  44. package/dist/posthog-bootstrap-DWxFrxlt.d.mts.map +1 -0
  45. package/dist/providers-http-client.d.mts +37 -0
  46. package/dist/providers-http-client.d.mts.map +1 -0
  47. package/dist/providers-http-client.mjs +320 -0
  48. package/dist/providers-http-client.mjs.map +1 -0
  49. package/dist/providers-http-server.d.mts +31 -0
  50. package/dist/providers-http-server.d.mts.map +1 -0
  51. package/dist/providers-http-server.mjs +297 -0
  52. package/dist/providers-http-server.mjs.map +1 -0
  53. package/dist/providers-http.d.mts +46 -0
  54. package/dist/providers-http.d.mts.map +1 -0
  55. package/dist/providers-http.mjs +4 -0
  56. package/dist/server-edge.d.mts +9 -0
  57. package/dist/server-edge.d.mts.map +1 -0
  58. package/dist/server-edge.mjs +373 -0
  59. package/dist/server-edge.mjs.map +1 -0
  60. package/dist/server-next.d.mts +67 -0
  61. package/dist/server-next.d.mts.map +1 -0
  62. package/dist/server-next.mjs +193 -0
  63. package/dist/server-next.mjs.map +1 -0
  64. package/dist/server.d.mts +10 -0
  65. package/dist/server.mjs +7 -0
  66. package/dist/service-cYtBBL8x.mjs +945 -0
  67. package/dist/service-cYtBBL8x.mjs.map +1 -0
  68. package/dist/shared.d.mts +16 -0
  69. package/dist/shared.d.mts.map +1 -0
  70. package/dist/shared.mjs +93 -0
  71. package/dist/shared.mjs.map +1 -0
  72. package/dist/types-BxBnNQ0V.d.mts +354 -0
  73. package/dist/types-BxBnNQ0V.d.mts.map +1 -0
  74. package/dist/types-CBvxUEaF.d.mts +216 -0
  75. package/dist/types-CBvxUEaF.d.mts.map +1 -0
  76. package/dist/types.d.mts +4 -0
  77. package/dist/types.mjs +0 -0
  78. package/dist/vercel-types-lwakUfoI.d.mts +102 -0
  79. package/dist/vercel-types-lwakUfoI.d.mts.map +1 -0
  80. package/package.json +129 -0
  81. package/src/client/index.ts +164 -0
  82. package/src/client/manager.ts +71 -0
  83. package/src/client/next/components.tsx +270 -0
  84. package/src/client/next/hooks.ts +217 -0
  85. package/src/client/next/manager.ts +141 -0
  86. package/src/client/next.ts +144 -0
  87. package/src/client-next.ts +101 -0
  88. package/src/client.ts +89 -0
  89. package/src/examples/ai-sdk-patterns.ts +583 -0
  90. package/src/examples/emitter-patterns.ts +476 -0
  91. package/src/examples/nextjs-emitter-patterns.tsx +403 -0
  92. package/src/next/app-router.tsx +564 -0
  93. package/src/next/client.ts +419 -0
  94. package/src/next/index.ts +84 -0
  95. package/src/next/middleware.ts +429 -0
  96. package/src/next/rsc.tsx +300 -0
  97. package/src/next/server.ts +253 -0
  98. package/src/next/types.d.ts +220 -0
  99. package/src/providers/base-provider.ts +419 -0
  100. package/src/providers/console/client.ts +10 -0
  101. package/src/providers/console/index.ts +152 -0
  102. package/src/providers/console/server.ts +6 -0
  103. package/src/providers/console/types.ts +15 -0
  104. package/src/providers/http/client.ts +464 -0
  105. package/src/providers/http/index.ts +30 -0
  106. package/src/providers/http/server.ts +396 -0
  107. package/src/providers/http/types.ts +135 -0
  108. package/src/providers/posthog/client.ts +518 -0
  109. package/src/providers/posthog/index.ts +11 -0
  110. package/src/providers/posthog/server.ts +329 -0
  111. package/src/providers/posthog/types.ts +104 -0
  112. package/src/providers/segment/client.ts +113 -0
  113. package/src/providers/segment/index.ts +11 -0
  114. package/src/providers/segment/server.ts +115 -0
  115. package/src/providers/segment/types.ts +51 -0
  116. package/src/providers/vercel/client.ts +102 -0
  117. package/src/providers/vercel/index.ts +11 -0
  118. package/src/providers/vercel/server.ts +89 -0
  119. package/src/providers/vercel/types.ts +27 -0
  120. package/src/server/index.ts +103 -0
  121. package/src/server/manager.ts +62 -0
  122. package/src/server/next.ts +210 -0
  123. package/src/server-edge.ts +442 -0
  124. package/src/server-next.ts +39 -0
  125. package/src/server.ts +106 -0
  126. package/src/shared/emitters/ai/README.md +981 -0
  127. package/src/shared/emitters/ai/events/agent.ts +130 -0
  128. package/src/shared/emitters/ai/events/artifacts.ts +167 -0
  129. package/src/shared/emitters/ai/events/chat.ts +126 -0
  130. package/src/shared/emitters/ai/events/chatbot-ecommerce.ts +133 -0
  131. package/src/shared/emitters/ai/events/completion.ts +103 -0
  132. package/src/shared/emitters/ai/events/content-generation.ts +347 -0
  133. package/src/shared/emitters/ai/events/conversation.ts +332 -0
  134. package/src/shared/emitters/ai/events/product-features.ts +1402 -0
  135. package/src/shared/emitters/ai/events/streaming.ts +114 -0
  136. package/src/shared/emitters/ai/events/tool.ts +93 -0
  137. package/src/shared/emitters/ai/index.ts +69 -0
  138. package/src/shared/emitters/ai/track-ai-sdk.ts +74 -0
  139. package/src/shared/emitters/ai/track-ai.ts +50 -0
  140. package/src/shared/emitters/ai/types.ts +1041 -0
  141. package/src/shared/emitters/ai/utils.ts +468 -0
  142. package/src/shared/emitters/ecommerce/events/cart-checkout.ts +106 -0
  143. package/src/shared/emitters/ecommerce/events/coupon.ts +49 -0
  144. package/src/shared/emitters/ecommerce/events/engagement.ts +61 -0
  145. package/src/shared/emitters/ecommerce/events/marketplace.ts +119 -0
  146. package/src/shared/emitters/ecommerce/events/order.ts +199 -0
  147. package/src/shared/emitters/ecommerce/events/product.ts +205 -0
  148. package/src/shared/emitters/ecommerce/events/registry.ts +123 -0
  149. package/src/shared/emitters/ecommerce/events/wishlist-sharing.ts +140 -0
  150. package/src/shared/emitters/ecommerce/index.ts +46 -0
  151. package/src/shared/emitters/ecommerce/track-ecommerce.ts +53 -0
  152. package/src/shared/emitters/ecommerce/types.ts +314 -0
  153. package/src/shared/emitters/ecommerce/utils.ts +216 -0
  154. package/src/shared/emitters/emitter-types.ts +974 -0
  155. package/src/shared/emitters/emitters.ts +292 -0
  156. package/src/shared/emitters/helpers.ts +419 -0
  157. package/src/shared/emitters/index.ts +66 -0
  158. package/src/shared/index.ts +142 -0
  159. package/src/shared/ingestion/index.ts +66 -0
  160. package/src/shared/ingestion/schemas.ts +386 -0
  161. package/src/shared/ingestion/service.ts +628 -0
  162. package/src/shared/node22-features.ts +848 -0
  163. package/src/shared/providers/console-provider.ts +160 -0
  164. package/src/shared/types/base-types.ts +54 -0
  165. package/src/shared/types/console-types.ts +19 -0
  166. package/src/shared/types/posthog-types.ts +131 -0
  167. package/src/shared/types/segment-types.ts +15 -0
  168. package/src/shared/types/types.ts +397 -0
  169. package/src/shared/types/vercel-types.ts +19 -0
  170. package/src/shared/utils/config-client.ts +19 -0
  171. package/src/shared/utils/config.ts +250 -0
  172. package/src/shared/utils/emitter-adapter.ts +212 -0
  173. package/src/shared/utils/manager.test.ts +36 -0
  174. package/src/shared/utils/manager.ts +1322 -0
  175. package/src/shared/utils/posthog-bootstrap.ts +136 -0
  176. package/src/shared/utils/posthog-client-utils.ts +48 -0
  177. package/src/shared/utils/posthog-next-utils.ts +282 -0
  178. package/src/shared/utils/posthog-server-utils.ts +210 -0
  179. package/src/shared/utils/rate-limit.ts +289 -0
  180. package/src/shared/utils/security.ts +545 -0
  181. package/src/shared/utils/validation-client.ts +161 -0
  182. package/src/shared/utils/validation.ts +399 -0
  183. package/src/shared.ts +155 -0
  184. package/src/types/index.ts +62 -0
@@ -0,0 +1,583 @@
1
+ /**
2
+ * @fileoverview AI SDK v6 Analytics Tracking Patterns
3
+ * AI SDK v6 Analytics Tracking Patterns
4
+ *
5
+ * Comprehensive examples demonstrating how to track AI SDK v6 operations
6
+ * for agents, completions, tools, streaming, and e-commerce chatbots.
7
+ */
8
+
9
+ import { useId } from 'react';
10
+
11
+ import { logWarn } from '@repo/shared/logger';
12
+ /**
13
+ * NOTE: These imports require optional peer dependencies:
14
+ * - @repo/ai/generation (AI SDK generation utilities)
15
+ * - @repo/ai/ui/react (AI SDK React hooks)
16
+ * - ai (Vercel AI SDK)
17
+ *
18
+ * Install them with: pnpm add ai @ai-sdk/openai
19
+ */
20
+
21
+ // Commented out for type safety - uncomment when dependencies are installed
22
+ // import { Chat } from '@repo/ai/generation';
23
+ // import { useChat } from '@repo/ai/ui/react';
24
+
25
+ import { aiSdk } from '../shared/emitters';
26
+ import {
27
+ agentExecutionCompleted,
28
+ agentExecutionFailed,
29
+ agentExecutionStarted,
30
+ AI_SDK_EVENTS,
31
+ calculateCost,
32
+ generateOperationId,
33
+ trackAISDK,
34
+ } from '../shared/emitters/ai';
35
+
36
+ // Commented out for type safety - uncomment when dependencies are installed
37
+ // import type { Agent } from 'ai';
38
+
39
+ // Placeholder types for example code
40
+ type Agent = any;
41
+
42
+ // Placeholder useChat hook - replace with actual import when AI SDK is installed
43
+ const useChat = (_options: any) => ({
44
+ send: (_text: string) => {},
45
+ messages: [],
46
+ isLoading: false,
47
+ });
48
+
49
+ // =============================================================================
50
+ // Pattern 1: Basic Agent Execution Tracking
51
+ // =============================================================================
52
+
53
+ export async function basicAgentTracking(agent: Agent, prompt: string) {
54
+ const agentId = 'customer-support-agent';
55
+ const startTime = Date.now();
56
+
57
+ try {
58
+ // Track agent start
59
+ agentExecutionStarted({
60
+ model_id: 'claude-3-5-sonnet',
61
+ agent_id: agentId,
62
+ agent_name: 'Customer Support Agent',
63
+ });
64
+
65
+ // Execute agent
66
+ const result = await agent.generate({ prompt });
67
+
68
+ // Track successful completion
69
+ agentExecutionCompleted({
70
+ model_id: 'claude-3-5-sonnet',
71
+ agent_id: agentId,
72
+ status: 'completed',
73
+ completion_type: 'text',
74
+ total_duration_ms: Date.now() - startTime,
75
+ input_tokens: result.usage?.inputTokens,
76
+ output_tokens: result.usage?.outputTokens,
77
+ step_count: result.steps?.length,
78
+ });
79
+
80
+ return result;
81
+ } catch (error: any) {
82
+ // Track failure
83
+ agentExecutionFailed({
84
+ model_id: 'claude-3-5-sonnet',
85
+ agent_id: agentId,
86
+ error_message: error.message,
87
+ total_duration_ms: Date.now() - startTime,
88
+ completion_type: 'text',
89
+ });
90
+
91
+ throw error;
92
+ }
93
+ }
94
+
95
+ // =============================================================================
96
+ // Pattern 2: Chat Session Tracking with Messages
97
+ // =============================================================================
98
+
99
+ export class TrackedChatSession {
100
+ private sessionId: string;
101
+ private messageCount = 0;
102
+ private totalTokens = 0;
103
+ private sessionStartTime: number;
104
+
105
+ constructor(sessionId: string) {
106
+ this.sessionId = sessionId;
107
+ this.sessionStartTime = Date.now();
108
+
109
+ // Track session start
110
+ aiSdk.chatSessionStarted({
111
+ model_id: 'gpt-4-turbo',
112
+ session_id: sessionId,
113
+ session_type: 'chat',
114
+ });
115
+ }
116
+
117
+ async sendMessage(content: string, userId?: string) {
118
+ this.messageCount++;
119
+
120
+ // Track user message
121
+ aiSdk.chatMessageSent({
122
+ model_id: 'gpt-4-turbo',
123
+ session_id: this.sessionId,
124
+ user_id: userId,
125
+ message_role: 'user',
126
+ message_length: content.length,
127
+ message_index: this.messageCount,
128
+ });
129
+
130
+ const startTime = Date.now();
131
+ // Placeholder - replace with actual Chat.create when AI SDK is installed
132
+ const result: any = await Promise.resolve({
133
+ text: '',
134
+ finishReason: 'stop',
135
+ usage: { totalTokens: 0 },
136
+ });
137
+
138
+ // Track assistant response
139
+ aiSdk.chatMessageReceived({
140
+ model_id: 'gpt-4-turbo',
141
+ session_id: this.sessionId,
142
+ message_role: 'assistant',
143
+ message_length: result.text?.length,
144
+ message_index: this.messageCount + 1,
145
+ response_time_ms: Date.now() - startTime,
146
+ finish_reason: result.finishReason,
147
+ });
148
+
149
+ this.messageCount++;
150
+ if (result.usage?.totalTokens) {
151
+ this.totalTokens += result.usage.totalTokens;
152
+ }
153
+
154
+ return result;
155
+ }
156
+
157
+ endSession(reason?: 'user-ended' | 'timeout' | 'error') {
158
+ aiSdk.chatSessionEnded({
159
+ model_id: 'gpt-4-turbo',
160
+ session_id: this.sessionId,
161
+ duration_ms: Date.now() - this.sessionStartTime,
162
+ message_count: this.messageCount,
163
+ total_tokens: this.totalTokens,
164
+ session_end_reason: reason ?? 'user-ended',
165
+ });
166
+ }
167
+ }
168
+
169
+ // =============================================================================
170
+ // Pattern 3: Tool Execution Tracking with Metrics
171
+ /**
172
+ * Wraps a tool invocation with analytics tracking for start, success, and failure events.
173
+ *
174
+ * @param toolName - The name of the tool being invoked
175
+ * @param modelId - The model identifier associated with the tool call
176
+ * @param execute - An async function that performs the tool operation; its resolved value is returned
177
+ * @returns The resolved value from `execute`
178
+ * @throws Any error thrown by `execute` after emitting a failure tracking event
179
+ */
180
+
181
+ export async function trackToolExecution<T>(
182
+ toolName: string,
183
+ modelId: string,
184
+ execute: () => Promise<T>,
185
+ ): Promise<T> {
186
+ const startTime = Date.now();
187
+ const operationId = generateOperationId('tool');
188
+
189
+ try {
190
+ // Track tool start
191
+ aiSdk.toolCallStarted({
192
+ model_id: modelId,
193
+ operation_id: operationId,
194
+ tool_name: toolName,
195
+ tool_type: 'custom',
196
+ });
197
+
198
+ const result = await execute();
199
+
200
+ // Track successful completion
201
+ aiSdk.toolCallCompleted({
202
+ model_id: modelId,
203
+ operation_id: operationId,
204
+ tool_name: toolName,
205
+ tool_type: 'custom',
206
+ result_status: 'success',
207
+ execution_time_ms: Date.now() - startTime,
208
+ output_size: JSON.stringify(result).length,
209
+ });
210
+
211
+ return result;
212
+ } catch (error: any) {
213
+ // Track failure
214
+ aiSdk.toolCallFailed({
215
+ model_id: modelId,
216
+ operation_id: operationId,
217
+ tool_name: toolName,
218
+ tool_type: 'custom',
219
+ error_message: error.message,
220
+ execution_time_ms: Date.now() - startTime,
221
+ });
222
+
223
+ throw error;
224
+ }
225
+ }
226
+
227
+ // =============================================================================
228
+ // Pattern 4: Streaming with Chunk Sampling
229
+ // =============================================================================
230
+
231
+ export async function trackStreamingCompletion(_messages: any[]) {
232
+ const operationId = generateOperationId('stream');
233
+ const startTime = Date.now();
234
+ let chunkCount = 0;
235
+ let firstChunkTime: number | undefined;
236
+
237
+ try {
238
+ // Track stream start
239
+ aiSdk.streamStarted({
240
+ model_id: 'claude-3-5-sonnet',
241
+ operation_id: operationId,
242
+ stream_type: 'text',
243
+ });
244
+
245
+ // Placeholder - replace with actual Chat.stream when AI SDK is installed
246
+ const result: any = { textStream: null };
247
+
248
+ // Process stream
249
+ if (result.textStream) {
250
+ const reader = result.textStream.getReader();
251
+
252
+ while (true) {
253
+ const { done } = await reader.read();
254
+ if (done) break;
255
+
256
+ chunkCount++;
257
+
258
+ // Record first chunk time
259
+ firstChunkTime ??= Date.now();
260
+
261
+ // Sample every 10th chunk to avoid overwhelming analytics
262
+ if (chunkCount % 10 === 0) {
263
+ aiSdk.streamChunkReceived({
264
+ model_id: 'claude-3-5-sonnet',
265
+ operation_id: operationId,
266
+ stream_type: 'text',
267
+ chunk_index: chunkCount,
268
+ });
269
+ }
270
+ }
271
+ }
272
+
273
+ const duration = Date.now() - startTime;
274
+
275
+ // Track successful completion
276
+ aiSdk.streamCompleted({
277
+ model_id: 'claude-3-5-sonnet',
278
+ operation_id: operationId,
279
+ stream_type: 'text',
280
+ chunk_count: chunkCount,
281
+ stream_duration_ms: duration,
282
+ time_to_first_chunk_ms: firstChunkTime ? firstChunkTime - startTime : undefined,
283
+ chunks_per_second: duration > 0 ? (chunkCount / duration) * 1000 : undefined,
284
+ });
285
+
286
+ return result;
287
+ } catch (error: any) {
288
+ aiSdk.streamFailed({
289
+ model_id: 'claude-3-5-sonnet',
290
+ operation_id: operationId,
291
+ stream_type: 'text',
292
+ error_message: error.message,
293
+ chunk_count: chunkCount,
294
+ stream_duration_ms: Date.now() - startTime,
295
+ });
296
+
297
+ throw error;
298
+ }
299
+ }
300
+
301
+ // =============================================================================
302
+ // Pattern 5: E-commerce Chatbot Intent Detection
303
+ /**
304
+ * Handles an incoming chatbot message, routes it by detected intent, emits analytics events, and returns the appropriate response payload.
305
+ *
306
+ * @param message - The raw user message to analyze and act on
307
+ * @param conversationId - Identifier for the chat conversation used in analytics events
308
+ * @param userId - Identifier for the user sending the message
309
+ * @returns An object describing the action taken:
310
+ * - `{ type: 'product-recommendations', products }` when a product search is detected
311
+ * - `{ type: 'cart-update', cart }` when cart management is detected
312
+ * - `{ type: 'order-status', order }` when order tracking is detected
313
+ * - `{ type: 'general', response: string }` for fallback/general responses
314
+ */
315
+
316
+ export async function handleChatbotMessage(
317
+ message: string,
318
+ conversationId: string,
319
+ userId: string,
320
+ ) {
321
+ // Track intent detection (auto-detected from message)
322
+ aiSdk.chatbotIntentDetected({
323
+ model_id: 'gpt-4',
324
+ conversation_id: conversationId,
325
+ user_id: userId,
326
+ message,
327
+ });
328
+
329
+ // Process based on detected intent
330
+ const intent = message.toLowerCase();
331
+
332
+ if (intent.includes('laptop') || intent.includes('search')) {
333
+ // Product search scenario
334
+ const products = await searchProducts(message);
335
+
336
+ // Track product recommendations
337
+ aiSdk.chatbotProductRecommended({
338
+ model_id: 'gpt-4',
339
+ conversation_id: conversationId,
340
+ user_id: userId,
341
+ product_ids: products.map(p => p.id),
342
+ product_count: products.length,
343
+ intent_detected: 'product-search',
344
+ });
345
+
346
+ return { type: 'product-recommendations', products };
347
+ } else if (intent.includes('cart') || intent.includes('add')) {
348
+ // Cart assistance scenario
349
+ const cart = await getCart(userId);
350
+
351
+ aiSdk.chatbotCartAssisted({
352
+ model_id: 'gpt-4',
353
+ conversation_id: conversationId,
354
+ user_id: userId,
355
+ cart_id: cart.id,
356
+ cart_value: cart.total,
357
+ product_count: cart.items.length,
358
+ product_ids: cart.items.map(i => i.productId),
359
+ intent_detected: 'cart-management',
360
+ });
361
+
362
+ return { type: 'cart-update', cart };
363
+ } else if (intent.includes('order') || intent.includes('track')) {
364
+ // Order tracking scenario
365
+ const orders = await getUserOrders(userId);
366
+ const latestOrder = orders[0];
367
+
368
+ if (latestOrder) {
369
+ aiSdk.chatbotOrderAssisted({
370
+ model_id: 'gpt-4',
371
+ conversation_id: conversationId,
372
+ user_id: userId,
373
+ order_id: latestOrder.id,
374
+ intent_detected: 'order-tracking',
375
+ });
376
+
377
+ return { type: 'order-status', order: latestOrder };
378
+ }
379
+ }
380
+
381
+ return { type: 'general', response: 'How can I help you?' };
382
+ }
383
+
384
+ // =============================================================================
385
+ // Pattern 6: Cost Tracking with Budget Monitoring
386
+ // =============================================================================
387
+
388
+ export class CostTracker {
389
+ private totalCost = 0;
390
+ private budget: number;
391
+
392
+ constructor(dailyBudget: number) {
393
+ this.budget = dailyBudget;
394
+ }
395
+
396
+ async trackCompletion(
397
+ modelId: string,
398
+ usage: { input_tokens: number; output_tokens: number },
399
+ pricing: { input_price_per_1k: number; output_price_per_1k: number },
400
+ ) {
401
+ // Calculate cost
402
+ const cost = calculateCost(usage, pricing);
403
+ this.totalCost += cost;
404
+
405
+ // Track cost
406
+ trackAISDK({
407
+ name: AI_SDK_EVENTS.TOKEN_USAGE_TRACKED,
408
+ category: 'ai-sdk',
409
+ properties: {
410
+ model_id: modelId,
411
+ input_tokens: usage.input_tokens,
412
+ output_tokens: usage.output_tokens,
413
+ total_tokens: usage.input_tokens + usage.output_tokens,
414
+ cost,
415
+ cost_currency: 'USD',
416
+ cost_breakdown: {
417
+ input_cost: (usage.input_tokens / 1000) * pricing.input_price_per_1k,
418
+ output_cost: (usage.output_tokens / 1000) * pricing.output_price_per_1k,
419
+ },
420
+ },
421
+ });
422
+
423
+ // Check budget
424
+ if (this.totalCost > this.budget) {
425
+ logWarn(`Budget exceeded! Total: $${this.totalCost}, Budget: $${this.budget}`, {
426
+ totalCost: this.totalCost,
427
+ budget: this.budget,
428
+ });
429
+ }
430
+
431
+ return cost;
432
+ }
433
+
434
+ getRemainingBudget(): number {
435
+ return Math.max(0, this.budget - this.totalCost);
436
+ }
437
+ }
438
+
439
+ // =============================================================================
440
+ // Pattern 7: React Component with Tracking
441
+ /**
442
+ * React component that wraps a chat UI with analytics hooks to emit tracking events for user messages, assistant responses, and chat errors.
443
+ *
444
+ * @param userId - The identifier of the current user used in emitted tracking events
445
+ * @returns A React element representing the chat interface (placeholder implementation)
446
+ */
447
+
448
+ export function ChatInterfaceWithTracking({ userId }: { userId: string }) {
449
+ // Example component - conversationId would typically come from props or context
450
+ const conversationId = useId();
451
+
452
+ const chat = useChat({
453
+ api: '/api/chat',
454
+ id: conversationId,
455
+
456
+ onFinish: (message: { content: string }) => {
457
+ // Track assistant message
458
+ aiSdk.chatMessageReceived({
459
+ model_id: 'claude-3-5-sonnet',
460
+ conversation_id: conversationId,
461
+ user_id: userId,
462
+ message_role: 'assistant',
463
+ message_length: message.content.length,
464
+ finish_reason: 'stop',
465
+ });
466
+ },
467
+
468
+ onError: (error: Error) => {
469
+ // Track error
470
+ agentExecutionFailed({
471
+ model_id: 'claude-3-5-sonnet',
472
+ conversation_id: conversationId,
473
+ error_message: error.message,
474
+ completion_type: 'chat',
475
+ });
476
+ },
477
+ });
478
+
479
+ // In a real implementation, you would use chat.send() to send messages
480
+ // Void expression to satisfy unused variable check
481
+ void chat;
482
+
483
+ return null; // Component implementation
484
+ }
485
+
486
+ // =============================================================================
487
+ // Pattern 8: Multi-Step Agent with Step Tracking
488
+ /**
489
+ * Execute a multi-step agent prompt while emitting analytics events for start, per-step progress, completion, and failures.
490
+ *
491
+ * Emits lifecycle events that record operation id, step counts, duration, stop reason, and token usage.
492
+ *
493
+ * @param agent - The Agent instance to run the multi-step generation with
494
+ * @param prompt - The prompt string to pass to the agent
495
+ * @returns The agent's generation result object (may include `steps` and `usage` information)
496
+ * @throws Propagates any error thrown by the agent after emitting a failure analytics event
497
+ */
498
+
499
+ export async function trackMultiStepAgent(agent: Agent, prompt: string) {
500
+ const operationId = generateOperationId('multi-step');
501
+ const startTime = Date.now();
502
+ let stepCount = 0;
503
+
504
+ try {
505
+ trackAISDK({
506
+ name: AI_SDK_EVENTS.MULTI_STEP_STARTED,
507
+ category: 'ai-sdk',
508
+ properties: {
509
+ model_id: 'claude-3-5-sonnet',
510
+ operation_id: operationId,
511
+ step_count: 0,
512
+ },
513
+ });
514
+
515
+ const result = await agent.generate({ prompt });
516
+
517
+ stepCount = result.steps?.length ?? 0;
518
+
519
+ // Track each step progression
520
+ result.steps?.forEach((_step: any, index: number) => {
521
+ trackAISDK({
522
+ name: AI_SDK_EVENTS.MULTI_STEP_PROGRESSED,
523
+ category: 'ai-sdk',
524
+ properties: {
525
+ model_id: 'claude-3-5-sonnet',
526
+ operation_id: operationId,
527
+ step_count: index + 1,
528
+ },
529
+ });
530
+ });
531
+
532
+ trackAISDK({
533
+ name: AI_SDK_EVENTS.MULTI_STEP_COMPLETED,
534
+ category: 'ai-sdk',
535
+ properties: {
536
+ model_id: 'claude-3-5-sonnet',
537
+ operation_id: operationId,
538
+ step_count: stepCount,
539
+ total_duration_ms: Date.now() - startTime,
540
+ stop_reason: 'condition-met',
541
+ input_tokens: result.usage?.inputTokens,
542
+ output_tokens: result.usage?.outputTokens,
543
+ },
544
+ });
545
+
546
+ return result;
547
+ } catch (error: any) {
548
+ agentExecutionFailed({
549
+ model_id: 'claude-3-5-sonnet',
550
+ operation_id: operationId,
551
+ error_message: error.message,
552
+ completion_type: 'multi-step',
553
+ step_count: stepCount,
554
+ total_duration_ms: Date.now() - startTime,
555
+ });
556
+
557
+ throw error;
558
+ }
559
+ }
560
+
561
+ // =============================================================================
562
+ // Helper Functions (Mocked for Examples)
563
+ // =============================================================================
564
+
565
+ async function searchProducts(_query: string): Promise<{ id: string }[]> {
566
+ return [{ id: 'prod_1' }, { id: 'prod_2' }];
567
+ }
568
+
569
+ async function getCart(_userId: string): Promise<{
570
+ id: string;
571
+ total: number;
572
+ items: { productId: string }[];
573
+ }> {
574
+ return {
575
+ id: 'cart_123',
576
+ total: 299.99,
577
+ items: [{ productId: 'prod_1' }],
578
+ };
579
+ }
580
+
581
+ async function getUserOrders(_userId: string): Promise<{ id: string }[]> {
582
+ return [{ id: 'order_123' }];
583
+ }