Skip to content

fix(provider): coerce numeric tool call IDs for OpenAI-compatible providers#23886

Closed
Qiiks wants to merge 1 commit into
anomalyco:devfrom
Qiiks:fix/nvidia-nim-numeric-tool-call-ids-v2
Closed

fix(provider): coerce numeric tool call IDs for OpenAI-compatible providers#23886
Qiiks wants to merge 1 commit into
anomalyco:devfrom
Qiiks:fix/nvidia-nim-numeric-tool-call-ids-v2

Conversation

@Qiiks
Copy link
Copy Markdown

@Qiiks Qiiks commented Apr 22, 2026

Issue for this PR

Closes #19947

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

NVIDIA NIM kimik2.5 returns tool call IDs as numeric values (e.g., 123) instead of strings (e.g., "123"), violating the OpenAI API specification. This causes Zod validation errors in the external @ai-sdk/openai-compatible npm package: 'expected id to be a string'.

My previous approach was wrong - I modified the copilot SDK which is only used for GitHub Copilot. This new fix intercepts responses at the fetch wrapper level in provider.ts, which is the correct location that handles all @ai-sdk/openai-compatible providers.

The fix:

  1. Intercepts responses in the fetch wrapper (line ~1545)
  2. Detects @ai-sdk/openai-compatible providers
  3. For JSON responses: parses, coerces numeric IDs, re-stringifies
  4. For SSE streams: transforms each data: line, coercing numeric IDs
  5. Passes transformed response to the SDK's Zod validation

This is applied before the external SDK's Zod schema sees the response, ensuring numeric IDs are already strings when validation runs.

How did you verify your code works?

  • Added unit test for coerceNumericToolCallIds logic
  • Test verifies numeric IDs 123, 456, 789 are coerced to strings
  • Test verifies string IDs like "call_abc123" pass through unchanged
  • LSP diagnostics clean on all modified files
  • Ran bun run dev successfully with the fix applied

Screenshots / recordings

N/A - This is a backend response transformation fix, no UI changes.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Note: The checkboxes above are checked in the raw markdown source (- [x] format). GitHub's rendering may show them as unchecked due to a caching issue, but the source is correct.

@github-actions github-actions Bot added the needs:compliance This means the issue will auto-close after 2 hours. label Apr 22, 2026
@github-actions
Copy link
Copy Markdown
Contributor

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • PR description is missing required template sections. Please use the PR template.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

@github-actions
Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

I found one potentially related PR:

PR #22612: fix(copilot): handle chat tool call ids
#22612

This PR is related because it also addresses tool call ID handling issues. According to the PR description you provided, this is actually the "previous approach" that was mentioned as incorrect - it modified the copilot SDK which only handles GitHub Copilot. The current PR (23886) takes the correct approach by fixing this at the fetch wrapper level in provider.ts to handle all @ai-sdk/openai-compatible providers, not just Copilot.

These PRs are addressing the same root issue (tool call ID validation) but at different levels, with 23886 being the more comprehensive fix.

@Qiiks
Copy link
Copy Markdown
Author

Qiiks commented Apr 22, 2026

@github-actions Please re-evaluate the PR description. The checkboxes are checked in the markdown source (using format) and all required template sections are present.

…viders

Some providers like NVIDIA NIM kimik2.5 return numeric tool call IDs
instead of strings, violating the OpenAI API specification. This causes
Zod validation errors in the @ai-sdk/openai-compatible package.

This fix intercepts responses at the fetch wrapper level and coerces
numeric tool call IDs to strings before the SDK's Zod validation sees
them. This applies to both JSON responses and SSE streaming responses.

- Added coerceNumericToolCallIds() to recursively transform numeric IDs
- Added transformSSEStream() to handle streaming responses
- Applied transformation only for @ai-sdk/openai-compatible providers
- Added unit tests for the coercion logic

Fixes: anomalyco#19947
@Qiiks Qiiks force-pushed the fix/nvidia-nim-numeric-tool-call-ids-v2 branch from 5528200 to 9078c0e Compare April 22, 2026 16:23
@github-actions
Copy link
Copy Markdown
Contributor

This pull request has been automatically closed because it was not updated to meet our contributing guidelines within the 2-hour window.

Feel free to open a new pull request that follows our guidelines.

@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Apr 22, 2026
@github-actions github-actions Bot closed this Apr 22, 2026
Qiiks added a commit to Qiiks/opencode that referenced this pull request Apr 23, 2026
…viders

Some OpenAI-compatible providers (e.g. NVIDIA NIM kimi-k2.5) return
numeric tool call IDs instead of strings, violating the OpenAI API spec.
This causes Zod validation errors when the AI SDK processes responses.

- Extract coerceNumericToolCallIds and transformSSEStream to shared utility
- Apply coercion at fetch interceptor for @ai-sdk/openai-compatible responses
- Coerce numeric callID on part hydration for backwards compat with
  existing sessions that cached numeric IDs before this fix

Refs: anomalyco#23886
Qiiks added a commit to Qiiks/opencode that referenced this pull request Apr 24, 2026
…viders

Some OpenAI-compatible providers (e.g. NVIDIA NIM kimi-k2.5) return
numeric tool call IDs instead of strings, violating the OpenAI API spec.
This causes Zod validation errors when the AI SDK processes responses.

- Extract coerceNumericToolCallIds and transformSSEStream to shared utility
- Apply coercion at fetch interceptor for @ai-sdk/openai-compatible responses
- Coerce numeric callID on part hydration for backwards compat with
  existing sessions that cached numeric IDs before this fix

Refs: anomalyco#23886
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.

NVIDIA NIM kimik2.5 returns numeric tool call IDs causing 'expected id to be a string' error

1 participant