Ctrl K
ComunidadGuías…

internal/pluginhost/rpc_schema.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package pluginhost

import (
	"encoding/json"
	"net/http"

	"github.com/router-for-me/CLIProxyAPI/v8/sdk/pluginapi"
)

type rpcLifecycleRequest struct {
	ConfigYAML         []byte `json:"config_yaml"`
	SchemaVersion      uint32 `json:"schema_version"`
	MultiAuthProviders bool   `json:"multi_auth_providers,omitempty"`
}

type rpcRegistration struct {
	SchemaVersion uint32             `json:"schema_version"`
	Metadata      pluginapi.Metadata `json:"metadata"`
	Capabilities  rpcCapabilities    `json:"capabilities"`
}

type rpcCapabilities struct {
	ModelRegistrar                    bool                         `json:"model_registrar"`
	ModelProvider                     bool                         `json:"model_provider"`
	AuthProvider                      bool                         `json:"auth_provider"`
	FrontendAuthProvider              bool                         `json:"frontend_auth_provider"`
	FrontendAuthProviderExclusive     bool                         `json:"frontend_auth_provider_exclusive"`
	FrontendAuthProviderOmitBody      bool                         `json:"frontend_auth_provider_omit_body,omitempty"`
	FrontendAuthOmitBody              bool                         `json:"frontend_auth_omit_body,omitempty"`
	Scheduler                         bool                         `json:"scheduler"`
	SchedulerAcrossPriorities         bool                         `json:"scheduler_across_priorities,omitempty"`
	ModelRouter                       bool                         `json:"model_router"`
	Executor                          bool                         `json:"executor"`
	ExecutorModelScope                pluginapi.ExecutorModelScope `json:"executor_model_scope"`
	ExecutorInputFormats              []string                     `json:"executor_input_formats,omitempty"`
	ExecutorOutputFormats             []string                     `json:"executor_output_formats,omitempty"`
	RequestTranslator                 bool                         `json:"request_translator"`
	RequestNormalizer                 bool                         `json:"request_normalizer"`
	RequestInterceptor                bool                         `json:"request_interceptor"`
	RequestInterceptorOmitBodyBefore  bool                         `json:"request_interceptor_omit_body_before,omitempty"`
	RequestInterceptorOmitBodyAfter   bool                         `json:"request_interceptor_omit_body_after,omitempty"`
	RequestBodyPatcherBefore          bool                         `json:"request_body_patcher_before,omitempty"`
	RequestBodyPatcherAfter           bool                         `json:"request_body_patcher_after,omitempty"`
	RequestInterceptorPatchBodyBefore bool                         `json:"request_interceptor_patch_body_before,omitempty"`
	RequestInterceptorPatchBodyAfter  bool                         `json:"request_interceptor_patch_body_after,omitempty"`
	RequestLifecyclePlugin            bool                         `json:"request_lifecycle_plugin"`
	ResponseTranslator                bool                         `json:"response_translator"`
	ResponseBeforeTranslator          bool                         `json:"response_before_translator"`
	ResponseAfterTranslator           bool                         `json:"response_after_translator"`
	ResponseInterceptor               bool                         `json:"response_interceptor"`
	StreamChunkInterceptor            bool                         `json:"response_stream_interceptor"`
	WebSocketResponseObserver         bool                         `json:"websocket_response_observer"`
	ThinkingApplier                   bool                         `json:"thinking_applier"`
	UsagePlugin                       bool                         `json:"usage_plugin"`
	CommandLinePlugin                 bool                         `json:"command_line_plugin"`
	ManagementAPI                     bool                         `json:"management_api"`
	QuotaProvider                     bool                         `json:"quota_provider"`
}

type rpcAuthProviderEntry struct {
	Identifier string `json:"identifier"`
	Name       string `json:"name,omitempty"`
	Logo       string `json:"logo,omitempty"`
}

type rpcIdentifierResponse struct {
	Identifier          string                 `json:"identifier"`
	Identifiers         []string               `json:"identifiers,omitempty"`
	CredentialProviders []string               `json:"credential_providers,omitempty"`
	Entries             []rpcAuthProviderEntry `json:"entries,omitempty"`
}

type rpcExecutorStreamResponse struct {
	Headers http.Header                     `json:"headers,omitempty"`
	Chunks  []pluginapi.ExecutorStreamChunk `json:"chunks,omitempty"`
}

type rpcAuthLoginStartRequest struct {
	pluginapi.AuthLoginStartRequest
	HostCallbackID string `json:"host_callback_id,omitempty"`
}

type rpcAuthLoginPollRequest struct {
	pluginapi.AuthLoginPollRequest
	HostCallbackID string `json:"host_callback_id,omitempty"`
}

type rpcAuthRefreshRequest struct {
	pluginapi.AuthRefreshRequest
	HostCallbackID string `json:"host_callback_id,omitempty"`
}

type rpcAuthModelRequest struct {
	pluginapi.AuthModelRequest
	HostCallbackID string `json:"host_callback_id,omitempty"`
}

type rpcExecutorRequest struct {
	pluginapi.ExecutorRequest
	StreamID       string `json:"stream_id,omitempty"`
	HostCallbackID string `json:"host_callback_id,omitempty"`
}

type rpcExecutorHTTPRequest struct {
	pluginapi.ExecutorHTTPRequest
	HostCallbackID string `json:"host_callback_id,omitempty"`
}

type rpcRequestInterceptRequest struct {
	pluginapi.RequestInterceptRequest
	HostCallbackID string `json:"host_callback_id,omitempty"`
}

type rpcModelRouteRequest struct {
	pluginapi.ModelRouteRequest
	HostCallbackID string `json:"host_callback_id,omitempty"`
}

type rpcRequestCompletion struct {
	pluginapi.RequestCompletion
	HostCallbackID string `json:"host_callback_id,omitempty"`
}

type rpcResponseInterceptRequest struct {
	pluginapi.ResponseInterceptRequest
	HostCallbackID string `json:"host_callback_id,omitempty"`
}

type rpcStreamChunkInterceptRequest struct {
	pluginapi.StreamChunkInterceptRequest
	HostCallbackID string `json:"host_callback_id,omitempty"`
}

type rpcWebSocketResponseEvent struct {
	pluginapi.WebSocketResponseEvent
	HostCallbackID string `json:"host_callback_id,omitempty"`
}

type rpcThinkingApplyRequest struct {
	pluginapi.ThinkingApplyRequest
	HostCallbackID string `json:"host_callback_id,omitempty"`
}

type rpcManagementRequest struct {
	pluginapi.ManagementRequest
	HostCallbackID string `json:"host_callback_id,omitempty"`
}

type rpcManagementRegistrationResponse struct {
	Routes    []pluginapi.ManagementRoute `json:"routes,omitempty"`
	Resources []pluginapi.ResourceRoute   `json:"resources,omitempty"`
}

type rpcQuotaFetchRequest struct {
	pluginapi.QuotaFetchRequest
	HostCallbackID string `json:"host_callback_id,omitempty"`
}

type rpcQuotaResetRequest struct {
	pluginapi.QuotaResetRequest
	HostCallbackID string `json:"host_callback_id,omitempty"`
}

type rpcEmptyResponse struct{}

func frontendAuthProviderWantsOmitBody(caps pluginapi.Capabilities) bool {
	if caps.FrontendAuthProvider == nil {
		return false
	}
	if caps.FrontendAuthProviderOmitBody || caps.FrontendAuthOmitBody {
		return true
	}
	if opt, ok := caps.FrontendAuthProvider.(interface{ FrontendAuthProviderWantsOmitBody() bool }); ok && opt != nil {
		return opt.FrontendAuthProviderWantsOmitBody()
	}
	if opt, ok := caps.FrontendAuthProvider.(interface{ FrontendAuthWantsOmitBody() bool }); ok && opt != nil {
		return opt.FrontendAuthWantsOmitBody()
	}
	return false
}

func requestInterceptorWantsOmitBody(caps pluginapi.Capabilities, before bool) bool {
	if caps.RequestInterceptor == nil {
		return false
	}
	if before && caps.RequestInterceptorOmitBodyBefore {
		return true
	}
	if !before && caps.RequestInterceptorOmitBodyAfter {
		return true
	}
	if opt, ok := caps.RequestInterceptor.(interface{ RequestInterceptorWantsOmitBody(bool) bool }); ok && opt != nil {
		return opt.RequestInterceptorWantsOmitBody(before)
	}
	return false
}

func requestInterceptorWantsPatchBody(caps pluginapi.Capabilities, before bool) bool {
	if before {
		if caps.RequestBodyPatcherBefore != nil || caps.RequestInterceptorPatchBodyBefore {
			return true
		}
	} else {
		if caps.RequestBodyPatcherAfter != nil || caps.RequestInterceptorPatchBodyAfter {
			return true
		}
	}
	if opt, ok := caps.RequestInterceptor.(interface{ RequestInterceptorWantsPatchBody(bool) bool }); ok && opt != nil {
		return opt.RequestInterceptorWantsPatchBody(before)
	}
	return false
}

func schedulerWantsAcrossPriorities(caps pluginapi.Capabilities) bool {
	if caps.Scheduler == nil {
		return false
	}
	if caps.SchedulerAcrossPriorities {
		return true
	}
	if opt, ok := caps.Scheduler.(interface{ SchedulerWantsAcrossPriorities() bool }); ok && opt != nil {
		return opt.SchedulerWantsAcrossPriorities()
	}
	return false
}

func rpcCapabilitiesFromPlugin(plugin pluginapi.Plugin) rpcCapabilities {
	caps := plugin.Capabilities
	return rpcCapabilities{
		ModelRegistrar:                    caps.ModelRegistrar != nil,
		ModelProvider:                     caps.ModelProvider != nil,
		AuthProvider:                      hasAuthProviderCap(caps),
		FrontendAuthProvider:              caps.FrontendAuthProvider != nil,
		FrontendAuthProviderExclusive:     caps.FrontendAuthProvider != nil && caps.FrontendAuthProviderExclusive,
		FrontendAuthProviderOmitBody:      frontendAuthProviderWantsOmitBody(caps),
		FrontendAuthOmitBody:              frontendAuthProviderWantsOmitBody(caps),
		Scheduler:                         caps.Scheduler != nil,
		SchedulerAcrossPriorities:         schedulerWantsAcrossPriorities(caps),
		ModelRouter:                       caps.ModelRouter != nil,
		Executor:                          caps.Executor != nil,
		ExecutorModelScope:                normalizedExecutorModelScope(caps),
		ExecutorInputFormats:              append([]string(nil), caps.ExecutorInputFormats...),
		ExecutorOutputFormats:             append([]string(nil), caps.ExecutorOutputFormats...),
		RequestTranslator:                 caps.RequestTranslator != nil,
		RequestNormalizer:                 caps.RequestNormalizer != nil,
		RequestInterceptor:                caps.RequestInterceptor != nil,
		RequestInterceptorOmitBodyBefore:  requestInterceptorWantsOmitBody(caps, true),
		RequestInterceptorOmitBodyAfter:   requestInterceptorWantsOmitBody(caps, false),
		RequestBodyPatcherBefore:          requestInterceptorWantsPatchBody(caps, true),
		RequestBodyPatcherAfter:           requestInterceptorWantsPatchBody(caps, false),
		RequestInterceptorPatchBodyBefore: requestInterceptorWantsPatchBody(caps, true),
		RequestInterceptorPatchBodyAfter:  requestInterceptorWantsPatchBody(caps, false),
		RequestLifecyclePlugin:            caps.RequestLifecyclePlugin != nil,
		ResponseTranslator:                caps.ResponseTranslator != nil,
		ResponseBeforeTranslator:          caps.ResponseBeforeTranslator != nil,
		ResponseAfterTranslator:           caps.ResponseAfterTranslator != nil,
		ResponseInterceptor:               caps.ResponseInterceptor != nil,
		StreamChunkInterceptor:            caps.StreamChunkInterceptor != nil,
		WebSocketResponseObserver:         caps.WebSocketResponseObserver != nil,
		ThinkingApplier:                   caps.ThinkingApplier != nil,
		UsagePlugin:                       caps.UsagePlugin != nil,
		CommandLinePlugin:                 caps.CommandLinePlugin != nil,
		ManagementAPI:                     caps.ManagementAPI != nil,
		QuotaProvider:                     caps.QuotaProvider != nil,
	}
}

func marshalRPCResult(v any) ([]byte, error) {
	result, errMarshal := json.Marshal(v)
	if errMarshal != nil {
		return nil, errMarshal
	}
	return marshalRPCEnvelope(json.RawMessage(result))
}