Repository navigation
test: port the upstream xAI tests - #312
Conversation
@ai-sdk/xai 5.0.12 opens the STT WebSocket inside the returned stream (xai-transcription-model.ts:276-358), so doStream resolves and a connect failure errors the stream, cancelling the caller's audio. aimux connected before returning and failed do_stream itself. The connect now runs first inside the stream; on failure the stream yields the error and ends, which drops the audio. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
In @ai-sdk/xai 5.0.12, cancelling the transcription stream runs cleanup, which calls connection.close() (xai-transcription-model.ts:290-298, :459-462). aimux only sent a close frame after transcript.done or an error event; a stream dropped earlier released the transport without one. The socket now lives in a guard that, when dropped before it was closed, sends the close frame on the runtime. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
Upstream's ReadableStream start runs when doStream builds the stream, so the WebSocket is opened before doStream resolves even if the stream is never read. Connecting on the stream's first poll would skip the connection for a stream dropped unread; connect in do_stream instead and hand the outcome to the stream, which still yields a failure as its error. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
…/xai-stt-closes-the-socket-when-the-stream-is-dropped # Conflicts: # aimux-providers/src/xai/transcription.rs
Tests that match an @ai-sdk/xai 5.0.12 case one to one get its marker and sit in describe-level mods; tests that cover a case only in part keep a partial: doc line naming the full port in src/xai/tests/. Bodies are unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
One Rust file per upstream test file under src/xai/tests/, with the upstream fixtures and snapshots beside them. The error part of a stream error event is compared through a view that renames providerCode to code and takes type from the event: aimux has no AI_StreamProviderError, so the part is an AI_APICallError. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
…opped Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
…est/port-the-upstream-xai-tests Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
…the-socket-when-the-stream-is-dropped # Conflicts: # CHANGELOG.md
…en dropped The socket guard was built in the first statement of the async_stream::stream! body, which runs only on the first poll. A stream that do_stream returned with an open socket but that was dropped before next() released the transport without a close frame. The guard is now built in do_stream, right after the connect, and moved into the stream. The CHANGELOG said the socket is opened inside the stream; do_stream still awaits ws_connect. The entry now says what changed: a connect failure arrives as the stream's error. Test: dropping_an_unpolled_stream_closes_the_socket (tests/xai_transcription_test.rs) fails without the change. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
eric8810
left a comment
There was a problem hiding this comment.
xAI test port:297 个 marker + 4 个 layout case 覆盖 367 个 in-scope case,11 个 fixtures 逐字节一致,无生产变化。Approve。
…en-the-stream-is-dropped' into test/port-the-upstream-xai-tests
…eam-xai-tests # Conflicts: # aimux-providers/layout.toml
…eam-xai-tests # Conflicts: # aimux-providers/layout.toml
…eam-xai-tests # Conflicts: # aimux-providers/layout.toml
…eam-xai-tests # Conflicts: # aimux-providers/layout.toml
…eam-xai-tests # Conflicts: # aimux-providers/layout.toml
eric8810
left a comment
There was a problem hiding this comment.
Rebase is content-preserving: only master/parent merges and CHANGELOG/layout conflict resolution; tests and CI unchanged. Re-approving current head.
…eam-xai-tests # Conflicts: # aimux-providers/layout.toml
eric8810
left a comment
There was a problem hiding this comment.
Rebase verified content-preserving: only master/parent merges and CHANGELOG/layout conflict resolution; CI 16/16. Re-approving current head.
…eam-xai-tests # Conflicts: # aimux-providers/layout.toml
eric8810
left a comment
There was a problem hiding this comment.
Rebase verified content-preserving: only master/parent merges and conflict resolution; CI 16/16. Re-approving current head.
…eam-xai-tests # Conflicts: # aimux-providers/layout.toml
|
Generated by Claude Code Generated by Claude Code |
eric8810
left a comment
There was a problem hiding this comment.
Rebase verified content-preserving: only master/parent merges and conflict resolution; CI 16/16. Re-approving current head.
…eam-xai-tests # Conflicts: # aimux-providers/layout.toml
eric8810
left a comment
There was a problem hiding this comment.
Rebase verified content-preserving: only master merges and conflict resolution; CI 16/16. Re-approving current head.
…eam-xai-tests # Conflicts: # aimux-providers/layout.toml
eric8810
left a comment
There was a problem hiding this comment.
Rebase verified content-preserving: only master merges and conflict resolution; CI 16/16. Re-approving current head.
Summary
按 RFC-0045(#281)把
@ai-sdk/xai@5.0.12的上游测试迁完,按厂商分批的第六个(Mistral #295、Cohere #296、DeepSeek #299、Groq #301、Hugging Face #303)。上游 15 个测试文件共 367 个用例:
missing(Provider 构造与配置:迁移后遗留缺口 #275);Batch 16 个、Realtime 2 个是not-applicable(对齐文档写明本期不做)。sub-feature:provider 的 3 个imageModel用例(Provider 构造与配置:迁移后遗留缺口 #275,aimux 没有 xAI 图片模型);视频doStatus的 expired 用例要比对response,aimux 的错误状态是Err,不带响应信息(Core 运行时:与 AI SDK 的剩余差距(对齐文档 §9.1 已知差距) #276)。迁移中发现两处行为差异,各自单独一个 fix PR,都已合入 master:
do_stream直接返回Err;上游doStream照常返回,错误从流里出来。connection.close()。另有一处只是错误类型不同,没有当作差异修:流里的
error、response.failed事件,上游产出createProviderStreamError的对象(带type、code),aimux 产出AI_APICallError(providerCode存上游的code,type留在data里)。message、statusCode、isRetryable、data 都和上游一致。这 3 个用例经一个视图函数改名后比对,期望值没改。位置按新定的布局:xAI 的新测试全放
src/xai/tests/,一个上游测试文件对应一个 Rust 文件。原有的tests/xai_*_test.rs留在原地,由包拆分线程的搬移 PR 合进来。一、体系概览:xAI 的测试现在怎么跑(master
b91829af)上游
packages/xai/src/对应:改动前 74 个原有测试里只有 36 个能和上游用例一一对应,出处只写了
it文本,没有 describe 链。二、本 PR 的改动(细节)
1. 原有测试补标记(
tests/xai_speech_test.rs、xai_transcription_test.rs、xai_video_test.rs、xai_upstream_e2e_test.rs)一一对应的加标记、按
describe包mod;只覆盖了部分断言或换了输入的不加标记,注释写明完整用例在src/xai/tests/的哪个文件。函数体不变。#310、#311 各加的 1 个 aimux 测试在xai_transcription_test.rs末尾。2. 剩下的上游用例(新目录,
xai/mod.rs末尾#[cfg(test)] mod tests;)3.
aimux-providers/layout.toml(只有[xai])harness 上的差别(期望值都没改):快照里值为
undefined的键在 JSON 里省略;上游靠_internal.currentDate注入固定日期,Rust 侧没有这个入口,改成检查时间戳落在调用前后之间;undici 的 multipart boundary 只比multipart/form-data; boundary=前缀;user-agent 比ai-sdk-xai/5.0.12;result.stream.cancel()换成丢弃流,await flush()换成等关闭帧发出。Type of change
Checklist
cargo +1.99 fmt -p aimux-providers -- --checkpassescargo +1.99 clippy -p aimux-providers --lib --tests -- -D warningspassescargo +1.99 test -p aimux-providers:lib 397(其中 xai 262)、xai_speech 17、xai_transcription 20、xai_video 34、xai_upstream_e2e 5,以及用到 xAI 的 cassette_full、cassette_multimodal、conformance、data_loss_regression、openai_compatible、package_user_agent、vertex_upstream_e2e,全过scripts/check_provider_boundaries.shpassesNotes for reviewers
src/test_support/mod.rs、aimux-providers/layout.toml,并改了边界脚本的同两行;这几处在各 PR 里内容相同,后合入的只需合并layout.toml的厂商表。layout.toml的手写排除里。15571d85,master 209be26);layout.toml是 master 的原文后接 xai 表。Generated by Claude Code