Skip to content

feat(agent-cache-py): streaming response caching for the OpenAI Agents SDK adapter - #318

Open
amitkojha05 wants to merge 1 commit into
BetterDB-inc:masterfrom
amitkojha05:feat/agent-cache-py-streaming-openai-agents
Open

amitkojha05 wants to merge 1 commit into
BetterDB-inc:masterfrom
amitkojha05:feat/agent-cache-py-streaming-openai-agents

Conversation

@amitkojha05

@amitkojha05 amitkojha05 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Brings streaming response caching to the OpenAI Agents SDK adapter, the Python counterpart to @betterdb/agent-cache v0.11.0's wrapStream for the Vercel AI SDK. When I shipped the Agents SDK adapter in v0.10.0 I documented "stream_response() is delegated uncached (per the BetterDB streaming convention)." This PR closes that gap.

What changed

  • CachedModel.stream_response() is now cache-aware.
    • Miss: every upstream event flows to the caller unchanged; the terminal response.completed event is captured and persisted via cache.llm.store_multipart() after the stream drains.
    • Hit: the stored response is replayed as synthesized Responses stream events (output_text.delta + response.completed); the underlying model is not called.
  • Cache-key parity with get_response — streamed and non-streamed requests share entries in both directions. A Runner.run_streamed(...) call hits what a Runner.run(...) call stored, and vice-versa. Same prepare_params() call, same exclusions.
  • Store is fail-open — Valkey failures log a warning and never surface to the caller mid- or post-stream. Upstream errors propagate unchanged; partial streams are not cached.

Design note — one open question

Tool-call streams are not stored in this PR, mirroring the wrapStream convention of not caching half-executed agent steps. This creates a small streaming/non-streaming asymmetry: non-streaming get_response() on this adapter continues to cache tool calls (a decision from #149 that suits the single-Agent wrapping pattern), while streaming skips them.

Three consistent options:

  • (a) keep this asymmetry — parity with the TS wrapStream shape;
  • (b) also skip tool calls on get_response — full streaming/non-streaming symmetry;
  • (c) also cache tool-call streams — full same-adapter symmetry.

This PR picks (a) because it matches the TS shape and keeps the streaming convention aligned across packages. Happy to switch to (b) or (c) in a follow-up — which would you prefer?

Tests

Six new tests in tests/adapters/test_openai_agents.py:

  • test_stream_miss_passes_through_and_stores
  • test_stream_hit_replays_without_calling_model
  • test_stream_hit_after_nonstream_store — cache-key parity
  • test_stream_tool_calls_are_not_stored
  • test_stream_error_does_not_store
  • test_stream_store_failure_is_fail_open

Removed the obsolete test_stream_response_delegates_directly.

Checklist

@amitkojha05

Copy link
Copy Markdown
Contributor Author

Hi @KIvanow — this is ready when you have time. Python counterpart to wrapStream from #262, closing the "streaming is not cached by any adapter" gap on the Agents SDK adapter.

KIvanow added a commit that referenced this pull request Aug 7, 2026
brace-expansion is vulnerable to denial of service across all major
lines: unbounded expansion length causing OOM (CVE-2026-14257),
unbounded intermediate arrays bypassing that fix (CVE-2026-69152),
and exponential-time expansion of consecutive non-expanding {} groups
(CVE-2026-13149).

Tighten the existing 1.x override and add pins for the 2.x and 5.x
lines: 1.1.14 -> 1.1.18, 2.1.2 -> 2.1.4, 5.0.5 -> 5.0.9.

Fixes Dependabot alerts #274, #308, #316, #317, #318, #266.
KIvanow added a commit that referenced this pull request Aug 7, 2026
…364)

* fix(deps): force seroval >=1.5.3 to resolve CVE-2026-59940

seroval <=1.5.2 has a critical type-confusion flaw in fromJSON():
Promise control nodes can operate on attacker-controlled values from
the deserialization reference table, allowing unintended server-side
invocation and potentially RCE when untrusted Seroval JSON is
deserialized with plugins enabled (GHSA-mv8w-475r-vwqw).

Add a pnpm override pinning seroval to >=1.5.3 <1.6.0, staying within
the ~1.5.0 range required by solid-js (pulled in via react-grab in
apps/web). Resolves to 1.5.6.

Fixes Dependabot alert #300.

* fix(deps): force form-data 4.x >=4.0.6 to resolve CVE-2026-12143

form-data 4.x before 4.0.6 does not escape CR/LF in multipart field
names and filenames, allowing CRLF injection into multipart bodies
(GHSA-hmw2-7cc7-3qxx). Consumed via axios and ibm-cloud-sdk-core in
apps/api. Resolves 4.0.5 -> 4.0.6.

Also prunes orphaned duplicate @babel/hasown lockfile entries left
over from an earlier resolution (dedupe-only, no version changes for
consumers).

Fixes Dependabot alert #249.

* fix(deps): pin brace-expansion lines to patched versions (DoS CVEs)

brace-expansion is vulnerable to denial of service across all major
lines: unbounded expansion length causing OOM (CVE-2026-14257),
unbounded intermediate arrays bypassing that fix (CVE-2026-69152),
and exponential-time expansion of consecutive non-expanding {} groups
(CVE-2026-13149).

Tighten the existing 1.x override and add pins for the 2.x and 5.x
lines: 1.1.14 -> 1.1.18, 2.1.2 -> 2.1.4, 5.0.5 -> 5.0.9.

Fixes Dependabot alerts #274, #308, #316, #317, #318, #266.

* fix(deps): raise ip-address override to >=10.3.1 (CVE-2026-69192)

ip-address <=10.3.0 decodes leading-zero IPv4 octets as decimal while
resolvers decode them as octal, so Address4-based trust-boundary
checks (isPrivate, isLoopback, isInSubnet, ...) disagree with where
the network stack actually connects, enabling SSRF filter bypass
(GHSA-mwp4-54f8-5fhr). Consumed via express-rate-limit and socks in
apps/api. Resolves 10.2.0 -> 10.4.0.

Fixes Dependabot alert #321.

* fix(deps): raise fast-uri override to >=3.1.5 (host confusion CVEs)

fast-uri 3.x before 3.1.5 can misparse the authority component:
backslash accepted as authority introducer (CVE-2026-18446), literal
backslash as authority delimiter (CVE-2026-16221), and failed IDN
canonicalization (CVE-2026-13676), each yielding a different host
than WHATWG URL consumers resolve, enabling SSRF/allowlist bypass.
Consumed via fastify/ajv in apps/api. Resolves 3.1.2 -> 3.1.5.

Fixes Dependabot alerts #288, #291, #320.

* fix(deps): raise postcss override to >=8.5.18 (source map file reads)

postcss <=8.5.17 auto-loads attacker-controlled sourceMappingURL
comments, allowing path traversal and arbitrary .map file disclosure
(CVE-2026-45623 / GHSA-6g55-p6wh-862q) including an incomplete-fix
variant (GHSA-r28c-9q8g-f849). Used by the vite/tailwind pipeline in
apps/web. Resolves 8.5.10/8.5.15 -> 8.5.26 (nanoid follows as its
direct dependency).

Fixes Dependabot alerts #294, #302.

* fix(deps): raise shell-quote override to >=1.9.0 (CVE-2026-13311)

shell-quote <=1.8.4 has quadratic-complexity parse() (CWE-407),
allowing denial of service on long crafted input. Dev-scope, consumed
by concurrently in the root dev scripts. Resolves 1.8.4 -> 1.10.0.

Fixes Dependabot alert #278.

* fix(deps): pin js-yaml 3.x/4.x to patched versions (CVE-2026-59869)

js-yaml before 3.15.0 / 4.3.0 allows YAML merge-key alias chains to
force quadratic CPU consumption, a denial-of-service vector when
parsing untrusted YAML (GHSA-52cp-r559-cp3m, plus the related
GHSA-h67p-54hq-rp68 hardening). Consumed via cosmiconfig and test
tooling. Resolves 3.14.2 -> 3.15.1 and 4.1.1 -> 4.3.1.

Fixes Dependabot alerts #276, #277 (and medium #260, #261).

* fix(deps): bump pinned axios to 1.18.0 (proxy inheritance flaw)

axios >=1.15.2 <1.18.0 can pick up an inherited (prototype-polluted)
proxy configuration after interceptor config cloning in the Node HTTP
adapter, letting requests be routed through an attacker-influenced
proxy (GHSA-gcfj-64vw-6mp9). The 1.18.0 release also hardens several
related medium-severity issues (formToJSON recursion, maxBodyLength
bypasses, NO_PROXY handling, auth subfield pollution).

Fixes Dependabot alert #270 (and related medium axios alerts).

* fix(deps): force adm-zip >=0.6.0 (CVE-2026-39244)

adm-zip <0.6.0 trusts crafted ZIP headers and can allocate up to 4GB
of memory for a single entry, enabling denial of service via a small
malicious archive (GHSA-xcpc-8h2w-3j85). Consumed by onnxruntime-node
in the apps/api embedding stack. Resolves 0.5.17 -> 0.6.0.

Fixes Dependabot alert #264.

* fix(deps): force find-my-way >=9.7.0 (CVE-2026-47219)

find-my-way <=9.6.0 is vulnerable to denial of service over HTTP/2
(GHSA-c96f-x56v-gq3h). It is the router underneath fastify in
apps/api. Resolves 9.5.0/9.6.0 -> 9.7.0 (which also drops its
safe-regex2 dependency).

Fixes Dependabot alert #295.

* fix(deps): force @fastify/static >=10.1.1 (CVE-2026-15074)

@fastify/static <=10.1.0 allows route guard bypass via path traversal
(GHSA-83w8-p2f5-377r), with a related authorization bypass through
non-canonical URL paths (CVE-2026-7120). apps/api already used 10.1.2
directly, but @fastify/swagger-ui pulled a vulnerable 9.3.0; the
override dedupes everything to 10.1.2.

Fixes Dependabot alert #303 (and medium #304).

* fix(deps): force sharp >=0.35.0 (inherited libvips CVEs)

sharp <0.35.0 bundles libvips versions affected by CVE-2026-33327,
CVE-2026-33328, CVE-2026-35590 and CVE-2026-35591 (GHSA-f88m-g3jw-g9cj),
exploitable via malicious image input. Consumed via
@huggingface/transformers in the apps/api embedding stack. Resolves
0.34.5 -> 0.35.3; native binary verified to load and process images.

Fixes Dependabot alert #290.

* fix(deps): force react-router >=8.3.0 (CSRF bypass + route-match DoS)

react-router <8.3.0 allows RSC-mode CSRF bypass executing actions
before the 400 response (GHSA-qwww-vcr4-c8h2), and <7.18.0 allows
unauthenticated DoS via inefficient route matching (CVE-2026-55685).
8.3.0 also covers the open-redirect (CVE-2026-53669), RSCErrorHandler
XSS (CVE-2026-53667) and constructor-injection (CVE-2026-53666)
mediums.

Note: react-router-dom has no 8.x line, so apps/web keeps
react-router-dom 7.13.2 as the import surface with react-router
overridden to 8.3.0 underneath. tsc, vite build and the full web
suite (45 files, 309 tests) pass with this pairing, but it is not an
upstream-tested combination - manual QA of navigation flows is
recommended before release.

Fixes Dependabot alerts #299, #305 (and medium #296, #297, #298).

* fix(deps): use react-router 7.18.x instead of the 8.x override

The 8.3.0 override paired react-router-dom@7.13.2 with react-router
8.x, which requires React >=19.2.7 and Node >=22.22.0 - outside this
repo's supported matrix (React 19.2.4, Node >=20) and an
upstream-untested combination.

7.18.2 stays within the supported matrix and still patches the
route-matching DoS (CVE-2026-55685) plus the open-redirect
(CVE-2026-53669), RSCErrorHandler XSS (CVE-2026-53667) and
constructor-injection (CVE-2026-53666) issues.

The RSC-mode CSRF bypass (GHSA-qwww-vcr4-c8h2, alert #305) is patched
only in 8.3.0 and therefore remains open; apps/web is a client-side
Vite SPA that does not use RSC mode, so the vulnerable code path is
not reachable. Revisit if react-router-dom ships an 8.x line.

Fixes Dependabot alerts #299, #296, #297, #298; leaves #305 open by
design.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant