@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.
- package/README.md +509 -0
- package/dist/ai-YMnynb-t.mjs +3347 -0
- package/dist/ai-YMnynb-t.mjs.map +1 -0
- package/dist/chunk-DQk6qfdC.mjs +18 -0
- package/dist/client-CTzJVFU5.mjs +9 -0
- package/dist/client-CTzJVFU5.mjs.map +1 -0
- package/dist/client-CcFTauAh.mjs +54 -0
- package/dist/client-CcFTauAh.mjs.map +1 -0
- package/dist/client-CeOLjbac.mjs +281 -0
- package/dist/client-CeOLjbac.mjs.map +1 -0
- package/dist/client-D339NFJS.mjs +267 -0
- package/dist/client-D339NFJS.mjs.map +1 -0
- package/dist/client-next.d.mts +62 -0
- package/dist/client-next.d.mts.map +1 -0
- package/dist/client-next.mjs +525 -0
- package/dist/client-next.mjs.map +1 -0
- package/dist/client.d.mts +30 -0
- package/dist/client.d.mts.map +1 -0
- package/dist/client.mjs +186 -0
- package/dist/client.mjs.map +1 -0
- package/dist/config-DPS6bSYo.d.mts +34 -0
- package/dist/config-DPS6bSYo.d.mts.map +1 -0
- package/dist/config-P6P5adJg.mjs +287 -0
- package/dist/config-P6P5adJg.mjs.map +1 -0
- package/dist/console-8bND3mMU.mjs +128 -0
- package/dist/console-8bND3mMU.mjs.map +1 -0
- package/dist/ecommerce-Cgu4wlux.mjs +993 -0
- package/dist/ecommerce-Cgu4wlux.mjs.map +1 -0
- package/dist/emitters-6-nKo8i-.mjs +208 -0
- package/dist/emitters-6-nKo8i-.mjs.map +1 -0
- package/dist/emitters-DldkVSPp.d.mts +12 -0
- package/dist/emitters-DldkVSPp.d.mts.map +1 -0
- package/dist/index-BfNWgfa5.d.mts +1494 -0
- package/dist/index-BfNWgfa5.d.mts.map +1 -0
- package/dist/index-BkIWe--N.d.mts +953 -0
- package/dist/index-BkIWe--N.d.mts.map +1 -0
- package/dist/index-jPzXRn52.d.mts +184 -0
- package/dist/index-jPzXRn52.d.mts.map +1 -0
- package/dist/manager-DvRRjza6.d.mts +76 -0
- package/dist/manager-DvRRjza6.d.mts.map +1 -0
- package/dist/posthog-bootstrap-CYfIy_WS.mjs +1769 -0
- package/dist/posthog-bootstrap-CYfIy_WS.mjs.map +1 -0
- package/dist/posthog-bootstrap-DWxFrxlt.d.mts +81 -0
- package/dist/posthog-bootstrap-DWxFrxlt.d.mts.map +1 -0
- package/dist/providers-http-client.d.mts +37 -0
- package/dist/providers-http-client.d.mts.map +1 -0
- package/dist/providers-http-client.mjs +320 -0
- package/dist/providers-http-client.mjs.map +1 -0
- package/dist/providers-http-server.d.mts +31 -0
- package/dist/providers-http-server.d.mts.map +1 -0
- package/dist/providers-http-server.mjs +297 -0
- package/dist/providers-http-server.mjs.map +1 -0
- package/dist/providers-http.d.mts +46 -0
- package/dist/providers-http.d.mts.map +1 -0
- package/dist/providers-http.mjs +4 -0
- package/dist/server-edge.d.mts +9 -0
- package/dist/server-edge.d.mts.map +1 -0
- package/dist/server-edge.mjs +373 -0
- package/dist/server-edge.mjs.map +1 -0
- package/dist/server-next.d.mts +67 -0
- package/dist/server-next.d.mts.map +1 -0
- package/dist/server-next.mjs +193 -0
- package/dist/server-next.mjs.map +1 -0
- package/dist/server.d.mts +10 -0
- package/dist/server.mjs +7 -0
- package/dist/service-cYtBBL8x.mjs +945 -0
- package/dist/service-cYtBBL8x.mjs.map +1 -0
- package/dist/shared.d.mts +16 -0
- package/dist/shared.d.mts.map +1 -0
- package/dist/shared.mjs +93 -0
- package/dist/shared.mjs.map +1 -0
- package/dist/types-BxBnNQ0V.d.mts +354 -0
- package/dist/types-BxBnNQ0V.d.mts.map +1 -0
- package/dist/types-CBvxUEaF.d.mts +216 -0
- package/dist/types-CBvxUEaF.d.mts.map +1 -0
- package/dist/types.d.mts +4 -0
- package/dist/types.mjs +0 -0
- package/dist/vercel-types-lwakUfoI.d.mts +102 -0
- package/dist/vercel-types-lwakUfoI.d.mts.map +1 -0
- package/package.json +129 -0
- package/src/client/index.ts +164 -0
- package/src/client/manager.ts +71 -0
- package/src/client/next/components.tsx +270 -0
- package/src/client/next/hooks.ts +217 -0
- package/src/client/next/manager.ts +141 -0
- package/src/client/next.ts +144 -0
- package/src/client-next.ts +101 -0
- package/src/client.ts +89 -0
- package/src/examples/ai-sdk-patterns.ts +583 -0
- package/src/examples/emitter-patterns.ts +476 -0
- package/src/examples/nextjs-emitter-patterns.tsx +403 -0
- package/src/next/app-router.tsx +564 -0
- package/src/next/client.ts +419 -0
- package/src/next/index.ts +84 -0
- package/src/next/middleware.ts +429 -0
- package/src/next/rsc.tsx +300 -0
- package/src/next/server.ts +253 -0
- package/src/next/types.d.ts +220 -0
- package/src/providers/base-provider.ts +419 -0
- package/src/providers/console/client.ts +10 -0
- package/src/providers/console/index.ts +152 -0
- package/src/providers/console/server.ts +6 -0
- package/src/providers/console/types.ts +15 -0
- package/src/providers/http/client.ts +464 -0
- package/src/providers/http/index.ts +30 -0
- package/src/providers/http/server.ts +396 -0
- package/src/providers/http/types.ts +135 -0
- package/src/providers/posthog/client.ts +518 -0
- package/src/providers/posthog/index.ts +11 -0
- package/src/providers/posthog/server.ts +329 -0
- package/src/providers/posthog/types.ts +104 -0
- package/src/providers/segment/client.ts +113 -0
- package/src/providers/segment/index.ts +11 -0
- package/src/providers/segment/server.ts +115 -0
- package/src/providers/segment/types.ts +51 -0
- package/src/providers/vercel/client.ts +102 -0
- package/src/providers/vercel/index.ts +11 -0
- package/src/providers/vercel/server.ts +89 -0
- package/src/providers/vercel/types.ts +27 -0
- package/src/server/index.ts +103 -0
- package/src/server/manager.ts +62 -0
- package/src/server/next.ts +210 -0
- package/src/server-edge.ts +442 -0
- package/src/server-next.ts +39 -0
- package/src/server.ts +106 -0
- package/src/shared/emitters/ai/README.md +981 -0
- package/src/shared/emitters/ai/events/agent.ts +130 -0
- package/src/shared/emitters/ai/events/artifacts.ts +167 -0
- package/src/shared/emitters/ai/events/chat.ts +126 -0
- package/src/shared/emitters/ai/events/chatbot-ecommerce.ts +133 -0
- package/src/shared/emitters/ai/events/completion.ts +103 -0
- package/src/shared/emitters/ai/events/content-generation.ts +347 -0
- package/src/shared/emitters/ai/events/conversation.ts +332 -0
- package/src/shared/emitters/ai/events/product-features.ts +1402 -0
- package/src/shared/emitters/ai/events/streaming.ts +114 -0
- package/src/shared/emitters/ai/events/tool.ts +93 -0
- package/src/shared/emitters/ai/index.ts +69 -0
- package/src/shared/emitters/ai/track-ai-sdk.ts +74 -0
- package/src/shared/emitters/ai/track-ai.ts +50 -0
- package/src/shared/emitters/ai/types.ts +1041 -0
- package/src/shared/emitters/ai/utils.ts +468 -0
- package/src/shared/emitters/ecommerce/events/cart-checkout.ts +106 -0
- package/src/shared/emitters/ecommerce/events/coupon.ts +49 -0
- package/src/shared/emitters/ecommerce/events/engagement.ts +61 -0
- package/src/shared/emitters/ecommerce/events/marketplace.ts +119 -0
- package/src/shared/emitters/ecommerce/events/order.ts +199 -0
- package/src/shared/emitters/ecommerce/events/product.ts +205 -0
- package/src/shared/emitters/ecommerce/events/registry.ts +123 -0
- package/src/shared/emitters/ecommerce/events/wishlist-sharing.ts +140 -0
- package/src/shared/emitters/ecommerce/index.ts +46 -0
- package/src/shared/emitters/ecommerce/track-ecommerce.ts +53 -0
- package/src/shared/emitters/ecommerce/types.ts +314 -0
- package/src/shared/emitters/ecommerce/utils.ts +216 -0
- package/src/shared/emitters/emitter-types.ts +974 -0
- package/src/shared/emitters/emitters.ts +292 -0
- package/src/shared/emitters/helpers.ts +419 -0
- package/src/shared/emitters/index.ts +66 -0
- package/src/shared/index.ts +142 -0
- package/src/shared/ingestion/index.ts +66 -0
- package/src/shared/ingestion/schemas.ts +386 -0
- package/src/shared/ingestion/service.ts +628 -0
- package/src/shared/node22-features.ts +848 -0
- package/src/shared/providers/console-provider.ts +160 -0
- package/src/shared/types/base-types.ts +54 -0
- package/src/shared/types/console-types.ts +19 -0
- package/src/shared/types/posthog-types.ts +131 -0
- package/src/shared/types/segment-types.ts +15 -0
- package/src/shared/types/types.ts +397 -0
- package/src/shared/types/vercel-types.ts +19 -0
- package/src/shared/utils/config-client.ts +19 -0
- package/src/shared/utils/config.ts +250 -0
- package/src/shared/utils/emitter-adapter.ts +212 -0
- package/src/shared/utils/manager.test.ts +36 -0
- package/src/shared/utils/manager.ts +1322 -0
- package/src/shared/utils/posthog-bootstrap.ts +136 -0
- package/src/shared/utils/posthog-client-utils.ts +48 -0
- package/src/shared/utils/posthog-next-utils.ts +282 -0
- package/src/shared/utils/posthog-server-utils.ts +210 -0
- package/src/shared/utils/rate-limit.ts +289 -0
- package/src/shared/utils/security.ts +545 -0
- package/src/shared/utils/validation-client.ts +161 -0
- package/src/shared/utils/validation.ts +399 -0
- package/src/shared.ts +155 -0
- 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
|
+
}
|