Revert "Feat/channel tool feedback animation (#2569)" (#2596)

This reverts commit e556a816e4.
This commit is contained in:
lxowalle
2026-04-20 18:30:29 +08:00
committed by GitHub
parent e556a816e4
commit 6421f146a9
35 changed files with 169 additions and 3317 deletions
+12 -81
View File
@@ -70,23 +70,11 @@ func NewHTTPClient(proxy string) *http.Client {
// It mirrors protocoltypes.Message but omits SystemParts, which is an
// internal field that would be unknown to third-party endpoints.
type openaiMessage struct {
Role string `json:"role"`
Content string `json:"content"`
ReasoningContent string `json:"reasoning_content,omitempty"`
ToolCalls []openaiToolCall `json:"tool_calls,omitempty"`
ToolCallID string `json:"tool_call_id,omitempty"`
}
type openaiToolCall struct {
ID string `json:"id"`
Type string `json:"type,omitempty"`
Function *openaiFunctionCall `json:"function,omitempty"`
}
type openaiFunctionCall struct {
Name string `json:"name"`
Arguments string `json:"arguments"`
ThoughtSignature string `json:"thought_signature,omitempty"`
Role string `json:"role"`
Content string `json:"content"`
ReasoningContent string `json:"reasoning_content,omitempty"`
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
ToolCallID string `json:"tool_call_id,omitempty"`
}
// SerializeMessages converts internal Message structs to the OpenAI wire format.
@@ -96,13 +84,12 @@ type openaiFunctionCall struct {
func SerializeMessages(messages []Message) []any {
out := make([]any, 0, len(messages))
for _, m := range messages {
toolCalls := serializeToolCalls(m.ToolCalls)
if len(m.Media) == 0 {
out = append(out, openaiMessage{
Role: m.Role,
Content: m.Content,
ReasoningContent: m.ReasoningContent,
ToolCalls: toolCalls,
ToolCalls: m.ToolCalls,
ToolCallID: m.ToolCallID,
})
continue
@@ -145,8 +132,8 @@ func SerializeMessages(messages []Message) []any {
if m.ToolCallID != "" {
msg["tool_call_id"] = m.ToolCallID
}
if len(toolCalls) > 0 {
msg["tool_calls"] = toolCalls
if len(m.ToolCalls) > 0 {
msg["tool_calls"] = m.ToolCalls
}
if m.ReasoningContent != "" {
msg["reasoning_content"] = m.ReasoningContent
@@ -156,55 +143,6 @@ func SerializeMessages(messages []Message) []any {
return out
}
func serializeToolCalls(toolCalls []ToolCall) []openaiToolCall {
if len(toolCalls) == 0 {
return nil
}
out := make([]openaiToolCall, 0, len(toolCalls))
for _, tc := range toolCalls {
wireCall := openaiToolCall{
ID: tc.ID,
Type: tc.Type,
}
if tc.Function != nil {
thoughtSignature := tc.Function.ThoughtSignature
if thoughtSignature == "" {
thoughtSignature = tc.ThoughtSignature
}
if thoughtSignature == "" && tc.ExtraContent != nil && tc.ExtraContent.Google != nil {
thoughtSignature = tc.ExtraContent.Google.ThoughtSignature
}
wireCall.Function = &openaiFunctionCall{
Name: tc.Function.Name,
Arguments: tc.Function.Arguments,
ThoughtSignature: thoughtSignature,
}
} else if tc.Name != "" || len(tc.Arguments) > 0 || tc.ThoughtSignature != "" {
thoughtSignature := tc.ThoughtSignature
if thoughtSignature == "" && tc.ExtraContent != nil && tc.ExtraContent.Google != nil {
thoughtSignature = tc.ExtraContent.Google.ThoughtSignature
}
argsJSON := "{}"
if len(tc.Arguments) > 0 {
if encoded, err := json.Marshal(tc.Arguments); err == nil {
argsJSON = string(encoded)
}
}
wireCall.Function = &openaiFunctionCall{
Name: tc.Name,
Arguments: argsJSON,
ThoughtSignature: thoughtSignature,
}
}
out = append(out, wireCall)
}
return out
}
func parseDataAudioURL(mediaURL string) (format, data string, ok bool) {
if !strings.HasPrefix(mediaURL, "data:audio/") {
return "", "", false
@@ -247,7 +185,6 @@ func ParseResponse(body io.Reader) (*LLMResponse, error) {
Google *struct {
ThoughtSignature string `json:"thought_signature"`
} `json:"google"`
ToolFeedbackExplanation string `json:"tool_feedback_explanation"`
} `json:"extra_content"`
} `json:"tool_calls"`
} `json:"message"`
@@ -291,17 +228,11 @@ func ParseResponse(body io.Reader) (*LLMResponse, error) {
ThoughtSignature: thoughtSignature,
}
if tc.ExtraContent != nil {
extraContent := &ExtraContent{
ToolFeedbackExplanation: tc.ExtraContent.ToolFeedbackExplanation,
}
if thoughtSignature != "" {
extraContent.Google = &GoogleExtra{
if thoughtSignature != "" {
toolCall.ExtraContent = &ExtraContent{
Google: &GoogleExtra{
ThoughtSignature: thoughtSignature,
}
}
if extraContent.Google != nil || strings.TrimSpace(extraContent.ToolFeedbackExplanation) != "" {
toolCall.ExtraContent = extraContent
},
}
}
-119
View File
@@ -162,104 +162,6 @@ func TestSerializeMessages_StripsSystemParts(t *testing.T) {
}
}
func TestSerializeMessages_StripsInternalToolCallExtraContent(t *testing.T) {
messages := []Message{
{
Role: "assistant",
ToolCalls: []ToolCall{{
ID: "call_1",
Type: "function",
Function: &FunctionCall{
Name: "read_file",
Arguments: `{"path":"README.md"}`,
ThoughtSignature: "sig-1",
},
ExtraContent: &ExtraContent{
Google: &GoogleExtra{
ThoughtSignature: "sig-ignored-here",
},
ToolFeedbackExplanation: "Read README.md first.",
},
}},
},
}
result := SerializeMessages(messages)
data, err := json.Marshal(result)
if err != nil {
t.Fatalf("json.Marshal() error = %v", err)
}
payload := string(data)
if strings.Contains(payload, "extra_content") {
t.Fatalf("serialized payload should not include internal extra_content: %s", payload)
}
if !strings.Contains(payload, "thought_signature") {
t.Fatalf("serialized payload should preserve function thought_signature: %s", payload)
}
}
func TestSerializeMessages_PreservesTopLevelThoughtSignature(t *testing.T) {
messages := []Message{
{
Role: "assistant",
ToolCalls: []ToolCall{{
ID: "call_1",
Type: "function",
ThoughtSignature: "sig-1",
Function: &FunctionCall{
Name: "read_file",
Arguments: `{"path":"README.md"}`,
},
}},
},
}
result := SerializeMessages(messages)
data, err := json.Marshal(result)
if err != nil {
t.Fatalf("json.Marshal() error = %v", err)
}
payload := string(data)
if !strings.Contains(payload, `"thought_signature":"sig-1"`) {
t.Fatalf("serialized payload should preserve top-level thought signature: %s", payload)
}
}
func TestSerializeMessages_PreservesGoogleExtraThoughtSignature(t *testing.T) {
messages := []Message{
{
Role: "assistant",
ToolCalls: []ToolCall{{
ID: "call_1",
Type: "function",
Function: &FunctionCall{
Name: "read_file",
Arguments: `{"path":"README.md"}`,
},
ExtraContent: &ExtraContent{
Google: &GoogleExtra{ThoughtSignature: "sig-1"},
},
}},
},
}
result := SerializeMessages(messages)
data, err := json.Marshal(result)
if err != nil {
t.Fatalf("json.Marshal() error = %v", err)
}
payload := string(data)
if strings.Contains(payload, "extra_content") {
t.Fatalf("serialized payload should not include extra_content: %s", payload)
}
if !strings.Contains(payload, `"thought_signature":"sig-1"`) {
t.Fatalf("serialized payload should preserve google thought signature: %s", payload)
}
}
// --- ParseResponse tests ---
func TestParseResponse_BasicContent(t *testing.T) {
@@ -332,27 +234,6 @@ func TestParseResponse_WithReasoningContent(t *testing.T) {
}
}
func TestParseResponse_WithToolFeedbackExplanationExtraContent(t *testing.T) {
body := `{"choices":[{"message":{"content":"","tool_calls":[{"id":"call_1","type":"function","function":{"name":"test_tool","arguments":"{}"},"extra_content":{"tool_feedback_explanation":"Check the current config before editing."}}]},"finish_reason":"tool_calls"}]}`
out, err := ParseResponse(strings.NewReader(body))
if err != nil {
t.Fatalf("ParseResponse() error = %v", err)
}
if len(out.ToolCalls) != 1 {
t.Fatalf("len(ToolCalls) = %d, want 1", len(out.ToolCalls))
}
if out.ToolCalls[0].ExtraContent == nil {
t.Fatal("ExtraContent is nil")
}
if out.ToolCalls[0].ExtraContent.ToolFeedbackExplanation != "Check the current config before editing." {
t.Fatalf(
"ToolFeedbackExplanation = %q, want %q",
out.ToolCalls[0].ExtraContent.ToolFeedbackExplanation,
"Check the current config before editing.",
)
}
}
func TestParseResponse_InvalidJSON(t *testing.T) {
_, err := ParseResponse(strings.NewReader("not json"))
if err == nil {