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

This commit is contained in:
Apple\Apple
2025-06-09 22:28:08 +08:00
5 changed files with 75 additions and 7 deletions

View File

@@ -1,5 +1,7 @@
package gemini
import "encoding/json"
type GeminiChatRequest struct {
Contents []GeminiChatContent `json:"contents"`
SafetySettings []GeminiChatSafetySettings `json:"safetySettings,omitempty"`
@@ -22,6 +24,30 @@ type GeminiInlineData struct {
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 {
FunctionName string `json:"name"`
Arguments any `json:"args"`
@@ -58,6 +84,33 @@ type GeminiPart struct {
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 {
Role string `json:"role,omitempty"`
Parts []GeminiPart `json:"parts"`

View File

@@ -205,7 +205,22 @@ func CovertGemini2OpenAI(textRequest dto.GeneralOpenAIRequest, info *relaycommon
} else if val, exists := tool_call_ids[message.ToolCallId]; exists {
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{
Name: name,
Response: contentMap,

View File

@@ -47,7 +47,7 @@ func requestOpenAI2Mistral(request *dto.GeneralOpenAIRequest) *dto.GeneralOpenAI
}
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{}
}
for j, mediaMessage := range mediaMessages {

View File

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

View File

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