lmnr 0.7.0__tar.gz → 0.7.2__tar.gz

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 (97) hide show
  1. {lmnr-0.7.0 → lmnr-0.7.2}/PKG-INFO +48 -51
  2. lmnr-0.7.2/pyproject.toml +145 -0
  3. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/decorators/__init__.py +43 -4
  4. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/litellm/__init__.py +5 -2
  5. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/anthropic/__init__.py +85 -6
  6. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/anthropic/span_utils.py +57 -14
  7. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/anthropic/streaming.py +106 -6
  8. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/__init__.py +8 -3
  9. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/__init__.py +6 -0
  10. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/chat_wrappers.py +139 -10
  11. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/completion_wrappers.py +8 -3
  12. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/embeddings_wrappers.py +6 -2
  13. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v1/assistant_wrappers.py +6 -3
  14. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v1/event_handler_wrapper.py +4 -1
  15. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v1/responses_wrappers.py +14 -5
  16. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/tracing/context.py +18 -1
  17. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/browser/pw_utils.py +43 -122
  18. lmnr-0.7.2/src/lmnr/sdk/browser/recorder/record.umd.min.cjs +84 -0
  19. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/laminar.py +51 -26
  20. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/types.py +17 -5
  21. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/version.py +1 -1
  22. lmnr-0.7.0/pyproject.toml +0 -153
  23. lmnr-0.7.0/src/lmnr/sdk/browser/rrweb/rrweb.umd.min.cjs +0 -98
  24. {lmnr-0.7.0 → lmnr-0.7.2}/README.md +0 -0
  25. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/__init__.py +0 -0
  26. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/cli.py +0 -0
  27. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/.flake8 +0 -0
  28. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/__init__.py +0 -0
  29. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/litellm/utils.py +0 -0
  30. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/anthropic/config.py +0 -0
  31. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/anthropic/event_emitter.py +0 -0
  32. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/anthropic/event_models.py +0 -0
  33. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/anthropic/utils.py +0 -0
  34. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/anthropic/version.py +0 -0
  35. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/config.py +0 -0
  36. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/schema_utils.py +0 -0
  37. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/google_genai/utils.py +0 -0
  38. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/groq/__init__.py +0 -0
  39. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/groq/config.py +0 -0
  40. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/groq/event_emitter.py +0 -0
  41. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/groq/event_models.py +0 -0
  42. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/groq/span_utils.py +0 -0
  43. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/groq/utils.py +0 -0
  44. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/groq/version.py +0 -0
  45. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/langgraph/__init__.py +0 -0
  46. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/langgraph/utils.py +0 -0
  47. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/__init__.py +0 -0
  48. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/config.py +0 -0
  49. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/event_emitter.py +0 -0
  50. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/event_models.py +0 -0
  51. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/shared/image_gen_wrappers.py +0 -0
  52. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/utils.py +0 -0
  53. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v0/__init__.py +0 -0
  54. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/v1/__init__.py +0 -0
  55. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/openai/version.py +0 -0
  56. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/opentelemetry/__init__.py +0 -0
  57. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/skyvern/__init__.py +0 -0
  58. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/opentelemetry/instrumentation/threading/__init__.py +0 -0
  59. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/tracing/__init__.py +0 -0
  60. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/tracing/_instrument_initializers.py +0 -0
  61. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/tracing/attributes.py +0 -0
  62. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/tracing/exporter.py +0 -0
  63. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/tracing/instruments.py +0 -0
  64. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/tracing/processor.py +0 -0
  65. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/tracing/tracer.py +0 -0
  66. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/utils/__init__.py +0 -0
  67. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/utils/json_encoder.py +0 -0
  68. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/opentelemetry_lib/utils/package_check.py +0 -0
  69. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/py.typed +0 -0
  70. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/__init__.py +0 -0
  71. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/browser/__init__.py +0 -0
  72. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/browser/browser_use_otel.py +0 -0
  73. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/browser/patchright_otel.py +0 -0
  74. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/browser/playwright_otel.py +0 -0
  75. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/browser/utils.py +0 -0
  76. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/client/asynchronous/async_client.py +0 -0
  77. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/client/asynchronous/resources/__init__.py +0 -0
  78. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/client/asynchronous/resources/agent.py +0 -0
  79. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/client/asynchronous/resources/base.py +0 -0
  80. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/client/asynchronous/resources/browser_events.py +0 -0
  81. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/client/asynchronous/resources/evals.py +0 -0
  82. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/client/asynchronous/resources/evaluators.py +0 -0
  83. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/client/asynchronous/resources/tags.py +0 -0
  84. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/client/synchronous/resources/__init__.py +0 -0
  85. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/client/synchronous/resources/agent.py +0 -0
  86. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/client/synchronous/resources/base.py +0 -0
  87. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/client/synchronous/resources/browser_events.py +0 -0
  88. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/client/synchronous/resources/evals.py +0 -0
  89. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/client/synchronous/resources/evaluators.py +0 -0
  90. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/client/synchronous/resources/tags.py +0 -0
  91. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/client/synchronous/sync_client.py +0 -0
  92. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/datasets.py +0 -0
  93. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/decorators.py +0 -0
  94. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/eval_control.py +0 -0
  95. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/evaluations.py +0 -0
  96. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/log.py +0 -0
  97. {lmnr-0.7.0 → lmnr-0.7.2}/src/lmnr/sdk/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lmnr
3
- Version: 0.7.0
3
+ Version: 0.7.2
4
4
  Summary: Python SDK for Laminar
5
5
  Author: lmnr.ai
6
6
  Author-email: lmnr.ai <founders@lmnr.ai>
@@ -19,61 +19,59 @@ Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.33.0
19
19
  Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.33.0
20
20
  Requires-Dist: opentelemetry-instrumentation>=0.54b0
21
21
  Requires-Dist: opentelemetry-semantic-conventions>=0.54b0
22
- Requires-Dist: opentelemetry-semantic-conventions-ai>=0.4.9
22
+ Requires-Dist: opentelemetry-semantic-conventions-ai>=0.4.11
23
23
  Requires-Dist: tqdm>=4.0
24
24
  Requires-Dist: tenacity>=8.0
25
25
  Requires-Dist: grpcio>=1
26
26
  Requires-Dist: httpx>=0.25.0
27
27
  Requires-Dist: orjson>=3.10.18
28
28
  Requires-Dist: packaging>=22.0
29
- Requires-Dist: opentelemetry-instrumentation-alephalpha>=0.40.12 ; extra == 'alephalpha'
30
- Requires-Dist: opentelemetry-instrumentation-alephalpha>=0.40.12 ; extra == 'all'
31
- Requires-Dist: opentelemetry-instrumentation-bedrock>=0.40.12 ; extra == 'all'
32
- Requires-Dist: opentelemetry-instrumentation-chromadb>=0.40.12 ; extra == 'all'
33
- Requires-Dist: opentelemetry-instrumentation-cohere>=0.40.12 ; extra == 'all'
34
- Requires-Dist: opentelemetry-instrumentation-crewai>=0.40.12 ; extra == 'all'
35
- Requires-Dist: opentelemetry-instrumentation-google-generativeai<0.40.10 ; extra == 'all'
36
- Requires-Dist: opentelemetry-instrumentation-haystack>=0.40.12 ; extra == 'all'
37
- Requires-Dist: opentelemetry-instrumentation-lancedb>=0.40.12 ; extra == 'all'
38
- Requires-Dist: opentelemetry-instrumentation-langchain>=0.40.12 ; extra == 'all'
39
- Requires-Dist: opentelemetry-instrumentation-llamaindex>=0.40.12 ; extra == 'all'
40
- Requires-Dist: opentelemetry-instrumentation-marqo>=0.40.12 ; extra == 'all'
41
- Requires-Dist: opentelemetry-instrumentation-mcp>=0.40.12 ; extra == 'all'
42
- Requires-Dist: opentelemetry-instrumentation-milvus>=0.40.12 ; extra == 'all'
43
- Requires-Dist: opentelemetry-instrumentation-mistralai>=0.40.12 ; extra == 'all'
44
- Requires-Dist: opentelemetry-instrumentation-ollama>=0.40.12 ; extra == 'all'
45
- Requires-Dist: opentelemetry-instrumentation-pinecone>=0.40.12 ; extra == 'all'
46
- Requires-Dist: opentelemetry-instrumentation-qdrant>=0.40.12 ; extra == 'all'
47
- Requires-Dist: opentelemetry-instrumentation-replicate>=0.40.12 ; extra == 'all'
48
- Requires-Dist: opentelemetry-instrumentation-sagemaker>=0.40.12 ; extra == 'all'
49
- Requires-Dist: opentelemetry-instrumentation-together>=0.40.12 ; extra == 'all'
50
- Requires-Dist: opentelemetry-instrumentation-transformers>=0.40.12 ; extra == 'all'
51
- Requires-Dist: opentelemetry-instrumentation-vertexai>=0.40.12 ; extra == 'all'
52
- Requires-Dist: opentelemetry-instrumentation-watsonx>=0.40.12 ; extra == 'all'
53
- Requires-Dist: opentelemetry-instrumentation-weaviate>=0.40.12 ; extra == 'all'
54
- Requires-Dist: opentelemetry-instrumentation-bedrock>=0.40.12 ; extra == 'bedrock'
55
- Requires-Dist: opentelemetry-instrumentation-chromadb>=0.40.12 ; extra == 'chromadb'
56
- Requires-Dist: opentelemetry-instrumentation-cohere>=0.40.12 ; extra == 'cohere'
57
- Requires-Dist: opentelemetry-instrumentation-crewai>=0.40.12 ; extra == 'crewai'
58
- Requires-Dist: opentelemetry-instrumentation-google-generativeai<0.40.10 ; extra == 'google-generativeai'
59
- Requires-Dist: opentelemetry-instrumentation-haystack>=0.40.12 ; extra == 'haystack'
60
- Requires-Dist: opentelemetry-instrumentation-lancedb>=0.40.12 ; extra == 'lancedb'
61
- Requires-Dist: opentelemetry-instrumentation-langchain>=0.40.12 ; extra == 'langchain'
62
- Requires-Dist: opentelemetry-instrumentation-llamaindex>=0.40.12 ; extra == 'llamaindex'
63
- Requires-Dist: opentelemetry-instrumentation-marqo>=0.40.12 ; extra == 'marqo'
64
- Requires-Dist: opentelemetry-instrumentation-mcp>=0.40.12 ; extra == 'mcp'
65
- Requires-Dist: opentelemetry-instrumentation-milvus>=0.40.12 ; extra == 'milvus'
66
- Requires-Dist: opentelemetry-instrumentation-mistralai>=0.40.12 ; extra == 'mistralai'
67
- Requires-Dist: opentelemetry-instrumentation-ollama>=0.40.12 ; extra == 'ollama'
68
- Requires-Dist: opentelemetry-instrumentation-pinecone>=0.40.12 ; extra == 'pinecone'
69
- Requires-Dist: opentelemetry-instrumentation-qdrant>=0.40.12 ; extra == 'qdrant'
70
- Requires-Dist: opentelemetry-instrumentation-replicate>=0.40.12 ; extra == 'replicate'
71
- Requires-Dist: opentelemetry-instrumentation-sagemaker>=0.40.12 ; extra == 'sagemaker'
72
- Requires-Dist: opentelemetry-instrumentation-together>=0.40.12 ; extra == 'together'
73
- Requires-Dist: opentelemetry-instrumentation-transformers>=0.40.12 ; extra == 'transformers'
74
- Requires-Dist: opentelemetry-instrumentation-vertexai>=0.40.12 ; extra == 'vertexai'
75
- Requires-Dist: opentelemetry-instrumentation-watsonx>=0.40.12 ; extra == 'watsonx'
76
- Requires-Dist: opentelemetry-instrumentation-weaviate>=0.40.12 ; extra == 'weaviate'
29
+ Requires-Dist: opentelemetry-instrumentation-alephalpha>=0.44.0 ; extra == 'alephalpha'
30
+ Requires-Dist: opentelemetry-instrumentation-alephalpha>=0.44.0 ; extra == 'all'
31
+ Requires-Dist: opentelemetry-instrumentation-bedrock>=0.44.0 ; extra == 'all'
32
+ Requires-Dist: opentelemetry-instrumentation-chromadb>=0.44.0 ; extra == 'all'
33
+ Requires-Dist: opentelemetry-instrumentation-cohere>=0.44.0 ; extra == 'all'
34
+ Requires-Dist: opentelemetry-instrumentation-crewai>=0.44.0 ; extra == 'all'
35
+ Requires-Dist: opentelemetry-instrumentation-haystack>=0.44.0 ; extra == 'all'
36
+ Requires-Dist: opentelemetry-instrumentation-lancedb>=0.44.0 ; extra == 'all'
37
+ Requires-Dist: opentelemetry-instrumentation-langchain>=0.44.0 ; extra == 'all'
38
+ Requires-Dist: opentelemetry-instrumentation-llamaindex>=0.44.0 ; extra == 'all'
39
+ Requires-Dist: opentelemetry-instrumentation-marqo>=0.44.0 ; extra == 'all'
40
+ Requires-Dist: opentelemetry-instrumentation-mcp>=0.44.0 ; extra == 'all'
41
+ Requires-Dist: opentelemetry-instrumentation-milvus>=0.44.0 ; extra == 'all'
42
+ Requires-Dist: opentelemetry-instrumentation-mistralai>=0.44.0 ; extra == 'all'
43
+ Requires-Dist: opentelemetry-instrumentation-ollama>=0.44.0 ; extra == 'all'
44
+ Requires-Dist: opentelemetry-instrumentation-pinecone>=0.44.0 ; extra == 'all'
45
+ Requires-Dist: opentelemetry-instrumentation-qdrant>=0.44.0 ; extra == 'all'
46
+ Requires-Dist: opentelemetry-instrumentation-replicate>=0.44.0 ; extra == 'all'
47
+ Requires-Dist: opentelemetry-instrumentation-sagemaker>=0.44.0 ; extra == 'all'
48
+ Requires-Dist: opentelemetry-instrumentation-together>=0.44.0 ; extra == 'all'
49
+ Requires-Dist: opentelemetry-instrumentation-transformers>=0.44.0 ; extra == 'all'
50
+ Requires-Dist: opentelemetry-instrumentation-vertexai>=0.44.0 ; extra == 'all'
51
+ Requires-Dist: opentelemetry-instrumentation-watsonx>=0.44.0 ; extra == 'all'
52
+ Requires-Dist: opentelemetry-instrumentation-weaviate>=0.44.0 ; extra == 'all'
53
+ Requires-Dist: opentelemetry-instrumentation-bedrock>=0.44.0 ; extra == 'bedrock'
54
+ Requires-Dist: opentelemetry-instrumentation-chromadb>=0.44.0 ; extra == 'chromadb'
55
+ Requires-Dist: opentelemetry-instrumentation-cohere>=0.44.0 ; extra == 'cohere'
56
+ Requires-Dist: opentelemetry-instrumentation-crewai>=0.44.0 ; extra == 'crewai'
57
+ Requires-Dist: opentelemetry-instrumentation-haystack>=0.44.0 ; extra == 'haystack'
58
+ Requires-Dist: opentelemetry-instrumentation-lancedb>=0.44.0 ; extra == 'lancedb'
59
+ Requires-Dist: opentelemetry-instrumentation-langchain>=0.44.0 ; extra == 'langchain'
60
+ Requires-Dist: opentelemetry-instrumentation-llamaindex>=0.44.0 ; extra == 'llamaindex'
61
+ Requires-Dist: opentelemetry-instrumentation-marqo>=0.44.0 ; extra == 'marqo'
62
+ Requires-Dist: opentelemetry-instrumentation-mcp>=0.44.0 ; extra == 'mcp'
63
+ Requires-Dist: opentelemetry-instrumentation-milvus>=0.44.0 ; extra == 'milvus'
64
+ Requires-Dist: opentelemetry-instrumentation-mistralai>=0.44.0 ; extra == 'mistralai'
65
+ Requires-Dist: opentelemetry-instrumentation-ollama>=0.44.0 ; extra == 'ollama'
66
+ Requires-Dist: opentelemetry-instrumentation-pinecone>=0.44.0 ; extra == 'pinecone'
67
+ Requires-Dist: opentelemetry-instrumentation-qdrant>=0.44.0 ; extra == 'qdrant'
68
+ Requires-Dist: opentelemetry-instrumentation-replicate>=0.44.0 ; extra == 'replicate'
69
+ Requires-Dist: opentelemetry-instrumentation-sagemaker>=0.44.0 ; extra == 'sagemaker'
70
+ Requires-Dist: opentelemetry-instrumentation-together>=0.44.0 ; extra == 'together'
71
+ Requires-Dist: opentelemetry-instrumentation-transformers>=0.44.0 ; extra == 'transformers'
72
+ Requires-Dist: opentelemetry-instrumentation-vertexai>=0.44.0 ; extra == 'vertexai'
73
+ Requires-Dist: opentelemetry-instrumentation-watsonx>=0.44.0 ; extra == 'watsonx'
74
+ Requires-Dist: opentelemetry-instrumentation-weaviate>=0.44.0 ; extra == 'weaviate'
77
75
  Requires-Python: >=3.10, <4
78
76
  Provides-Extra: alephalpha
79
77
  Provides-Extra: all
@@ -81,7 +79,6 @@ Provides-Extra: bedrock
81
79
  Provides-Extra: chromadb
82
80
  Provides-Extra: cohere
83
81
  Provides-Extra: crewai
84
- Provides-Extra: google-generativeai
85
82
  Provides-Extra: haystack
86
83
  Provides-Extra: lancedb
87
84
  Provides-Extra: langchain
@@ -0,0 +1,145 @@
1
+ # Laminar Python
2
+
3
+ # If you are looking for information about possible extras installations,
4
+ # i.e. what you can pass into `pip install 'lmnr[extra1,extra2]'`, please see the
5
+ # `[project.optional-dependencies]` section below.
6
+
7
+ [project]
8
+ name = "lmnr"
9
+ version = "0.7.2"
10
+ description = "Python SDK for Laminar"
11
+ authors = [
12
+ { name = "lmnr.ai", email = "founders@lmnr.ai" }
13
+ ]
14
+ readme = "README.md"
15
+ requires-python = ">=3.10,<4"
16
+ license = "Apache-2.0"
17
+ dependencies = [
18
+ "pydantic (>=2.0.3,<3.0.0)",
19
+ "python-dotenv (>=1.0)",
20
+ "opentelemetry-api (>=1.33.0)",
21
+ "opentelemetry-sdk (>=1.33.0)",
22
+ "opentelemetry-exporter-otlp-proto-http (>=1.33.0)",
23
+ "opentelemetry-exporter-otlp-proto-grpc (>=1.33.0)",
24
+ "opentelemetry-instrumentation (>=0.54b0)",
25
+ "opentelemetry-semantic-conventions (>=0.54b0)",
26
+ "opentelemetry-semantic-conventions-ai (>=0.4.11)",
27
+ "tqdm (>=4.0)",
28
+ "tenacity (>=8.0)",
29
+ # Since 1.68.0, grpcio writes a warning message
30
+ # that looks scary, but is harmless.
31
+ # WARNING: All log messages before absl::InitializeLog() is called are written to STDERR
32
+ # E0000 00:00:1737439981.199902 9456033 init.cc:229] grpc_wait_for_shutdown_with_timeout() timed out.
33
+ #
34
+ # Remove this comment when we make sure that grpcio has resolved this.
35
+ # Related issue:
36
+ # https://discuss.ai.google.dev/t/warning-all-log-messages-before-absl-initializelog-is-called-are-written-to-stderr-e0000-001731955515-629532-17124-init-cc-229-grpc-wait-for-shutdown-with-timeout-timed-out/50020
37
+ # https://github.com/grpc/grpc/issues/38490
38
+ "grpcio>=1",
39
+ "httpx>=0.25.0",
40
+ "orjson>=3.10.18",
41
+ "packaging>=22.0",
42
+ ]
43
+ # poetry would auto-generate these based on requires-python, but other build
44
+ # systems don't, so we need to specify them manually.
45
+ classifiers = [
46
+ "License :: OSI Approved :: Apache Software License",
47
+ "Programming Language :: Python :: 3",
48
+ "Programming Language :: Python :: 3.10",
49
+ "Programming Language :: Python :: 3.11",
50
+ "Programming Language :: Python :: 3.12",
51
+ "Programming Language :: Python :: 3.13",
52
+ ]
53
+
54
+ [project.scripts]
55
+ lmnr = "lmnr.cli:cli"
56
+
57
+ [project.optional-dependencies]
58
+ # List of all possible extras. You can specify one or more of these extras
59
+ # when installing the package, using any of the following examples:
60
+ # `pip install 'lmnr[anthropic,groq]'`
61
+ # `uv pip install 'lmnr[anthropic,groq]'`
62
+ # `uv add lmnr --extra anthropic --extra groq`
63
+ # `poetry add 'lmnr[anthropic,groq]'`
64
+
65
+ alephalpha=["opentelemetry-instrumentation-alephalpha>=0.44.0"]
66
+ bedrock=["opentelemetry-instrumentation-bedrock>=0.44.0"]
67
+ chromadb=["opentelemetry-instrumentation-chromadb>=0.44.0"]
68
+ cohere=["opentelemetry-instrumentation-cohere>=0.44.0"]
69
+ crewai=["opentelemetry-instrumentation-crewai>=0.44.0"]
70
+ haystack=["opentelemetry-instrumentation-haystack>=0.44.0"]
71
+ lancedb=["opentelemetry-instrumentation-lancedb>=0.44.0"]
72
+ langchain=["opentelemetry-instrumentation-langchain>=0.44.0"]
73
+ llamaindex=["opentelemetry-instrumentation-llamaindex>=0.44.0"]
74
+ marqo=["opentelemetry-instrumentation-marqo>=0.44.0"]
75
+ mcp=["opentelemetry-instrumentation-mcp>=0.44.0"]
76
+ milvus=["opentelemetry-instrumentation-milvus>=0.44.0"]
77
+ mistralai=["opentelemetry-instrumentation-mistralai>=0.44.0"]
78
+ ollama=["opentelemetry-instrumentation-ollama>=0.44.0"]
79
+ pinecone=["opentelemetry-instrumentation-pinecone>=0.44.0"]
80
+ qdrant=["opentelemetry-instrumentation-qdrant>=0.44.0"]
81
+ replicate=["opentelemetry-instrumentation-replicate>=0.44.0"]
82
+ sagemaker=["opentelemetry-instrumentation-sagemaker>=0.44.0"]
83
+ together=["opentelemetry-instrumentation-together>=0.44.0"]
84
+ transformers=["opentelemetry-instrumentation-transformers>=0.44.0"]
85
+ vertexai=["opentelemetry-instrumentation-vertexai>=0.44.0"]
86
+ watsonx=["opentelemetry-instrumentation-watsonx>=0.44.0"]
87
+ weaviate=["opentelemetry-instrumentation-weaviate>=0.44.0"]
88
+ # `all` is the group added for convenience, if you want to install all
89
+ # the instrumentations.
90
+ # we suggest using package-manager-specific commands instead,
91
+ # like `uv add lmnr --all-extras`
92
+ all = [
93
+ "opentelemetry-instrumentation-alephalpha>=0.44.0",
94
+ "opentelemetry-instrumentation-bedrock>=0.44.0",
95
+ "opentelemetry-instrumentation-chromadb>=0.44.0",
96
+ "opentelemetry-instrumentation-cohere>=0.44.0",
97
+ "opentelemetry-instrumentation-crewai>=0.44.0",
98
+ "opentelemetry-instrumentation-haystack>=0.44.0",
99
+ "opentelemetry-instrumentation-lancedb>=0.44.0",
100
+ "opentelemetry-instrumentation-langchain>=0.44.0",
101
+ "opentelemetry-instrumentation-llamaindex>=0.44.0",
102
+ "opentelemetry-instrumentation-marqo>=0.44.0",
103
+ "opentelemetry-instrumentation-mcp>=0.44.0",
104
+ "opentelemetry-instrumentation-milvus>=0.44.0",
105
+ "opentelemetry-instrumentation-mistralai>=0.44.0",
106
+ "opentelemetry-instrumentation-ollama>=0.44.0",
107
+ "opentelemetry-instrumentation-pinecone>=0.44.0",
108
+ "opentelemetry-instrumentation-qdrant>=0.44.0",
109
+ "opentelemetry-instrumentation-replicate>=0.44.0",
110
+ "opentelemetry-instrumentation-sagemaker>=0.44.0",
111
+ "opentelemetry-instrumentation-together>=0.44.0",
112
+ "opentelemetry-instrumentation-transformers>=0.44.0",
113
+ "opentelemetry-instrumentation-vertexai>=0.44.0",
114
+ "opentelemetry-instrumentation-watsonx>=0.44.0",
115
+ "opentelemetry-instrumentation-weaviate>=0.44.0"
116
+ ]
117
+
118
+ [dependency-groups]
119
+ dev = [
120
+ "autopep8>=2.3.2",
121
+ "flake8>=7.2.0",
122
+ "pytest>=8.3.5",
123
+ "pytest-sugar>=1.0.0",
124
+ "pytest-asyncio>=0.26.0",
125
+ "playwright>=1.52.0",
126
+ "vcrpy>=7.0.0",
127
+ "openai>=1.98.0",
128
+ "pytest-recording>=0.13.4",
129
+ "patchright>=1.52.3",
130
+ "google-genai>=1.19.0",
131
+ "langgraph>=0.4.8",
132
+ "langchain-core>=0.3.64",
133
+ "langchain>=0.3.25",
134
+ "litellm>=1.72.6",
135
+ "groq>=0.30.0",
136
+ "anthropic>=0.60.0",
137
+ "langchain-openai>=0.3.28",
138
+ ]
139
+
140
+ [build-system]
141
+ requires = ["uv_build>=0.7.21,<0.8"]
142
+ build-backend = "uv_build"
143
+
144
+ [tool.uv.workspace]
145
+ members = ["examples/fastapi-app"]
@@ -6,8 +6,15 @@ import types
6
6
  from typing import Any, AsyncGenerator, Callable, Generator, Literal
7
7
 
8
8
  from opentelemetry import context as context_api
9
- from opentelemetry.trace import Span
10
-
9
+ from opentelemetry.trace import Span, Status, StatusCode
10
+
11
+ from lmnr.opentelemetry_lib.tracing.context import (
12
+ CONTEXT_SESSION_ID_KEY,
13
+ CONTEXT_USER_ID_KEY,
14
+ attach_context,
15
+ detach_context,
16
+ get_event_attributes_from_context,
17
+ )
11
18
  from lmnr.sdk.utils import get_input_from_func_args, is_method
12
19
  from lmnr.opentelemetry_lib import MAX_MANUAL_SPAN_PAYLOAD_SIZE
13
20
  from lmnr.opentelemetry_lib.tracing.tracer import get_tracer_with_context
@@ -180,7 +187,21 @@ def observe_base(
180
187
 
181
188
  span = _setup_span(span_name, span_type, association_properties)
182
189
  new_context = wrapper.push_span_context(span)
190
+ if session_id := association_properties.get("session_id"):
191
+ new_context = context_api.set_value(
192
+ CONTEXT_SESSION_ID_KEY, session_id, new_context
193
+ )
194
+ if user_id := association_properties.get("user_id"):
195
+ new_context = context_api.set_value(
196
+ CONTEXT_USER_ID_KEY, user_id, new_context
197
+ )
198
+ # Some auto-instrumentations are not under our control, so they
199
+ # don't have access to our isolated context. We attach the context
200
+ # to the OTEL global context, so that spans know their parent
201
+ # span and trace_id.
183
202
  ctx_token = context_api.attach(new_context)
203
+ # update our isolated context too
204
+ isolated_ctx_token = attach_context(new_context)
184
205
 
185
206
  _process_input(
186
207
  span, fn, args, kwargs, ignore_input, ignore_inputs, input_formatter
@@ -195,7 +216,7 @@ def observe_base(
195
216
  finally:
196
217
  # Always restore global context
197
218
  context_api.detach(ctx_token)
198
-
219
+ detach_context(isolated_ctx_token)
199
220
  # span will be ended in the generator
200
221
  if isinstance(res, types.GeneratorType):
201
222
  return _handle_generator(span, ctx_token, res)
@@ -240,7 +261,21 @@ def async_observe_base(
240
261
 
241
262
  span = _setup_span(span_name, span_type, association_properties)
242
263
  new_context = wrapper.push_span_context(span)
264
+ if session_id := association_properties.get("session_id"):
265
+ new_context = context_api.set_value(
266
+ CONTEXT_SESSION_ID_KEY, session_id, new_context
267
+ )
268
+ if user_id := association_properties.get("user_id"):
269
+ new_context = context_api.set_value(
270
+ CONTEXT_USER_ID_KEY, user_id, new_context
271
+ )
272
+ # Some auto-instrumentations are not under our control, so they
273
+ # don't have access to our isolated context. We attach the context
274
+ # to the OTEL global context, so that spans know their parent
275
+ # span and trace_id.
243
276
  ctx_token = context_api.attach(new_context)
277
+ # update our isolated context too
278
+ isolated_ctx_token = attach_context(new_context)
244
279
 
245
280
  _process_input(
246
281
  span, fn, args, kwargs, ignore_input, ignore_inputs, input_formatter
@@ -255,6 +290,7 @@ def async_observe_base(
255
290
  finally:
256
291
  # Always restore global context
257
292
  context_api.detach(ctx_token)
293
+ detach_context(isolated_ctx_token)
258
294
 
259
295
  # span will be ended in the generator
260
296
  if isinstance(res, types.AsyncGeneratorType):
@@ -288,4 +324,7 @@ async def _ahandle_generator(span: Span, wrapper: TracerWrapper, res: AsyncGener
288
324
 
289
325
  def _process_exception(span: Span, e: Exception):
290
326
  # Note that this `escaped` is sent as a StringValue("True"), not a boolean.
291
- span.record_exception(e, escaped=True)
327
+ span.record_exception(
328
+ e, attributes=get_event_attributes_from_context(), escaped=True
329
+ )
330
+ span.set_status(Status(StatusCode.ERROR, str(e)))
@@ -7,6 +7,7 @@ from opentelemetry.trace import SpanKind, Status, StatusCode, Tracer
7
7
  from lmnr.opentelemetry_lib.litellm.utils import model_as_dict, set_span_attribute
8
8
  from lmnr.opentelemetry_lib.tracing import TracerWrapper
9
9
 
10
+ from lmnr.opentelemetry_lib.tracing.context import get_event_attributes_from_context
10
11
  from lmnr.opentelemetry_lib.utils.package_check import is_package_installed
11
12
  from lmnr.sdk.log import get_default_logger
12
13
 
@@ -141,10 +142,12 @@ try:
141
142
  else:
142
143
  span.set_status(Status(StatusCode.ERROR))
143
144
  if isinstance(response_obj, Exception):
144
- span.record_exception(response_obj)
145
+ attributes = get_event_attributes_from_context()
146
+ span.record_exception(response_obj, attributes=attributes)
145
147
 
146
148
  except Exception as e:
147
- span.record_exception(e)
149
+ attributes = get_event_attributes_from_context()
150
+ span.record_exception(e, attributes=attributes)
148
151
  logger.error(f"Error in Laminar LiteLLM instrumentation: {e}")
149
152
  finally:
150
153
  span.end(int(end_time.timestamp() * 1e9))
@@ -29,6 +29,10 @@ from .utils import (
29
29
  shared_metrics_attributes,
30
30
  should_emit_events,
31
31
  )
32
+ from .streaming import (
33
+ WrappedAsyncMessageStreamManager,
34
+ WrappedMessageStreamManager,
35
+ )
32
36
  from .version import __version__
33
37
 
34
38
  from lmnr.opentelemetry_lib.tracing.context import get_current_context
@@ -52,6 +56,7 @@ logger = logging.getLogger(__name__)
52
56
 
53
57
  _instruments = ("anthropic >= 0.3.11",)
54
58
 
59
+
55
60
  WRAPPED_METHODS = [
56
61
  {
57
62
  "package": "anthropic.resources.completions",
@@ -71,6 +76,15 @@ WRAPPED_METHODS = [
71
76
  "method": "stream",
72
77
  "span_name": "anthropic.chat",
73
78
  },
79
+ # This method is on an async resource, but is meant to be called as
80
+ # an async context manager (async with), which we don't need to await;
81
+ # thus, we wrap it with a sync wrapper
82
+ {
83
+ "package": "anthropic.resources.messages",
84
+ "object": "AsyncMessages",
85
+ "method": "stream",
86
+ "span_name": "anthropic.chat",
87
+ },
74
88
  ]
75
89
 
76
90
  WRAPPED_AMETHODS = [
@@ -86,12 +100,6 @@ WRAPPED_AMETHODS = [
86
100
  "method": "create",
87
101
  "span_name": "anthropic.chat",
88
102
  },
89
- {
90
- "package": "anthropic.resources.messages",
91
- "object": "AsyncMessages",
92
- "method": "stream",
93
- "span_name": "anthropic.chat",
94
- },
95
103
  ]
96
104
 
97
105
 
@@ -99,6 +107,23 @@ def is_streaming_response(response):
99
107
  return isinstance(response, Stream) or isinstance(response, AsyncStream)
100
108
 
101
109
 
110
+ def is_stream_manager(response):
111
+ """Check if response is a MessageStreamManager or AsyncMessageStreamManager"""
112
+ try:
113
+ from anthropic.lib.streaming._messages import (
114
+ MessageStreamManager,
115
+ AsyncMessageStreamManager,
116
+ )
117
+
118
+ return isinstance(response, (MessageStreamManager, AsyncMessageStreamManager))
119
+ except ImportError:
120
+ # Check by class name as fallback
121
+ return (
122
+ response.__class__.__name__ == "MessageStreamManager"
123
+ or response.__class__.__name__ == "AsyncMessageStreamManager"
124
+ )
125
+
126
+
102
127
  @dont_throw
103
128
  async def _aset_token_usage(
104
129
  span,
@@ -437,6 +462,33 @@ def _wrap(
437
462
  event_logger,
438
463
  kwargs,
439
464
  )
465
+ elif is_stream_manager(response):
466
+ if response.__class__.__name__ == "AsyncMessageStreamManager":
467
+ return WrappedAsyncMessageStreamManager(
468
+ response,
469
+ span,
470
+ instance._client,
471
+ start_time,
472
+ token_histogram,
473
+ choice_counter,
474
+ duration_histogram,
475
+ exception_counter,
476
+ event_logger,
477
+ kwargs,
478
+ )
479
+ else:
480
+ return WrappedMessageStreamManager(
481
+ response,
482
+ span,
483
+ instance._client,
484
+ start_time,
485
+ token_histogram,
486
+ choice_counter,
487
+ duration_histogram,
488
+ exception_counter,
489
+ event_logger,
490
+ kwargs,
491
+ )
440
492
  elif response:
441
493
  try:
442
494
  metric_attributes = shared_metrics_attributes(response)
@@ -532,6 +584,33 @@ async def _awrap(
532
584
  event_logger,
533
585
  kwargs,
534
586
  )
587
+ elif is_stream_manager(response):
588
+ if response.__class__.__name__ == "AsyncMessageStreamManager":
589
+ return WrappedAsyncMessageStreamManager(
590
+ response,
591
+ span,
592
+ instance._client,
593
+ start_time,
594
+ token_histogram,
595
+ choice_counter,
596
+ duration_histogram,
597
+ exception_counter,
598
+ event_logger,
599
+ kwargs,
600
+ )
601
+ else:
602
+ return WrappedMessageStreamManager(
603
+ response,
604
+ span,
605
+ instance._client,
606
+ start_time,
607
+ token_histogram,
608
+ choice_counter,
609
+ duration_histogram,
610
+ exception_counter,
611
+ event_logger,
612
+ kwargs,
613
+ )
535
614
  elif response:
536
615
  metric_attributes = shared_metrics_attributes(response)
537
616
 
@@ -113,18 +113,43 @@ async def aset_input_attributes(span, kwargs):
113
113
  )
114
114
  for i, message in enumerate(kwargs.get("messages")):
115
115
  prompt_index = i + (1 if has_system_message else 0)
116
+ content = message.get("content")
117
+ tool_use_blocks = []
118
+ other_blocks = []
119
+ if isinstance(content, list):
120
+ for block in content:
121
+ if dict(block).get("type") == "tool_use":
122
+ tool_use_blocks.append(dict(block))
123
+ else:
124
+ other_blocks.append(block)
125
+ content = other_blocks
116
126
  set_span_attribute(
117
127
  span,
118
128
  f"{SpanAttributes.LLM_PROMPTS}.{prompt_index}.content",
119
- await _dump_content(
120
- message_index=i, span=span, content=message.get("content")
121
- ),
129
+ await _dump_content(message_index=i, span=span, content=content),
122
130
  )
123
131
  set_span_attribute(
124
132
  span,
125
133
  f"{SpanAttributes.LLM_PROMPTS}.{prompt_index}.role",
126
134
  message.get("role"),
127
135
  )
136
+ if tool_use_blocks:
137
+ for tool_num, tool_use_block in enumerate(tool_use_blocks):
138
+ set_span_attribute(
139
+ span,
140
+ f"{SpanAttributes.LLM_PROMPTS}.{prompt_index}.tool_calls.{tool_num}.id",
141
+ tool_use_block.get("id"),
142
+ )
143
+ set_span_attribute(
144
+ span,
145
+ f"{SpanAttributes.LLM_PROMPTS}.{prompt_index}.tool_calls.{tool_num}.name",
146
+ tool_use_block.get("name"),
147
+ )
148
+ set_span_attribute(
149
+ span,
150
+ f"{SpanAttributes.LLM_PROMPTS}.{prompt_index}.tool_calls.{tool_num}.arguments",
151
+ json.dumps(tool_use_block.get("input")),
152
+ )
128
153
 
129
154
  if kwargs.get("tools") is not None:
130
155
  for i, tool in enumerate(kwargs.get("tools")):
@@ -160,8 +185,8 @@ def _set_span_completions(span, response):
160
185
  content_block_type = content.type
161
186
  # usually, Antrhopic responds with just one text block,
162
187
  # but the API allows for multiple text blocks, so concatenate them
163
- if content_block_type == "text":
164
- text += content.text
188
+ if content_block_type == "text" and hasattr(content, "text"):
189
+ text += content.text or ""
165
190
  elif content_block_type == "thinking":
166
191
  content = dict(content)
167
192
  # override the role to thinking
@@ -242,15 +267,33 @@ def set_streaming_response_attributes(span, complete_response_events):
242
267
  if not span.is_recording() or not complete_response_events:
243
268
  return
244
269
 
245
- try:
246
- for event in complete_response_events:
247
- index = event.get("index")
248
- prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{index}"
270
+ index = 0
271
+ for event in complete_response_events:
272
+ prefix = f"{SpanAttributes.LLM_COMPLETIONS}.{index}"
273
+ set_span_attribute(span, f"{prefix}.finish_reason", event.get("finish_reason"))
274
+ role = "thinking" if event.get("type") == "thinking" else "assistant"
275
+ # Thinking is added as a separate completion, so we need to increment the index
276
+ if event.get("type") == "thinking":
277
+ index += 1
278
+ set_span_attribute(span, f"{prefix}.role", role)
279
+ if event.get("type") == "tool_use":
280
+ set_span_attribute(
281
+ span,
282
+ f"{prefix}.tool_calls.0.id",
283
+ event.get("id"),
284
+ )
249
285
  set_span_attribute(
250
- span, f"{prefix}.finish_reason", event.get("finish_reason")
286
+ span,
287
+ f"{prefix}.tool_calls.0.name",
288
+ event.get("name"),
251
289
  )
252
- role = "thinking" if event.get("type") == "thinking" else "assistant"
253
- set_span_attribute(span, f"{prefix}.role", role)
290
+ tool_arguments = event.get("input")
291
+ if tool_arguments is not None:
292
+ set_span_attribute(
293
+ span,
294
+ f"{prefix}.tool_calls.0.arguments",
295
+ # already stringified
296
+ tool_arguments,
297
+ )
298
+ else:
254
299
  set_span_attribute(span, f"{prefix}.content", event.get("text"))
255
- except Exception as e:
256
- logger.warning("Failed to set completion attributes, error: %s", str(e))