@posthog/ai 4.2.1 → 4.3.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.
@@ -14,7 +14,7 @@ interface ClientOptions {
14
14
  posthogModelOverride?: string
15
15
  posthogProviderOverride?: string
16
16
  posthogCostOverride?: CostOverride
17
- fullDebug?: boolean
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
- fullDebug?: boolean
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
- while (Buffer.byteLength(serialized, 'utf8') > MAX_OUTPUT_SIZE && inputs.length > 0) {
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: 'assistant',
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
- fullDebug: options.fullDebug,
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
- fullDebug: options.fullDebug,
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
- fullDebug: options.fullDebug,
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
- fullDebug: options.fullDebug,
365
+ captureImmediate: options.posthogCaptureImmediate,
364
366
  })
365
367
  throw error
366
368
  }
@@ -6,6 +6,7 @@ jest.mock('posthog-node', () => {
6
6
  PostHog: jest.fn().mockImplementation(() => {
7
7
  return {
8
8
  capture: jest.fn(),
9
+ captureImmediate: jest.fn(),
9
10
  privacyMode: false,
10
11
  }
11
12
  }),
@@ -261,4 +262,18 @@ describe('PostHogOpenAI - Jest test suite', () => {
261
262
  expect(properties['$ai_reasoning_tokens']).toBe(15)
262
263
  expect(properties['$ai_cache_read_input_tokens']).toBe(5)
263
264
  })
265
+
266
+ // New test: ensure captureImmediate is used when flag is set
267
+ conditionalTest('captureImmediate flag', async () => {
268
+ await client.chat.completions.create({
269
+ model: 'gpt-4',
270
+ messages: [{ role: 'user', content: 'Hello' }],
271
+ posthogDistinctId: 'test-id',
272
+ posthogCaptureImmediate: true,
273
+ })
274
+
275
+ // captureImmediate should be called once, and capture should not be called
276
+ expect(mockPostHogClient.captureImmediate).toHaveBeenCalledTimes(1)
277
+ expect(mockPostHogClient.capture).toHaveBeenCalledTimes(0)
278
+ })
264
279
  })
package/tsconfig.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "extends": "../tsconfig.json",
3
3
  "compilerOptions": {
4
4
  "incremental": false,
5
- "types": ["node"],
5
+ "types": ["node", "jest"],
6
6
  "typeRoots": ["./node_modules/@types", "../node_modules/@types"],
7
7
  "moduleResolution": "node",
8
8
  "skipLibCheck": true,