fix: null content on tool_calls messages; skip empty tool names; rollback on error

This commit is contained in:
Levi Neely 2026-04-05 11:53:36 +02:00
parent 37fc5ee968
commit 92db8f88cd
3 changed files with 20 additions and 4 deletions

View File

@ -98,6 +98,15 @@ func Run(ctx context.Context, cfg Config, state State) error {
var results []ToolResult
for _, tc := range toolCalls {
if tc.Name == "" {
results = append(results, ToolResult{
ToolCallID: tc.ID,
Name: tc.Name,
Content: "error: empty tool name",
IsError: true,
})
continue
}
emit(cfg, OutputMsg{Role: "call", Name: tc.Name, Content: string(tc.Arguments)})
var result string

View File

@ -32,7 +32,7 @@ func NewOpenAI(baseURL, apiKey string) *OpenAIBackend {
type openAIMessage struct {
Role string `json:"role"`
Content string `json:"content,omitempty"`
Content *string `json:"content"`
ToolCalls []openAIToolCall `json:"tool_calls,omitempty"`
ToolCallID string `json:"tool_call_id,omitempty"`
}
@ -99,13 +99,12 @@ type openAIStreamResponse struct {
func (b *OpenAIBackend) ChatStream(ctx context.Context, model string, messages []Message, tools []Tool) (<-chan StreamEvent, error) {
wireMessages := make([]openAIMessage, len(messages))
for i, m := range messages {
wireMessages[i] = openAIMessage{
wm := openAIMessage{
Role: m.Role,
Content: m.Content,
ToolCallID: m.ToolCallID,
}
for _, tc := range m.ToolCalls {
wireMessages[i].ToolCalls = append(wireMessages[i].ToolCalls, openAIToolCall{
wm.ToolCalls = append(wm.ToolCalls, openAIToolCall{
ID: tc.ID,
Type: "function",
Function: openAIFunctionCall{
@ -114,6 +113,11 @@ func (b *OpenAIBackend) ChatStream(ctx context.Context, model string, messages [
},
})
}
// OpenAI spec: content must be null (not "") when tool_calls is present.
if len(wm.ToolCalls) == 0 {
wm.Content = &m.Content
}
wireMessages[i] = wm
}
var wireTools []openAITool

View File

@ -587,6 +587,9 @@ func (m *model) apply(am agentMsg) {
case "error":
m.finalizeBuf()
m.appendDisplay("Error: " + am.content)
if m.session != nil {
m.session.Rollback()
}
case "confirm":
m.state = agentConfirming