Files
MyGoNavi/internal/ai/provider/custom.go
2026-06-23 18:26:20 +08:00

96 lines
2.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package provider
import (
"context"
"encoding/json"
"fmt"
"strings"
"GoNavi-Wails/internal/ai"
)
// CustomProvider 自定义 Provider根据 apiFormat 选择底层协议
// 支持 openai / anthropic / gemini / cursor-agent 等 API 格式
type CustomProvider struct {
inner Provider
name string
}
// NewCustomProvider 创建自定义 Provider 实例
func NewCustomProvider(config ai.ProviderConfig) (Provider, error) {
// 根据 apiFormat 决定使用哪个底层协议,默认 openai
apiFormat := strings.ToLower(strings.TrimSpace(config.APIFormat))
if apiFormat == "" {
apiFormat = "openai"
}
if strings.TrimSpace(config.BaseURL) == "" && apiFormat != "claude-cli" && apiFormat != "codebuddy-cli" {
return nil, fmt.Errorf("custom provider Base URL is required")
}
var innerProvider Provider
var err error
switch apiFormat {
case "anthropic":
innerProvider, err = NewAnthropicProvider(config)
case "gemini":
innerProvider, err = NewGeminiProvider(config)
case "cursor-agent":
innerProvider, err = NewCursorAgentProvider(config)
case "claude-cli":
innerProvider, err = NewClaudeCLIProvider(config)
case "codebuddy-cli":
innerProvider, err = NewCodeBuddyCLIProvider(config)
default: // "openai" 及其他
innerProvider, err = NewOpenAIProvider(config)
}
if err != nil {
return nil, err
}
name := strings.TrimSpace(config.Name)
if name == "" {
name = "Custom"
}
return &CustomProvider{
inner: innerProvider,
name: name,
}, nil
}
func (p *CustomProvider) Name() string {
return p.name
}
func (p *CustomProvider) Validate() error {
if strings.TrimSpace(p.inner.(interface{ Name() string }).Name()) == "" {
// 对自定义 ProviderAPI Key 可选(部分本地服务不需要)
}
return nil
}
func (p *CustomProvider) Chat(ctx context.Context, req ai.ChatRequest) (*ai.ChatResponse, error) {
return p.inner.Chat(ctx, req)
}
func (p *CustomProvider) ChatStream(ctx context.Context, req ai.ChatRequest, callback func(ai.StreamChunk)) error {
return p.inner.ChatStream(ctx, req, callback)
}
func (p *CustomProvider) ChatWithState(ctx context.Context, state json.RawMessage, req ai.ChatRequest) (*ai.ChatResponse, json.RawMessage, error) {
sessionProvider, ok := p.inner.(SessionChatProvider)
if !ok {
resp, err := p.inner.Chat(ctx, req)
return resp, nil, err
}
return sessionProvider.ChatWithState(ctx, state, req)
}
func (p *CustomProvider) ChatStreamWithState(ctx context.Context, state json.RawMessage, req ai.ChatRequest, callback func(ai.StreamChunk)) (json.RawMessage, error) {
sessionProvider, ok := p.inner.(SessionStreamProvider)
if !ok {
return nil, p.inner.ChatStream(ctx, req, callback)
}
return sessionProvider.ChatStreamWithState(ctx, state, req, callback)
}