virtualserver

package
v0.260806.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 6, 2026 License: MPL-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package virtualserver provides the HTTP handler for virtual model endpoints. It serves OpenAI Chat and Anthropic Messages API formats backed by separate per-provider virtual model registries.

This is the production HTTP surface for internal/virtualmodel: the parent server mounts it under /virtual/v1/* so end users can reach the synthetic provider for onboarding, demos, and dry-runs without configuring a real upstream provider. Test consumers do not depend on this package; they use the registry primitives in internal/virtualmodel directly.

Index

Constants

View Source
const (
	BuiltinAnthropicUUID = "vmodel-builtin-anthropic"
	BuiltinOpenAIUUID    = "vmodel-builtin-openai"

	BuiltinAnthropicName = "Virtual Models (Anthropic)"
	BuiltinOpenAIName    = "Virtual Models (OpenAI)"
)

Sentinel UUIDs and names for builtin virtual-model providers. Stable across restarts so seeding is idempotent.

Variables

This section is empty.

Functions

This section is empty.

Types

type AnthropicContent

type AnthropicContent struct {
	Type  string          `json:"type"`
	Text  string          `json:"text,omitempty"`
	ID    string          `json:"id,omitempty"`
	Name  string          `json:"name,omitempty"`
	Input json.RawMessage `json:"input,omitempty"`
}

AnthropicContent is a content block in an Anthropic response.

type AnthropicDelta

type AnthropicDelta struct {
	Type       string `json:"type,omitempty"`
	Text       string `json:"text,omitempty"`
	Thinking   string `json:"thinking,omitempty"`
	StopReason string `json:"stop_reason,omitempty"`
}

AnthropicDelta is a delta in an Anthropic streaming response.

type AnthropicMessage

type AnthropicMessage = anthropic.BetaMessageParam

Request types aliased from protocol / Anthropic SDK

type AnthropicMessageRequest

type AnthropicMessageRequest = protocol.AnthropicBetaMessagesRequest

Request types aliased from protocol / Anthropic SDK

type AnthropicMessageResponse

type AnthropicMessageResponse struct {
	ID         string             `json:"id"`
	Type       string             `json:"type"`
	Role       string             `json:"role"`
	Model      string             `json:"model"`
	Content    []AnthropicContent `json:"content"`
	StopReason string             `json:"stop_reason"`
	Usage      AnthropicUsage     `json:"usage"`
}

AnthropicMessageResponse is an Anthropic-compatible message response.

type AnthropicModelsResponse

type AnthropicModelsResponse struct {
	Data    []vmodel.Model `json:"data"`
	FirstID string         `json:"first_id"`
	LastID  string         `json:"last_id"`
	HasMore bool           `json:"has_more"`
}

AnthropicModelsResponse is Anthropic's native /v1/models envelope. It differs from OpenAI's shape (no "object" field; cursor fields instead). We always emit has_more=false because vmodel returns the full registry in one shot.

type AnthropicStreamEvent

type AnthropicStreamEvent struct {
	Type    string                    `json:"type"`
	Message *AnthropicMessageResponse `json:"message,omitempty"`
	Index   int                       `json:"index,omitempty"`
	Delta   *AnthropicDelta           `json:"delta,omitempty"`
	Usage   *AnthropicUsage           `json:"usage,omitempty"`
}

AnthropicStreamEvent is a streaming event in Anthropic format.

type AnthropicTool

type AnthropicTool = anthropic.BetaToolParam

Request types aliased from protocol / Anthropic SDK

type AnthropicUsage

type AnthropicUsage struct {
	InputTokens  int64 `json:"input_tokens"`
	OutputTokens int64 `json:"output_tokens"`
}

AnthropicUsage holds token usage in Anthropic format.

type ChatCompletionRequest

type ChatCompletionRequest = protocol.OpenAIChatCompletionRequest

ChatCompletionRequest is an OpenAI-compatible chat completion request.

type ChatCompletionResponse

type ChatCompletionResponse = openai.ChatCompletion

Response types aliased from OpenAI SDK

type ChatCompletionStreamResponse

type ChatCompletionStreamResponse = openai.ChatCompletionChunk

Response types aliased from OpenAI SDK

type Choice

Response types aliased from OpenAI SDK

type Delta

Response types aliased from OpenAI SDK

type FunctionCall

Response types aliased from OpenAI SDK

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

Handler handles HTTP requests for virtual model endpoints.

func NewHandler

func NewHandler(anthropicReg *anthropicvm.Registry, openaiReg *openaivm.Registry) *Handler

NewHandler creates a new Handler backed by the given per-provider registries.

func (*Handler) ChatCompletions

func (h *Handler) ChatCompletions(c *gin.Context)

ChatCompletions handles POST /virtual/v1/chat/completions.

func (*Handler) ListAnthropicModels

func (h *Handler) ListAnthropicModels(c *gin.Context)

ListAnthropicModels handles GET /virtual/anthropic/v1/models — returns only the Anthropic-protocol registry in Anthropic's native envelope shape (data + first_id/last_id/has_more, no "object" field).

func (*Handler) ListModels deprecated

func (h *Handler) ListModels(c *gin.Context)

ListModels handles GET /virtual/v1/models — returns the union of both registries.

Deprecated: prefer ListOpenAIModels / ListAnthropicModels for the protocol-split entrypoints. Retained for the legacy mixed-protocol route and for test fixtures that want both registries on one endpoint.

func (*Handler) ListOpenAIModels

func (h *Handler) ListOpenAIModels(c *gin.Context)

ListOpenAIModels handles GET /virtual/openai/v1/models — returns only the OpenAI-protocol registry so clients pointed at the OpenAI base URL don't see Anthropic-only model IDs they cannot dispatch.

func (*Handler) Messages

func (h *Handler) Messages(c *gin.Context)

Messages handles POST /virtual/v1/messages (Anthropic format).

Accepts both Anthropic v1 and beta wire formats. The query parameter "beta=true" mirrors the real Anthropic API gating used in internal/server/anthropic.go. Internally everything is canonicalized to the beta superset struct so vmodel implementations only deal with one request shape.

func (*Handler) Responses added in v0.260716.1

func (h *Handler) Responses(c *gin.Context)

Responses handles POST /virtual/openai/v1/responses (OpenAI Responses API).

type Message

type Message = openai.ChatCompletionMessage

Response types aliased from OpenAI SDK

type OpenAIModelsResponse

type OpenAIModelsResponse struct {
	Object string         `json:"object"`
	Data   []vmodel.Model `json:"data"`
}

OpenAIModelsResponse is the OpenAI models list response format.

type ProviderSaver

type ProviderSaver interface {
	GetByUUID(uuid string) (*typ.Provider, error)
	Save(provider *typ.Provider) error
}

ProviderSaver is the minimal ProviderStore surface needed for seeding. Using an interface lets callers (server.go) pass the live *db.ProviderStore without virtualserver depending on the db package.

type ResponsesRequest added in v0.260716.1

type ResponsesRequest struct {
	Model  string          `json:"model"`
	Stream bool            `json:"stream"`
	Input  json.RawMessage `json:"input"`
}

ResponsesRequest is the subset of the OpenAI Responses API request the virtual server needs: model routing, the stream flag, and the input text (echo models and token estimation read it; static mocks ignore it).

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service manages the virtual model service.

Each protocol has its own registry. A model registered in the Anthropic registry is callable only via /messages; a model in the OpenAI registry is callable only via /chat/completions. ID collisions across the two registries are intentional and legal — the registry IS the protocol context.

func NewService

func NewService() *Service

NewService creates a fully initialized Service with default models registered in both protocol registries.

func (*Service) BuildBuiltinProviders

func (s *Service) BuildBuiltinProviders() []*typ.Provider

BuildBuiltinProviders returns the list of builtin virtual-model providers that should be present in the ProviderStore. The list is built from the service's currently registered models so the seed always reflects the in-process registries.

func (*Service) EnsureBuiltinProviders

func (s *Service) EnsureBuiltinProviders(store ProviderSaver) error

EnsureBuiltinProviders inserts or refreshes the builtin virtual-model providers in the given store. It is idempotent and safe to call on every startup:

  • If a builtin provider is missing it is created (Enabled=true).
  • If a builtin provider already exists its Enabled flag is preserved (users may have disabled it) while the model list is refreshed to match what is currently registered.

func (*Service) GetAnthropicRegistry

func (s *Service) GetAnthropicRegistry() *anthropicvm.Registry

GetAnthropicRegistry returns the Anthropic-protocol model registry.

func (*Service) GetHandler

func (s *Service) GetHandler() *Handler

GetHandler returns the HTTP handler.

func (*Service) GetOpenAIRegistry

func (s *Service) GetOpenAIRegistry() *openaivm.Registry

GetOpenAIRegistry returns the OpenAI Chat-protocol model registry.

func (*Service) SetupAnthropicRoutes

func (s *Service) SetupAnthropicRoutes(group *gin.RouterGroup)

SetupAnthropicRoutes mounts the Anthropic-only entrypoints on the given group. Typical wiring:

anthropic := engine.Group("/virtual/anthropic")
svc.SetupAnthropicRoutes(anthropic)

This produces /virtual/anthropic/v1/models and /virtual/anthropic/v1/messages — drop-in compatible with the Anthropic SDK base URL convention.

func (*Service) SetupOpenAIRoutes

func (s *Service) SetupOpenAIRoutes(group *gin.RouterGroup)

SetupOpenAIRoutes mounts the OpenAI-only entrypoints on the given group. Typical wiring:

openai := engine.Group("/virtual/openai")
svc.SetupOpenAIRoutes(openai)

This produces /virtual/openai/v1/models and /virtual/openai/v1/chat/completions — drop-in compatible with the OpenAI SDK base URL convention.

func (*Service) SetupRoutes deprecated

func (s *Service) SetupRoutes(group *gin.RouterGroup)

SetupRoutes mounts virtual-model endpoints on a single mixed-protocol group at <group>/{models,chat/completions,messages}.

Deprecated: prefer SetupOpenAIRoutes + SetupAnthropicRoutes so OpenAI and Anthropic clients each see only their own model IDs. Retained for test fixtures.

type StreamChoice

type StreamChoice = openai.ChatCompletionChunkChoice

Response types aliased from OpenAI SDK

type ToolCall

Response types aliased from OpenAI SDK

type Usage

type Usage = openai.CompletionUsage

Response types aliased from OpenAI SDK

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL