Skip to content

chore: release main#424

Open
stainless-app[bot] wants to merge 10 commits into
mainfrom
release-please--branches--main--changes--next
Open

chore: release main#424
stainless-app[bot] wants to merge 10 commits into
mainfrom
release-please--branches--main--changes--next

Conversation

@stainless-app

@stainless-app stainless-app Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

✨ Stainless prepared a new release

agentex-client: 0.15.0

0.15.0 (2026-06-23)

Full Changelog: agentex-client-v0.14.0...agentex-client-v0.15.0

Features

  • claude-code: stream-json parser tap for the unified harness surface (#420) (904339c)
  • codex: event-stream parser tap for the unified harness surface (#421) (9b2b031)
  • harness: public adk facade + docs for the unified harness surface (PR 9) (#423) (fa60632)
  • harness: unified harness surface — foundation (span derivation, delivery adapters, emitter) (#412) (a9cacf4)
  • langgraph: migrate LangGraph harness onto unified surface (#417) (d344228)
  • openai-agents: migrate onto the unified harness surface (#416) (d10e151)
  • pydantic-ai: migrate onto unified harness surface (PR4) (#415) (5ec62c2)
  • streaming: stream tool call argument deltas in TemporalStreamingModel (#355) (c8de1d4)

Bug Fixes

  • harness: assert cross-channel (yield vs auto-send) conformance equivalence [AGX1-373] (#414) (694960f)
agentex-sdk: 0.14.0

0.14.0 (2026-06-23)

Full Changelog: agentex-sdk-v0.13.2...agentex-sdk-v0.14.0

Features

  • harness: public adk facade + docs for the unified harness surface (PR 9) (#423) (fa60632)

This pull request is managed by Stainless's GitHub App.

The semver version number is based on included commit messages. Alternatively, you can manually set the version number in the title of this pull request.

For a better experience, it is recommended to use either rebase-merge or squash-merge when merging this pull request.

🔗 Stainless website
📚 Read the docs
🙋 Reach out for help or questions

Greptile Summary

This is the 0.15.0 / 0.14.0 release PR, cutting changes already merged to main. The core addition is a unified harness surface (src/agentex/lib/core/harness/) that gives every agent harness a shared path for streaming delivery, span derivation, and turn-usage reporting via UnifiedEmitter, SpanDeriver, and SpanTracer. On top of that foundation, two new tap modules are introduced for parsing the Claude Code stream-json format and the Codex exec --json event stream, and the OpenAI Agents SDK is adapted via a new OpenAITurn wrapper. The TemporalStreamingModel is extended to stream tool-call argument deltas incrementally instead of buffering them silently.

  • New harness core: UnifiedEmitter ties a canonical StreamTaskMessage* stream to either yield (sync HTTP ACP) or auto-send (async/Temporal) delivery, with span derivation as a side effect.
  • New taps: convert_claude_code_to_agentex_events and convert_codex_to_agentex_events are added and exported from agentex.lib.adk, along with ClaudeCodeTurn and CodexTurn implementing the HarnessTurn protocol.
  • Temporal streaming: TemporalStreamingModel now opens a streaming_task_message_context per function call and streams ToolRequestDelta updates; a defensive cleanup loop closes any orphaned contexts on truncated streams.

Confidence Score: 5/5

Safe to merge — all changes are additive new harness infrastructure and tap implementations built on already-merged commits; no existing call sites are broken.

The new harness surface introduces well-isolated, well-tested modules. The only issues found are documentation inconsistencies that do not affect runtime behavior.

adk/docs/harness.md and src/agentex/lib/adk/_modules/_codex_sync.py both have stale documentation that should be updated.

Important Files Changed

Filename Overview
adk/docs/harness.md New harness surface docs; the tap table and the sentence about AGX1-420/421 are already stale — claude-code and codex taps ship in this very release.
src/agentex/lib/adk/_modules/_codex_sync.py New codex event-stream parser tap; module-level canonical-mapping table for agent_message is inconsistent with the actual implementation (missing StreamTaskMessageStart).
src/agentex/lib/adk/_modules/_claude_code_sync.py New claude-code stream-json parser tap; well-documented dedup logic for thinking blocks, per-block streaming state correctly reset at message boundaries.
src/agentex/lib/core/harness/emitter.py New UnifiedEmitter facade: cleanly separates yield vs auto-send delivery, correctly defers turn.usage() read until after stream exhaustion.
src/agentex/lib/core/harness/auto_send.py Canonical stream to adk.streaming side-effect delivery; index-keyed context map, guarded cleanup, _close_all teardown — logic looks correct.
src/agentex/lib/core/harness/span_derivation.py Pure stateful reducer from stream events to span open/close signals; correctly handles Start+Done (streaming) and Full (batch) tool-request patterns.
src/agentex/lib/adk/providers/_modules/openai_turn.py New OpenAITurn implementing HarnessTurn; usage is correctly aggregated from raw_responses only after stream exhaustion.
src/agentex/lib/core/temporal/plugins/openai_agents/models/temporal_streaming_model.py Adds per-function-call streaming context + ToolRequestDelta delivery; defensive orphan-close loop in finally path; existing stream_update(Full) pattern for reasoning already in use.
tests/lib/core/harness/conformance/runner.py New cross-channel conformance engine; cleanly compares yield vs auto_send logical deliveries and span signals per fixture.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["Harness Tap\n(pydantic-ai / LangGraph /\nOpenAI / claude-code / codex)"] -->|"canonical StreamTaskMessage* stream"| B["HarnessTurn\n(events + usage())"]
    B --> C["UnifiedEmitter"]
    C -->|"yield_turn()"| D["yield_events()\n(passthrough + tracing)"]
    C -->|"auto_send_turn()"| E["auto_send()\n(adk.streaming contexts + tracing)"]
    D --> F["Caller yields events\nover HTTP response"]
    E --> G["Redis / Task stream\n(adk.streaming)"]
    D --> H["SpanDeriver to SpanTracer"]
    E --> H
    H --> I["adk.tracing\n(span open/close)"]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["Harness Tap\n(pydantic-ai / LangGraph /\nOpenAI / claude-code / codex)"] -->|"canonical StreamTaskMessage* stream"| B["HarnessTurn\n(events + usage())"]
    B --> C["UnifiedEmitter"]
    C -->|"yield_turn()"| D["yield_events()\n(passthrough + tracing)"]
    C -->|"auto_send_turn()"| E["auto_send()\n(adk.streaming contexts + tracing)"]
    D --> F["Caller yields events\nover HTTP response"]
    E --> G["Redis / Task stream\n(adk.streaming)"]
    D --> H["SpanDeriver to SpanTracer"]
    E --> H
    H --> I["adk.tracing\n(span open/close)"]
Loading

Reviews (4): Last reviewed commit: "chore: release main" | Re-trigger Greptile

…gModel (#355)

Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
Co-authored-by: Declan Brady <declan.brady@scale.com>
Co-authored-by: Nitesh Dhanpal <NiteshDhanpal@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@stainless-app stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from a191216 to bc0de88 Compare June 22, 2026 20:03
@stainless-app stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from bc0de88 to 4265db1 Compare June 22, 2026 20:09
Comment on lines +174 to +179
elif isinstance(event, StreamTaskMessageDelta):
if event.index is not None and event.delta is not None:
if isinstance(event.delta, TextDelta) and event.delta.text_delta:
accumulated.setdefault(event.index, []).append(event.delta.text_delta)
elif isinstance(event.delta, ReasoningContentDelta) and event.delta.content_delta:
accumulated.setdefault(event.index, []).append(event.delta.content_delta)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 ReasoningSummaryDelta not accumulated in payload comparison — both _yield_logical_deliveries (here) and _auto_send_logical_deliveries (line 394) handle TextDelta and ReasoningContentDelta but silently drop ReasoningSummaryDelta events. A fixture that streams reasoning summaries as deltas would have both channels produce an identical (truncated) payload, so a regression where one channel drops summary deltas would pass the cross-channel assertion undetected.

Prompt To Fix With AI
This is a comment left during a code review.
Path: tests/lib/core/harness/conformance/runner.py
Line: 174-179

Comment:
`ReasoningSummaryDelta` not accumulated in payload comparison — both `_yield_logical_deliveries` (here) and `_auto_send_logical_deliveries` (line 394) handle `TextDelta` and `ReasoningContentDelta` but silently drop `ReasoningSummaryDelta` events. A fixture that streams reasoning summaries as deltas would have both channels produce an identical (truncated) payload, so a regression where one channel drops summary deltas would pass the cross-channel assertion undetected.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Cursor Fix in Claude Code Fix in Codex

@stainless-app stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from 4265db1 to 5f73947 Compare June 22, 2026 22:21
@stainless-app stainless-app Bot force-pushed the release-please--branches--main--changes--next branch 2 times, most recently from 40522a9 to dc4d0af Compare June 22, 2026 22:22
@stainless-app stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from dc4d0af to d01f757 Compare June 22, 2026 22:45
@stainless-app stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from d01f757 to d5e53aa Compare June 22, 2026 22:46
@stainless-app stainless-app Bot force-pushed the release-please--branches--main--changes--next branch from d5e53aa to eea2ce6 Compare June 23, 2026 00:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants