Repository navigation
Conversation
* fix(ai): keep streamed OpenAI tool calls that have no index accumulate_openai_tool_calls skipped every delta without an index, so tool calls from OpenAI-compatible providers that omit it never reached $ai_output. A delta with a new id now opens a call, and one without an id continues the latest call. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * fix(ai): keep synthetic tool call keys apart from provider indexes A call without an index took key max + 1, which a later call with that real index overwrote, merging two calls and dropping one. Index-less calls now get string keys of their own. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * fix(ai): widen the streamed tool call accumulator key type Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ai): update streamed tool call API snapshot --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> Co-authored-by: Manoel Aranda Neto <marandaneto@gmail.com> (cherry picked from commit ffde3c5)
(cherry picked from commit 7f4c9be)
(cherry picked from commit b5eb2de)
Contributors often open PRs with unsigned commits because signing isn't documented here. (cherry picked from commit e65ed67)
* fix(flags): fall back for incompatible local regex evaluation * fix(flags): defer nested regex quantifiers and fast-path ASCII values * fix(flags): defer strict-end searches with final newline backtracking * perf(flags): cache pure regex pattern metadata (cherry picked from commit d58380e)
(cherry picked from commit 72e0131)
(cherry picked from commit a020e70)
… example (#1109) OpenAI shuts down gpt-image-1 on 2026-10-23 and lists gpt-image-2.5-sunburst or gpt-image-2.5-flare as the replacement (https://developers.openai.com/api/docs/deprecations). Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> (cherry picked from commit efc866e)
* fix(mcp): send one $mcp_initialize per initialize request The Python MCP SDK answers initialize itself, so posthog.mcp sent the event on the first request of each session, once per process. A stateless fleet sent one event per pod. A client that sent only initialize sent no event. Now MCP SDK 2.x reports the event from Server.middleware, on every transport. MCP SDK 1.x over HTTP reports it from PostHogMcpStatelessSessionMiddleware, which takes a new optional server= argument. MCP SDK 1.x over stdio keeps the first-request fallback. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(mcp): read only the initialize response head on mcp 1.x The mcp 1.x hook now keeps only the status and the Mcp-Session-Id header of the initialize response. It no longer parses the JSON or SSE body. The event uses the protocol version that the client asked for. record_initialize now reads the client name, version, and protocol from the initialize params and reply, so both hooks pass them through. The new tests share their request helpers and drop the SSE body case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(mcp): address review on the initialize hooks - SSE transport: the initialize event now lands in the session that the SSE calls use. On SDK 1.x the middleware leaves SSE requests to the first-request fallback. On SDK 2.x the hook uses the process session. - The bound middleware marks each request that it passes on. The fallback now stops only for marked requests, not for every HTTP request. - The hooks compute the handshake session without a write to the shared session that McpAnalytics.capture() reads. - A server= value that cannot be bound no longer breaks requests. - Remove the unused _mint_token_if_initialize. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(mcp): wait for the initialize capture inside its handshake task Both handshake hooks run record_initialize in a tracked background task. It started the capture as a second task, after flush() took its snapshot of pending tasks. With a slow before_send, flush() returned early and shutdown dropped $mcp_initialize. The handshake task now awaits the capture itself. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(mcp): resolve the v2 handshake session from an incoming header On MCP SDK 2.x, a stateless client can send initialize with an existing Mcp-Session-Id and keep sending it. Its later calls resolve their session from that header, but the handshake hook read only the connection id and the minted token. The event landed in a generated session. The hook now falls back to the incoming header. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(mcp): capture a v1 initialize that carries a session header On MCP SDK 1.x, the middleware read the body only of a POST with no Mcp-Session-Id, because only those need a token. A client that sent initialize with an existing session id got no event: the middleware marked the request, so the first-request fallback did not run either. A middleware bound to a server now reads those bodies too, behind a cheap check for "initialize". It still mints only without a header. The event uses the header that the client keeps sending. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(mcp): pass a disconnect mid-body through the session middleware When the client disconnected while it sent the body, the middleware stopped its read and replayed the partial body as a complete request. The app parsed half a request and never saw the disconnect. The middleware now replays the partial body with more_body set, then hands the app the disconnect. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(mcp): stop buffering tool calls once they are not an initialize A bound middleware reads the body of a POST that carries a session id, to catch an initialize that reuses one. That held every tool call in memory, up to 256 KB, before the app saw it. The middleware now stops after 4 KB when "initialize" is not in it, and streams the rest. JSON-RPC clients put "method" before "params", so a handshake shows up in that window. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(mcp): read the v2 handshake header through _resolve_ctx The v2 handshake hook read the Mcp-Session-Id header and decoded the token itself. Every later request gets the same pair from _resolve_ctx. The hook now calls it, so the handshake and later requests follow one rule and cannot drift apart into two sessions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(mcp): run the initialize callbacks inline in the handshake request Both handshake hooks ran identify and event_properties in a detached background task. If a callback never returned, each handshake left one more task pending, with no bound, and flush() waited for all of them. The spec requires pending state to be bounded by count. The hooks now run the callbacks inline, the same as a tool call does. A hung callback holds that request, where the host sees it, and leaves no task behind. The capture still runs in the background after the callbacks, as for every other event. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(mcp): record the v1 handshake inside the request's auth context The session middleware sits outside FastMCP's AuthContextMiddleware. It ran identify after the app returned, when that middleware had already reset the authenticated user. An identify that calls get_access_token() got None, so $mcp_initialize stayed anonymous under OAuth. The middleware now records the handshake when the response starts, while the app still handles the request. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(mcp): stop the body peek only on a method that is not initialize The 4 KB peek stopped when "initialize" was not in the first 4 KB. JSON key order is arbitrary, so an initialize with large params before its method got no event. The peek now stops only when the prefix shows a "method" and no "initialize". Without a method yet, it reads up to the full cap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(mcp): drop the body byte checks from the session middleware The middleware guessed from raw bytes whether a request was initialize. A nested "method" key in params stopped the 4 KB peek too early, and a JSON-escaped "initialize" failed the quick byte check. That second case also stopped the token mint, which worked before this PR. The middleware now parses the body as JSON, as main does, and reads only requests with no Mcp-Session-Id. On MCP SDK 1.x, an initialize that reuses an existing session id is not captured. The README lists this limit. MCP SDK 2.x still captures it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit 8cd8eb5)
… SDK message_delta (#1112) The tracker only read output_tokens from a message_delta. Its usage is cumulative, and with server tools (web search, ...) the input and cache counts exceed the message_start values, so streamed generations under-reported them, and the number of web searches was never recorded. Keep the larger input and cache counts, as the Anthropic wrapper does, and set $ai_web_search_count from server_tool_use.web_search_requests. Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> (cherry picked from commit 48889b6)
(cherry picked from commit 5a2ea5f)
(cherry picked from commit e3fd9a4)
* fix(ai): record the HTTP status of google-genai errors The generation and embedding wrappers read the HTTP status of a failed call from the exception's status_code, which OpenAI and Anthropic errors have. google-genai's APIError (ClientError, ServerError) carries it as code, so every failed Gemini call was captured with $ai_http_status 0. Read either attribute through a small helper; a code outside the HTTP range still counts as no status. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * fix: remove unused import from HTTP status tests --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> Co-authored-by: Manoel Aranda Neto <marandaneto@gmail.com> (cherry picked from commit 25d2767)
(cherry picked from commit 82f948b)
(cherry picked from commit b0a2783)
* fix: ai privacy mode leaks * fix: address privacy mode review findings * fix: strip remaining otel content in privacy mode * fix: redact mcp credentials in otel tool definitions * fix: address otel privacy review findings * fix: always redact mcp credentials in otel tool definitions * fix: strip otel embedding vectors in privacy mode * fix: drop only the otel span that fails redaction * fix: keep vercel rerank scores in otel privacy mode * fix: strip logfire payload attributes in otel privacy mode (cherry picked from commit 04e6a4c)
(cherry picked from commit fb9b66b)
(cherry picked from commit 16d618b)
Bumps [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python) from 1.40.0 to 1.45.1. - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) --- updated-dependencies: - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> (cherry picked from commit bc7b403)
Bumps [djangorestframework](https://github.com/encode/django-rest-framework) from 3.18.1 to 3.18.2. - [Release notes](https://github.com/encode/django-rest-framework/releases) - [Commits](encode/django-rest-framework@3.18.1...3.18.2) --- updated-dependencies: - dependency-name: djangorestframework dependency-version: 3.18.2 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> (cherry picked from commit 125b266)
…1119) Bumps the uv group with 1 update in the /examples/example-ai-anthropic directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-autogen directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-aws-bedrock directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-azure-openai directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-cerebras directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-cloudflare-ai-gateway directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-cohere directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-crewai directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-dedalus directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-deepseek directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-fireworks-ai directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-gemini directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-groq directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-helicone directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-hugging-face directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-instructor directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-langchain directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-langgraph directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-llamaindex directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-mirascope directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-mistral directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-ollama directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-openai directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-openrouter directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-perplexity directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-portkey directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-semantic-kernel directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-smolagents directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-together-ai directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-vercel-ai-gateway directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Bumps the uv group with 1 update in the /examples/example-ai-xai directory: [opentelemetry-api](https://github.com/open-telemetry/opentelemetry-python). Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.34.1 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) Updates `opentelemetry-api` from 1.40.0 to 1.45.1 - [Release notes](https://github.com/open-telemetry/opentelemetry-python/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-python/blob/main/CHANGELOG.md) - [Commits](open-telemetry/opentelemetry-python@v1.40.0...v1.45.1) --- updated-dependencies: - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv - dependency-name: opentelemetry-api dependency-version: 1.45.1 dependency-type: indirect dependency-group: uv ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> (cherry picked from commit 3f6c80e)
(cherry picked from commit 284340d)
(cherry picked from commit 7d15127)
(cherry picked from commit 7833e95)
…back handler (#1097) * feat(ai): record the Anthropic web search count in the LangChain callback handler Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * chore: update public API snapshot for ModelUsage.web_search_count Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * chore: regenerate LangChain ModelUsage API snapshot * fix(ai): read the LangChain web search count from llm_output usage and omit zero Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> Co-authored-by: Manoel Aranda Neto <marandaneto@gmail.com> (cherry picked from commit b0a2b59)
(cherry picked from commit a736b43)
(cherry picked from commit 3044d8e)
* feat(mcp): add a capture_initialize option MCPAnalyticsOptions(capture_initialize=False) stops $mcp_initialize. The option is on by default. Many clients reconnect before every few tool calls, so the handshake event can outnumber $mcp_tool_call. With the option off, record_initialize and the first-request fallback return early. Nothing else changes: the middleware still mints the session token, so tool calls keep their sessions and client names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(mcp): keep the handshake identity with capture_initialize off record_initialize returned before handle_identify when the option was off. An identify callback that resolves the user only from the initialize request then left the session anonymous, so later tool calls lost the user. Identify now runs first, and the option stops only the event. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(mcp): rename capture_initialize to send_initialize_event PostHogMCP already has a capture_initialize() method that sends the event by hand. An option with the same name next to that method makes readers link the two. The new name says what the option controls. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(mcp): name the PostHog screens that read $mcp_initialize MCP onboarding and the users and sessions tiles of the default MCP dashboard read $mcp_initialize. The README now says that they show no data while send_initialize_event is off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit d8a1b97)
(cherry picked from commit 786db57)
(cherry picked from commit 0894015)
(cherry picked from commit 75a1794)
Bumps the github-actions group with 3 updates: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/analyze](https://github.com/github/codeql-action) and [PostHog/posthog-sdk-test-harness/.github/workflows/test-sdk-action.yml](https://github.com/posthog/posthog-sdk-test-harness). Updates `github/codeql-action/init` from 4.38.3 to 4.39.0 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@24c5418...6f2ac81) Updates `github/codeql-action/analyze` from 4.38.3 to 4.39.0 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@24c5418...6f2ac81) Updates `PostHog/posthog-sdk-test-harness/.github/workflows/test-sdk-action.yml` from 1.15.0 to 1.17.0 - [Release notes](https://github.com/posthog/posthog-sdk-test-harness/releases) - [Changelog](https://github.com/PostHog/posthog-sdk-test-harness/blob/main/CHANGELOG.md) - [Commits](PostHog/posthog-sdk-test-harness@64ffa6a...8ca75c4) --- updated-dependencies: - dependency-name: github/codeql-action/init dependency-version: 4.39.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: github/codeql-action/analyze dependency-version: 4.39.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions - dependency-name: PostHog/posthog-sdk-test-harness/.github/workflows/test-sdk-action.yml dependency-version: 1.17.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> (cherry picked from commit 7083998)
* feat: report unresolved local flags on evaluate_flags snapshots Implements the "Snapshot unresolved flag reporting" and "Warning for flags local evaluation never resolves" requirements of the evaluate-flags spec (PostHog/sdk-specs#85). - Add `FeatureFlagEvaluations.unresolved_flags`, with an `UnresolvedFlagReason` for each flag and the spec's fixed precedence. - Report `local_evaluation_inconclusive` instead of `flag_missing` when a snapshot read hits an unresolved flag. - Do not stop a condition at the first inconclusive filter, so a filter that does not match resolves the condition locally. - Check `active` before experience continuity, also for dependencies. - Log one warning per flag that local evaluation can never resolve, repeated only when its definition changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: 39793b31-809e-4689-a5d8-b4359cbb22c1 * fix: address review findings for unresolved local flags * test(flags): check flag warnings run outside the publication lock * fix(flags): fall back to the server when a flag dependency needs server data * fix(flags): keep server fallback when the definition reason lookup fails (cherry picked from commit bb2b9d6)
(cherry picked from commit 91d3188)
(cherry picked from commit 130f5a1)
…rics (#992) * feat(metrics): add metrics autocapture for HTTP, database and runtime metrics `metrics={"autocapture": True}` starts the installed OpenTelemetry instrumentors with private meter and tracer providers and exports to `/i/v1/metrics`. The packages come from the new `posthog[metrics]` extra. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: ef9b57c2-47ff-47e6-a509-8873ffe1fab4 * test: check concurrent LangChain traces without assuming order Generated-By: PostHog Desktop Task-Id: c0218209-575c-46f0-a201-d0c831e38096 * fix(metrics): address autocapture review findings - Honour send=False in the autocapture export gate. - Strip trailing slashes from the host before building the metrics endpoint. - Set OTEL_SEMCONV_STABILITY_OPT_IN only while the instrumentors load, then restore the process environment. - Limit each synchronous instrument to 2000 attribute sets; send the rest to an otel.metric.overflow series, so user-supplied hosts cannot grow the SDK cache. - After fork, replace the module lock and point the runtime instrumentor at the child process. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: 10838116-90e2-4d23-af38-8099d7887d07 * fix(metrics): keep app-owned instrumentors intact and hold ownership through shutdown - Skip an instrumentor whose singleton the app already instrumented before creating it. Creating it ran __init__ again and reset the app's system metrics config. - Uninstrument while the module lock is held, so a client that starts during shutdown cannot skip libraries that are about to be uninstrumented. The last export still runs outside the lock. - Correct the module docstring: an app cannot instrument a library again with its own OpenTelemetry setup while autocapture instruments it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: a129c1a0-57e3-4370-a4df-6542e710ab75 * fix(metrics): use stable HTTP metric names when another instrumentor read the opt-in first OpenTelemetry reads OTEL_SEMCONV_STABILITY_OPT_IN once per process. If any instrumentor ran before the client started, autocapture sent http.client.duration (ms) and not http.client.request.duration (s). When the app has not set an opt-in, autocapture now sets the HTTP mode to stable after initialisation, so the names do not depend on import order. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: a129c1a0-57e3-4370-a4df-6542e710ab75 * fix(metrics): address the second review round of metrics autocapture - Do not send the app's OTEL_EXPORTER_OTLP_* settings (other vendors' headers, endpoint, TLS files) to PostHog: the private exporter is built without them. - Give HTTP instrumentors a no-op tracer, so app requests no longer carry an unsampled traceparent that makes downstream services drop their traces. - Record nothing while the client is disabled, and apply metrics.before_send to autocaptured measurements and runtime observations (value and attributes, or drop). - Exclude the PostHog host in any case and with or without its default port, escape commas, keep OTEL_PYTHON_*_EXCLUDED_URLS, and apply the exclusion to httpx. - Reset the reader's export lock in a forked child, export autocaptured metrics on Client.flush() and within the client's exit budget (no 10 s exit wait), roll back on a failed start, and uninstrument and reinstrument Flask apps across a restart. - Start autocapture on a later module-level setup(), once per client. - Validate flush_interval like client.metrics, use the same resource as client.metrics, keep the first word of db.operation.name, and raise the minimum OpenTelemetry versions to the first ones with the runtime metric names. - Rename the module to posthog/_metrics_autocapture.py to keep internals out of the public API. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: a129c1a0-57e3-4370-a4df-6542e710ab75 * fix(metrics): keep app middleware on shutdown, stop context propagation, and fix fork and flush issues - Flask: shutdown uninstruments an app only when its WSGI app is still the one the instrumentation set. uninstrument_app() would otherwise remove middleware the app added later, such as authentication. Instrumentation left in place records nothing after shutdown. - Do not propagate context: the instrumentors that autocapture starts no longer inject trace context or baggage into outgoing requests, including a trace extracted from an incoming request. - Keep the attributes that a database span starts with (asyncpg passes db.system then). - Export the last window at exit in sync mode. - Replace the metrics SDK collection and aggregation locks in a forked child, where a parent thread could hold them. - Use one flush thread at a time, with one follow-up export for calls made during a flush. - Run metrics.before_send as an SDK callback, so a flush() it calls is deferred and cannot deadlock the collection. - Raise the minimum OpenTelemetry instrumentation version to 0.60b0, the first in which the httpx instrumentor excludes URLs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: a129c1a0-57e3-4370-a4df-6542e710ab75 * fix(metrics): do not let the Django instrumentor configure empty settings Without configured settings, DjangoInstrumentor calls settings.configure() with empty settings, so an app that configures its settings in code after creating the client fails with "Settings already configured". Autocapture now starts the Django instrumentor only when the settings are configured, as in AppConfig.ready(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: a129c1a0-57e3-4370-a4df-6542e710ab75 * fix(metrics): drop raw URL attributes, normalize hook attributes, and stop flush loops from hooks - Never record raw URLs and paths (url.full, http.url, http.target, ...), client addresses, user agents or captured headers. Instrumentors such as Tornado put them on metrics, and they can hold tokens and emails. Routes stay. - Keep only valid OpenTelemetry attribute values, with sequences as tuples, before and after metrics.before_send. SDK 1.39 raised TypeError for a list value inside the app's request. Recording errors no longer reach the instrumented call. - A flush() called from a metrics before_send hook still flushes events and spans, but does not start another autocapture export, which ran the hook again without end. - Each flush request waits only for the first export that starts after it, not for later exports. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: a129c1a0-57e3-4370-a4df-6542e710ab75 * fix(metrics): isolate exporter settings and autocapture lifecycle state * fix(metrics): address remaining autocapture lifecycle feedback --------- Co-authored-by: Manoel Aranda Neto <marandaneto@gmail.com> (cherry picked from commit febb3ed)
(cherry picked from commit ce03e47)
(cherry picked from commit 175fac6)
(cherry picked from commit 58d69e3)
(cherry picked from commit e4f43a4)
(cherry picked from commit 9a9d806)
(cherry picked from commit ad79bd0)
* fix(ai): report OpenAI Agents cached and reasoning tokens The Agents SDK nests cached input and reasoning tokens under the usage details fields: input_tokens_details/output_tokens_details on generation span usage and on the Responses usage object of response spans. The processor read flat keys that the SDK never sets, so both were always dropped. Read the nested fields, keeping the flat keys for custom models. * fix(ai): declare inclusive cache reporting for nested Agents usage OpenAI-shaped usage counts cached tokens inside input_tokens. Declare $ai_cache_reporting_exclusive: False when the cache count comes from the nested usage details, as the Node Agents processor does, so the cost backend does not infer exclusive reporting from a Claude model name served through an OpenAI-compatible endpoint. Flat custom-model keys keep their own convention, and a caller-supplied value still takes precedence. * fix(ai): don't forward inclusive Agents reasoning tokens OpenAI-compatible providers such as OpenRouter count reasoning inside completion_tokens, while the cost backend adds reasoning on top for Gemini model names, so forwarding the nested count priced reasoning twice. Keep the original flat reasoning_tokens key only; cached tokens are unchanged. (cherry picked from commit 4d6e447)
(cherry picked from commit 2989cd2)
(cherry picked from commit c380dc8)
…le-ai-autogen in the uv group across 1 directory (#1131) chore(deps): bump setuptools Bumps the uv group with 1 update in the /examples/example-ai-llamaindex directory: [setuptools](https://github.com/pypa/setuptools). Updates `setuptools` from 83.0.0 to 84.1.0 - [Release notes](https://github.com/pypa/setuptools/releases) - [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst) - [Commits](pypa/setuptools@v83.0.0...v84.1.0) --- updated-dependencies: - dependency-name: setuptools dependency-version: 84.1.0 dependency-type: indirect dependency-group: uv ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> (cherry picked from commit 6f765a3)
Bumps [authlib](https://github.com/authlib/authlib) from 1.7.2 to 1.9.1. - [Release notes](https://github.com/authlib/authlib/releases) - [Commits](authlib/authlib@v1.7.2...v1.9.1) --- updated-dependencies: - dependency-name: authlib dependency-version: 1.9.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> (cherry picked from commit 871ad9e)
…dates (#1145) Bumps the ai-providers group with 7 updates in the / directory: | Package | From | To | | --- | --- | --- | | [langchain](https://github.com/langchain-ai/langchain) | `1.4.4` | `1.4.7` | | [langgraph](https://github.com/langchain-ai/langgraph) | `1.2.14` | `1.2.16` | | [langchain-core](https://github.com/langchain-ai/langchain) | `1.6.9` | `1.6.13` | | [langchain-openai](https://github.com/langchain-ai/langchain) | `1.7.0` | `1.7.2` | | [langchain-anthropic](https://github.com/langchain-ai/langchain) | `1.7.5` | `1.7.6` | | [google-genai](https://github.com/googleapis/python-genai) | `2.29.0` | `2.32.0` | | [langchain-protocol](https://github.com/langchain-ai/agent-protocol) | `0.0.19` | `0.0.20` | Updates `langchain` from 1.4.4 to 1.4.7 - [Release notes](https://github.com/langchain-ai/langchain/releases) - [Commits](langchain-ai/langchain@langchain==1.4.4...langchain==1.4.7) Updates `langgraph` from 1.2.14 to 1.2.16 - [Release notes](https://github.com/langchain-ai/langgraph/releases) - [Commits](langchain-ai/langgraph@1.2.14...1.2.16) Updates `langchain-core` from 1.6.9 to 1.6.13 - [Release notes](https://github.com/langchain-ai/langchain/releases) - [Commits](langchain-ai/langchain@langchain-core==1.6.9...langchain-core==1.6.13) Updates `langchain-openai` from 1.7.0 to 1.7.2 - [Release notes](https://github.com/langchain-ai/langchain/releases) - [Commits](langchain-ai/langchain@langchain-openai==1.7.0...langchain-openai==1.7.2) Updates `langchain-anthropic` from 1.7.5 to 1.7.6 - [Release notes](https://github.com/langchain-ai/langchain/releases) - [Commits](langchain-ai/langchain@langchain-anthropic==1.7.5...langchain-anthropic==1.7.6) Updates `google-genai` from 2.29.0 to 2.32.0 - [Release notes](https://github.com/googleapis/python-genai/releases) - [Changelog](https://github.com/googleapis/python-genai/blob/main/CHANGELOG.md) - [Commits](googleapis/python-genai@v2.29.0...v2.32.0) Updates `langchain-protocol` from 0.0.19 to 0.0.20 - [Release notes](https://github.com/langchain-ai/agent-protocol/releases) - [Commits](langchain-ai/agent-protocol@langchain-protocol==0.0.19...langchain-protocol==0.0.20) --- updated-dependencies: - dependency-name: langchain dependency-version: 1.4.7 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: ai-providers - dependency-name: langgraph dependency-version: 1.2.16 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: ai-providers - dependency-name: langchain-core dependency-version: 1.6.13 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: ai-providers - dependency-name: langchain-openai dependency-version: 1.7.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: ai-providers - dependency-name: langchain-anthropic dependency-version: 1.7.6 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: ai-providers - dependency-name: google-genai dependency-version: 2.32.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: ai-providers - dependency-name: langchain-protocol dependency-version: 0.0.20 dependency-type: indirect update-type: version-update:semver-patch dependency-group: ai-providers ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> (cherry picked from commit c9105c5)
(cherry picked from commit 50cf357)
* feat: send transactional email from posthog templates Add posthog.emails.send() on Client and AsyncClient, plus standalone Emails and AsyncEmails in posthog.emails for processes that only send email. Sends go to the app host with a project secret API key and an Idempotency-Key, and retry network errors, rate limits, an in-flight key and 503 with the same key. Errors raise EmailError with PostHog's code and a Resend-style name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: c62b30cd-eb2e-496c-a73d-2a6e7a52a62e * fix: keep the email secret key off custom hosts and close email transports client.emails only infers PostHog Cloud app hosts. A custom host raises app_host_required before any request, so an ingestion proxy never receives the project secret key. A kept emails reference now reads the client's disabled state on every send. Shutdown closes the email transport, a forked child drops the parent's email session, and the retry ceiling applies after jitter. Docs examples use client.emails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: c62b30cd-eb2e-496c-a73d-2a6e7a52a62e * fix: refuse email sends after shutdown and drain async sends first client.emails now asks the parent client to admit each send. After shutdown, a kept or new client.emails raises EmailError with code client_closed and makes no request. On AsyncClient, an admitted send is an in-flight operation, so shutdown waits for it, retries included, before it closes the email transport. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: c62b30cd-eb2e-496c-a73d-2a6e7a52a62e * feat: configure email sends on the client and document setup Posthog and AsyncPosthog take app_host, email_request_timeout_seconds and email_request_max_retries, so client.emails works behind a custom host and a job runner can turn retries off. Emails takes a session and AsyncEmails an http_client, which gives tests a supported no-network path. The posthog.emails module docs now hold a setup quickstart: keys and scope, template ID, hosts, retries, errors to expect, cleanup and testing. The release note names client.emails.send(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: c62b30cd-eb2e-496c-a73d-2a6e7a52a62e * fix: match the email contract's missing_app_host and keep network causes - A non-Cloud host without app_host now fails with missing_app_host, the code the cross-SDK contract in PostHog/posthog#120921 defines, matching posthog-node. - A network_error keeps the requests or httpx exception as __cause__, so a failed send is easier to debug. - Regenerate the public API snapshot after the rebase onto main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: e72a2c10-f145-4f7c-8754-a4fcc06a18be * fix: keep the bearer token and send timeout on injected async clients An httpx.AsyncClient passed as http_client can carry its own auth and timeout. Its auth replaced the email's Bearer header, and its timeout replaced the send timeout, so a client built with timeout=None left sends unbounded. Each async send now passes auth=None and timeout=self.timeout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: e72a2c10-f145-4f7c-8754-a4fcc06a18be * fix: name 422 send checks validation_error The template send route answers 422 for recipient_suppressed, sending_paused and sending_suspended as well as idempotency_key_reused. Only idempotency_key_reused is now invalid_idempotent_request; the send checks are validation_error, as the cross-SDK contract names them and posthog-node does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: e72a2c10-f145-4f7c-8754-a4fcc06a18be * fix: raise client_disabled for email sends from a disabled client A disabled client returned SendEmailResult(id=None), so a caller that treats a returned result as sent dropped the email silently. It now sends nothing and raises EmailError with code client_disabled (name application_error), as the cross-SDK contract in PostHog/posthog#120921 defines and posthog-node does. SendEmailResult.id is always the queued message ID, so its type is str. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: e72a2c10-f145-4f7c-8754-a4fcc06a18be * feat: send transactional email through the single send endpoint `emails.send()` now posts to `/api/projects/@current/messaging/send/email/` with the template ID in the body as `template.id`, instead of the template-scoped route. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: e72a2c10-f145-4f7c-8754-a4fcc06a18be * feat: read a transactional email's status with emails.get `emails.get(message_id)` on `Emails` and `AsyncEmails` reads `/api/projects/@current/messaging/emails/{id}/` and returns an `EmailStatus` with `status`, `created_at`, `status_at` and `reason`. It retries network errors, rate limits and an unavailable service like `send`, which now shares that attempt loop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: e72a2c10-f145-4f7c-8754-a4fcc06a18be * docs: describe the email error name as a category Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: e72a2c10-f145-4f7c-8754-a4fcc06a18be * feat: add a per-send max_retries to emails.send `send(max_retries=...)` on `Emails` and `AsyncEmails` overrides the client's retry limit for one send, like posthog-node's `maxRetries`. A negative or non-integer value raises `ValueError` before any request. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Generated-By: PostHog Desktop Task-Id: e72a2c10-f145-4f7c-8754-a4fcc06a18be (cherry picked from commit 01e91db)
(cherry picked from commit 139161e)
(cherry picked from commit af8e1aa)
Co-authored-by: Manoel Aranda Neto <marandaneto@gmail.com> (cherry picked from commit be77b83)
Gemini returns IDs on function calls and function responses, but the captured $ai_output_choices and $ai_input dropped them, so tool results could not be matched to their calls. Keep the call ID on output (streaming and non-streaming) and on input history calls, and the result's ID as tool_use_id, matching PostHog/posthog-js#5087. Co-authored-by: Manoel Aranda Neto <marandaneto@gmail.com> (cherry picked from commit a61e64d)
(cherry picked from commit f23efe9)
(cherry picked from commit dca2207)
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
💡 Motivation and Context
mainshipped 7.75.7 through 7.81.1 after the last sync (#1120), so 8.0 would drop those features and fixes, including the privacy-mode fix that keeps content out of AI events (#1105), transactional email (#1093) and metrics autocapture (#992).Changes
-xpicks of everymaincommit after chore: sync main into v1 (7.69.0–7.75.6) #1120's last pick (chore(deps): bump uv to 0.13.4 and certifi to 2026.10.19 #1104), in order, release and reference commits included: 60 commits, none skipped.flush()lane drain and do not bring back the library-identity helpers v1 removed in feat!: MCP no longer relabels the client SDK identity #1034.emails.pyimports_parse_retry_afterfromcapture_send(renamed module); the synced AI tests assertcapture_ai, which v1's integrations use.💚 How did you test it?
pytest posthog/test, ruff, mypy,check_public_api.pyanduv lock --checklocally. Three metrics-autocapture fork tests fail on macOS on unmodifiedmaintoo.posthog/ai/openai/_embeddings.py.📝 Checklist
If releasing new changes
sampo addto generate a changeset file🤖 Agent context
Autonomy: Human-driven (agent-assisted)
claude-opus-5-5), following the release runbook's main-sync step and chore: sync main into v1 (7.69.0–7.75.6) #1120's method.🤖 Generated with Claude Code