diff --git a/CHANGELOG.md b/CHANGELOG.md index ef615a7..5278cc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on Keep a Changelog and this project adheres to Semantic Versioning. -## [0.1.97b1] - 2026-07-28 +## [0.1.97] - - **Label evaluation/simulation traces on the root span** - Root spans produced by evaluation test runs (`Netra.evaluation`) and simulation runs (`Netra.simulation`) now carry a `netra.trace.origin` attribute set to `evaluation`, letting the backend and frontend distinguish these traces from normal workflow invocations. @@ -24,6 +24,8 @@ The format is based on Keep a Changelog and this project adheres to Semantic Ver - **Refactor stream wrapper architecture to use callback injection** - `stream_utils` is now a pure utility module with no Netra-internal imports. The commit logic (serialize and set attribute on root span) is injected as a callback from `SessionManager`, eliminating the circular dependency between `stream_utils` and `SessionManager`. +- **Fix OpenAI Responses API stream handling** — `Response API` instrumentation spans now include token usage and completion output when a stream ends due to reaching the token limit (`incomplete` status). + ## [0.1.96] - 2026-07-23 - **Reparent children of blocked root instruments instead of dropping the subtree** - When an instrumentation is not allowed to emit root-level spans, its children are now re-parented onto the nearest valid ancestor rather than dropping the entire subtree, so downstream spans are preserved. @@ -336,4 +338,4 @@ Users can be now overwrite the input and ouput attributes of spans created by in - Added utility to set input and output data for any active span in a trace -[0.1.97b1]: https://github.com/KeyValueSoftwareSystems/netra-sdk-py/tree/main +[0.1.97]: https://github.com/KeyValueSoftwareSystems/netra-sdk-py/tree/main diff --git a/netra/instrumentation/openai/wrappers.py b/netra/instrumentation/openai/wrappers.py index 3d013f5..dcf204e 100644 --- a/netra/instrumentation/openai/wrappers.py +++ b/netra/instrumentation/openai/wrappers.py @@ -397,7 +397,10 @@ def _process_chunk(self, chunk: Any) -> None: record_span_timing(self._span, RELATIVE_TIME_TO_FIRST_TOKEN, first_token_time, use_root_span=True) if chunk_dict.get("response"): response = chunk_dict.get("response", {}) - if response.get("status") == "completed": + if response.get("status") in ("completed", "incomplete"): + if response.get("model"): + self._complete_response["model"] = response["model"] + response_output = response.get("output") or [] for output in response_output: if output.get("type") == "function_call": @@ -547,7 +550,10 @@ def _process_chunk(self, chunk: Any) -> None: record_span_timing(self._span, RELATIVE_TIME_TO_FIRST_TOKEN, first_token_time, use_root_span=True) if chunk_dict.get("response"): response = chunk_dict.get("response", {}) - if response.get("status") == "completed": + if response.get("status") in ("completed", "incomplete"): + if response.get("model"): + self._complete_response["model"] = response["model"] + response_output = response.get("output") or [] for output in response_output: if output.get("type") == "function_call": diff --git a/netra/version.py b/netra/version.py index 1b6f4db..a1eb4c9 100644 --- a/netra/version.py +++ b/netra/version.py @@ -1 +1 @@ -__version__ = "0.1.97b1" +__version__ = "0.1.97dev1" diff --git a/pyproject.toml b/pyproject.toml index af628bd..038d782 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api" [project] name = "netra-sdk" -version = "0.1.97b1" +version = "0.1.97dev1" description = "A Python SDK for AI application observability that provides OpenTelemetry-based monitoring, tracing, and PII protection for LLM and vector database applications. Enables easy instrumentation, session tracking, and privacy-focused data collection for AI systems in production environments." authors = [ {name = "Sooraj Thomas",email = "sooraj@keyvalue.systems"}