paid-python 1.2.0__tar.gz → 1.2.1__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 (125) hide show
  1. {paid_python-1.2.0 → paid_python-1.2.1}/PKG-INFO +1 -1
  2. {paid_python-1.2.0 → paid_python-1.2.1}/pyproject.toml +1 -1
  3. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/client_wrapper.py +2 -2
  4. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/autoinstrumentation.py +3 -0
  5. paid_python-1.2.1/src/paid/tracing/openai_agents_patches/__init__.py +15 -0
  6. paid_python-1.2.1/src/paid/tracing/openai_agents_patches/patches.py +189 -0
  7. {paid_python-1.2.0 → paid_python-1.2.1}/LICENSE +0 -0
  8. {paid_python-1.2.0 → paid_python-1.2.1}/README.md +0 -0
  9. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/__init__.py +0 -0
  10. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/client.py +0 -0
  11. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/contacts/__init__.py +0 -0
  12. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/contacts/client.py +0 -0
  13. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/contacts/raw_client.py +0 -0
  14. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/contacts/types/__init__.py +0 -0
  15. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/contacts/types/create_contact_request_roles_item.py +0 -0
  16. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/__init__.py +0 -0
  17. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/api_error.py +0 -0
  18. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/datetime_utils.py +0 -0
  19. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/file.py +0 -0
  20. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/force_multipart.py +0 -0
  21. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/http_client.py +0 -0
  22. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/http_response.py +0 -0
  23. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/http_sse/__init__.py +0 -0
  24. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/http_sse/_api.py +0 -0
  25. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/http_sse/_decoders.py +0 -0
  26. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/http_sse/_exceptions.py +0 -0
  27. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/http_sse/_models.py +0 -0
  28. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/jsonable_encoder.py +0 -0
  29. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/pydantic_utilities.py +0 -0
  30. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/query_encoder.py +0 -0
  31. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/remove_none_from_dict.py +0 -0
  32. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/request_options.py +0 -0
  33. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/core/serialization.py +0 -0
  34. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/customers/__init__.py +0 -0
  35. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/customers/client.py +0 -0
  36. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/customers/raw_client.py +0 -0
  37. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/environment.py +0 -0
  38. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/errors/__init__.py +0 -0
  39. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/errors/bad_request_error.py +0 -0
  40. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/errors/forbidden_error.py +0 -0
  41. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/errors/internal_server_error.py +0 -0
  42. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/errors/not_found_error.py +0 -0
  43. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/invoices/__init__.py +0 -0
  44. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/invoices/client.py +0 -0
  45. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/invoices/raw_client.py +0 -0
  46. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/logger.py +0 -0
  47. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/orders/__init__.py +0 -0
  48. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/orders/client.py +0 -0
  49. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/orders/raw_client.py +0 -0
  50. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/products/__init__.py +0 -0
  51. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/products/client.py +0 -0
  52. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/products/raw_client.py +0 -0
  53. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/py.typed +0 -0
  54. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/signals/__init__.py +0 -0
  55. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/signals/client.py +0 -0
  56. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/signals/raw_client.py +0 -0
  57. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/__init__.py +0 -0
  58. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/anthropic_patches/__init__.py +0 -0
  59. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/anthropic_patches/patches.py +0 -0
  60. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/context_data.py +0 -0
  61. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/context_manager.py +0 -0
  62. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/distributed_tracing.py +0 -0
  63. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/gemini_patches/__init__.py +0 -0
  64. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/gemini_patches/patches.py +0 -0
  65. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/signal.py +0 -0
  66. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/tracing.py +0 -0
  67. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/wrappers/__init__.py +0 -0
  68. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/wrappers/anthropic/__init__.py +0 -0
  69. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/wrappers/anthropic/anthropicWrapper.py +0 -0
  70. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/wrappers/bedrock/__init__.py +0 -0
  71. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/wrappers/bedrock/bedrockWrapper.py +0 -0
  72. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/wrappers/gemini/__init__.py +0 -0
  73. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/wrappers/gemini/geminiWrapper.py +0 -0
  74. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/wrappers/langchain/__init__.py +0 -0
  75. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/wrappers/langchain/paidLangChainCallback.py +0 -0
  76. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/wrappers/mistral/__init__.py +0 -0
  77. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/wrappers/mistral/mistralWrapper.py +0 -0
  78. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/wrappers/openai/__init__.py +0 -0
  79. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/wrappers/openai/openAiWrapper.py +0 -0
  80. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/wrappers/openai_agents/__init__.py +0 -0
  81. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/wrappers/openai_agents/openaiAgentsHook.py +0 -0
  82. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/tracing/wrappers/utils.py +0 -0
  83. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/__init__.py +0 -0
  84. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/attribution.py +0 -0
  85. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/bulk_signals_response.py +0 -0
  86. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/contact.py +0 -0
  87. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/contact_billing_address.py +0 -0
  88. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/contact_list_response.py +0 -0
  89. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/contact_roles_item.py +0 -0
  90. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/create_order_line_attribute_request.py +0 -0
  91. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/create_order_line_request.py +0 -0
  92. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/customer.py +0 -0
  93. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/customer_attribution.py +0 -0
  94. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/customer_billing_address.py +0 -0
  95. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/customer_by_external_id.py +0 -0
  96. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/customer_by_id.py +0 -0
  97. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/customer_creation_state.py +0 -0
  98. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/customer_list_response.py +0 -0
  99. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/empty_response.py +0 -0
  100. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/error_response.py +0 -0
  101. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/invoice.py +0 -0
  102. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/invoice_line.py +0 -0
  103. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/invoice_line_payment_status.py +0 -0
  104. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/invoice_lines_response.py +0 -0
  105. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/invoice_list_response.py +0 -0
  106. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/invoice_payment_status.py +0 -0
  107. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/invoice_source.py +0 -0
  108. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/invoice_status.py +0 -0
  109. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/invoice_tax_status.py +0 -0
  110. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/order.py +0 -0
  111. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/order_creation_state.py +0 -0
  112. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/order_line.py +0 -0
  113. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/order_lines_response.py +0 -0
  114. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/order_list_response.py +0 -0
  115. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/pagination.py +0 -0
  116. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/product.py +0 -0
  117. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/product_by_external_id.py +0 -0
  118. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/product_by_id.py +0 -0
  119. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/product_list_response.py +0 -0
  120. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/signal.py +0 -0
  121. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/update_contact_request.py +0 -0
  122. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/update_contact_request_roles_item.py +0 -0
  123. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/update_customer_request.py +0 -0
  124. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/types/update_product_request.py +0 -0
  125. {paid_python-1.2.0 → paid_python-1.2.1}/src/paid/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: paid-python
3
- Version: 1.2.0
3
+ Version: 1.2.1
4
4
  Summary:
5
5
  Requires-Python: >=3.10,<3.14
6
6
  Classifier: Intended Audience :: Developers
@@ -4,7 +4,7 @@ dynamic = ["version"]
4
4
 
5
5
  [tool.poetry]
6
6
  name = "paid-python"
7
- version = "1.2.0"
7
+ version = "1.2.1"
8
8
  description = ""
9
9
  readme = "README.md"
10
10
  authors = []
@@ -24,12 +24,12 @@ class BaseClientWrapper:
24
24
  import platform
25
25
 
26
26
  headers: typing.Dict[str, str] = {
27
- "User-Agent": "paid-python/1.2.0",
27
+ "User-Agent": "paid-python/1.2.1",
28
28
  "X-Fern-Language": "Python",
29
29
  "X-Fern-Runtime": f"python/{platform.python_version()}",
30
30
  "X-Fern-Platform": f"{platform.system().lower()}/{platform.release()}",
31
31
  "X-Fern-SDK-Name": "paid-python",
32
- "X-Fern-SDK-Version": "1.2.0",
32
+ "X-Fern-SDK-Version": "1.2.1",
33
33
  **(self.get_custom_headers() or {}),
34
34
  }
35
35
  headers["Authorization"] = f"Bearer {self._get_token()}"
@@ -203,10 +203,13 @@ def _instrument_openai_agents() -> None:
203
203
  logger.warning("OpenAI Agents library not available, skipping instrumentation")
204
204
  return
205
205
 
206
+ from .openai_agents_patches import instrument_openai_agents
207
+
206
208
  logger.debug("[paid:autoinstrument] Instrumenting openai-agents with OpenAIAgentsInstrumentor, provider=%s",
207
209
  type(tracing.paid_tracer_provider).__name__)
208
210
  # Instrument OpenAI Agents with Paid's tracer provider
209
211
  OpenAIAgentsInstrumentor().instrument(tracer_provider=tracing.paid_tracer_provider)
212
+ instrument_openai_agents()
210
213
 
211
214
  _initialized_instrumentors.append("openai-agents")
212
215
  logger.info("OpenAI Agents auto-instrumentation enabled")
@@ -0,0 +1,15 @@
1
+ """Patches for openinference-instrumentation-openai-agents.
2
+
3
+ Adds tool metadata to function/tool spans by carrying schema details from
4
+ response spans onto the later function execution spans.
5
+ """
6
+
7
+ from .patches import (
8
+ instrument_openai_agents,
9
+ uninstrument_openai_agents,
10
+ )
11
+
12
+ __all__ = [
13
+ "instrument_openai_agents",
14
+ "uninstrument_openai_agents",
15
+ ]
@@ -0,0 +1,189 @@
1
+ """Monkey-patches for openinference-instrumentation-openai-agents.
2
+
3
+ Upstream records full tool schemas on response spans, but function/tool spans only
4
+ get `tool.name`. This patch caches function tool metadata per trace when the
5
+ response span ends, then applies that metadata to subsequent function spans.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from datetime import datetime
11
+ from typing import Any, Optional
12
+
13
+ from agents.tracing.span_data import FunctionSpanData, ResponseSpanData
14
+ from openai.types.responses import FunctionTool, Response
15
+ from openinference.instrumentation import safe_json_dumps
16
+ from opentelemetry.context import detach
17
+ from opentelemetry.trace import Status, StatusCode
18
+ from opentelemetry.util.types import AttributeValue
19
+
20
+ from paid.logger import logger
21
+
22
+ _originals: dict[str, Any] = {}
23
+ _SEMCONV_FALLBACKS = {
24
+ "TOOL_DESCRIPTION": "tool.description",
25
+ "TOOL_PARAMETERS": "tool.parameters",
26
+ "TOOL_JSON_SCHEMA": "tool.json_schema",
27
+ }
28
+
29
+
30
+ def instrument_openai_agents() -> None:
31
+ """Apply all OpenAI Agents patches. Call after instrumenting the SDK."""
32
+ _patch_tracing_processor()
33
+
34
+
35
+ def uninstrument_openai_agents() -> None:
36
+ """Restore original OpenAI Agents methods."""
37
+ try:
38
+ from openinference.instrumentation.openai_agents import _processor as processor_mod
39
+ except ImportError:
40
+ _originals.clear()
41
+ return
42
+
43
+ processor = processor_mod.OpenInferenceTracingProcessor
44
+ if "on_span_end" in _originals:
45
+ processor.on_span_end = _originals.pop("on_span_end") # type: ignore[method-assign]
46
+ if "on_trace_end" in _originals:
47
+ processor.on_trace_end = _originals.pop("on_trace_end") # type: ignore[method-assign]
48
+ _originals.clear()
49
+
50
+
51
+ def _patch_tracing_processor() -> None:
52
+ try:
53
+ from openinference.instrumentation.openai_agents import _processor as processor_mod
54
+ except ImportError:
55
+ logger.debug("Could not import openai-agents tracing processor, skipping patch")
56
+ return
57
+
58
+ processor = processor_mod.OpenInferenceTracingProcessor
59
+ if "on_span_end" in _originals:
60
+ return
61
+
62
+ _originals["on_span_end"] = processor.on_span_end
63
+ _originals["on_trace_end"] = processor.on_trace_end
64
+
65
+ def _patched_on_trace_end(self, trace): # type: ignore[misc]
66
+ try:
67
+ return _originals["on_trace_end"](self, trace)
68
+ finally:
69
+ tool_cache = getattr(self, "_paid_tool_schemas_by_trace", None)
70
+ if isinstance(tool_cache, dict):
71
+ tool_cache.pop(trace.trace_id, None)
72
+
73
+ def _patched_on_span_end(self, span): # type: ignore[misc]
74
+ if token := self._tokens.pop(span.span_id, None):
75
+ detach(token) # type: ignore[arg-type]
76
+ if not (otel_span := self._otel_spans.pop(span.span_id, None)):
77
+ return
78
+
79
+ processing_error: Exception | None = None
80
+ end_time: Optional[int] = None
81
+ try:
82
+ otel_span.update_name(processor_mod._get_span_name(span))
83
+ data = span.span_data
84
+ if isinstance(data, ResponseSpanData):
85
+ if hasattr(data, "response") and isinstance(response := data.response, Response):
86
+ _cache_tool_schemas(self, span.trace_id, response)
87
+ otel_span.set_attribute(processor_mod.OUTPUT_MIME_TYPE, processor_mod.JSON)
88
+ otel_span.set_attribute(processor_mod.OUTPUT_VALUE, response.model_dump_json())
89
+ for k, v in processor_mod._get_attributes_from_response(response):
90
+ otel_span.set_attribute(k, v)
91
+ if hasattr(data, "input") and (input := data.input):
92
+ if isinstance(input, str):
93
+ otel_span.set_attribute(processor_mod.INPUT_VALUE, input)
94
+ elif isinstance(input, list):
95
+ otel_span.set_attribute(processor_mod.INPUT_MIME_TYPE, processor_mod.JSON)
96
+ otel_span.set_attribute(processor_mod.INPUT_VALUE, safe_json_dumps(input))
97
+ for k, v in processor_mod._get_attributes_from_input(input):
98
+ otel_span.set_attribute(k, v)
99
+ elif isinstance(data, FunctionSpanData):
100
+ for k, v in processor_mod._get_attributes_from_function_span_data(data):
101
+ otel_span.set_attribute(k, v)
102
+ for k, v in _get_enriched_function_attributes(self, span.trace_id, data.name):
103
+ otel_span.set_attribute(k, v)
104
+ elif isinstance(data, processor_mod.MCPListToolsSpanData):
105
+ for k, v in processor_mod._get_attributes_from_mcp_list_tool_span_data(data):
106
+ otel_span.set_attribute(k, v)
107
+ elif isinstance(data, processor_mod.HandoffSpanData):
108
+ if data.to_agent and data.from_agent:
109
+ key = f"{data.to_agent}:{span.trace_id}"
110
+ self._reverse_handoffs_dict[key] = data.from_agent
111
+ while len(self._reverse_handoffs_dict) > self._MAX_HANDOFFS_IN_FLIGHT:
112
+ self._reverse_handoffs_dict.popitem(last=False)
113
+ elif isinstance(data, processor_mod.AgentSpanData):
114
+ otel_span.set_attribute(processor_mod.GRAPH_NODE_ID, data.name)
115
+ key = f"{data.name}:{span.trace_id}"
116
+ if parent_node := self._reverse_handoffs_dict.pop(key, None):
117
+ otel_span.set_attribute(processor_mod.GRAPH_NODE_PARENT_ID, parent_node)
118
+ elif isinstance(data, processor_mod.GenerationSpanData):
119
+ for k, v in processor_mod._get_attributes_from_generation_span_data(data):
120
+ otel_span.set_attribute(k, v)
121
+ elif isinstance(data, (processor_mod.CustomSpanData, processor_mod.GuardrailSpanData)):
122
+ for k, v in processor_mod._flatten(data.export()):
123
+ otel_span.set_attribute(k, v)
124
+ except Exception as exc:
125
+ processing_error = exc
126
+ logger.debug("Failed to enrich openai-agents span", exc_info=True)
127
+ try:
128
+ otel_span.record_exception(exc)
129
+ except Exception:
130
+ logger.debug("Failed to record openai-agents patch exception", exc_info=True)
131
+ finally:
132
+ if span.ended_at:
133
+ try:
134
+ end_time = processor_mod._as_utc_nano(datetime.fromisoformat(span.ended_at))
135
+ except ValueError:
136
+ pass
137
+ if processing_error is not None:
138
+ otel_span.set_status(Status(StatusCode.ERROR, str(processing_error)))
139
+ else:
140
+ otel_span.set_status(status=processor_mod._get_span_status(span))
141
+ otel_span.end(end_time)
142
+
143
+ processor.on_trace_end = _patched_on_trace_end # type: ignore[method-assign]
144
+ processor.on_span_end = _patched_on_span_end # type: ignore[method-assign]
145
+ logger.debug("Patched OpenInferenceTracingProcessor to enrich openai-agents tool spans")
146
+
147
+
148
+ def _cache_tool_schemas(processor: Any, trace_id: str, response: Response) -> None:
149
+ per_trace = getattr(processor, "_paid_tool_schemas_by_trace", None)
150
+ if not isinstance(per_trace, dict):
151
+ per_trace = {}
152
+ setattr(processor, "_paid_tool_schemas_by_trace", per_trace)
153
+
154
+ tool_map = per_trace.setdefault(trace_id, {})
155
+ for tool in response.tools or []:
156
+ if not isinstance(tool, FunctionTool):
157
+ continue
158
+ attrs: dict[str, AttributeValue] = {}
159
+ if tool.description:
160
+ attrs[processor_mod_attr("TOOL_DESCRIPTION")] = tool.description
161
+ if tool.parameters is not None:
162
+ attrs[processor_mod_attr("TOOL_PARAMETERS")] = safe_json_dumps(tool.parameters)
163
+ attrs[processor_mod_attr("TOOL_JSON_SCHEMA")] = safe_json_dumps(
164
+ {
165
+ "type": "function",
166
+ "function": {
167
+ "name": tool.name,
168
+ "description": tool.description,
169
+ "parameters": tool.parameters,
170
+ "strict": tool.strict,
171
+ },
172
+ }
173
+ )
174
+ tool_map[tool.name] = attrs
175
+
176
+
177
+ def _get_enriched_function_attributes(
178
+ processor: Any,
179
+ trace_id: str,
180
+ tool_name: str,
181
+ ):
182
+ tool_map = getattr(processor, "_paid_tool_schemas_by_trace", {}).get(trace_id, {})
183
+ yield from tool_map.get(tool_name, {}).items()
184
+
185
+
186
+ def processor_mod_attr(name: str) -> str:
187
+ from openinference.instrumentation.openai_agents import _processor as processor_mod
188
+
189
+ return getattr(processor_mod, name, _SEMCONV_FALLBACKS.get(name, name.lower()))
File without changes
File without changes