braintrust 0.3.15__py3-none-any.whl → 0.4.1__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 (82) hide show
  1. braintrust/_generated_types.py +737 -672
  2. braintrust/audit.py +2 -2
  3. braintrust/bt_json.py +178 -19
  4. braintrust/cli/eval.py +6 -7
  5. braintrust/cli/push.py +11 -11
  6. braintrust/context.py +12 -17
  7. braintrust/contrib/temporal/__init__.py +16 -27
  8. braintrust/contrib/temporal/test_temporal.py +8 -3
  9. braintrust/devserver/auth.py +8 -8
  10. braintrust/devserver/cache.py +3 -4
  11. braintrust/devserver/cors.py +8 -7
  12. braintrust/devserver/dataset.py +3 -5
  13. braintrust/devserver/eval_hooks.py +7 -6
  14. braintrust/devserver/schemas.py +22 -19
  15. braintrust/devserver/server.py +19 -12
  16. braintrust/devserver/test_cached_login.py +4 -4
  17. braintrust/framework.py +139 -142
  18. braintrust/framework2.py +88 -87
  19. braintrust/functions/invoke.py +66 -59
  20. braintrust/functions/stream.py +3 -2
  21. braintrust/generated_types.py +3 -1
  22. braintrust/git_fields.py +11 -11
  23. braintrust/gitutil.py +2 -3
  24. braintrust/graph_util.py +10 -10
  25. braintrust/id_gen.py +2 -2
  26. braintrust/logger.py +373 -471
  27. braintrust/merge_row_batch.py +10 -9
  28. braintrust/oai.py +21 -20
  29. braintrust/otel/__init__.py +49 -49
  30. braintrust/otel/context.py +16 -30
  31. braintrust/otel/test_distributed_tracing.py +14 -11
  32. braintrust/otel/test_otel_bt_integration.py +32 -31
  33. braintrust/parameters.py +8 -8
  34. braintrust/prompt.py +14 -14
  35. braintrust/prompt_cache/disk_cache.py +5 -4
  36. braintrust/prompt_cache/lru_cache.py +3 -2
  37. braintrust/prompt_cache/prompt_cache.py +13 -14
  38. braintrust/queue.py +4 -4
  39. braintrust/score.py +4 -4
  40. braintrust/serializable_data_class.py +4 -4
  41. braintrust/span_identifier_v1.py +1 -2
  42. braintrust/span_identifier_v2.py +3 -4
  43. braintrust/span_identifier_v3.py +23 -20
  44. braintrust/span_identifier_v4.py +34 -25
  45. braintrust/test_bt_json.py +644 -0
  46. braintrust/test_framework.py +72 -6
  47. braintrust/test_helpers.py +5 -5
  48. braintrust/test_id_gen.py +2 -3
  49. braintrust/test_logger.py +211 -107
  50. braintrust/test_otel.py +61 -53
  51. braintrust/test_queue.py +0 -1
  52. braintrust/test_score.py +1 -3
  53. braintrust/test_span_components.py +29 -44
  54. braintrust/util.py +9 -8
  55. braintrust/version.py +2 -2
  56. braintrust/wrappers/_anthropic_utils.py +4 -4
  57. braintrust/wrappers/agno/__init__.py +3 -4
  58. braintrust/wrappers/agno/agent.py +1 -2
  59. braintrust/wrappers/agno/function_call.py +1 -2
  60. braintrust/wrappers/agno/model.py +1 -2
  61. braintrust/wrappers/agno/team.py +1 -2
  62. braintrust/wrappers/agno/utils.py +12 -12
  63. braintrust/wrappers/anthropic.py +7 -8
  64. braintrust/wrappers/claude_agent_sdk/__init__.py +3 -4
  65. braintrust/wrappers/claude_agent_sdk/_wrapper.py +29 -27
  66. braintrust/wrappers/dspy.py +15 -17
  67. braintrust/wrappers/google_genai/__init__.py +17 -30
  68. braintrust/wrappers/langchain.py +22 -24
  69. braintrust/wrappers/litellm.py +4 -3
  70. braintrust/wrappers/openai.py +15 -15
  71. braintrust/wrappers/pydantic_ai.py +225 -110
  72. braintrust/wrappers/test_agno.py +0 -1
  73. braintrust/wrappers/test_dspy.py +0 -1
  74. braintrust/wrappers/test_google_genai.py +64 -4
  75. braintrust/wrappers/test_litellm.py +0 -1
  76. braintrust/wrappers/test_pydantic_ai_integration.py +819 -22
  77. {braintrust-0.3.15.dist-info → braintrust-0.4.1.dist-info}/METADATA +3 -2
  78. braintrust-0.4.1.dist-info/RECORD +121 -0
  79. braintrust-0.3.15.dist-info/RECORD +0 -120
  80. {braintrust-0.3.15.dist-info → braintrust-0.4.1.dist-info}/WHEEL +0 -0
  81. {braintrust-0.3.15.dist-info → braintrust-0.4.1.dist-info}/entry_points.txt +0 -0
  82. {braintrust-0.3.15.dist-info → braintrust-0.4.1.dist-info}/top_level.txt +0 -0
@@ -5,7 +5,6 @@ import base64
5
5
  import dataclasses
6
6
  import json
7
7
  from enum import Enum
8
- from typing import Dict, Optional, Union
9
8
 
10
9
  from .span_identifier_v3 import (
11
10
  SpanComponentsV3,
@@ -14,6 +13,7 @@ from .span_identifier_v3 import (
14
13
 
15
14
  ENCODING_VERSION_NUMBER_V4 = 4
16
15
 
16
+
17
17
  def _try_make_hex_trace_id(s):
18
18
  """Try to convert hex string to 16-byte binary (for trace IDs)"""
19
19
  try:
@@ -25,6 +25,7 @@ def _try_make_hex_trace_id(s):
25
25
  pass
26
26
  return None, False
27
27
 
28
+
28
29
  def _try_make_hex_span_id(s):
29
30
  """Try to convert hex string to 8-byte binary (for span IDs)"""
30
31
  try:
@@ -36,14 +37,17 @@ def _try_make_hex_span_id(s):
36
37
  pass
37
38
  return None, False
38
39
 
40
+
39
41
  INVALID_ENCODING_ERRMSG_V4 = f"SpanComponents string is not properly encoded. This library only supports encoding versions up to {ENCODING_VERSION_NUMBER_V4}. Please make sure the SDK library used to decode the SpanComponents is at least as new as any library used to encode it."
40
42
 
43
+
41
44
  class Fields(Enum):
42
45
  OBJECT_ID = 1
43
46
  ROW_ID = 2
44
47
  SPAN_ID = 3 # 8-byte hex
45
48
  ROOT_SPAN_ID = 4 # 16-byte hex
46
49
 
50
+
47
51
  _FIELDS_ID_TO_NAME = {
48
52
  Fields.OBJECT_ID: "object_id",
49
53
  Fields.ROW_ID: "row_id",
@@ -57,16 +61,16 @@ class SpanComponentsV4:
57
61
  object_type: SpanObjectTypeV3
58
62
 
59
63
  # Must provide one or the other.
60
- object_id: Optional[str] = None
61
- compute_object_metadata_args: Optional[Dict] = None
64
+ object_id: str | None = None
65
+ compute_object_metadata_args: dict | None = None
62
66
 
63
67
  # Either all of these must be provided or none.
64
- row_id: Optional[str] = None
65
- span_id: Optional[str] = None
66
- root_span_id: Optional[str] = None
68
+ row_id: str | None = None
69
+ span_id: str | None = None
70
+ root_span_id: str | None = None
67
71
 
68
72
  # Additional span properties.
69
- propagated_event: Optional[Dict] = None
73
+ propagated_event: dict | None = None
70
74
 
71
75
  def __post_init__(self):
72
76
  # Reuse V3 validation logic
@@ -98,10 +102,12 @@ class SpanComponentsV4:
98
102
  )
99
103
  json_obj = {k: v for k, v in json_obj.items() if v is not None}
100
104
 
101
- raw_bytes = bytes([
102
- ENCODING_VERSION_NUMBER_V4,
103
- self.object_type.value,
104
- ])
105
+ raw_bytes = bytes(
106
+ [
107
+ ENCODING_VERSION_NUMBER_V4,
108
+ self.object_type.value,
109
+ ]
110
+ )
105
111
 
106
112
  hex_entries = []
107
113
 
@@ -199,7 +205,7 @@ class SpanComponentsV4:
199
205
  except Exception:
200
206
  raise Exception(INVALID_ENCODING_ERRMSG_V4)
201
207
 
202
- def object_id_fields(self) -> Dict[str, str]:
208
+ def object_id_fields(self) -> dict[str, str]:
203
209
  # Reuse V3 logic
204
210
  if not self.object_id:
205
211
  raise Exception(
@@ -218,7 +224,7 @@ class SpanComponentsV4:
218
224
  return self.to_str()
219
225
 
220
226
  @staticmethod
221
- def _from_json_obj(json_obj: Dict) -> "SpanComponentsV4":
227
+ def _from_json_obj(json_obj: dict) -> "SpanComponentsV4":
222
228
  kwargs = {
223
229
  **json_obj,
224
230
  "object_type": SpanObjectTypeV3(json_obj["object_type"]),
@@ -226,8 +232,7 @@ class SpanComponentsV4:
226
232
  return SpanComponentsV4(**kwargs)
227
233
 
228
234
 
229
-
230
- def parse_parent(parent: Union[str, Dict, None]) -> Optional[str]:
235
+ def parse_parent(parent: str | dict | None) -> str | None:
231
236
  """Parse a parent object into a string representation using V4 format."""
232
237
  # Reuse V3 logic but with V4 components
233
238
  if isinstance(parent, str):
@@ -250,17 +255,21 @@ def parse_parent(parent: Union[str, Dict, None]) -> Optional[str]:
250
255
 
251
256
  row_ids = parent.get("row_ids")
252
257
  if row_ids:
253
- kwargs.update({
254
- "row_id": row_ids.get("id"),
255
- "span_id": row_ids.get("span_id"),
256
- "root_span_id": row_ids.get("root_span_id"),
257
- })
258
+ kwargs.update(
259
+ {
260
+ "row_id": row_ids.get("id"),
261
+ "span_id": row_ids.get("span_id"),
262
+ "root_span_id": row_ids.get("root_span_id"),
263
+ }
264
+ )
258
265
  else:
259
- kwargs.update({
260
- "row_id": None,
261
- "span_id": None,
262
- "root_span_id": None,
263
- })
266
+ kwargs.update(
267
+ {
268
+ "row_id": None,
269
+ "span_id": None,
270
+ "root_span_id": None,
271
+ }
272
+ )
264
273
 
265
274
  if "propagated_event" in parent:
266
275
  kwargs["propagated_event"] = parent.get("propagated_event")