refactor: 实现 ConversionEngine 协议转换引擎,替代旧 protocol 包
引入 Canonical Model 和 ProtocolAdapter 架构,支持 OpenAI/Anthropic 协议间 无缝转换,统一 ProxyHandler 替代分散的 OpenAI/Anthropic Handler,简化 ProviderClient 为协议无关的 HTTP 发送器,Provider 新增 protocol 字段。
This commit is contained in:
85
backend/internal/conversion/middleware_test.go
Normal file
85
backend/internal/conversion/middleware_test.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package conversion
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"nex/backend/internal/conversion/canonical"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// recordingMiddleware 记录调用顺序的中间件
|
||||
type recordingMiddleware struct {
|
||||
name string
|
||||
records *[]string
|
||||
err error
|
||||
}
|
||||
|
||||
func (m *recordingMiddleware) Intercept(req *canonical.CanonicalRequest, clientProtocol, providerProtocol string, ctx *ConversionContext) (*canonical.CanonicalRequest, error) {
|
||||
*m.records = append(*m.records, m.name)
|
||||
if m.err != nil {
|
||||
return nil, m.err
|
||||
}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (m *recordingMiddleware) InterceptStreamEvent(event *canonical.CanonicalStreamEvent, clientProtocol, providerProtocol string, ctx *ConversionContext) (*canonical.CanonicalStreamEvent, error) {
|
||||
*m.records = append(*m.records, "stream:"+m.name)
|
||||
if m.err != nil {
|
||||
return nil, m.err
|
||||
}
|
||||
return event, nil
|
||||
}
|
||||
|
||||
func TestMiddlewareChain_Empty(t *testing.T) {
|
||||
chain := NewMiddlewareChain()
|
||||
req := &canonical.CanonicalRequest{Model: "test"}
|
||||
ctx := NewConversionContext(InterfaceTypeChat)
|
||||
|
||||
result, err := chain.Apply(req, "a", "b", ctx)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "test", result.Model)
|
||||
}
|
||||
|
||||
func TestMiddlewareChain_Order(t *testing.T) {
|
||||
var records []string
|
||||
chain := NewMiddlewareChain()
|
||||
chain.Use(&recordingMiddleware{name: "first", records: &records})
|
||||
chain.Use(&recordingMiddleware{name: "second", records: &records})
|
||||
chain.Use(&recordingMiddleware{name: "third", records: &records})
|
||||
|
||||
req := &canonical.CanonicalRequest{Model: "test"}
|
||||
ctx := NewConversionContext(InterfaceTypeChat)
|
||||
_, err := chain.Apply(req, "a", "b", ctx)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []string{"first", "second", "third"}, records)
|
||||
}
|
||||
|
||||
func TestMiddlewareChain_ErrorInterrupt(t *testing.T) {
|
||||
var records []string
|
||||
chain := NewMiddlewareChain()
|
||||
chain.Use(&recordingMiddleware{name: "first", records: &records})
|
||||
chain.Use(&recordingMiddleware{name: "second", records: &records, err: errors.New("中断")})
|
||||
chain.Use(&recordingMiddleware{name: "third", records: &records})
|
||||
|
||||
req := &canonical.CanonicalRequest{Model: "test"}
|
||||
ctx := NewConversionContext(InterfaceTypeChat)
|
||||
_, err := chain.Apply(req, "a", "b", ctx)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "中断", err.Error())
|
||||
assert.Equal(t, []string{"first", "second"}, records)
|
||||
}
|
||||
|
||||
func TestMiddlewareChain_ApplyStreamEvent(t *testing.T) {
|
||||
var records []string
|
||||
chain := NewMiddlewareChain()
|
||||
chain.Use(&recordingMiddleware{name: "mw1", records: &records})
|
||||
|
||||
event := canonical.NewMessageStartEvent("id", "model")
|
||||
ctx := NewConversionContext(InterfaceTypeChat)
|
||||
result, err := chain.ApplyStreamEvent(&event, "a", "b", ctx)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, canonical.EventMessageStart, result.Type)
|
||||
assert.Equal(t, []string{"stream:mw1"}, records)
|
||||
}
|
||||
Reference in New Issue
Block a user