Fix bug OpenAI tooluse,Improve error messaging for deferred-loading tools under OpenAI‑compatible models.#199
Conversation
…ude-code-best#168) Fixes claude-code-best#168 OpenAI requires that an assistant message with tool_calls be immediately followed by tool messages. Previously, convertInternalUserMessage output user content before tool results, causing 400 errors. Now tool messages are pushed first.
提交描述:
修复了在使用OpenAI兼容API时TaskCreate工具调用失败的问题。
问题:
- 当使用OpenAI兼容API模型时,调用TaskCreate工具出现"InputValidationError: The required
parameter `subject` is missing"错误
- OpenAI兼容层没有正确处理deferred tools的过滤逻辑,导致工具schema没有被正确发送给模型
修复:
1. 在OpenAI兼容层中添加了与Anthropic API路径一致的deferred tools处理逻辑
2. 导入必要的工具搜索相关函数: isToolSearchEnabled, extractDiscoveredToolNames,
isDeferredTool等
3. 实现工具过滤逻辑:
- 检查工具搜索是否启用
- 构建deferred tools集合
- 过滤工具列表: 只包含非deferred工具或已发现的deferred工具
- 为deferred tools设置deferLoading标志
4. 修正了extractDiscoveredToolNames函数的导入路径错误
影响:
- 解决了TaskCreate工具调用时的参数验证错误
- 确保OpenAI兼容层与Anthropic API路径在处理deferred tools时行为一致
- 支持工具搜索功能在OpenAI兼容模式下正常工作
修改的文件:
- src/services/api/openai/index.ts - 主要修复文件
测试建议:
1. 使用OpenAI兼容API模型时,TaskCreate工具应该可以正常调用
2. 如果工具搜索功能启用,可能需要先使用ToolSearchTool来发现TaskCreate工具
3. 验证工具调用时不再出现"InputValidationError"错误
这个修复确保了当使用OpenAI兼容API(如Ollama、DeepSeek、vLLM等)时,deferred
tools(如TaskCreate)能够被正确处理,解决了工具调用失败的问题。
📝 WalkthroughWalkthroughNew documentation for OpenAI-compatible models' task tools usage. Implementation adds conditional tool search to filter deferred tools based on discovery status, reorders tool result messages in conversion logic, and updates error hints to guide users on tool discovery prerequisites. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant OpenAI_API as OpenAI Handler<br/>(index.ts)
participant ToolSearch
participant Deferred_Loader
participant Converter as Message Converter<br/>(convertMessages.ts)
Client->>OpenAI_API: queryModelOpenAI(messages, tools)
OpenAI_API->>OpenAI_API: isToolSearchEnabled()?
alt Tool Search Enabled
OpenAI_API->>ToolSearch: extractDiscoveredToolNames(messages)
ToolSearch-->>OpenAI_API: discovered tool names
OpenAI_API->>Deferred_Loader: isDeferredTool(tool) for each tool
Deferred_Loader-->>OpenAI_API: deferred tool names set
OpenAI_API->>OpenAI_API: filterTools: keep non-deferred<br/>+ ToolSearchTool<br/>+ discovered deferred tools
else Tool Search Disabled
OpenAI_API->>OpenAI_API: use all tools
end
OpenAI_API->>OpenAI_API: build tool schemas<br/>with deferLoading flag
OpenAI_API->>Client: send filtered tools to API
Client-->>OpenAI_API: tool_result in response
OpenAI_API->>Converter: convertInternalUserMessage()
Converter->>Converter: append tool_results<br/>BEFORE user content
Converter-->>OpenAI_API: converted messages
OpenAI_API-->>Client: processed message stream
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/services/api/openai/convertMessages.ts (1)
95-102: Update placeholder issue reference.Line 99 references
#xxxwhich appears to be a placeholder. Consider updating to the actual issue number (likely#168based on commit messages) or removing if not needed.📝 Proposed fix
- // See: https://github.com/anthropics/claude-code/issues/xxx + // See: https://github.com/anthropics/claude-code/issues/168🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/services/api/openai/convertMessages.ts` around lines 95 - 102, Update the placeholder issue reference in the comment above the tool message loop: replace the `#xxx` placeholder with the correct issue number (likely `#168`) or remove the reference entirely; the relevant context is the comment immediately preceding the for-loop that iterates over `toolResults` and calls `convertToolResult(tr)` to push into `result`, so edit that comment text to include the real issue link or drop it.docs/openai-task-tools.md (1)
7-13: Add language specifier to fenced code block.The error example code block is missing a language specifier, which affects rendering and accessibility.
📝 Proposed fix
-``` +```text Error: InputValidationError: TaskGet failed due to the following issues:🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@docs/openai-task-tools.md` around lines 7 - 13, The fenced code block that begins with the line "Error: InputValidationError: TaskGet failed due to the following issues:" is missing a language specifier; update the opening triple-backtick so it reads ```text (i.e., add the "text" language specifier) to ensure proper rendering and accessibility of the example error block.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/services/tools/toolExecution.ts`:
- Around line 593-595: The code assigns toolDisplayName directly from
tool.userFacingName(undefined) which can be an empty string; change the
assignment so it falls back to tool.name when userFacingName returns a
falsy/empty value. Update the toolDisplayName expression in toolExecution.ts
(the variable named toolDisplayName) to call tool.userFacingName(undefined),
trim the result and if it's empty or falsy use tool.name instead (e.g., result =
tool.userFacingName ? (tool.userFacingName(undefined)?.trim() || tool.name) :
tool.name). Ensure this covers tools like TeamCreateTool, TodoWriteTool,
TeamDeleteTool, ToolSearchTool, TaskStopTool that return "".
---
Nitpick comments:
In `@docs/openai-task-tools.md`:
- Around line 7-13: The fenced code block that begins with the line "Error:
InputValidationError: TaskGet failed due to the following issues:" is missing a
language specifier; update the opening triple-backtick so it reads ```text
(i.e., add the "text" language specifier) to ensure proper rendering and
accessibility of the example error block.
In `@src/services/api/openai/convertMessages.ts`:
- Around line 95-102: Update the placeholder issue reference in the comment
above the tool message loop: replace the `#xxx` placeholder with the correct
issue number (likely `#168`) or remove the reference entirely; the relevant
context is the comment immediately preceding the for-loop that iterates over
`toolResults` and calls `convertToolResult(tr)` to push into `result`, so edit
that comment text to include the real issue link or drop it.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 9839912e-101b-407d-8ce6-bbb52491f059
📒 Files selected for processing (4)
docs/openai-task-tools.mdsrc/services/api/openai/convertMessages.tssrc/services/api/openai/index.tssrc/services/tools/toolExecution.ts
| const toolDisplayName = tool.userFacingName | ||
| ? tool.userFacingName(undefined) | ||
| : tool.name |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if any deferred tools define userFacingName that could return undefined
ast-grep --pattern $'shouldDefer: true'
echo "---"
# Check userFacingName implementations in tool files
rg -n "userFacingName" --type=ts -A 3 | head -80Repository: claude-code-best/claude-code
Length of output: 4793
Handle case where userFacingName returns an empty string.
Several tools (TeamCreateTool, TodoWriteTool, TeamDeleteTool, ToolSearchTool, TaskStopTool) define userFacingName to return an empty string. The current code will assign an empty string to toolDisplayName instead of falling back to tool.name, resulting in confusing error messages like Tool "" is deferred-loading....
🛡️ Proposed fix with fallback
- const toolDisplayName = tool.userFacingName
- ? tool.userFacingName(undefined)
- : tool.name
+ const toolDisplayName = tool.userFacingName?.(undefined) || tool.name📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const toolDisplayName = tool.userFacingName | |
| ? tool.userFacingName(undefined) | |
| : tool.name | |
| const toolDisplayName = tool.userFacingName?.(undefined) || tool.name |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/services/tools/toolExecution.ts` around lines 593 - 595, The code assigns
toolDisplayName directly from tool.userFacingName(undefined) which can be an
empty string; change the assignment so it falls back to tool.name when
userFacingName returns a falsy/empty value. Update the toolDisplayName
expression in toolExecution.ts (the variable named toolDisplayName) to call
tool.userFacingName(undefined), trim the result and if it's empty or falsy use
tool.name instead (e.g., result = tool.userFacingName ?
(tool.userFacingName(undefined)?.trim() || tool.name) : tool.name). Ensure this
covers tools like TeamCreateTool, TodoWriteTool, TeamDeleteTool, ToolSearchTool,
TaskStopTool that return "".
PR Title: Improve error messaging for deferred-loading tools under OpenAI‑compatible models
Reference: #188 (resolved; remaining minor bugs addressed separately)
Overview
This commit improves the error hint shown when a deferred‑loading tool (specifically the
taskfamily of tools) is invoked before its schema has been discovered, particularly when using OpenAI‑compatible models like DeepSeek, Ollama, vLLM, etc.Background
When working with OpenAI‑compatible backends, deferred‑loading tools such as
TaskGet,TaskCreate,TaskUpdate, andTaskListmust first have their schemas discovered via theToolSearchtool before they can be used correctly. The previous error message did not adequately guide the model toward the required discovery flow.Changes
File:
src/services/tools/toolExecution.ts:589-606Enhancements:
Clearer error structure
Detailed usage guidance
ToolSearch, then call the target tool.Important notes
camelCase(e.g.,taskId), notsnake_case(task_id).Technical Details
buildSchemaNotSentHint()Example Comparison
Before:
After:
Related Issues
Summary by CodeRabbit
Release Notes
Documentation
New Features
Bug Fixes