mirror of
https://github.com/CJackHwang/ds2api.git
synced 2026-05-01 23:15:27 +08:00
157 lines
3.7 KiB
Go
157 lines
3.7 KiB
Go
package openai
|
|
|
|
import (
|
|
"encoding/json"
|
|
"sort"
|
|
"strings"
|
|
|
|
openaifmt "ds2api/internal/format/openai"
|
|
"ds2api/internal/util"
|
|
)
|
|
|
|
func (s *responsesStreamRuntime) closeIncompleteFunctionItems() {
|
|
if len(s.functionAdded) == 0 {
|
|
return
|
|
}
|
|
indices := make([]int, 0, len(s.functionAdded))
|
|
for idx, added := range s.functionAdded {
|
|
if !added || s.functionDone[idx] {
|
|
continue
|
|
}
|
|
indices = append(indices, idx)
|
|
}
|
|
if len(indices) == 0 {
|
|
return
|
|
}
|
|
sort.Ints(indices)
|
|
for _, idx := range indices {
|
|
name := strings.TrimSpace(s.functionNames[idx])
|
|
if name == "" {
|
|
continue
|
|
}
|
|
args := strings.TrimSpace(s.functionArgs[idx])
|
|
if args == "" {
|
|
args = "{}"
|
|
}
|
|
outputIndex := s.ensureFunctionOutputIndex(idx)
|
|
itemID := s.ensureFunctionItemID(idx)
|
|
callID := s.ensureToolCallID(idx)
|
|
s.sendEvent(
|
|
"response.function_call_arguments.done",
|
|
openaifmt.BuildResponsesFunctionCallArgumentsDonePayload(s.responseID, itemID, outputIndex, callID, name, args),
|
|
)
|
|
item := map[string]any{
|
|
"id": itemID,
|
|
"type": "function_call",
|
|
"call_id": callID,
|
|
"name": name,
|
|
"arguments": args,
|
|
"status": "completed",
|
|
}
|
|
s.sendEvent(
|
|
"response.output_item.done",
|
|
openaifmt.BuildResponsesOutputItemDonePayload(s.responseID, itemID, outputIndex, item),
|
|
)
|
|
s.functionDone[idx] = true
|
|
s.toolCallsDoneEmitted = true
|
|
}
|
|
}
|
|
|
|
func (s *responsesStreamRuntime) buildCompletedResponseObject(finalThinking, finalText string, calls []util.ParsedToolCall) map[string]any {
|
|
type indexedItem struct {
|
|
index int
|
|
item map[string]any
|
|
}
|
|
indexed := make([]indexedItem, 0, len(calls)+1)
|
|
|
|
if s.messageAdded {
|
|
text := s.visibleText.String()
|
|
indexed = append(indexed, indexedItem{
|
|
index: s.ensureMessageOutputIndex(),
|
|
item: map[string]any{
|
|
"id": s.ensureMessageItemID(),
|
|
"type": "message",
|
|
"role": "assistant",
|
|
"status": "completed",
|
|
"content": []map[string]any{
|
|
{
|
|
"type": "output_text",
|
|
"text": text,
|
|
},
|
|
},
|
|
},
|
|
})
|
|
} else if len(calls) == 0 {
|
|
content := make([]map[string]any, 0, 2)
|
|
if strings.TrimSpace(finalThinking) != "" {
|
|
content = append(content, map[string]any{
|
|
"type": "reasoning",
|
|
"text": finalThinking,
|
|
})
|
|
}
|
|
if strings.TrimSpace(finalText) != "" {
|
|
content = append(content, map[string]any{
|
|
"type": "output_text",
|
|
"text": finalText,
|
|
})
|
|
}
|
|
if len(content) > 0 {
|
|
indexed = append(indexed, indexedItem{
|
|
index: s.ensureMessageOutputIndex(),
|
|
item: map[string]any{
|
|
"id": s.ensureMessageItemID(),
|
|
"type": "message",
|
|
"role": "assistant",
|
|
"status": "completed",
|
|
"content": content,
|
|
},
|
|
})
|
|
}
|
|
}
|
|
|
|
for idx, tc := range calls {
|
|
if strings.TrimSpace(tc.Name) == "" {
|
|
continue
|
|
}
|
|
argsBytes, _ := json.Marshal(tc.Input)
|
|
indexed = append(indexed, indexedItem{
|
|
index: s.ensureFunctionOutputIndex(idx),
|
|
item: map[string]any{
|
|
"id": s.ensureFunctionItemID(idx),
|
|
"type": "function_call",
|
|
"call_id": s.ensureToolCallID(idx),
|
|
"name": tc.Name,
|
|
"arguments": string(argsBytes),
|
|
"status": "completed",
|
|
},
|
|
})
|
|
}
|
|
|
|
sort.SliceStable(indexed, func(i, j int) bool {
|
|
return indexed[i].index < indexed[j].index
|
|
})
|
|
output := make([]any, 0, len(indexed))
|
|
for _, it := range indexed {
|
|
output = append(output, it.item)
|
|
}
|
|
|
|
outputText := s.visibleText.String()
|
|
if strings.TrimSpace(outputText) == "" && len(calls) == 0 {
|
|
if strings.TrimSpace(finalText) != "" {
|
|
outputText = finalText
|
|
} else if strings.TrimSpace(finalThinking) != "" {
|
|
outputText = finalThinking
|
|
}
|
|
}
|
|
|
|
return openaifmt.BuildResponseObjectFromItems(
|
|
s.responseID,
|
|
s.model,
|
|
s.finalPrompt,
|
|
finalThinking,
|
|
finalText,
|
|
output,
|
|
outputText,
|
|
)
|
|
}
|