1118 lines · 34.7 KB · Go
RawDownload
package pluginhost import (	"bytes"	"context"	"encoding/json"	"fmt"	"io"	"net/http"	"sort"	"strings"	"sync" 	"github.com/router-for-me/CLIProxyAPI/v7/internal/registry"	"github.com/router-for-me/CLIProxyAPI/v7/internal/runtime/executor/helps"	"github.com/router-for-me/CLIProxyAPI/v7/internal/thinking"	coreauth "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/auth"	coreexecutor "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/executor"	"github.com/router-for-me/CLIProxyAPI/v7/sdk/pluginapi"	sdktranslator "github.com/router-for-me/CLIProxyAPI/v7/sdk/translator") type executorManager interface {	Executor(provider string) (coreauth.ProviderExecutor, bool)	RegisterExecutor(coreauth.ProviderExecutor)	UnregisterExecutor(provider string)} type executorRegistration struct {	provider string	adapter  *executorAdapter} func (h *Host) RegisterExecutors(manager executorManager, modelRegistry modelProviderRegistry) {	if h == nil || manager == nil {		return	} 	snap := h.Snapshot()	records := h.activeRecordsFromSnapshot(snap)	registrations := h.snapshotModelRegistrations()	selectedModels := make(map[string][]*registry.ModelInfo)	providerModels := make(map[string][]*registry.ModelInfo)	claimedModels := make(map[string]struct{})	claimedProviders := make(map[string]string)	for _, registration := range registrations {		if !registration.hasExecutor {			appendModelsForProvider(providerModels, registration.provider, registration.models)		}	}	for _, record := range records {		executor := record.plugin.Capabilities.Executor		if executor == nil || h.isPluginFused(record.id) {			continue		}		provider, okProvider := h.executorProvider(record, executor)		if !okProvider {			continue		}		registration := h.modelRegistration(record.id)		if h.providerHasNativeExecutor(manager, provider) {			appendModelsForProvider(providerModels, provider, registration.models)			continue		}		if len(registration.models) == 0 {			continue		}		if owner := claimedProviders[provider]; owner != "" && owner != record.id {			continue		}		for _, model := range registration.models {			modelID := strings.TrimSpace(model.ID)			if modelID == "" {				continue			}			if _, claimed := claimedModels[modelID]; claimed {				continue			}			if h.modelHasNativeExecutor(manager, modelRegistry, modelID) {				continue			}			claimedModels[modelID] = struct{}{}			claimedProviders[provider] = record.id			selectedModels[record.id] = append(selectedModels[record.id], model)		}	} 	seenProviders := make(map[string]struct{})	nextProviders := make(map[string]struct{})	nextModelClients := make(map[string]struct{})	executorRegistrations := make([]executorRegistration, 0)	modelClientRegistrations := make([]modelClientRegistration, 0)	for _, record := range records {		executor := record.plugin.Capabilities.Executor		if executor == nil || h.isPluginFused(record.id) {			continue		} 		provider, okProvider := h.executorProvider(record, executor)		if !okProvider {			continue		}		registration := h.modelRegistration(record.id)		if len(registration.models) > 0 && len(selectedModels[record.id]) == 0 {			continue		}		if _, seenProvider := seenProviders[provider]; seenProvider {			continue		}		seenProviders[provider] = struct{}{}		if h.providerHasNativeExecutor(manager, provider) {			continue		} 		nextProviders[provider] = struct{}{}		executorRegistrations = append(executorRegistrations, newExecutorAdapterRegistration(h, record, provider, executor))		appendModelsForProvider(providerModels, provider, selectedModels[record.id])		if len(selectedModels[record.id]) > 0 {			clientID := pluginExecutorModelClientID(record.id, provider)			modelClientRegistrations = append(modelClientRegistrations, modelClientRegistration{				clientID: clientID,				provider: provider,				models:   selectedModels[record.id],			})			nextModelClients[clientID] = struct{}{}		}	}	h.commitExecutorState(snap, manager, modelRegistry, providerModels, executorRegistrations, nextProviders, modelClientRegistrations, nextModelClients)} func pluginExecutorModelClientID(pluginID, provider string) string {	return "plugin:" + pluginID + ":" + provider + ":executor"} func (h *Host) commitExecutorState(snap *Snapshot, manager executorManager, modelRegistry modelRegistry, providerModels map[string][]*registry.ModelInfo, registrations []executorRegistration, nextProviders map[string]struct{}, modelClientRegistrations []modelClientRegistration, nextModelClients map[string]struct{}) {	if h == nil || manager == nil {		return	} 	h.mu.Lock()	if h.Snapshot() != snap {		h.mu.Unlock()		return	} 	h.providerModels = make(map[string][]*registryModelInfo, len(providerModels))	for provider, models := range providerModels {		h.providerModels[provider] = cloneRegistryModels(models)	} 	staleProviders := make([]string, 0)	for provider := range h.executorProviders {		if _, okProvider := nextProviders[provider]; !okProvider {			staleProviders = append(staleProviders, provider)		}	}	h.executorProviders = nextProviders	if nextModelClients == nil {		nextModelClients = make(map[string]struct{})	}	staleModelClients := make([]string, 0)	for clientID := range h.executorModelClientIDs {		if _, okClient := nextModelClients[clientID]; !okClient {			staleModelClients = append(staleModelClients, clientID)		}	}	h.executorModelClientIDs = nextModelClients 	for _, registration := range registrations {		if registration.adapter == nil || registration.provider == "" {			continue		}		manager.RegisterExecutor(registration.adapter)	}	for _, provider := range staleProviders {		existing, okExecutor := manager.Executor(provider)		if !okExecutor || !h.ownsExecutor(existing) {			continue		}		manager.UnregisterExecutor(provider)	}	h.mu.Unlock() 	if modelRegistry == nil {		return	}	for _, registration := range modelClientRegistrations {		modelRegistry.RegisterClient(registration.clientID, registration.provider, registration.models)	}	for _, clientID := range staleModelClients {		modelRegistry.UnregisterClient(clientID)	}} func newExecutorAdapterRegistration(h *Host, record capabilityRecord, provider string, executor pluginapi.ProviderExecutor) executorRegistration {	return executorRegistration{		provider: provider,		adapter: &executorAdapter{			host:          h,			pluginID:      record.id,			path:          record.path,			version:       record.version,			provider:      provider,			executor:      executor,			inputFormats:  normalizeExecutorFormats(record.plugin.Capabilities.ExecutorInputFormats),			outputFormats: normalizeExecutorFormats(record.plugin.Capabilities.ExecutorOutputFormats),		},	}} func (h *Host) snapshotModelRegistrations() []pluginModelRegistration {	if h == nil {		return nil	}	h.mu.Lock()	defer h.mu.Unlock()	registrations := make([]pluginModelRegistration, 0, len(h.modelRegistrations))	for _, registration := range h.modelRegistrations {		registration.models = cloneRegistryModels(registration.models)		registrations = append(registrations, registration)	}	sort.SliceStable(registrations, func(i, j int) bool {		if registrations[i].priority == registrations[j].priority {			return registrations[i].pluginID < registrations[j].pluginID		}		return registrations[i].priority > registrations[j].priority	})	return registrations} func (h *Host) modelRegistration(pluginID string) pluginModelRegistration {	if h == nil {		return pluginModelRegistration{}	}	h.mu.Lock()	defer h.mu.Unlock()	registration := h.modelRegistrations[pluginID]	registration.models = cloneRegistryModels(registration.models)	return registration} func (h *Host) executorProvider(record capabilityRecord, executor pluginapi.ProviderExecutor) (string, bool) {	if h == nil || !h.recordCurrent(record) {		return "", false	}	provider := h.modelProvider(record.id)	if provider == "" {		identifier, okIdentifier := h.callExecutorIdentifier(record.id, executor)		if !okIdentifier {			return "", false		}		provider = identifier	}	provider = strings.ToLower(strings.TrimSpace(provider))	return provider, provider != ""} func (h *Host) callExecutorIdentifier(pluginID string, executor pluginapi.ProviderExecutor) (provider string, ok bool) {	if h == nil || executor == nil || h.isPluginFused(pluginID) {		return "", false	}	defer func() {		if recovered := recover(); recovered != nil {			h.fusePlugin(pluginID, "Executor.Identifier", recovered)			provider = ""			ok = false		}	}()	return executor.Identifier(), true} func (h *Host) providerHasNativeExecutor(manager executorManager, provider string) bool {	if h == nil || manager == nil {		return false	}	existing, okExecutor := manager.Executor(provider)	return okExecutor && existing != nil && !h.ownsExecutor(existing)} func (h *Host) modelHasNativeExecutor(manager executorManager, modelRegistry modelProviderRegistry, modelID string) bool {	if h == nil || manager == nil || modelRegistry == nil {		return false	}	for _, provider := range modelRegistry.GetModelProviders(modelID) {		if h.providerHasNativeExecutor(manager, provider) {			return true		}	}	return false} func appendModelsForProvider(out map[string][]*registry.ModelInfo, provider string, models []*registry.ModelInfo) {	provider = strings.ToLower(strings.TrimSpace(provider))	if provider == "" || len(models) == 0 {		return	}	seen := make(map[string]struct{}, len(out[provider])+len(models))	for _, model := range out[provider] {		if model != nil && strings.TrimSpace(model.ID) != "" {			seen[strings.TrimSpace(model.ID)] = struct{}{}		}	}	for _, model := range models {		if model == nil {			continue		}		modelID := strings.TrimSpace(model.ID)		if modelID == "" {			continue		}		if _, exists := seen[modelID]; exists {			continue		}		seen[modelID] = struct{}{}		out[provider] = append(out[provider], cloneRegistryModels([]*registry.ModelInfo{model})...)	}} func (h *Host) ModelsForProvider(provider string) []*registry.ModelInfo {	if h == nil {		return nil	}	provider = strings.ToLower(strings.TrimSpace(provider))	if provider == "" {		return nil	}	h.mu.Lock()	defer h.mu.Unlock()	return cloneRegistryModels(h.providerModels[provider])} func (h *Host) HasExecutorCandidateProvider(provider string) bool {	if h == nil {		return false	}	provider = strings.ToLower(strings.TrimSpace(provider))	if provider == "" {		return false	}	for _, record := range h.activeRecords() {		executor := record.plugin.Capabilities.Executor		if executor == nil || h.isPluginFused(record.id) {			continue		}		candidate, okCandidate := h.executorProvider(record, executor)		if okCandidate && candidate == provider {			return true		}	}	return false} // OwnsExecutor reports whether executor is an adapter managed by this host.func (h *Host) OwnsExecutor(executor coreauth.ProviderExecutor) bool {	return h.ownsExecutor(executor)} func (h *Host) ownsExecutor(executor coreauth.ProviderExecutor) bool {	adapter, okAdapter := executor.(*executorAdapter)	return okAdapter && adapter != nil && adapter.host == h} func (h *Host) modelProvider(pluginID string) string {	if h == nil {		return ""	}	h.mu.Lock()	defer h.mu.Unlock()	return h.modelProviders[pluginID]} type executorAdapter struct {	host          *Host	pluginID      string	path          string	version       string	provider      string	executor      pluginapi.ProviderExecutor	inputFormats  []sdktranslator.Format	outputFormats []sdktranslator.Format} func (a *executorAdapter) Identifier() string {	if a == nil {		return ""	}	return a.provider} type preparedExecutorCall struct {	req             coreexecutor.Request	opts            coreexecutor.Options	inputRequested  sdktranslator.Format	requestedFormat sdktranslator.Format	inputFormat     sdktranslator.Format	outputFormat    sdktranslator.Format} func (a *executorAdapter) prepareExecutorCall(req coreexecutor.Request, opts coreexecutor.Options) (preparedExecutorCall, error) {	inputRequested := executorInputFormat(req, opts)	requestedFormat := executorRequestedFormat(req, opts)	inputFormat, errInput := a.selectExecutorInputFormat(inputRequested)	if errInput != nil {		return preparedExecutorCall{}, errInput	}	outputFormat, errOutput := a.selectExecutorOutputFormat(requestedFormat, inputFormat)	if errOutput != nil {		return preparedExecutorCall{}, errOutput	} 	nativeReq := req	nativeOpts := opts	if inputRequested != "" && inputRequested != inputFormat {		nativeReq.Payload = sdktranslator.TranslateRequest(inputRequested, inputFormat, req.Model, req.Payload, opts.Stream)	}	nativeReq.Format = outputFormat	nativeOpts.SourceFormat = inputFormat	nativeOpts.ResponseFormat = outputFormat 	return preparedExecutorCall{		req:             nativeReq,		opts:            nativeOpts,		inputRequested:  inputRequested,		requestedFormat: requestedFormat,		inputFormat:     inputFormat,		outputFormat:    outputFormat,	}, nil} func (a *executorAdapter) RequestToFormat(req coreexecutor.Request, opts coreexecutor.Options) sdktranslator.Format {	if a == nil {		return ""	}	inputRequested := executorInputFormat(req, opts)	inputFormat, errInput := a.selectExecutorInputFormat(inputRequested)	if errInput != nil {		return ""	}	return inputFormat} func executorInputFormat(req coreexecutor.Request, opts coreexecutor.Options) sdktranslator.Format {	if opts.SourceFormat != "" {		return normalizeExecutorFormatName(opts.SourceFormat.String())	}	if req.Format != "" {		return normalizeExecutorFormatName(req.Format.String())	}	return sdktranslator.FormatOpenAI} func executorRequestedFormat(req coreexecutor.Request, opts coreexecutor.Options) sdktranslator.Format {	if format := coreexecutor.ResponseFormatOrSource(opts); format != "" {		return normalizeExecutorFormatName(format.String())	}	if req.Format != "" {		return normalizeExecutorFormatName(req.Format.String())	}	return sdktranslator.FormatOpenAI} func (a *executorAdapter) selectExecutorInputFormat(requested sdktranslator.Format) (sdktranslator.Format, error) {	if len(a.inputFormats) == 0 {		return "", fmt.Errorf("plugin executor %s declares no input formats", a.Identifier())	}	if executorFormatContains(a.inputFormats, requested) {		return requested, nil	}	for _, format := range a.inputFormats {		if requested == "" || sdktranslator.HasRequestTransformer(requested, format) {			return format, nil		}	}	return "", fmt.Errorf("plugin executor %s does not support input format %q", a.Identifier(), requested)} func (a *executorAdapter) selectExecutorOutputFormat(requested, inputFormat sdktranslator.Format) (sdktranslator.Format, error) {	if len(a.outputFormats) == 0 {		return "", fmt.Errorf("plugin executor %s declares no output formats", a.Identifier())	}	if executorFormatContains(a.outputFormats, requested) {		return requested, nil	}	if executorFormatContains(a.outputFormats, inputFormat) && a.executorResponseTranslationAvailable(inputFormat, requested) {		return inputFormat, nil	}	for _, format := range a.outputFormats {		if requested == "" || a.executorResponseTranslationAvailable(format, requested) {			return format, nil		}	}	return "", fmt.Errorf("plugin executor %s does not support output format %q", a.Identifier(), requested)} func (a *executorAdapter) executorResponseTranslationAvailable(from, to sdktranslator.Format) bool {	if from == "" || to == "" || from == to {		return true	}	if sdktranslator.HasResponseTransformer(to, from) {		return true

Lines 1–500 of 1118.