gptel
gptel copied to clipboard
Fix tool argument parsing for hyphenated parameter names
Fixes #924
Summary
This PR fixes a bug where tool arguments with hyphenated names (e.g., "file-path", "file-edits") failed to parse correctly, causing tool functions to receive nil arguments instead of the actual values from the LLM.
Root Cause
When tool argument names contain hyphens, the code was using make-symbol to create JSON schema property keys. This created uninterned symbols whose names include the leading colon (e.g., ":file-path"), which then became JSON keys. When the LLM returned these keys and the JSON was parsed back, there was a mismatch:
- Schema creation (with
make-symbol): JSON key":file-path"→ parsed as keyword::file-path - Value retrieval (with
intern): Looks for keyword:file-path - Result: Keys don't match,
plist-getreturnsnil, tool function receivesnilarguments
Changes
1. Changed make-symbol to intern (3 files)
- gptel-request.el:1496 - Base
gptel--parse-toolsimplementation - gptel-anthropic.el:275 - Anthropic-specific tool schema generation
- gptel-gemini.el:209 - Gemini-specific tool schema generation
This ensures proper keywords are created that survive JSON round-trip correctly.
2. Improved error handling in gptel-openai.el
- Replaced silent
ignore-errorswithcondition-casethat logs parse failures - Provides context: tool name, error message, raw arguments
- Applied to both streaming (lines 213-221) and non-streaming (lines 284-292) code paths
- Helps debug future issues while maintaining safe fallback behavior
Why This Fix is Correct
The retrieval code in gptel-request.el:1699 uses intern:
(let ((key (intern (concat ":" (plist-get arg :name)))))
(plist-get args key))
By using intern during schema creation as well, both sides create the same keyword object, so plist-get succeeds.
Testing
The issue reporter confirmed that:
- Non-streaming mode works correctly
- Streaming mode had the bug (now fixed)
This fix ensures both modes work correctly by addressing the root cause.
Impact
- ✅ No breaking changes - The old behavior was broken for hyphenated arg names
- ✅ Consistent across all backends - OpenAI, Anthropic, Gemini all fixed
- ✅ Better debugging - Error logging helps identify future parse issues
- ✅ Backward compatible - Tool specs are created fresh each session
🤖 Generated with Claude Code