Add projects
This commit is contained in:
parent
2d3a9ad623
commit
8b607dd700
1802 changed files with 503346 additions and 2 deletions
155
backend/internal/pluginhost/model_router.go
Normal file
155
backend/internal/pluginhost/model_router.go
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
package pluginhost
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/router-for-me/CLIProxyAPI/v7/sdk/pluginapi"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (h *Host) RouteModel(ctx context.Context, req pluginapi.ModelRouteRequest) (pluginapi.ModelRouteResponse, bool) {
|
||||
return h.RouteModelExcept(ctx, req, "")
|
||||
}
|
||||
|
||||
func (h *Host) HasModelRouters() bool {
|
||||
return h.HasModelRoutersExcept("")
|
||||
}
|
||||
|
||||
func (h *Host) HasModelRoutersExcept(skipPluginID string) bool {
|
||||
if h == nil {
|
||||
return false
|
||||
}
|
||||
skipPluginID = strings.TrimSpace(skipPluginID)
|
||||
for _, record := range h.activeRecords() {
|
||||
if record.plugin.Capabilities.ModelRouter != nil && !h.isPluginFused(record.id) && record.id != skipPluginID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (h *Host) RouteModelExcept(ctx context.Context, req pluginapi.ModelRouteRequest, skipPluginID string) (pluginapi.ModelRouteResponse, bool) {
|
||||
if h == nil {
|
||||
return pluginapi.ModelRouteResponse{}, false
|
||||
}
|
||||
skipPluginID = strings.TrimSpace(skipPluginID)
|
||||
req.AvailableProviders = h.availableProvidersSnapshot()
|
||||
for _, record := range h.activeRecords() {
|
||||
router := record.plugin.Capabilities.ModelRouter
|
||||
if router == nil || h.isPluginFused(record.id) || record.id == skipPluginID {
|
||||
continue
|
||||
}
|
||||
nextReq := cloneModelRouteRequest(req)
|
||||
nextReq.Plugin = clonePluginMetadata(record.meta)
|
||||
nextReq.PluginID = record.id
|
||||
resp, ok := h.callModelRouter(ctx, record.id, router, nextReq)
|
||||
if !ok || !resp.Handled {
|
||||
continue
|
||||
}
|
||||
resp, valid := normalizeModelRouteResponse(record.id, resp)
|
||||
if !valid {
|
||||
log.WithFields(log.Fields{"plugin_id": record.id, "target_kind": resp.TargetKind, "target": resp.Target}).Warn("pluginhost: model router returned invalid target")
|
||||
continue
|
||||
}
|
||||
switch resp.TargetKind {
|
||||
case pluginapi.ModelRouteTargetProvider:
|
||||
if !h.HasBuiltinProvider(resp.Target) {
|
||||
log.WithFields(log.Fields{"plugin_id": record.id, "target_provider": resp.Target}).Warn("pluginhost: model router returned unavailable provider")
|
||||
continue
|
||||
}
|
||||
return resp, true
|
||||
case pluginapi.ModelRouteTargetSelf, pluginapi.ModelRouteTargetExecutor:
|
||||
if !h.executorPluginReady(resp.Target, nextReq) {
|
||||
log.WithFields(log.Fields{"plugin_id": record.id, "target_plugin_id": resp.Target}).Warn("pluginhost: model router returned unavailable executor plugin")
|
||||
continue
|
||||
}
|
||||
return resp, true
|
||||
default:
|
||||
log.WithFields(log.Fields{"plugin_id": record.id, "target_kind": resp.TargetKind}).Warn("pluginhost: model router returned unsupported target kind")
|
||||
continue
|
||||
}
|
||||
}
|
||||
return pluginapi.ModelRouteResponse{}, false
|
||||
}
|
||||
|
||||
func (h *Host) callModelRouter(ctx context.Context, pluginID string, router pluginapi.ModelRouter, req pluginapi.ModelRouteRequest) (out pluginapi.ModelRouteResponse, ok bool) {
|
||||
if h == nil || router == nil || h.isPluginFused(pluginID) {
|
||||
return pluginapi.ModelRouteResponse{}, false
|
||||
}
|
||||
defer func() {
|
||||
if recovered := recover(); recovered != nil {
|
||||
h.fusePlugin(pluginID, "ModelRouter.RouteModel", recovered)
|
||||
out = pluginapi.ModelRouteResponse{}
|
||||
ok = false
|
||||
}
|
||||
}()
|
||||
resp, errRoute := router.RouteModel(ctx, req)
|
||||
if errRoute != nil {
|
||||
log.WithField("plugin_id", pluginID).WithError(errRoute).Warn("pluginhost: model router failed")
|
||||
return pluginapi.ModelRouteResponse{}, false
|
||||
}
|
||||
return resp, true
|
||||
}
|
||||
|
||||
func normalizeModelRouteResponse(routerPluginID string, resp pluginapi.ModelRouteResponse) (pluginapi.ModelRouteResponse, bool) {
|
||||
resp.TargetModel = strings.TrimSpace(resp.TargetModel)
|
||||
switch resp.TargetKind {
|
||||
case pluginapi.ModelRouteTargetSelf:
|
||||
resp.Target = strings.TrimSpace(routerPluginID)
|
||||
if resp.Target == "" {
|
||||
return pluginapi.ModelRouteResponse{}, false
|
||||
}
|
||||
return resp, true
|
||||
case pluginapi.ModelRouteTargetExecutor:
|
||||
resp.Target = strings.TrimSpace(resp.Target)
|
||||
if resp.Target == "" {
|
||||
return pluginapi.ModelRouteResponse{}, false
|
||||
}
|
||||
return resp, true
|
||||
case pluginapi.ModelRouteTargetProvider:
|
||||
resp.Target = strings.ToLower(strings.TrimSpace(resp.Target))
|
||||
if resp.Target == "" {
|
||||
return pluginapi.ModelRouteResponse{}, false
|
||||
}
|
||||
return resp, true
|
||||
default:
|
||||
return pluginapi.ModelRouteResponse{}, false
|
||||
}
|
||||
}
|
||||
|
||||
func cloneModelRouteRequest(req pluginapi.ModelRouteRequest) pluginapi.ModelRouteRequest {
|
||||
req.Headers = cloneHeader(req.Headers)
|
||||
req.Query = cloneValues(req.Query)
|
||||
req.Body = bytes.Clone(req.Body)
|
||||
req.Metadata = cloneInterceptorMetadata(req.Metadata)
|
||||
req.AvailableProviders = cloneStringSlice(req.AvailableProviders)
|
||||
return req
|
||||
}
|
||||
|
||||
// HasBuiltinProvider reports whether a built-in provider currently has at least one
|
||||
// registered auth record.
|
||||
func (h *Host) HasBuiltinProvider(provider string) bool {
|
||||
if h == nil || h.authManager == nil {
|
||||
return false
|
||||
}
|
||||
return h.authManager.HasProviderAuth(provider)
|
||||
}
|
||||
|
||||
// BuiltinProviders returns built-in provider keys that currently have auth registered.
|
||||
func (h *Host) BuiltinProviders() []string {
|
||||
if h == nil || h.authManager == nil {
|
||||
return nil
|
||||
}
|
||||
return h.authManager.AvailableProviders()
|
||||
}
|
||||
|
||||
// availableProvidersSnapshot returns a defensive copy of BuiltinProviders for routing input.
|
||||
func (h *Host) availableProvidersSnapshot() []string {
|
||||
providers := h.BuiltinProviders()
|
||||
if len(providers) == 0 {
|
||||
return nil
|
||||
}
|
||||
return cloneStringSlice(providers)
|
||||
}
|
||||
Loading…
Reference in a new issue