Files
Pine 28e53d90fc feat: 算力引擎 Go 后端核心(new-api)
- 统一 OpenAI 兼容 /v1 中继 + 渠道/额度/令牌/流水
- 各领域包:relay 模型网关、model 数据层、controller 管理 API
2026-08-23 22:38:46 +08:00

216 lines
5.4 KiB
Go

// Package convmeta defines the conversion-context contract between format
// converters (future relaykit) and the hosting application. Converters read
// protocol state and per-request options exclusively through the Meta
// interface; the host's RelayInfo implements it.
package convmeta
import (
"github.com/QuantumNous/new-api/relaykit/dto"
"github.com/QuantumNous/new-api/relaykit/types"
)
// Meta is the only view of the relay session that format converters may use.
// It is satisfied by *relaycommon.RelayInfo on the host side; other embedders
// (tests, external relaykit users) can use *Values.
// Implementations backed by pointer types must make every method safe on a nil
// receiver: a typed-nil pointer stored in Meta is still a non-nil interface,
// and relaykit deliberately does not use reflection to detect that case.
type Meta interface {
GetOriginModelName() string
GetUpstreamModelName() string
// HasChannelMeta reports whether upstream channel information is attached;
// converters use it to decide if GetUpstreamModelName is meaningful.
HasChannelMeta() bool
GetChannelID() int
GetChannelType() int
GetIsStream() bool
GetReasoningEffort() string
// SetReasoningEffort records the effort level a converter derived from a
// model-name suffix so downstream billing/logging can see it.
SetReasoningEffort(effort string)
GetEstimatePromptTokens() int
// EnsureClaudeConvertInfo lazily creates and returns the mutable
// OpenAI→Claude stream conversion state. For non-nil receivers, the same
// instance must be returned for the lifetime of one streaming session; a
// nil receiver may return a temporary initialized state.
EnsureClaudeConvertInfo() *ClaudeConvertInfo
// GetSendResponseCount / IncrSendResponseCount expose the shared
// downstream-chunk counter (the host may also increment it).
GetSendResponseCount() int
IncrSendResponseCount()
// AppendRequestConversion records a hop in the request format chain.
AppendRequestConversion(format types.RelayFormat)
// ConvOptions returns the request-scoped conversion options snapshot.
// Must never return nil.
ConvOptions() *Options
}
// ClaudeConvertInfo carries mutable state for OpenAI chat → Claude Messages
// stream conversion. Moved here from relay/common (which keeps an alias).
type ClaudeConvertInfo struct {
LastMessagesType string
Index int
Usage *dto.Usage
FinishReason string
Done bool
ToolCallBaseIndex int
ToolCallMaxIndexOffset int
}
const (
LastMessageTypeNone = "none"
LastMessageTypeText = "text"
LastMessageTypeTools = "tools"
LastMessageTypeThinking = "thinking"
)
// Values is a plain-struct Meta implementation for tests and non-RelayInfo
// hosts (the relaykit-native entry point).
type Values struct {
OriginModelName string
UpstreamModelName string
ChannelMetaAttached bool
ChannelID int
ChannelType int
IsStream bool
ReasoningEffort string
EstimatePromptTokens int
ClaudeConvertInfo *ClaudeConvertInfo
SendResponseCount int
ConversionChain []types.RelayFormat
Options *Options
}
var _ Meta = (*Values)(nil)
func (v *Values) GetOriginModelName() string {
if v == nil {
return ""
}
return v.OriginModelName
}
func (v *Values) GetUpstreamModelName() string {
if v == nil {
return ""
}
return v.UpstreamModelName
}
func (v *Values) HasChannelMeta() bool {
return v != nil && v.ChannelMetaAttached
}
func (v *Values) GetChannelID() int {
if v == nil {
return 0
}
return v.ChannelID
}
func (v *Values) GetChannelType() int {
if v == nil {
return 0
}
return v.ChannelType
}
func (v *Values) GetIsStream() bool {
return v != nil && v.IsStream
}
func (v *Values) GetReasoningEffort() string {
if v == nil {
return ""
}
return v.ReasoningEffort
}
func (v *Values) SetReasoningEffort(effort string) {
if v != nil {
v.ReasoningEffort = effort
}
}
func (v *Values) GetEstimatePromptTokens() int {
if v == nil {
return 0
}
return v.EstimatePromptTokens
}
func (v *Values) EnsureClaudeConvertInfo() *ClaudeConvertInfo {
if v == nil {
return &ClaudeConvertInfo{LastMessagesType: LastMessageTypeNone}
}
if v.ClaudeConvertInfo == nil {
v.ClaudeConvertInfo = &ClaudeConvertInfo{LastMessagesType: LastMessageTypeNone}
}
return v.ClaudeConvertInfo
}
func (v *Values) GetSendResponseCount() int {
if v == nil {
return 0
}
return v.SendResponseCount
}
func (v *Values) IncrSendResponseCount() {
if v != nil {
v.SendResponseCount++
}
}
func (v *Values) AppendRequestConversion(format types.RelayFormat) {
if v == nil || format == "" {
return
}
if n := len(v.ConversionChain); n > 0 && v.ConversionChain[n-1] == format {
return
}
v.ConversionChain = append(v.ConversionChain, format)
}
func (v *Values) ConvOptions() *Options {
if v == nil {
return &Options{}
}
if v.Options == nil {
v.Options = &Options{}
}
return v.Options
}
// UpstreamModelName / ChannelTypeOf are nil-safe accessors for optional Meta
// values (converters are often called with a nil Meta in tests and compat
// shims).
func UpstreamModelName(m Meta) string {
if m == nil || !m.HasChannelMeta() {
return ""
}
return m.GetUpstreamModelName()
}
func ChannelTypeOf(m Meta) int {
if m == nil || !m.HasChannelMeta() {
return 0
}
return m.GetChannelType()
}
// OptionsOf returns m's conversion options, or empty defaults when m is nil.
func OptionsOf(m Meta) *Options {
if m == nil {
return &Options{}
}
return m.ConvOptions()
}