package anthropic import ( "encoding/json" "regexp" "strings" "nex/backend/internal/conversion" "nex/backend/internal/conversion/canonical" ) // Adapter Anthropic 协议适配器 type Adapter struct{} // NewAdapter 创建 Anthropic 适配器 func NewAdapter() *Adapter { return &Adapter{} } var modelInfoRegex = regexp.MustCompile(`^/v1/models/[^/]+$`) // ProtocolName 返回协议名称 func (a *Adapter) ProtocolName() string { return "anthropic" } // ProtocolVersion 返回协议版本 func (a *Adapter) ProtocolVersion() string { return "2023-06-01" } // SupportsPassthrough 支持同协议透传 func (a *Adapter) SupportsPassthrough() bool { return true } // DetectInterfaceType 根据路径检测接口类型 func (a *Adapter) DetectInterfaceType(nativePath string) conversion.InterfaceType { switch { case nativePath == "/v1/messages": return conversion.InterfaceTypeChat case nativePath == "/v1/models": return conversion.InterfaceTypeModels case modelInfoRegex.MatchString(nativePath): return conversion.InterfaceTypeModelInfo default: return conversion.InterfaceTypePassthrough } } // BuildUrl 根据接口类型构建 URL func (a *Adapter) BuildUrl(nativePath string, interfaceType conversion.InterfaceType) string { switch interfaceType { case conversion.InterfaceTypeChat: return "/v1/messages" case conversion.InterfaceTypeModels: return "/v1/models" default: return nativePath } } // BuildHeaders 构建请求头 func (a *Adapter) BuildHeaders(provider *conversion.TargetProvider) map[string]string { headers := map[string]string{ "x-api-key": provider.APIKey, "anthropic-version": "2023-06-01", "Content-Type": "application/json", } if v, ok := provider.AdapterConfig["anthropic_version"].(string); ok && v != "" { headers["anthropic-version"] = v } if betas, ok := provider.AdapterConfig["anthropic_beta"].([]string); ok && len(betas) > 0 { headers["anthropic-beta"] = strings.Join(betas, ",") } else if betas, ok := provider.AdapterConfig["anthropic_beta"].([]any); ok && len(betas) > 0 { var parts []string for _, b := range betas { if s, ok := b.(string); ok { parts = append(parts, s) } } if len(parts) > 0 { headers["anthropic-beta"] = strings.Join(parts, ",") } } return headers } // SupportsInterface 检查是否支持接口类型 func (a *Adapter) SupportsInterface(interfaceType conversion.InterfaceType) bool { switch interfaceType { case conversion.InterfaceTypeChat, conversion.InterfaceTypeModels, conversion.InterfaceTypeModelInfo: return true default: return false } } // DecodeRequest 解码请求 func (a *Adapter) DecodeRequest(raw []byte) (*canonical.CanonicalRequest, error) { return decodeRequest(raw) } // EncodeRequest 编码请求 func (a *Adapter) EncodeRequest(req *canonical.CanonicalRequest, provider *conversion.TargetProvider) ([]byte, error) { return encodeRequest(req, provider) } // DecodeResponse 解码响应 func (a *Adapter) DecodeResponse(raw []byte) (*canonical.CanonicalResponse, error) { return decodeResponse(raw) } // EncodeResponse 编码响应 func (a *Adapter) EncodeResponse(resp *canonical.CanonicalResponse) ([]byte, error) { return encodeResponse(resp) } // CreateStreamDecoder 创建流式解码器 func (a *Adapter) CreateStreamDecoder() conversion.StreamDecoder { return NewStreamDecoder() } // CreateStreamEncoder 创建流式编码器 func (a *Adapter) CreateStreamEncoder() conversion.StreamEncoder { return NewStreamEncoder() } // EncodeError 编码错误 func (a *Adapter) EncodeError(err *conversion.ConversionError) ([]byte, int) { errType := string(err.Code) statusCode := 500 errMsg := ErrorResponse{ Type: "error", Error: ErrorDetail{ Type: errType, Message: err.Message, }, } body, _ := json.Marshal(errMsg) return body, statusCode } // DecodeModelsResponse 解码模型列表响应 func (a *Adapter) DecodeModelsResponse(raw []byte) (*canonical.CanonicalModelList, error) { return decodeModelsResponse(raw) } // EncodeModelsResponse 编码模型列表响应 func (a *Adapter) EncodeModelsResponse(list *canonical.CanonicalModelList) ([]byte, error) { return encodeModelsResponse(list) } // DecodeModelInfoResponse 解码模型详情响应 func (a *Adapter) DecodeModelInfoResponse(raw []byte) (*canonical.CanonicalModelInfo, error) { return decodeModelInfoResponse(raw) } // EncodeModelInfoResponse 编码模型详情响应 func (a *Adapter) EncodeModelInfoResponse(info *canonical.CanonicalModelInfo) ([]byte, error) { return encodeModelInfoResponse(info) } // DecodeEmbeddingRequest Anthropic 不支持嵌入 func (a *Adapter) DecodeEmbeddingRequest(raw []byte) (*canonical.CanonicalEmbeddingRequest, error) { return nil, conversion.NewConversionError(conversion.ErrorCodeInterfaceNotSupported, "Anthropic 不支持 Embeddings 接口") } // EncodeEmbeddingRequest Anthropic 不支持嵌入 func (a *Adapter) EncodeEmbeddingRequest(req *canonical.CanonicalEmbeddingRequest, provider *conversion.TargetProvider) ([]byte, error) { return nil, conversion.NewConversionError(conversion.ErrorCodeInterfaceNotSupported, "Anthropic 不支持 Embeddings 接口") } // DecodeEmbeddingResponse Anthropic 不支持嵌入 func (a *Adapter) DecodeEmbeddingResponse(raw []byte) (*canonical.CanonicalEmbeddingResponse, error) { return nil, conversion.NewConversionError(conversion.ErrorCodeInterfaceNotSupported, "Anthropic 不支持 Embeddings 接口") } // EncodeEmbeddingResponse Anthropic 不支持嵌入 func (a *Adapter) EncodeEmbeddingResponse(resp *canonical.CanonicalEmbeddingResponse) ([]byte, error) { return nil, conversion.NewConversionError(conversion.ErrorCodeInterfaceNotSupported, "Anthropic 不支持 Embeddings 接口") } // DecodeRerankRequest Anthropic 不支持重排序 func (a *Adapter) DecodeRerankRequest(raw []byte) (*canonical.CanonicalRerankRequest, error) { return nil, conversion.NewConversionError(conversion.ErrorCodeInterfaceNotSupported, "Anthropic 不支持 Rerank 接口") } // EncodeRerankRequest Anthropic 不支持重排序 func (a *Adapter) EncodeRerankRequest(req *canonical.CanonicalRerankRequest, provider *conversion.TargetProvider) ([]byte, error) { return nil, conversion.NewConversionError(conversion.ErrorCodeInterfaceNotSupported, "Anthropic 不支持 Rerank 接口") } // DecodeRerankResponse Anthropic 不支持重排序 func (a *Adapter) DecodeRerankResponse(raw []byte) (*canonical.CanonicalRerankResponse, error) { return nil, conversion.NewConversionError(conversion.ErrorCodeInterfaceNotSupported, "Anthropic 不支持 Rerank 接口") } // EncodeRerankResponse Anthropic 不支持重排序 func (a *Adapter) EncodeRerankResponse(resp *canonical.CanonicalRerankResponse) ([]byte, error) { return nil, conversion.NewConversionError(conversion.ErrorCodeInterfaceNotSupported, "Anthropic 不支持 Rerank 接口") }