@posthog/ai 4.2.1 → 4.3.1
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/CHANGELOG.md +6 -0
- package/lib/anthropic/index.cjs.js +84 -84
- package/lib/anthropic/index.cjs.js.map +1 -1
- package/lib/anthropic/index.d.ts +1 -1
- package/lib/anthropic/index.esm.js +84 -84
- package/lib/anthropic/index.esm.js.map +1 -1
- package/lib/index.cjs.js +127 -115
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.esm.js +127 -115
- package/lib/index.esm.js.map +1 -1
- package/lib/langchain/index.cjs.js.map +1 -1
- package/lib/langchain/index.esm.js.map +1 -1
- package/lib/openai/index.cjs.js +84 -84
- package/lib/openai/index.cjs.js.map +1 -1
- package/lib/openai/index.d.ts +1 -1
- package/lib/openai/index.esm.js +84 -84
- package/lib/openai/index.esm.js.map +1 -1
- package/lib/posthog-ai/src/utils.d.ts +3 -3
- package/lib/posthog-ai/src/vercel/middleware.d.ts +2 -2
- package/lib/vercel/index.cjs.js +82 -85
- package/lib/vercel/index.cjs.js.map +1 -1
- package/lib/vercel/index.d.ts +1 -1
- package/lib/vercel/index.esm.js +82 -85
- package/lib/vercel/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/anthropic/index.ts +11 -6
- package/src/openai/azure.ts +11 -6
- package/src/openai/index.ts +11 -6
- package/src/utils.ts +63 -74
- package/src/vercel/middleware.ts +15 -13
- package/tests/openai.test.ts +65 -2
- package/tsconfig.json +1 -1
package/src/vercel/middleware.ts
CHANGED
|
@@ -14,7 +14,7 @@ interface ClientOptions {
|
|
|
14
14
|
posthogModelOverride?: string
|
|
15
15
|
posthogProviderOverride?: string
|
|
16
16
|
posthogCostOverride?: CostOverride
|
|
17
|
-
|
|
17
|
+
posthogCaptureImmediate?: boolean
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
interface CreateInstrumentationMiddlewareOptions {
|
|
@@ -26,7 +26,7 @@ interface CreateInstrumentationMiddlewareOptions {
|
|
|
26
26
|
posthogModelOverride?: string
|
|
27
27
|
posthogProviderOverride?: string
|
|
28
28
|
posthogCostOverride?: CostOverride
|
|
29
|
-
|
|
29
|
+
posthogCaptureImmediate?: boolean
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
interface PostHogInput {
|
|
@@ -128,7 +128,9 @@ const mapVercelPrompt = (prompt: LanguageModelV1Prompt): PostHogInput[] => {
|
|
|
128
128
|
// Trim the inputs array until its JSON size fits within MAX_OUTPUT_SIZE
|
|
129
129
|
let serialized = JSON.stringify(inputs)
|
|
130
130
|
let removedCount = 0
|
|
131
|
-
|
|
131
|
+
// We need to keep track of the initial size of the inputs array because we're going to be mutating it
|
|
132
|
+
let initialSize = inputs.length
|
|
133
|
+
for (let i = 0; i < initialSize && Buffer.byteLength(serialized, 'utf8') > MAX_OUTPUT_SIZE; i++) {
|
|
132
134
|
inputs.shift()
|
|
133
135
|
removedCount++
|
|
134
136
|
serialized = JSON.stringify(inputs)
|
|
@@ -136,7 +138,7 @@ const mapVercelPrompt = (prompt: LanguageModelV1Prompt): PostHogInput[] => {
|
|
|
136
138
|
if (removedCount > 0) {
|
|
137
139
|
// Add one placeholder to indicate how many were removed
|
|
138
140
|
inputs.unshift({
|
|
139
|
-
role: '
|
|
141
|
+
role: 'posthog',
|
|
140
142
|
content: `[${removedCount} message${removedCount === 1 ? '' : 's'} removed due to size limit]`,
|
|
141
143
|
})
|
|
142
144
|
}
|
|
@@ -224,7 +226,7 @@ export const createInstrumentationMiddleware = (
|
|
|
224
226
|
}
|
|
225
227
|
: {}),
|
|
226
228
|
}
|
|
227
|
-
sendEventToPosthog({
|
|
229
|
+
await sendEventToPosthog({
|
|
228
230
|
client: phClient,
|
|
229
231
|
distinctId: options.posthogDistinctId,
|
|
230
232
|
traceId: options.posthogTraceId,
|
|
@@ -241,13 +243,13 @@ export const createInstrumentationMiddleware = (
|
|
|
241
243
|
outputTokens: result.usage.completionTokens,
|
|
242
244
|
...additionalTokenValues,
|
|
243
245
|
},
|
|
244
|
-
|
|
246
|
+
captureImmediate: options.posthogCaptureImmediate,
|
|
245
247
|
})
|
|
246
248
|
|
|
247
249
|
return result
|
|
248
250
|
} catch (error: any) {
|
|
249
251
|
const modelId = model.modelId
|
|
250
|
-
sendEventToPosthog({
|
|
252
|
+
await sendEventToPosthog({
|
|
251
253
|
client: phClient,
|
|
252
254
|
distinctId: options.posthogDistinctId,
|
|
253
255
|
traceId: options.posthogTraceId,
|
|
@@ -265,7 +267,7 @@ export const createInstrumentationMiddleware = (
|
|
|
265
267
|
},
|
|
266
268
|
isError: true,
|
|
267
269
|
error: truncate(JSON.stringify(error)),
|
|
268
|
-
|
|
270
|
+
captureImmediate: options.posthogCaptureImmediate,
|
|
269
271
|
})
|
|
270
272
|
throw error
|
|
271
273
|
}
|
|
@@ -317,9 +319,9 @@ export const createInstrumentationMiddleware = (
|
|
|
317
319
|
controller.enqueue(chunk)
|
|
318
320
|
},
|
|
319
321
|
|
|
320
|
-
flush() {
|
|
322
|
+
flush: async () => {
|
|
321
323
|
const latency = (Date.now() - startTime) / 1000
|
|
322
|
-
sendEventToPosthog({
|
|
324
|
+
await sendEventToPosthog({
|
|
323
325
|
client: phClient,
|
|
324
326
|
distinctId: options.posthogDistinctId,
|
|
325
327
|
traceId: options.posthogTraceId,
|
|
@@ -332,7 +334,7 @@ export const createInstrumentationMiddleware = (
|
|
|
332
334
|
params: mergedParams as any,
|
|
333
335
|
httpStatus: 200,
|
|
334
336
|
usage,
|
|
335
|
-
|
|
337
|
+
captureImmediate: options.posthogCaptureImmediate,
|
|
336
338
|
})
|
|
337
339
|
},
|
|
338
340
|
})
|
|
@@ -342,7 +344,7 @@ export const createInstrumentationMiddleware = (
|
|
|
342
344
|
...rest,
|
|
343
345
|
}
|
|
344
346
|
} catch (error: any) {
|
|
345
|
-
sendEventToPosthog({
|
|
347
|
+
await sendEventToPosthog({
|
|
346
348
|
client: phClient,
|
|
347
349
|
distinctId: options.posthogDistinctId,
|
|
348
350
|
traceId: options.posthogTraceId,
|
|
@@ -360,7 +362,7 @@ export const createInstrumentationMiddleware = (
|
|
|
360
362
|
},
|
|
361
363
|
isError: true,
|
|
362
364
|
error: truncate(JSON.stringify(error)),
|
|
363
|
-
|
|
365
|
+
captureImmediate: options.posthogCaptureImmediate,
|
|
364
366
|
})
|
|
365
367
|
throw error
|
|
366
368
|
}
|
package/tests/openai.test.ts
CHANGED
|
@@ -1,19 +1,65 @@
|
|
|
1
1
|
import { PostHog } from 'posthog-node'
|
|
2
2
|
import PostHogOpenAI from '../src/openai'
|
|
3
|
+
import openaiModule from 'openai'
|
|
4
|
+
|
|
5
|
+
let mockOpenAiChatResponse: any = {}
|
|
6
|
+
let mockOpenAiEmbeddingResponse: any = {}
|
|
3
7
|
|
|
4
8
|
jest.mock('posthog-node', () => {
|
|
5
9
|
return {
|
|
6
10
|
PostHog: jest.fn().mockImplementation(() => {
|
|
7
11
|
return {
|
|
8
12
|
capture: jest.fn(),
|
|
13
|
+
captureImmediate: jest.fn(),
|
|
9
14
|
privacyMode: false,
|
|
10
15
|
}
|
|
11
16
|
}),
|
|
12
17
|
}
|
|
13
18
|
})
|
|
14
19
|
|
|
15
|
-
|
|
16
|
-
|
|
20
|
+
jest.mock('openai', () => {
|
|
21
|
+
// Mock Completions class – `create` is declared on the prototype so that
|
|
22
|
+
// subclasses can safely `super.create(...)` without it being shadowed by an
|
|
23
|
+
// instance field (which would overwrite the subclass implementation).
|
|
24
|
+
class MockCompletions {
|
|
25
|
+
constructor() {}
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
27
|
+
create(..._args: any[]): any {
|
|
28
|
+
/* will be stubbed in beforeEach */
|
|
29
|
+
return undefined
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Mock Chat class
|
|
34
|
+
class MockChat {
|
|
35
|
+
constructor() {}
|
|
36
|
+
static Completions = MockCompletions
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Mock OpenAI class
|
|
40
|
+
class MockOpenAI {
|
|
41
|
+
chat: any
|
|
42
|
+
embeddings: any
|
|
43
|
+
constructor() {
|
|
44
|
+
this.chat = {
|
|
45
|
+
completions: {
|
|
46
|
+
create: jest.fn(),
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
this.embeddings = {
|
|
50
|
+
create: jest.fn(),
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
static Chat = MockChat
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
__esModule: true,
|
|
58
|
+
default: MockOpenAI,
|
|
59
|
+
OpenAI: MockOpenAI,
|
|
60
|
+
Chat: MockChat,
|
|
61
|
+
}
|
|
62
|
+
})
|
|
17
63
|
|
|
18
64
|
describe('PostHogOpenAI - Jest test suite', () => {
|
|
19
65
|
let mockPostHogClient: PostHog
|
|
@@ -79,6 +125,9 @@ describe('PostHogOpenAI - Jest test suite', () => {
|
|
|
79
125
|
total_tokens: 10,
|
|
80
126
|
},
|
|
81
127
|
}
|
|
128
|
+
|
|
129
|
+
const ChatMock: any = openaiModule.Chat
|
|
130
|
+
;(ChatMock.Completions as any).prototype.create = jest.fn().mockResolvedValue(mockOpenAiChatResponse)
|
|
82
131
|
})
|
|
83
132
|
|
|
84
133
|
// Wrap each test with conditional skip
|
|
@@ -261,4 +310,18 @@ describe('PostHogOpenAI - Jest test suite', () => {
|
|
|
261
310
|
expect(properties['$ai_reasoning_tokens']).toBe(15)
|
|
262
311
|
expect(properties['$ai_cache_read_input_tokens']).toBe(5)
|
|
263
312
|
})
|
|
313
|
+
|
|
314
|
+
// New test: ensure captureImmediate is used when flag is set
|
|
315
|
+
conditionalTest('captureImmediate flag', async () => {
|
|
316
|
+
await client.chat.completions.create({
|
|
317
|
+
model: 'gpt-4',
|
|
318
|
+
messages: [{ role: 'user', content: 'Hello' }],
|
|
319
|
+
posthogDistinctId: 'test-id',
|
|
320
|
+
posthogCaptureImmediate: true,
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
// captureImmediate should be called once, and capture should not be called
|
|
324
|
+
expect(mockPostHogClient.captureImmediate).toHaveBeenCalledTimes(1)
|
|
325
|
+
expect(mockPostHogClient.capture).toHaveBeenCalledTimes(0)
|
|
326
|
+
})
|
|
264
327
|
})
|
package/tsconfig.json
CHANGED