Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: scaleapi/scale-agentex-python
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: e1effb5
Choose a base ref
...
head repository: scaleapi/scale-agentex-python
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: f17ad00
Choose a head ref
  • 2 commits
  • 28 files changed
  • 4 contributors

Commits on Apr 30, 2026

  1. fix(tests): repair test_streaming_model so all 28 tests run and pass (#…

    …334)
    
    Four pre-existing bugs left this entire test file unrunnable on main (4
    failures + 24 errors); fixing them here so the suite actually exercises
    TemporalStreamingModel and protects against regressions.
    
    Bug 1 (24 errors): `conftest.py` defines fixture `mock_adk_streaming` (no
    underscore) but every test in TestStreamingModelSettings and
    TestStreamingModelTools requested it as `_mock_adk_streaming`, so pytest
    failed to resolve the fixture before the body ever ran. The fixture is
    ``autouse=True`` and the param value was never used in any test body, so
    the parameter was vestigial — replaced with `_streaming_context_vars`,
    which provides the ContextVar setup these tests now actually need.
    
    Bug 2 (4 failures): `TemporalStreamingModel.get_response()` reads
    `task_id`, `trace_id`, and `parent_span_id` from ContextVars populated
    by `ContextInterceptor` from request headers in real Temporal flows.
    Tests had been passing `task_id=...` as a kwarg, which is silently
    swallowed by `**kwargs` and ignored, so all three ContextVars stayed at
    their defaults and the validation at the top of `get_response` raised
    before any work happened. New `_streaming_context_vars` fixture in
    conftest sets all three vars (and resets them on teardown), simulating
    what `ContextInterceptor` does in production.
    
    Bug 3 (test_computer_tool): A recent commit narrowed `ComputerTool`
    serialization to require an actual `Computer`/`AsyncComputer` instance,
    but `sample_computer_tool` still built a bare `MagicMock`. Switched to
    `MagicMock(spec=Computer)` so the production isinstance check passes.
    
    Bug 4 (3 streaming-context tests): The 3 tests in TestStreamingModelBasics
    that assert on `streaming_task_message_context` calls built event
    sequences with raw `MagicMock(type="...")`. Production dispatches via
    `isinstance(event, ResponseOutputItemAddedEvent)` etc., which `MagicMock`
    without `spec` never satisfies, so dispatch was silently skipped and
    the assertions failed. Switched to `MagicMock(spec=...)` for each event
    type — passes isinstance without triggering pydantic validation on the
    event's required fields. Also fixed `test_task_id_threading` which had
    been asserting against a hardcoded `task_id="test_task_12345"` that was
    never actually threaded anywhere (the kwarg was ignored, just like in
    Bug 2); it now asserts against the value yielded by the fixture, which
    is the value production reads from the ContextVar.
    
    After all four fixes: 28/28 pass, ruff clean, pyright clean.
    smoreinis authored Apr 30, 2026
    Configuration menu
    Copy the full SHA
    7e5e69c View commit details
    Browse the repository at this point in the history
  2. release: 0.10.3 (#330)

    * feat(api): api update
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * chore(internal): more robust bootstrap script
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * fix: use correct field name format for multipart file arrays
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * feat: support setting headers via env
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * codegen metadata
    
    * fix: allow litellm security patch (#336)
    
    * fix(adk): Always inject headers on execute activity (#337)
    
    * perf(streaming): coalesce per-token publishes to Redis (50ms / 128-char window) (#333)
    
    * perf(streaming): coalesce per-token publishes to Redis (50ms / 128-char window)
    
    Per-token Redis publishes from TemporalStreamingModel were adding ~45s
    (56-62%) overhead to agent response latency, mostly from head-of-line
    blocking on the model's event loop: each `await streaming_context.stream_update(...)`
    inside the OpenAI stream `async for` paused token consumption until the
    publish round-trip completed.
    
    This change introduces a `CoalescingBuffer` driven by an `asyncio.Event`,
    so the producer never awaits on Redis. Deltas are merged consecutive-only
    (preserving character order in every (type, index) channel) and flushed
    on a 50ms timer, on a 128-char size threshold, or immediately for the
    first delta to keep perceived responsiveness high. The buffer's `close()`
    drains remaining deltas before the DONE event, so consumers see the full
    sequence in order.
    
    A new `StreamingMode = Literal["off", "per_token", "coalesced"]` lives
    in `streaming.py` as the single source of truth and is plumbed through
    the adk streaming module, `StreamingService.streaming_task_message_context`,
    and `StreamingTaskMessageContext`. Default is `"coalesced"` everywhere,
    so all 13+ existing context callers (claude_agents, langgraph, litellm
    provider, openai sync provider, etc.) benefit automatically.
    
    * chore(streaming): fix import ordering (ruff I001)
    
    * fix(streaming): address greptile review findings
    
    - _run: when CancelledError is raised mid-flush in the for-loop, re-enqueue
      the in-flight item plus any remaining items in the local `drained` list
      back into self._buf so close()'s final drain can recover them. Previously
      the local `drained` list was unreachable after CancelledError exited the
      for-loop, causing the last coalesced batch to be silently dropped on
      close-during-flush races. Trade-off: the in-flight item may be duplicated
      on the consumer side (Redis pub may have completed before cancel was
      delivered), which is preferable to silent loss for streaming UX.
    
    - _merge_pair: replace `return b` fallback with AssertionError. All six
      current TaskMessageDelta variants have explicit isinstance branches, so
      the fallback is unreachable today. But _can_merge returns True for any
      same-type pair, so adding a 7th delta variant without updating
      _merge_pair would silently drop `a`'s accumulated content. Asserting
      turns a future silent data-loss into an immediate, diagnosable crash.
    
    * test(streaming): add coalescing-layer tests; loosen one model assertion
    
    After merging the test-suite repair from main (#334) into this branch, one
    model test (test_responses_api_streaming) regressed because its
    assert_called_with strict-matched all kwargs of streaming_task_message_context
    and didn't tolerate the new `streaming_mode='coalesced'` kwarg this PR
    adds. Switched to assert_called() + targeted kwarg checks so the test
    verifies what it cares about (task_id threading) without locking in
    implementation details.
    
    Replaced the ad-hoc smoke scripts that lived in conversation with a real
    pytest module at tests/lib/core/services/adk/test_streaming.py covering:
    
    - _delta_char_len, _can_merge, _merge_pair: per-channel correctness +
      None-handling
    - _merge_consecutive: pure-text collapse, cross-channel order preservation,
      per-channel reconstruction matches per-token semantics
    - CoalescingBuffer: first-delta-immediate flush within ~20ms,
      size-threshold flush before timer fires, multi-delta coalescing within
      one window, idle close, add-after-close no-op
    - CoalescingBuffer cancel-during-flush regression test for the P1 fix:
      five queued chunks must all surface across publishes when close()
      cancels mid-flush (asserts substring presence rather than exact
      ordering, since the documented trade-off allows duplicates of the
      in-flight item)
    - StreamingTaskMessageContext mode dispatch: "off" suppresses publishes
      but persists full content, "per_token" publishes each delta synchronously,
      "coalesced" batches and persists full content
    
    * chore(streaming): route TemporalStreamingModel logger through make_logger
    
    The model file used raw ``logging.getLogger("agentex.temporal.streaming")``,
    which returns a logger with no handler attached and no level configured —
    so the existing ``[TemporalStreamingModel] Initialized ... streaming_mode=...``
    INFO log was silently dropped, making it impossible to verify at runtime
    that a coalesced (or any) streaming mode was actually wired.
    
    Switch to the SDK's ``make_logger`` helper (level=INFO, RichHandler in
    local mode, StreamHandler otherwise) used everywhere else in the SDK.
    The explicit logger name ``agentex.temporal.streaming`` is preserved so
    any external logging configuration targeting that name keeps working.
    
    * codegen metadata
    
    * feat(api): api update
    
    * release: 0.10.3
    
    ---------
    
    Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com>
    Co-authored-by: Brandon Allen <brandon.allen@scale.com>
    Co-authored-by: Declan Brady <declan.brady@scale.com>
    Co-authored-by: Stas Moreinis <stas.moreinis@scale.com>
    4 people authored Apr 30, 2026
    Configuration menu
    Copy the full SHA
    f17ad00 View commit details
    Browse the repository at this point in the history
Loading