Repository navigation
Conversation
… error A streamed SSE event whose data is not JSON yielded `JsonParse` with only the parser's message. The AI SDK's `parseJsonEventStream` reads each event with `safeParseJSON`, whose `JSONParseError` reads `JSON parsing failed: Text: <text>.\nError message: <message>` (`@ai-sdk/provider` src/errors/json-parse-error.ts:16-19). Found while porting the `@ai-sdk/openai-compatible` 3.0.62 tests (`doStream › should handle unparsable stream parts`, chat and completion); every stream read through `create_event_source_response_handler` now reports it the same way. Well-formed JSON of the wrong shape stays `InvalidResponseData`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
Ports the tests of @ai-sdk/openai-compatible 3.0.62 (RFC-0045) into aimux-providers/src/openai_compatible/tests/, one Rust file per upstream test file, one mod per describe level and an `/// upstream:` marker on every test: 266 tests for 266 of the 268 upstream cases. The other 2 are ts-only in aimux-providers/layout.toml (`[openai_compatible]`): they read the settings handed to mocked model constructors, which aimux's completion, embedding and image models never read. Upstream fixtures are copied unchanged into chat/fixtures/, the four `toMatchSnapshot` values become chat/snapshots/*.json. The model `config` fields (and `CompletionConfig`) are widened to `pub(super)` so the tests can read the configuration a model was built with. Boundary rule 4c lets the in-crate tests name `crate::test_support`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
Old tests in openai_compatible_upstream_e2e_test.rs and openai_compatible_factory_test.rs that cover part of an upstream case get a `/// partial:` line naming the case and the file with its full port (20 lines). None of them covers a whole case, so none gets an `/// upstream:` marker. Test bodies are unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
Split src/openai_compatible/ into one Rust file per file of @ai-sdk/openai-compatible 3.0.62 (RFC-0046 §4.2), with the upstream chat/, completion/, embedding/, image/ and utils/ subdirectories: provider.rs (settings, create_openai_compatible, build, the provider and getCommonModelConfig's CompatModelConfig), error.rs, and under chat/ the model, options, usage, message conversion, finish reason, metadata extractor, tool preparation and API types. Function bodies change only in paths and visibility; no public path changes, and the crate-internal callers import from openai_compatible's root instead of the removed config module. Fold tests/openai_compatible_factory_test.rs, tests/openai_compatible_upstream_e2e_test.rs and the inline unit tests of chat.rs, config.rs and convert.rs into src/openai_compatible/tests/ without changing assertions. The factory test that sets OPENAI_API_KEY now runs #[serial], since it shares the lib test binary with the default-providers test that sets the same variable. Point layout.toml at the new paths, and let boundary rule 4b skip the vendor tests, whose recorded fixtures use a provider named groq. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0116HPMoqaLfFr1TyqDq1hrW
This was referenced Oct 20, 2026
…ai-sdk-parse-errors Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
…-errors into test/port-the-upstream-openai-compatible-tests 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_0116HPMoqaLfFr1TyqDq1hrW
cunninghamcard-bit
marked this pull request as ready for review
October 24, 2026 11:29
…eam-openai-compatible-tests
eric8810
approved these changes
Oct 25, 2026
eric8810
left a comment
Contributor
There was a problem hiding this comment.
OpenAI-compatible layout refactor:294→294 tests,move-only,公开路径/re-export 保留。Approve。
… deepseek Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0116HPMoqaLfFr1TyqDq1hrW
3 tasks done
Contributor
Author
|
批准之后推了 Generated by Claude Code |
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0116HPMoqaLfFr1TyqDq1hrW
layout.toml: master's [mistral] table (#295) and this PR's [openai_compatible] table are both kept. 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_0116HPMoqaLfFr1TyqDq1hrW
…eam-openai-compatible-tests # Conflicts: # aimux-providers/layout.toml
…mpatible-tests' into refactor/move-the-openai-compatible-files-to-the-upstream-layout Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0116HPMoqaLfFr1TyqDq1hrW
…to-the-upstream-layout Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0116HPMoqaLfFr1TyqDq1hrW
cunninghamcard-bit
changed the base branch from
test/port-the-upstream-openai-compatible-tests
to
master
October 25, 2026 15:01
Contributor
Author
eric8810
approved these changes
Oct 27, 2026
eric8810
left a comment
Contributor
There was a problem hiding this comment.
Verified the post-approval commits on this head: only additive tests/docs or tightened boundary checks; no weakening or behavior regression. Re-approving the current head.
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
把
src/openai_compatible/按@ai-sdk/openai-compatible@3.0.62一个文件对一个文件重排(RFC-0046 §4.2),照上游建chat/、completion/、embedding/、image/、utils/子目录。两个老测试程序和三个源文件里的单元测试并进厂商测试目录src/openai_compatible/tests/(RFC-0046 §5)。函数体只改了路径和可见性。公开路径都不变:openai_compatible::completion、::embedding、::image仍是公开模块,里面的模型类型路径照旧,crate 根和模块根的再导出也不动。测试数量和函数名前后一致;一个设OPENAI_API_KEY的老用例加了#[serial](见“共享进程状态”)。叠在测试 PR #355 上。实施进度在 #328 跟踪。已经测试分支
c4c73d0f合上 masterb69137eb,冲突按 master 的改动搬到新位置解决(config.rs的请求 URL 和 user-agent 错误 cause 落到provider.rs,convert.rs的两处落到chat/chat_language_model_options.rs,其余落到 chat、completion、embedding、image 各自的新文件);测试数前后仍相等(311 个:lib 294 个加留在tests/的 17 个,名字多重集相同)。一、体系现状(概览,测试 PR #355 头
85453d9d)上游同一条路:
createOpenAICompatible(openai-compatible-provider.ts)用getCommonModelConfig给每个模型一份{ provider, url, headers, fetch },建OpenAICompatibleChatLanguageModel(chat/)、-CompletionLanguageModel(completion/)、-EmbeddingModel(embedding/)、-ImageModel(image/);消息转换、工具准备、finish reason、usage、metadata extractor、选项各在chat/下自己的文件,toCamelCase在utils/,错误结构在 openai-compatible-error.ts。aimux 把这些放在 7 个文件里:mod.rs(provider)、config.rs(模型配置、聊天设置、metadata extractor、错误结构)、convert.rs(getArgs、消息转换、工具、finish reason、toCamelCase)、chat.rs、completion.rs、embedding.rs、image.rs、types.rs。测试:#355 的新用例在
src/openai_compatible/tests/(266 个);chat.rs、config.rs、convert.rs里还有 2 + 3 + 1 个单元测试;老用例在两个独立测试程序tests/openai_compatible_factory_test.rs(11 个)、tests/openai_compatible_upstream_e2e_test.rs(11 个)。二、本 PR 改动(细节)
mod.rs的模块文档、mod、pub usemod.rs(只有模块声明和导出)index.ts;internal/index.ts也指这里mod.rs的设置、create_openai_compatible、build、Assembly、OpenAICompatibleProvider和它的Provider/ProviderDiscovery实现provider.rsopenai-compatible-provider.tsconfig.rs的ResolveBaseUrl、ResolveFetchHeaders、BaseUrl、CompatModelConfig、RequestHeaders、FetchUserAgentprovider.rsgetCommonModelConfig(同一个文件)chat.rs的list_models_onceprovider.rs(和 Mistral 一样,发现放在 provider 旁边)config.rs的ErrorStructure、default_error_structureerror.rsopenai-compatible-error.tsconfig.rs的ConvertUsage、SupportedUrlsFn、ChatSettings;convert.rs的ChatBodySpec、RequestBodyResult、namespace、resolve_metadata_key、build_request_body;chat.rs的模型、流和其余函数chat/chat_language_model.rschat/openai-compatible-chat-language-model.ts(OpenAICompatibleChatConfig、getArgs都在这个文件);chat/get-response-metadata.ts在 aimux 是就地组装的,也指这里convert.rs的SCHEMA_KEYS、option_string、validate_optionschat/chat_language_model_options.rschat/openai-compatible-chat-language-model-options.tschat.rs的convert_usage、usage_from_rawchat/convert_chat_usage.rschat/convert-openai-compatible-chat-usage.tsconvert.rs的MessageSpec到convert_assistant_message、signature_stringchat/convert_to_chat_messages.rschat/convert-to-openai-compatible-chat-messages.tsconvert.rs的parse_finish_reasonchat/map_finish_reason.rschat/map-openai-compatible-finish-reason.ts;completion 的同名文件内容一样,aimux 只有一份,也指这里config.rs的MetadataExtractor、StreamMetadataExtractorchat/metadata_extractor.rschat/openai-compatible-metadata-extractor.tsconvert.rs的PreparedTools到prepare_function_toolschat/prepare_tools.rschat/openai-compatible-prepare-tools.tstypes.rschat/api_types.rs(原样)chat/openai-compatible-api-types.tscompletion.rs除下面三个函数completion/completion_language_model.rscompletion/openai-compatible-completion-language-model.ts;-options.ts在 aimux 是arguments里就地检查的,也指这里completion.rs的completion_prompt、usage、metadatacompletion/convert_to_completion_prompt.rs、convert_completion_usage.rs、get_response_metadata.rsembedding.rs除embedding_optionsembedding/embedding_model.rsembedding/openai-compatible-embedding-model.tsembedding.rs的embedding_optionsembedding/embedding_model_options.rsembedding/openai-compatible-embedding-model-options.tsimage.rsimage/image_model.rsimage/openai-compatible-image-model.ts;-options.ts、-settings.ts在 aimux 没有单独的代码,指这里convert.rs的to_camel_caseutils/to_camel_case.rsutils/to-camel-case.tscompletion、embedding、image三个pub mod保留,各自的mod.rs再导出模型类型,openai_compatible::completion::OpenAICompatibleCompletionModel这类路径照旧;chat仍是pub(crate),config、convert、types原来就是 crate 内部模块。config字段(chat、completion、embedding、image)和CompletionConfig从pub(super)改为pub(in crate::openai_compatible),test: port the upstream OpenAI-compatible tests #355 的测试仍能读;stream_error同样放宽,completion 经chat的再导出用它。拆到兄弟文件后要互相调用的私有函数改为pub(super):SCHEMA_KEYS、option_string、validate_options、completion_prompt、usage、metadata、embedding_options,以及CompletionResponse和它的id、created、model字段。chat/mod.rs把chat_language_model、convert_to_chat_messages、prepare_tools声明为pub(super) mod,测试直接用。BaseUrl、ChatSettings、CompatModelConfig、ResolveBaseUrl、ResolveFetchHeaders由openai_compatible/mod.rs以pub(crate) use导出,decision_support.rs、runtime_decision.rs、preset.rs、vertex/partner_provider.rs的use crate::openai_compatible::config::…改成use crate::openai_compatible::…(只改 import)。chat::usage_from_raw、chat::chat_test_stream、completion::OpenAICompatibleCompletionModel的路径不变。tests/openai_compatible_factory_test.rs(createOpenAICompatible对录制的 AI SDK 请求回放)整个放进tests/provider.rs末尾的recorded_fixtures模块,自带的 mock 和 fixture 读取不动。tests/openai_compatible_upstream_e2e_test.rs按被测模型拆进tests/chat/chat_language_model.rs(7 个)、tests/completion/completion_language_model.rs(1 个)、tests/embedding/embedding_model.rs(1 个)、tests/image/image_model.rs(2 个),各在一个upstream_e2e模块里;共用的provider、options、chat_response等放到tests/support.rs,mock_fetch改用crate::test_support::mock_fetch。config.rs的 3 个(ChatSettings::for_model)和chat.rs的 2 个进tests/chat/chat_language_model.rs,convert.rs的 1 个进tests/utils/to_camel_case.rs。config::…、convert::…import 改到新路径。断言都没改。tests/的:tests/openai_compatible_test.rs(625 个)是经create_provider跑 preset 的矩阵,测的是 preset,按 RFC-0046 §4.3 随 preset 那一批进preset/tests/,这里不动。layout.toml的[openai_compatible]25 个rust字段改到新路径。scripts/check_provider_boundaries.sh的规则 4b(共享包里不出现"groq"/"deepseek")跳过tests/目录:老的回放用例用的是以groq为名录制的 fixture,这是测试数据,不是按厂商分支。共享进程状态:老测试原来各是单独的测试程序,现在和 #355 的用例同在 lib 的一个测试程序里。只有老的
chat_without_an_api_key_sends_no_authorization动环境变量:它把OPENAI_API_KEY设成一个不该被读到的值,证明兼容层不读它;lib 里default_providers.rs的an_invalid_env_base_url_fails_each_call_not_creation(#[serial])也设这个变量,两个同时跑会互相恢复对方的值,所以给它加了#[serial],函数体不变。原来就有的a_lazy_base_url_is_evaluated_per_request_and_its_error_fails_the_request设AIMUX_TEST_COMPAT_LAZY_BASE_URL,本来就是#[serial]。没有全局计数器;every_fixture_is_replayed读fixtures/aisdk/openai-compatible/,路径按CARGO_MANIFEST_DIR算,位置不影响。验证
cargo test -p aimux-providers --lib加原来两个--test:前后都是 428 个测试(lib 406 + 11 + 11),函数名多重集相同;openai_compatible::tests::下 test: port the upstream OpenAI-compatible tests #355 的 266 个完整路径不变,openai_compatible 以外的 lib 测试路径不变。lib 测试程序连跑 5 次,428 个全过。cargo +1.99 clippy -p aimux-providers --lib --tests -- -D warnings、cargo +1.99 check -p aimux-providers --lib --tests --all-features、RUSTDOCFLAGS="-D warnings" cargo +1.99 doc -p aimux-providers --no-deps、cargo fmt --all -- --check、scripts/check_provider_boundaries.sh、cargo +1.99 check --workspace、cargo test -p aimux-providers通过。Type of change
Checklist
Generated by Claude Code