feat: configurable upstream + body-idle timeouts on RecordConfig#197
Merged
jpr5 merged 4 commits intoMay 15, 2026
Merged
Conversation
commit: |
tombeckenham
added a commit
to openstory-so/openstory
that referenced
this pull request
May 14, 2026
…rd config #701 The published `@copilotkit/aimock@1.24.0` RecordConfig type doesn't have these options yet — they're only on the linked aimock fork (CopilotKit/aimock#197) and were tripping `bun typecheck` on tests in CI which installs from the registry. Replaced with a comment that documents why they're needed and points at the upstream PR. CI is unaffected at runtime — `record:` only fires when E2E_RECORDING=1, which CI doesn't set. Local record runs that need the bumped timeouts can add the options back temporarily, or wait for the upstream release. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Posted prematurely — will follow up with a proper review.
Contributor
|
I pushed fixes on top of your commit:
Everything passes locally (tsc, 3026 tests, build). CI will need a push from your side to trigger — can you push an empty commit to kick the workflows? Take a look and let me know what you think. |
Contributor
|
I'm sorry for the state thrash — my bot is being a fucken idiot today. |
fcd3f60 to
19cbfca
Compare
Add upstreamTimeoutMs and bodyTimeoutMs to RecordConfig so callers can lift the hardcoded 30s ceilings used by the proxy. Defaults stay 30s. Includes clampTimeout validation (rejects 0/NaN/Infinity/ negatives) and Pick<RecordConfig, ...> for the internal param type.
19cbfca to
a8ab23c
Compare
Contributor
|
@tombeckenham OK all yours. |
Wire the new RecordConfig timeout fields into the llmock CLI with input validation matching existing patterns.
Verify custom bodyTimeoutMs and upstreamTimeoutMs are honored, and that 0/negative values clamp to the 30s default.
CHANGELOG entry under [Unreleased], record-replay page CLI table and Upstream Timeouts section, README CLI example.
a8ab23c to
41166b9
Compare
tombeckenham
commented
May 15, 2026
Contributor
Author
tombeckenham
left a comment
There was a problem hiding this comment.
Yes. This works nicely. Thank you!
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.
Summary
Adds `RecordConfig.upstreamTimeoutMs` and `RecordConfig.bodyTimeoutMs` so callers can lift the hardcoded 30s ceilings used by the proxy. Defaults stay 30s — back-compat preserved.
Motivation
Reasoning models (e.g. Grok 4.3 via OpenRouter with `response_format: json_schema`) routinely leave 30s+ gaps between SSE chunks during the thinking phase under concurrent load. The hardcoded `BODY_TIMEOUT_MS = 30_000` in `makeUpstreamRequest` fires `req.destroy()` mid-stream, and the captured fixture ends up with no `[DONE]` and no `finish_reason` — downstream `JSON.parse(text)` then blows up on `Unterminated string`.
Reproduces deterministically with a 6-way concurrent record run against the same Grok 4.3 + structured-output prompt:
```
BEFORE (hardcoded 30s):
jsonValid: 3/6 elapsed min=23.23s median=30.95s max=31.00s
3 streams cut off at exactly 30.95–31.00s, no [DONE], no finish_reason
AFTER (bodyTimeoutMs: 180_000):
jsonValid: 6/6 elapsed min=31.84s median=38.62s max=42.18s
All 6 finish=stop, all done=true, all JSON valid
```
For comparison, the same 6-way load fired direct to OpenRouter (no aimock in the loop) completes 6/6 up to 52s with clean `[DONE]` — i.e. the upstream is fine, only the proxy's idle timer was clipping us.
Change
Test plan
Back-compat
No behavior change when the new fields are omitted — defaults stay at the original 30_000.