posthoganalytics 6.7.5__py3-none-any.whl → 7.4.3__py3-none-any.whl

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 (37) hide show
  1. posthoganalytics/__init__.py +84 -7
  2. posthoganalytics/ai/anthropic/anthropic_async.py +30 -67
  3. posthoganalytics/ai/anthropic/anthropic_converter.py +40 -0
  4. posthoganalytics/ai/gemini/__init__.py +3 -0
  5. posthoganalytics/ai/gemini/gemini.py +1 -1
  6. posthoganalytics/ai/gemini/gemini_async.py +423 -0
  7. posthoganalytics/ai/gemini/gemini_converter.py +160 -24
  8. posthoganalytics/ai/langchain/callbacks.py +55 -11
  9. posthoganalytics/ai/openai/openai.py +27 -2
  10. posthoganalytics/ai/openai/openai_async.py +49 -5
  11. posthoganalytics/ai/openai/openai_converter.py +130 -0
  12. posthoganalytics/ai/sanitization.py +27 -5
  13. posthoganalytics/ai/types.py +1 -0
  14. posthoganalytics/ai/utils.py +32 -2
  15. posthoganalytics/client.py +338 -90
  16. posthoganalytics/contexts.py +81 -0
  17. posthoganalytics/exception_utils.py +250 -2
  18. posthoganalytics/feature_flags.py +26 -10
  19. posthoganalytics/flag_definition_cache.py +127 -0
  20. posthoganalytics/integrations/django.py +149 -50
  21. posthoganalytics/request.py +203 -23
  22. posthoganalytics/test/test_client.py +250 -22
  23. posthoganalytics/test/test_exception_capture.py +418 -0
  24. posthoganalytics/test/test_feature_flag_result.py +441 -2
  25. posthoganalytics/test/test_feature_flags.py +306 -102
  26. posthoganalytics/test/test_flag_definition_cache.py +612 -0
  27. posthoganalytics/test/test_module.py +0 -8
  28. posthoganalytics/test/test_request.py +536 -0
  29. posthoganalytics/test/test_utils.py +4 -1
  30. posthoganalytics/types.py +40 -0
  31. posthoganalytics/version.py +1 -1
  32. {posthoganalytics-6.7.5.dist-info → posthoganalytics-7.4.3.dist-info}/METADATA +12 -12
  33. posthoganalytics-7.4.3.dist-info/RECORD +57 -0
  34. posthoganalytics-6.7.5.dist-info/RECORD +0 -54
  35. {posthoganalytics-6.7.5.dist-info → posthoganalytics-7.4.3.dist-info}/WHEEL +0 -0
  36. {posthoganalytics-6.7.5.dist-info → posthoganalytics-7.4.3.dist-info}/licenses/LICENSE +0 -0
  37. {posthoganalytics-6.7.5.dist-info → posthoganalytics-7.4.3.dist-info}/top_level.txt +0 -0
@@ -53,6 +53,12 @@ def merge_usage_stats(
53
53
  if source_reasoning is not None:
54
54
  current = target.get("reasoning_tokens") or 0
55
55
  target["reasoning_tokens"] = current + source_reasoning
56
+
57
+ source_web_search = source.get("web_search_count")
58
+ if source_web_search is not None:
59
+ current = target.get("web_search_count") or 0
60
+ target["web_search_count"] = max(current, source_web_search)
61
+
56
62
  elif mode == "cumulative":
57
63
  # Replace with latest values (already cumulative)
58
64
  if source.get("input_tokens") is not None:
@@ -67,6 +73,9 @@ def merge_usage_stats(
67
73
  ]
68
74
  if source.get("reasoning_tokens") is not None:
69
75
  target["reasoning_tokens"] = source["reasoning_tokens"]
76
+ if source.get("web_search_count") is not None:
77
+ target["web_search_count"] = source["web_search_count"]
78
+
70
79
  else:
71
80
  raise ValueError(f"Invalid mode: {mode}. Must be 'incremental' or 'cumulative'")
72
81
 
@@ -276,7 +285,7 @@ def call_llm_and_track_usage(
276
285
 
277
286
  event_properties = {
278
287
  "$ai_provider": provider,
279
- "$ai_model": kwargs.get("model"),
288
+ "$ai_model": kwargs.get("model") or getattr(response, "model", None),
280
289
  "$ai_model_parameters": get_model_params(kwargs),
281
290
  "$ai_input": with_privacy_mode(
282
291
  ph_client, posthog_privacy_mode, sanitized_messages
@@ -311,6 +320,10 @@ def call_llm_and_track_usage(
311
320
  if reasoning is not None and reasoning > 0:
312
321
  event_properties["$ai_reasoning_tokens"] = reasoning
313
322
 
323
+ web_search_count = usage.get("web_search_count")
324
+ if web_search_count is not None and web_search_count > 0:
325
+ event_properties["$ai_web_search_count"] = web_search_count
326
+
314
327
  if posthog_distinct_id is None:
315
328
  event_properties["$process_person_profile"] = False
316
329
 
@@ -383,7 +396,7 @@ async def call_llm_and_track_usage_async(
383
396
 
384
397
  event_properties = {
385
398
  "$ai_provider": provider,
386
- "$ai_model": kwargs.get("model"),
399
+ "$ai_model": kwargs.get("model") or getattr(response, "model", None),
387
400
  "$ai_model_parameters": get_model_params(kwargs),
388
401
  "$ai_input": with_privacy_mode(
389
402
  ph_client, posthog_privacy_mode, sanitized_messages
@@ -414,6 +427,14 @@ async def call_llm_and_track_usage_async(
414
427
  if cache_creation is not None and cache_creation > 0:
415
428
  event_properties["$ai_cache_creation_input_tokens"] = cache_creation
416
429
 
430
+ reasoning = usage.get("reasoning_tokens")
431
+ if reasoning is not None and reasoning > 0:
432
+ event_properties["$ai_reasoning_tokens"] = reasoning
433
+
434
+ web_search_count = usage.get("web_search_count")
435
+ if web_search_count is not None and web_search_count > 0:
436
+ event_properties["$ai_web_search_count"] = web_search_count
437
+
417
438
  if posthog_distinct_id is None:
418
439
  event_properties["$process_person_profile"] = False
419
440
 
@@ -535,6 +556,15 @@ def capture_streaming_event(
535
556
  if value is not None and isinstance(value, int) and value > 0:
536
557
  event_properties[f"$ai_{field}"] = value
537
558
 
559
+ # Add web search count if present (all providers)
560
+ web_search_count = event_data["usage_stats"].get("web_search_count")
561
+ if (
562
+ web_search_count is not None
563
+ and isinstance(web_search_count, int)
564
+ and web_search_count > 0
565
+ ):
566
+ event_properties["$ai_web_search_count"] = web_search_count
567
+
538
568
  # Handle provider-specific fields
539
569
  if (
540
570
  event_data["provider"] == "openai"