Repository navigation
test: port the upstream Hugging Face tests - #303
Conversation
Each test that ports an @ai-sdk/huggingface@2.0.62 case carries the full describe chain as an `/// upstream:` marker and sits in nested describe mods. Tests that assert only part of an upstream case say so and point at the full port; aimux's own tests stay unmarked. Test bodies are unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
The upstream cases the old tests do not cover in full go to src/huggingface/tests/, one file per upstream test file (provider.rs, responses/responses_language_model.rs). The shared mock fetch is reached through src/test_support/. The boundary script skips files under tests/ dirs as it skips #[cfg(test)] blocks. Three cases fail here and are fixed in the next commits: MCP calls are marked dynamic, a function_call with an output has no tool-result, and a malformed stream chunk does not make the finish reason error. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
…ce@2.0.62 doGenerate pushes mcp_call and mcp_list_tools as provider-executed tool-calls and tool-results without a dynamic flag (huggingface-responses-language-model.ts:264-301). aimux set dynamic: true on all four parts. Without a local tool of that name, Core now returns the call marked invalid, as parseToolCall does; the old test of that path follows. Tests: huggingface::tests::responses::responses_language_model::hugging_face_responses_language_model::do_generate::basic_text_response::should_handle_mcp_tools_with_annotations. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
…ggingface@2.0.62 doGenerate pushes a tool-result after a function_call or mcp_call when part.output is truthy, with the output string as the result (huggingface-responses-language-model.ts:273, :312). aimux dropped the function_call output and, for mcp_call, also gave a tool-result for an empty string. Both now follow `if (part.output)`, and so does the stream's function_call. The old function_call test asserted the dropped output and follows. Tests: huggingface::tests::responses::responses_language_model::hugging_face_responses_language_model::tool_calls::should_handle_function_call_tool_responses. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
…sdk/huggingface@2.0.62
createHuggingFaceResponsesStreamError (huggingface-responses-language-model.ts:562-590)
reads only `error` and `response.failed` events: the details are
response.error for response.failed, else the event's error object or the
event itself, and the message must be a string. The transform then sets
finishReason { unified: 'error', raw: code or type } (:406-419); a chunk
that fails to parse sets { unified: 'error' } (:396-404).
aimux read only a top-level `error` field, so an `error` event with the
message on the event and every `response.failed` event went unnoticed,
and the finish reason stayed other. A first-event error is still returned
by do_stream (registered SSE pre-read), so the mid-stream case gets its
own aimux test.
Tests: huggingface::tests::responses::responses_language_model::hugging_face_responses_language_model::do_stream::should_handle_streaming_errors,
reads_mid_stream_error_events (tests/huggingface_responses_test.rs).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
[huggingface] maps the 12 source files of @ai-sdk/huggingface@2.0.62: 10 mapped, settings.ts and version.ts not-applicable. Four test cases are excluded by hand: the first-event stream error is the registered SSE pre-read; the NoSuchModelError and UnsupportedFunctionalityError message texts come from aimux-core, which #268 changes, and are tracked in #276. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
…ce@2.0.62 doGenerate pushes mcp_call and mcp_list_tools as provider-executed tool-calls and tool-results without a dynamic flag (huggingface-responses-language-model.ts:264-301). aimux set dynamic: true on all four parts. Without a local tool of that name, Core now returns the call marked invalid, as parseToolCall does. Tests: should_handle_mcp_tools_with_annotations (tests/huggingface_responses_test.rs) now expects the invalid call. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
…ggingface@2.0.62 doGenerate pushes a tool-result after a function_call or mcp_call when part.output is truthy, with the output string as the result (huggingface-responses-language-model.ts:273, :312). aimux dropped the function_call output and, for mcp_call, also gave a tool-result for an empty string. Both now follow `if (part.output)`, and so does the stream's function_call (:489). Tests: should_handle_function_call_tool_responses now expects the tool-result; mcp_call_with_empty_output_has_no_tool_result is new (tests/huggingface_responses_test.rs). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
…sdk/huggingface@2.0.62
createHuggingFaceResponsesStreamError (huggingface-responses-language-model.ts:562-590)
reads only `error` and `response.failed` events: the details are
response.error for response.failed, else the event's error object or the
event itself, and the message must be a string. The transform then sets
finishReason { unified: 'error', raw: code or type } (:406-419); a chunk
that fails to parse sets { unified: 'error' } (:396-404).
aimux read only a top-level `error` field, so an `error` event with the
message on the event and every `response.failed` event went unnoticed,
and the finish reason stayed other. A first-event error is still returned
by do_stream (registered SSE pre-read).
Tests: reads_mid_stream_error_events, malformed_chunk_ends_with_an_error_finish
(tests/huggingface_responses_test.rs).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
The three behaviour fixes now live in their own PRs (#305, #306, #307); this branch stacks on the last one. responses.rs and CHANGELOG.md are the same on both sides; the old test file keeps the markers and takes the two aimux tests the fix PRs added. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
#268 kept the NoSuchModel and UnsupportedFunctionality messages, so the three cases stay sub-feature; the reasons no longer point at it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
…nish Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
…st/port-the-upstream-hugging-face-tests Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
…nish 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.
Hugging Face test port:34 个 marker + 4 个 layout exclusion 覆盖 38 个上游 case,fixtures 一致,无生产行为变化。Approve。
…nd-with-an-error-finish' into test/port-the-upstream-hugging-face-tests
…ream-errors-end-with-an-error-finish # Conflicts: # CHANGELOG.md
…' into test/port-the-upstream-hugging-face-tests # Conflicts: # aimux-providers/layout.toml
…ream-errors-end-with-an-error-finish # Conflicts: # CHANGELOG.md
…' into test/port-the-upstream-hugging-face-tests # Conflicts: # aimux-providers/layout.toml
…ream-errors-end-with-an-error-finish # Conflicts: # CHANGELOG.md
…' into test/port-the-upstream-hugging-face-tests # Conflicts: # aimux-providers/layout.toml
…eam-hugging-face-tests # Conflicts: # aimux-providers/layout.toml
…eam-hugging-face-tests
…eam-hugging-face-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-hugging-face-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-hugging-face-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-hugging-face-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-hugging-face-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/huggingface@2.0.62的上游测试迁完,按厂商分批的第五个(Mistral #295、Cohere #296、DeepSeek #299、Groq #301)。上游 2 个测试文件共 38 个用例:
registered:首个 SSE 事件就是错误时,aimux 在do_stream里直接返回Err(已登记的「SSE 预读」)。sub-feature(Core 运行时:与 AI SDK 的剩余差距(对齐文档 §9.1 已知差距) #276):错误提示文字来自 aimux-core 的错误类型,NoSuchModel和UnsupportedFunctionality的消息格式和上游不同,[15/15] feat!: generate binding DTOs from the Rust types #268 合并后仍是这样。迁移中发现三处行为差异,各自单独一个 fix PR,本 PR 叠在最后一个上:
mcp_call、mcp_list_tools)多带了dynamic: true。function_call带output时没有输出 tool-result;mcp_call的output为空字符串时却输出了。error字段,response.failed和消息写在事件本身的error事件都漏掉;出错后结束原因停在other,上游是error。这几处修复最早在本分支上提交过,拆出去之后用一个合并提交把 #307 合进来。#307 已合入 master,所以相对 master 的 diff 只有测试和
layout.toml。原有测试里 18 个只覆盖了上游用例的一部分(或换了输入),完整用例在新文件里重新迁了一遍,原测试留着但不计数,注释指向完整的那个。
位置按新定的布局:一个厂商的测试全放
src/huggingface/tests/,一个上游测试文件对应一个 Rust 文件。原有的tests/huggingface_responses_test.rs留在原地,由包拆分线程的搬移 PR 合进来。一、体系概览:Hugging Face 的测试现在怎么跑(master
5743a40a)上游
packages/huggingface/src/对应:改动前 32 个测试和上游用例对不上号:出处只写了
it文本,没有 describe 链,18 个只比了部分字段或换了输入。二、本 PR 的改动(细节)
1. 原有 32 个测试补标记(
tests/huggingface_responses_test.rs)12 个和上游用例一一对应,加标记、按
describe包mod;18 个只比了部分字段或换了输入,注释写明缺什么、完整用例在哪;2 个是 aimux 自己的测试(坏帧之后流继续、supported_urls);三个 fix PR 另加的 3 个 aimux 测试也在这个文件末尾。函数体不变(逐行比对过)。2. 剩下的上游用例(新目录,
huggingface.rs末尾#[cfg(test)] mod tests;)3.
aimux-providers/layout.toml(只有[huggingface])harness 上的差别(期望值都没改):
createTestServer换成MockFetch,server.calls[0]换成它记下的请求体;快照里值为undefined的键在 JSON 里省略;typeof provider === 'function'换成调用HuggingFaceProvider::call。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 157(其中 huggingface 22)、huggingface_responses 35,以及用到 Hugging Face 的 cassette_full、conformance、package_user_agent、thin_wrapper_config,全过scripts/check_provider_boundaries.shpassesNotes for reviewers
src/test_support/mod.rs、aimux-providers/layout.toml,并改了边界脚本的同两行;这几处在各 PR 里内容相同,后合入的只需合并layout.toml的厂商表。layout.toml的手写排除里。https://claude.ai/code/session_01RoxcKU4zBD64Lri3e4Lrq5
Generated by Claude Code