@posthog/ai 6.4.1 → 6.4.2

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/dist/index.d.ts CHANGED
@@ -188,6 +188,7 @@ declare class WrappedModels {
188
188
  generateContent(params: GenerateContentParameters & MonitoringParams): Promise<GenerateContentResponse>;
189
189
  generateContentStream(params: GenerateContentParameters & MonitoringParams): AsyncGenerator<GenerateContentResponse, void, unknown>;
190
190
  private formatInput;
191
+ private extractSystemInstruction;
191
192
  private formatInputForPostHog;
192
193
  }
193
194
 
package/dist/index.mjs CHANGED
@@ -6,7 +6,15 @@ import { wrapLanguageModel } from 'ai';
6
6
  import AnthropicOriginal from '@anthropic-ai/sdk';
7
7
  import { GoogleGenAI } from '@google/genai';
8
8
 
9
- var version = "6.4.1";
9
+ var version = "6.4.2";
10
+
11
+ // Type guards for safer type checking
12
+ const isString = value => {
13
+ return typeof value === 'string';
14
+ };
15
+ const isObject = value => {
16
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
17
+ };
10
18
 
11
19
  // limit large outputs by truncating to 200kb (approx 200k bytes)
12
20
  const MAX_OUTPUT_SIZE = 200000;
@@ -420,14 +428,49 @@ const sendEventToPosthog = async ({
420
428
  client.capture(event);
421
429
  }
422
430
  };
423
-
424
- // Type guards for safer type checking
425
- const isString = value => {
426
- return typeof value === 'string';
427
- };
428
- const isObject = value => {
429
- return value !== null && typeof value === 'object' && !Array.isArray(value);
430
- };
431
+ function formatOpenAIResponsesInput(input, instructions) {
432
+ const messages = [];
433
+ if (instructions) {
434
+ messages.push({
435
+ role: 'system',
436
+ content: instructions
437
+ });
438
+ }
439
+ if (Array.isArray(input)) {
440
+ for (const item of input) {
441
+ if (typeof item === 'string') {
442
+ messages.push({
443
+ role: 'user',
444
+ content: item
445
+ });
446
+ } else if (item && typeof item === 'object') {
447
+ const obj = item;
448
+ const role = isString(obj.role) ? obj.role : 'user';
449
+ const content = obj.content || obj.text || String(item);
450
+ messages.push({
451
+ role,
452
+ content: String(content)
453
+ });
454
+ } else {
455
+ messages.push({
456
+ role: 'user',
457
+ content: String(item)
458
+ });
459
+ }
460
+ }
461
+ } else if (typeof input === 'string') {
462
+ messages.push({
463
+ role: 'user',
464
+ content: input
465
+ });
466
+ } else if (input) {
467
+ messages.push({
468
+ role: 'user',
469
+ content: String(input)
470
+ });
471
+ }
472
+ return messages;
473
+ }
431
474
 
432
475
  const REDACTED_IMAGE_PLACEHOLDER = '[base64 image redacted]';
433
476
  // ============================================
@@ -507,17 +550,6 @@ const sanitizeOpenAIImage = item => {
507
550
  }
508
551
  return item;
509
552
  };
510
- const sanitizeOpenAIResponseImage = item => {
511
- if (!isObject(item)) return item;
512
- // Handle input_image format
513
- if (item.type === 'input_image' && 'image_url' in item) {
514
- return {
515
- ...item,
516
- image_url: redactBase64DataUrl(item.image_url)
517
- };
518
- }
519
- return item;
520
- };
521
553
  const sanitizeAnthropicImage = item => {
522
554
  if (!isObject(item)) return item;
523
555
  // Handle Anthropic's image format
@@ -600,9 +632,6 @@ const sanitizeLangChainImage = item => {
600
632
  const sanitizeOpenAI = data => {
601
633
  return processMessages(data, sanitizeOpenAIImage);
602
634
  };
603
- const sanitizeOpenAIResponse = data => {
604
- return processMessages(data, sanitizeOpenAIResponseImage);
605
- };
606
635
  const sanitizeAnthropic = data => {
607
636
  return processMessages(data, sanitizeAnthropicImage);
608
637
  };
@@ -889,7 +918,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
889
918
  //@ts-expect-error
890
919
  model: openAIParams.model,
891
920
  provider: 'openai',
892
- input: sanitizeOpenAIResponse(openAIParams.input),
921
+ input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
893
922
  output: finalContent,
894
923
  latency,
895
924
  baseURL: this.baseURL,
@@ -906,7 +935,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
906
935
  //@ts-expect-error
907
936
  model: openAIParams.model,
908
937
  provider: 'openai',
909
- input: sanitizeOpenAIResponse(openAIParams.input),
938
+ input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
910
939
  output: [],
911
940
  latency: 0,
912
941
  baseURL: this.baseURL,
@@ -936,7 +965,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
936
965
  //@ts-expect-error
937
966
  model: openAIParams.model,
938
967
  provider: 'openai',
939
- input: sanitizeOpenAIResponse(openAIParams.input),
968
+ input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
940
969
  output: formatResponseOpenAI({
941
970
  output: result.output
942
971
  }),
@@ -961,7 +990,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
961
990
  ...posthogParams,
962
991
  model: String(openAIParams.model ?? ''),
963
992
  provider: 'openai',
964
- input: sanitizeOpenAIResponse(openAIParams.input),
993
+ input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
965
994
  output: [],
966
995
  latency: 0,
967
996
  baseURL: this.baseURL,
@@ -998,7 +1027,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
998
1027
  ...posthogParams,
999
1028
  model: String(openAIParams.model ?? ''),
1000
1029
  provider: 'openai',
1001
- input: sanitizeOpenAIResponse(openAIParams.input),
1030
+ input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
1002
1031
  output: result.output,
1003
1032
  latency,
1004
1033
  baseURL: this.baseURL,
@@ -1019,7 +1048,7 @@ let WrappedResponses$1 = class WrappedResponses extends Responses {
1019
1048
  ...posthogParams,
1020
1049
  model: String(openAIParams.model ?? ''),
1021
1050
  provider: 'openai',
1022
- input: sanitizeOpenAIResponse(openAIParams.input),
1051
+ input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
1023
1052
  output: [],
1024
1053
  latency: 0,
1025
1054
  baseURL: this.baseURL,
@@ -1231,7 +1260,7 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
1231
1260
  ...posthogParams,
1232
1261
  model: openAIParams.model,
1233
1262
  provider: 'azure',
1234
- input: openAIParams.messages,
1263
+ input: sanitizeOpenAI(openAIParams.messages),
1235
1264
  output: formattedOutput,
1236
1265
  latency,
1237
1266
  baseURL: this.baseURL,
@@ -1246,7 +1275,7 @@ class WrappedCompletions extends AzureOpenAI.Chat.Completions {
1246
1275
  ...posthogParams,
1247
1276
  model: openAIParams.model,
1248
1277
  provider: 'azure',
1249
- input: openAIParams.messages,
1278
+ input: sanitizeOpenAI(openAIParams.messages),
1250
1279
  output: [],
1251
1280
  latency: 0,
1252
1281
  baseURL: this.baseURL,
@@ -2258,7 +2287,7 @@ class WrappedModels {
2258
2287
  ...posthogParams,
2259
2288
  model: geminiParams.model,
2260
2289
  provider: 'gemini',
2261
- input: this.formatInputForPostHog(geminiParams.contents),
2290
+ input: this.formatInputForPostHog(geminiParams),
2262
2291
  output: formatResponseGemini(response),
2263
2292
  latency,
2264
2293
  baseURL: 'https://generativelanguage.googleapis.com',
@@ -2280,7 +2309,7 @@ class WrappedModels {
2280
2309
  ...posthogParams,
2281
2310
  model: geminiParams.model,
2282
2311
  provider: 'gemini',
2283
- input: this.formatInputForPostHog(geminiParams.contents),
2312
+ input: this.formatInputForPostHog(geminiParams),
2284
2313
  output: [],
2285
2314
  latency,
2286
2315
  baseURL: 'https://generativelanguage.googleapis.com',
@@ -2375,7 +2404,7 @@ class WrappedModels {
2375
2404
  ...posthogParams,
2376
2405
  model: geminiParams.model,
2377
2406
  provider: 'gemini',
2378
- input: this.formatInputForPostHog(geminiParams.contents),
2407
+ input: this.formatInputForPostHog(geminiParams),
2379
2408
  output,
2380
2409
  latency,
2381
2410
  baseURL: 'https://generativelanguage.googleapis.com',
@@ -2391,7 +2420,7 @@ class WrappedModels {
2391
2420
  ...posthogParams,
2392
2421
  model: geminiParams.model,
2393
2422
  provider: 'gemini',
2394
- input: this.formatInputForPostHog(geminiParams.contents),
2423
+ input: this.formatInputForPostHog(geminiParams),
2395
2424
  output: [],
2396
2425
  latency,
2397
2426
  baseURL: 'https://generativelanguage.googleapis.com',
@@ -2426,19 +2455,19 @@ class WrappedModels {
2426
2455
  const obj = item;
2427
2456
  if ('text' in obj && obj.text) {
2428
2457
  return {
2429
- role: obj.role || 'user',
2458
+ role: isString(obj.role) ? obj.role : 'user',
2430
2459
  content: obj.text
2431
2460
  };
2432
2461
  }
2433
2462
  if ('content' in obj && obj.content) {
2434
2463
  return {
2435
- role: obj.role || 'user',
2464
+ role: isString(obj.role) ? obj.role : 'user',
2436
2465
  content: obj.content
2437
2466
  };
2438
2467
  }
2439
2468
  if ('parts' in obj && Array.isArray(obj.parts)) {
2440
2469
  return {
2441
- role: obj.role || 'user',
2470
+ role: isString(obj.role) ? obj.role : 'user',
2442
2471
  content: obj.parts.map(part => {
2443
2472
  if (part && typeof part === 'object' && 'text' in part) {
2444
2473
  return part.text;
@@ -2474,9 +2503,54 @@ class WrappedModels {
2474
2503
  content: String(contents)
2475
2504
  }];
2476
2505
  }
2477
- formatInputForPostHog(contents) {
2478
- const sanitized = sanitizeGemini(contents);
2479
- return this.formatInput(sanitized);
2506
+ extractSystemInstruction(params) {
2507
+ if (!params || typeof params !== 'object' || !params.config) {
2508
+ return null;
2509
+ }
2510
+ const config = params.config;
2511
+ if (!('systemInstruction' in config)) {
2512
+ return null;
2513
+ }
2514
+ const systemInstruction = config.systemInstruction;
2515
+ if (typeof systemInstruction === 'string') {
2516
+ return systemInstruction;
2517
+ }
2518
+ if (systemInstruction && typeof systemInstruction === 'object' && 'text' in systemInstruction) {
2519
+ return systemInstruction.text;
2520
+ }
2521
+ if (systemInstruction && typeof systemInstruction === 'object' && 'parts' in systemInstruction && Array.isArray(systemInstruction.parts)) {
2522
+ for (const part of systemInstruction.parts) {
2523
+ if (part && typeof part === 'object' && 'text' in part && typeof part.text === 'string') {
2524
+ return part.text;
2525
+ }
2526
+ }
2527
+ }
2528
+ if (Array.isArray(systemInstruction)) {
2529
+ for (const part of systemInstruction) {
2530
+ if (typeof part === 'string') {
2531
+ return part;
2532
+ }
2533
+ if (part && typeof part === 'object' && 'text' in part && typeof part.text === 'string') {
2534
+ return part.text;
2535
+ }
2536
+ }
2537
+ }
2538
+ return null;
2539
+ }
2540
+ formatInputForPostHog(params) {
2541
+ const sanitized = sanitizeGemini(params.contents);
2542
+ const messages = this.formatInput(sanitized);
2543
+ const systemInstruction = this.extractSystemInstruction(params);
2544
+ if (systemInstruction) {
2545
+ const hasSystemMessage = messages.some(msg => msg.role === 'system');
2546
+ if (!hasSystemMessage) {
2547
+ return [{
2548
+ role: 'system',
2549
+ content: systemInstruction
2550
+ }, ...messages];
2551
+ }
2552
+ }
2553
+ return messages;
2480
2554
  }
2481
2555
  }
2482
2556