Просмотр исходного кода

Merge remote-tracking branch 'origin/alpha' into alpha

Apple\Apple 9 месяцев назад
Родитель
Сommit
b035b4d8af

+ 53 - 0
relay/channel/gemini/dto.go

@@ -1,5 +1,7 @@
 package gemini
 package gemini
 
 
+import "encoding/json"
+
 type GeminiChatRequest struct {
 type GeminiChatRequest struct {
 	Contents           []GeminiChatContent        `json:"contents"`
 	Contents           []GeminiChatContent        `json:"contents"`
 	SafetySettings     []GeminiChatSafetySettings `json:"safetySettings,omitempty"`
 	SafetySettings     []GeminiChatSafetySettings `json:"safetySettings,omitempty"`
@@ -22,6 +24,30 @@ type GeminiInlineData struct {
 	Data     string `json:"data"`
 	Data     string `json:"data"`
 }
 }
 
 
+// UnmarshalJSON custom unmarshaler for GeminiInlineData to support snake_case and camelCase for MimeType
+func (g *GeminiInlineData) UnmarshalJSON(data []byte) error {
+	type Alias GeminiInlineData // Use type alias to avoid recursion
+	var aux struct {
+		Alias
+		MimeTypeSnake string `json:"mime_type"`
+	}
+
+	if err := json.Unmarshal(data, &aux); err != nil {
+		return err
+	}
+
+	*g = GeminiInlineData(aux.Alias) // Copy other fields if any in future
+
+	// Prioritize snake_case if present
+	if aux.MimeTypeSnake != "" {
+		g.MimeType = aux.MimeTypeSnake
+	} else if aux.MimeType != "" { // Fallback to camelCase from Alias
+		g.MimeType = aux.MimeType
+	}
+	// g.Data would be populated by aux.Alias.Data
+	return nil
+}
+
 type FunctionCall struct {
 type FunctionCall struct {
 	FunctionName string `json:"name"`
 	FunctionName string `json:"name"`
 	Arguments    any    `json:"args"`
 	Arguments    any    `json:"args"`
@@ -58,6 +84,33 @@ type GeminiPart struct {
 	CodeExecutionResult *GeminiPartCodeExecutionResult `json:"codeExecutionResult,omitempty"`
 	CodeExecutionResult *GeminiPartCodeExecutionResult `json:"codeExecutionResult,omitempty"`
 }
 }
 
 
+// UnmarshalJSON custom unmarshaler for GeminiPart to support snake_case and camelCase for InlineData
+func (p *GeminiPart) UnmarshalJSON(data []byte) error {
+	// Alias to avoid recursion during unmarshalling
+	type Alias GeminiPart
+	var aux struct {
+		Alias
+		InlineDataSnake *GeminiInlineData `json:"inline_data,omitempty"` // snake_case variant
+	}
+
+	if err := json.Unmarshal(data, &aux); err != nil {
+		return err
+	}
+
+	// Assign fields from alias
+	*p = GeminiPart(aux.Alias)
+
+	// Prioritize snake_case for InlineData if present
+	if aux.InlineDataSnake != nil {
+		p.InlineData = aux.InlineDataSnake
+	} else if aux.InlineData != nil { // Fallback to camelCase from Alias
+		p.InlineData = aux.InlineData
+	}
+	// Other fields like Text, FunctionCall etc. are already populated via aux.Alias
+
+	return nil
+}
+
 type GeminiChatContent struct {
 type GeminiChatContent struct {
 	Role  string       `json:"role,omitempty"`
 	Role  string       `json:"role,omitempty"`
 	Parts []GeminiPart `json:"parts"`
 	Parts []GeminiPart `json:"parts"`

+ 16 - 1
relay/channel/gemini/relay-gemini.go

@@ -205,7 +205,22 @@ func CovertGemini2OpenAI(textRequest dto.GeneralOpenAIRequest, info *relaycommon
 			} else if val, exists := tool_call_ids[message.ToolCallId]; exists {
 			} else if val, exists := tool_call_ids[message.ToolCallId]; exists {
 				name = val
 				name = val
 			}
 			}
-			contentMap := common.StrToMap(message.StringContent())
+			var contentMap map[string]interface{}
+			contentStr := message.StringContent()
+
+			// 1. 尝试解析为 JSON 对象
+			if err := json.Unmarshal([]byte(contentStr), &contentMap); err != nil {
+				// 2. 如果失败,尝试解析为 JSON 数组
+				var contentSlice []interface{}
+				if err := json.Unmarshal([]byte(contentStr), &contentSlice); err == nil {
+					// 如果是数组,包装成对象
+					contentMap = map[string]interface{}{"result": contentSlice}
+				} else {
+					// 3. 如果再次失败,作为纯文本处理
+					contentMap = map[string]interface{}{"content": contentStr}
+				}
+			}
+
 			functionResp := &FunctionResponse{
 			functionResp := &FunctionResponse{
 				Name:     name,
 				Name:     name,
 				Response: contentMap,
 				Response: contentMap,

+ 1 - 1
relay/channel/mistral/text.go

@@ -47,7 +47,7 @@ func requestOpenAI2Mistral(request *dto.GeneralOpenAIRequest) *dto.GeneralOpenAI
 		}
 		}
 
 
 		mediaMessages := message.ParseContent()
 		mediaMessages := message.ParseContent()
-		if message.Role == "assistant" && message.ToolCalls != nil && message.Content != "null" {
+		if message.Role == "assistant" && message.ToolCalls != nil && message.Content == "" {
 			mediaMessages = []dto.MediaContent{}
 			mediaMessages = []dto.MediaContent{}
 		}
 		}
 		for j, mediaMessage := range mediaMessages {
 		for j, mediaMessage := range mediaMessages {

+ 4 - 4
web/src/components/table/ChannelsTable.js

@@ -6,9 +6,9 @@ import {
   showSuccess,
   showSuccess,
   timestamp2string,
   timestamp2string,
   renderGroup,
   renderGroup,
-  renderNumberWithPoint,
   renderQuota,
   renderQuota,
-  getChannelIcon
+  getChannelIcon,
+  renderQuotaWithAmount
 } from '../../helpers/index.js';
 } from '../../helpers/index.js';
 
 
 import {
 import {
@@ -256,7 +256,7 @@ const ChannelsTable = () => {
                     {renderQuota(record.used_quota)}
                     {renderQuota(record.used_quota)}
                   </Tag>
                   </Tag>
                 </Tooltip>
                 </Tooltip>
-                <Tooltip content={t('剩余额度') + record.balance + t(',点击更新')}>
+                <Tooltip content={t('剩余额度$') + record.balance + t(',点击更新')}>
                   <Tag
                   <Tag
                     color='white'
                     color='white'
                     type='ghost'
                     type='ghost'
@@ -265,7 +265,7 @@ const ChannelsTable = () => {
                     prefixIcon={<Coins size={14} />}
                     prefixIcon={<Coins size={14} />}
                     onClick={() => updateChannelBalance(record)}
                     onClick={() => updateChannelBalance(record)}
                   >
                   >
-                    ${renderNumberWithPoint(record.balance)}
+                    {renderQuotaWithAmount(record.balance)}
                   </Tag>
                   </Tag>
                 </Tooltip>
                 </Tooltip>
               </Space>
               </Space>

+ 1 - 1
web/src/helpers/render.js

@@ -854,7 +854,7 @@ export function renderQuotaWithAmount(amount) {
   if (displayInCurrency) {
   if (displayInCurrency) {
     return '$' + amount;
     return '$' + amount;
   } else {
   } else {
-    return renderUnitWithQuota(amount);
+    return renderNumber(renderUnitWithQuota(amount));
   }
   }
 }
 }