Merge branch 'main' into feature/antigravity_auth_image

This commit is contained in:
song
2025-12-29 21:29:38 +08:00
39 changed files with 4863 additions and 1715 deletions

View File

@@ -600,8 +600,3 @@ formatters:
replacement: 'any'
- pattern: 'a[b:len(a)]'
replacement: 'a[b:]'
exclusions:
paths:
- internal/pkg/antigravity/claude_types.go
- internal/pkg/antigravity/gemini_types.go
- internal/pkg/antigravity/stream_transformer.go

View File

@@ -38,8 +38,8 @@ type ClaudeMetadata struct {
// ClaudeTool Claude 工具定义
type ClaudeTool struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
InputSchema map[string]any `json:"input_schema"`
}
@@ -58,9 +58,9 @@ type ContentBlock struct {
Thinking string `json:"thinking,omitempty"`
Signature string `json:"signature,omitempty"`
// tool_use
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Input any `json:"input,omitempty"`
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Input any `json:"input,omitempty"`
// tool_result
ToolUseID string `json:"tool_use_id,omitempty"`
Content json.RawMessage `json:"content,omitempty"`
@@ -100,9 +100,9 @@ type ClaudeContentItem struct {
Signature string `json:"signature,omitempty"`
// tool_use
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Input any `json:"input,omitempty"`
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Input any `json:"input,omitempty"`
}
// ClaudeUsage Claude 用量统计

View File

@@ -47,16 +47,16 @@ type GeminiInlineData struct {
// GeminiFunctionCall Gemini 函数调用
type GeminiFunctionCall struct {
Name string `json:"name"`
Args any `json:"args,omitempty"`
ID string `json:"id,omitempty"`
Name string `json:"name"`
Args any `json:"args,omitempty"`
ID string `json:"id,omitempty"`
}
// GeminiFunctionResponse Gemini 函数响应
type GeminiFunctionResponse struct {
Name string `json:"name"`
Name string `json:"name"`
Response map[string]any `json:"response"`
ID string `json:"id,omitempty"`
ID string `json:"id,omitempty"`
}
// GeminiGenerationConfig Gemini 生成配置
@@ -83,8 +83,8 @@ type GeminiToolDeclaration struct {
// GeminiFunctionDecl Gemini 函数声明
type GeminiFunctionDecl struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
Parameters map[string]any `json:"parameters,omitempty"`
}

View File

@@ -135,18 +135,18 @@ func (p *StreamingProcessor) emitMessageStart(v1Resp *V1InternalResponse) []byte
responseID = "msg_" + generateRandomID()
}
message := map[string]interface{}{
message := map[string]any{
"id": responseID,
"type": "message",
"role": "assistant",
"content": []interface{}{},
"content": []any{},
"model": p.originalModel,
"stop_reason": nil,
"stop_sequence": nil,
"usage": usage,
}
event := map[string]interface{}{
event := map[string]any{
"type": "message_start",
"message": message,
}
@@ -205,14 +205,14 @@ func (p *StreamingProcessor) processThinking(text, signature string) []byte {
// 开始或继续 thinking 块
if p.blockType != BlockTypeThinking {
_, _ = result.Write(p.startBlock(BlockTypeThinking, map[string]interface{}{
_, _ = result.Write(p.startBlock(BlockTypeThinking, map[string]any{
"type": "thinking",
"thinking": "",
}))
}
if text != "" {
_, _ = result.Write(p.emitDelta("thinking_delta", map[string]interface{}{
_, _ = result.Write(p.emitDelta("thinking_delta", map[string]any{
"thinking": text,
}))
}
@@ -246,11 +246,11 @@ func (p *StreamingProcessor) processText(text, signature string) []byte {
// 非空 text 带签名 - 特殊处理
if signature != "" {
_, _ = result.Write(p.startBlock(BlockTypeText, map[string]interface{}{
_, _ = result.Write(p.startBlock(BlockTypeText, map[string]any{
"type": "text",
"text": "",
}))
_, _ = result.Write(p.emitDelta("text_delta", map[string]interface{}{
_, _ = result.Write(p.emitDelta("text_delta", map[string]any{
"text": text,
}))
_, _ = result.Write(p.endBlock())
@@ -260,13 +260,13 @@ func (p *StreamingProcessor) processText(text, signature string) []byte {
// 普通 text (无签名)
if p.blockType != BlockTypeText {
_, _ = result.Write(p.startBlock(BlockTypeText, map[string]interface{}{
_, _ = result.Write(p.startBlock(BlockTypeText, map[string]any{
"type": "text",
"text": "",
}))
}
_, _ = result.Write(p.emitDelta("text_delta", map[string]interface{}{
_, _ = result.Write(p.emitDelta("text_delta", map[string]any{
"text": text,
}))
@@ -284,11 +284,11 @@ func (p *StreamingProcessor) processFunctionCall(fc *GeminiFunctionCall, signatu
toolID = fmt.Sprintf("%s-%s", fc.Name, generateRandomID())
}
toolUse := map[string]interface{}{
toolUse := map[string]any{
"type": "tool_use",
"id": toolID,
"name": fc.Name,
"input": map[string]interface{}{}, // 必须为空,参数通过 delta 发送
"input": map[string]any{},
}
if signature != "" {
@@ -300,7 +300,7 @@ func (p *StreamingProcessor) processFunctionCall(fc *GeminiFunctionCall, signatu
// 发送 input_json_delta
if fc.Args != nil {
argsJSON, _ := json.Marshal(fc.Args)
_, _ = result.Write(p.emitDelta("input_json_delta", map[string]interface{}{
_, _ = result.Write(p.emitDelta("input_json_delta", map[string]any{
"partial_json": string(argsJSON),
}))
}
@@ -311,14 +311,14 @@ func (p *StreamingProcessor) processFunctionCall(fc *GeminiFunctionCall, signatu
}
// startBlock 开始新的内容块
func (p *StreamingProcessor) startBlock(blockType BlockType, contentBlock map[string]interface{}) []byte {
func (p *StreamingProcessor) startBlock(blockType BlockType, contentBlock map[string]any) []byte {
var result bytes.Buffer
if p.blockType != BlockTypeNone {
_, _ = result.Write(p.endBlock())
}
event := map[string]interface{}{
event := map[string]any{
"type": "content_block_start",
"index": p.blockIndex,
"content_block": contentBlock,
@@ -340,13 +340,13 @@ func (p *StreamingProcessor) endBlock() []byte {
// Thinking 块结束时发送暂存的签名
if p.blockType == BlockTypeThinking && p.pendingSignature != "" {
_, _ = result.Write(p.emitDelta("signature_delta", map[string]interface{}{
_, _ = result.Write(p.emitDelta("signature_delta", map[string]any{
"signature": p.pendingSignature,
}))
p.pendingSignature = ""
}
event := map[string]interface{}{
event := map[string]any{
"type": "content_block_stop",
"index": p.blockIndex,
}
@@ -360,15 +360,15 @@ func (p *StreamingProcessor) endBlock() []byte {
}
// emitDelta 发送 delta 事件
func (p *StreamingProcessor) emitDelta(deltaType string, deltaContent map[string]interface{}) []byte {
delta := map[string]interface{}{
func (p *StreamingProcessor) emitDelta(deltaType string, deltaContent map[string]any) []byte {
delta := map[string]any{
"type": deltaType,
}
for k, v := range deltaContent {
delta[k] = v
}
event := map[string]interface{}{
event := map[string]any{
"type": "content_block_delta",
"index": p.blockIndex,
"delta": delta,
@@ -381,14 +381,14 @@ func (p *StreamingProcessor) emitDelta(deltaType string, deltaContent map[string
func (p *StreamingProcessor) emitEmptyThinkingWithSignature(signature string) []byte {
var result bytes.Buffer
_, _ = result.Write(p.startBlock(BlockTypeThinking, map[string]interface{}{
_, _ = result.Write(p.startBlock(BlockTypeThinking, map[string]any{
"type": "thinking",
"thinking": "",
}))
_, _ = result.Write(p.emitDelta("thinking_delta", map[string]interface{}{
_, _ = result.Write(p.emitDelta("thinking_delta", map[string]any{
"thinking": "",
}))
_, _ = result.Write(p.emitDelta("signature_delta", map[string]interface{}{
_, _ = result.Write(p.emitDelta("signature_delta", map[string]any{
"signature": signature,
}))
_, _ = result.Write(p.endBlock())
@@ -422,9 +422,9 @@ func (p *StreamingProcessor) emitFinish(finishReason string) []byte {
OutputTokens: p.outputTokens,
}
deltaEvent := map[string]interface{}{
deltaEvent := map[string]any{
"type": "message_delta",
"delta": map[string]interface{}{
"delta": map[string]any{
"stop_reason": stopReason,
"stop_sequence": nil,
},
@@ -434,7 +434,7 @@ func (p *StreamingProcessor) emitFinish(finishReason string) []byte {
_, _ = result.Write(p.formatSSE("message_delta", deltaEvent))
if !p.messageStopSent {
stopEvent := map[string]interface{}{
stopEvent := map[string]any{
"type": "message_stop",
}
_, _ = result.Write(p.formatSSE("message_stop", stopEvent))
@@ -445,7 +445,7 @@ func (p *StreamingProcessor) emitFinish(finishReason string) []byte {
}
// formatSSE 格式化 SSE 事件
func (p *StreamingProcessor) formatSSE(eventType string, data interface{}) []byte {
func (p *StreamingProcessor) formatSSE(eventType string, data any) []byte {
jsonData, err := json.Marshal(data)
if err != nil {
return nil

View File

@@ -186,7 +186,7 @@ func (r *accountRepository) BatchUpdateLastUsed(ctx context.Context, updates map
ids = append(ids, id)
}
caseSql += " END WHERE id IN ?"
caseSql += " END WHERE id IN ? AND deleted_at IS NULL"
args = append(args, ids)
return r.db.WithContext(ctx).Exec(caseSql, args...).Error

View File

@@ -119,6 +119,7 @@ func (r *proxyRepository) CountAccountsByProxyID(ctx context.Context, proxyID in
var count int64
err := r.db.WithContext(ctx).Table("accounts").
Where("proxy_id = ?", proxyID).
Where("deleted_at IS NULL").
Count(&count).Error
return count, err
}
@@ -134,6 +135,7 @@ func (r *proxyRepository) GetAccountCountsForProxies(ctx context.Context) (map[i
Table("accounts").
Select("proxy_id, COUNT(*) as count").
Where("proxy_id IS NOT NULL").
Where("deleted_at IS NULL").
Group("proxy_id").
Scan(&results).Error
if err != nil {

View File

@@ -182,6 +182,7 @@ func (r *usageLogRepository) GetDashboardStats(ctx context.Context) (*DashboardS
COUNT(CASE WHEN rate_limited_at IS NOT NULL AND rate_limit_reset_at > ? THEN 1 END) as ratelimit_accounts,
COUNT(CASE WHEN overload_until IS NOT NULL AND overload_until > ? THEN 1 END) as overload_accounts
FROM accounts
WHERE deleted_at IS NULL
`, service.StatusActive, service.StatusError, now, now).Scan(&accountStats).Error; err != nil {
return nil, err
}

View File

@@ -20,9 +20,9 @@ func testConfig() *config.Config {
// mockAccountRepoForPlatform 单平台测试用的 mock
type mockAccountRepoForPlatform struct {
accounts []Account
accountsByID map[int64]*Account
listPlatformFunc func(ctx context.Context, platform string) ([]Account, error)
accounts []Account
accountsByID map[int64]*Account
listPlatformFunc func(ctx context.Context, platform string) ([]Account, error)
}
func (m *mockAccountRepoForPlatform) GetByID(ctx context.Context, id int64) (*Account, error) {

View File

@@ -56,7 +56,9 @@ func (m *mockAccountRepoForGemini) ListWithFilters(ctx context.Context, params p
func (m *mockAccountRepoForGemini) ListByGroup(ctx context.Context, groupID int64) ([]Account, error) {
return nil, nil
}
func (m *mockAccountRepoForGemini) ListActive(ctx context.Context) ([]Account, error) { return nil, nil }
func (m *mockAccountRepoForGemini) ListActive(ctx context.Context) ([]Account, error) {
return nil, nil
}
func (m *mockAccountRepoForGemini) ListByPlatform(ctx context.Context, platform string) ([]Account, error) {
return nil, nil
}