usecase

package
v0.260813.2 Latest Latest
Warning

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

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

Documentation

Overview

Package usecase holds application logic shared across every caller surface (CLI, TUI, Web handler, future GUI) for a given domain — Rule, Provider, Agent, Profile. Each domain is one concrete struct with Request-in/Result-out methods and typed errors; no user I/O happens in this package.

See .design/usecase-layer.md for the full contract and rationale.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AgentUseCase

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

AgentUseCase implements Agent Apply/Show/Restore request assembly and routing-rule resolution. It holds a *serverconfig.Config directly (not an AppManager — see .design/usecase-layer.md, "Construction").

Apply and Restore are thin wrappers over agent.AgentApply (internal/agent/rule_bridge.go), which already satisfies the use-case contract on its own (Request-in/Result-out, no I/O) — this package does not reimplement file-writing logic that already lives there. What this package owns is the piece that was duplicated per caller: routing-key lookup and pre-apply rule resolution.

func NewAgentUseCase

func NewAgentUseCase(cfg *serverconfig.Config, host string) *AgentUseCase

NewAgentUseCase constructs an AgentUseCase over the given config. host is passed through to agent.NewAgentApply — see its docs (pure hostname, port is handled internally).

func (*AgentUseCase) Apply

Apply configures an agent (writes its config files, optionally syncing a routing rule). Thin wrapper over agent.AgentApply.ApplyAgent, which already has no I/O of its own.

func (*AgentUseCase) ResolveRouting

func (uc *AgentUseCase) ResolveRouting(req ResolveRoutingRequest) (ResolveRoutingResult, error)

ResolveRouting looks up the existing routing rule for an agent type (mirrors the rule-lookup half of resolveAgentConfigFromRules in internal/command/agent_command.go, without any prompting or warning output — those stay in the caller).

func (*AgentUseCase) Restore

Restore restores an agent's config files from their most recent backup. Thin wrapper over agent.AgentApply.RestoreAgent, which already has no I/O of its own.

func (*AgentUseCase) RoutingKey

func (uc *AgentUseCase) RoutingKey(agentType agent.AgentType) (requestModel string, scenario typ.RuleScenario, err error)

RoutingKey returns the canonical (RequestModel, Scenario) pair that identifies the routing rule for an agent type. This is the single source of truth for that mapping — it replaces two independent, hand-copied tables that had already drifted:

  • internal/command/agent_command.go's agentRoutingKey (errored on an unsupported type)
  • internal/command/tui/agent_mode.go's agentRequestModel (silently fell back to string(t) instead of erroring)

This version errors on an unsupported type (the CLI's stricter behavior), since a silent fallback produces a routing key that matches no real rule and fails confusingly downstream instead of failing here with a clear cause.

func (*AgentUseCase) Show

func (uc *AgentUseCase) Show(req ShowRequest) (ShowResult, error)

Show assembles agent info plus its current routing rule status.

type AvailableModelsRequest

type AvailableModelsRequest struct {
	UUID string `json:"uuid"`
}

AvailableModelsRequest identifies the provider whose model list should be resolved, preferring cache.

type AvailableModelsResult

type AvailableModelsResult struct {
	Models []string `json:"models"`
	Source string   `json:"source"`
}

AvailableModelsResult is the output of AvailableModels.

type CreateProviderRequest

type CreateProviderRequest struct {
	Name     string            `json:"name"`
	APIBase  string            `json:"api_base"`
	Token    string            `json:"token"`
	APIStyle protocol.APIStyle `json:"api_style"`
	ProxyURL string            `json:"proxy_url,omitempty"`
}

CreateProviderRequest is the input to Add.

APIStyle is required — the CLI's name/URL keyword inference ("anthropic" in the name → APIStyleAnthropic, etc.) is a CLI-side interactive UX convenience, not business logic, and stays in internal/command per the no-inference decision recorded in .design/usecase-layer.md.

ProxyURL is optional and included even though the CLI doesn't currently expose it — this DTO is the union of what any caller can set, not the intersection of what today's CLI happens to ask for; TUI already sets it via a separate UpdateProviderByUUID call today, which Add now makes unnecessary.

type CreateProviderResult

type CreateProviderResult struct {
	Provider *typ.Provider `json:"provider"`
}

CreateProviderResult is the output of Add.

type CreateRuleRequest

type CreateRuleRequest struct {
	Scenario     typ.RuleScenario       `json:"scenario"`
	RequestModel string                 `json:"request_model"`
	Services     []*loadbalance.Service `json:"services"`
}

CreateRuleRequest is the input to Create. Service describes the single initial service on the rule — richer multi-service rules are assembled by the caller and passed to Create via Services directly if more than one is needed (mirrors config_rule.go's "add/update pick a single service" scope, but Create accepts the full slice since the DTO has no reason to artificially narrow it to one).

type CreateRuleResult

type CreateRuleResult struct {
	Rule typ.Rule `json:"rule"`
}

CreateRuleResult is the output of Create.

type DeleteProviderRequest

type DeleteProviderRequest struct {
	UUID string `json:"uuid"`
}

DeleteProviderRequest identifies the provider to delete.

type DeleteRuleRequest

type DeleteRuleRequest struct {
	UUID string `json:"uuid"`
}

DeleteRuleRequest identifies the rule to delete.

type ErrProfileNotFound

type ErrProfileNotFound struct {
	Scenario   typ.RuleScenario
	Identifier string
}

ErrProfileNotFound means no profile matched the supplied ID or name within the base scenario.

func (ErrProfileNotFound) Error

func (e ErrProfileNotFound) Error() string

type ErrProviderNotFound

type ErrProviderNotFound struct {
	UUID string
}

ErrProviderNotFound means no provider exists for the given UUID.

func (ErrProviderNotFound) Error

func (e ErrProviderNotFound) Error() string

type ErrRuleExists

type ErrRuleExists struct {
	RequestModel string
	Scenario     typ.RuleScenario
	UUID         string
}

ErrRuleExists means a rule for the same (RequestModel, Scenario) pair already exists. Carries the UUID of the existing rule so the caller can point the user at it (CLI: "use `config rule update`"; TUI: "use Edit"; a future HTTP handler: 409 with UUID in the body) without this package rendering any of that prose itself.

func (ErrRuleExists) Error

func (e ErrRuleExists) Error() string

type ErrRuleNotFound

type ErrRuleNotFound struct {
	UUID string
}

ErrRuleNotFound means no rule exists for the given UUID.

func (ErrRuleNotFound) Error

func (e ErrRuleNotFound) Error() string

type ErrUnsupportedAgentType

type ErrUnsupportedAgentType struct {
	AgentType agent.AgentType
}

ErrUnsupportedAgentType means RoutingKey was asked about an agent type with no registered routing key.

func (ErrUnsupportedAgentType) Error

func (e ErrUnsupportedAgentType) Error() string

type GetProfileRequest

type GetProfileRequest struct {
	Scenario   typ.RuleScenario `json:"scenario"`
	Identifier string           `json:"identifier"`
}

GetProfileRequest identifies a profile by ID or exact name.

type GetProfileResult

type GetProfileResult struct {
	Profile  typ.ProfileMeta  `json:"profile"`
	Scenario typ.RuleScenario `json:"scenario"`
	Rules    []ProfileRule    `json:"rules"`
}

GetProfileResult contains resolved profile identity plus its concrete profiled scenario and routing rules.

type GetProviderRequest

type GetProviderRequest struct {
	UUID string `json:"uuid"`
}

GetProviderRequest identifies a provider by UUID.

type GetProviderResult

type GetProviderResult struct {
	Provider *typ.Provider `json:"provider"`
}

GetProviderResult is the output of Get.

type GetRuleRequest

type GetRuleRequest struct {
	UUID string `json:"uuid"`
}

GetRuleRequest identifies a rule by UUID.

type GetRuleResult

type GetRuleResult struct {
	Rule typ.Rule `json:"rule"`
}

GetRuleResult is the output of Get.

type ListProfilesRequest

type ListProfilesRequest struct {
	Scenario typ.RuleScenario `json:"scenario"`
}

ListProfilesRequest identifies the base scenario whose profiles should be returned.

type ListProfilesResult

type ListProfilesResult struct {
	Profiles []typ.ProfileMeta `json:"profiles"`
}

ListProfilesResult is the output of List.

type ListProvidersResult

type ListProvidersResult struct {
	Providers []*typ.Provider `json:"providers"`
}

ListProvidersResult is the output of List.

type ListRulesResult

type ListRulesResult struct {
	Rules []typ.Rule `json:"rules"`
}

ListRulesResult is the output of List.

type ProfileRule

type ProfileRule struct {
	RequestModel string `json:"request_model"`
	ProviderUUID string `json:"provider_uuid,omitempty"`
	ProviderName string `json:"provider_name,omitempty"`
	Model        string `json:"model,omitempty"`
	Configured   bool   `json:"configured"`
	Active       bool   `json:"active"`
}

ProfileRule describes the display-relevant portion of one rule belonging to a profile. ProviderName falls back to ProviderUUID when the referenced provider no longer exists.

type ProfileUseCase

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

ProfileUseCase assembles profile metadata and routing details without imposing a CLI, TUI, or HTTP presentation. Profiles are an intentional product concept; this use case makes that concept reusable rather than treating the top-level profile command as an alias for another command.

func NewProfileUseCase

func NewProfileUseCase(cfg *serverconfig.Config) *ProfileUseCase

NewProfileUseCase constructs a ProfileUseCase over the given config.

func (*ProfileUseCase) Get

Get resolves a profile name or ID and assembles its routing details.

func (*ProfileUseCase) List

List returns a detached copy of the profiles for a base scenario.

func (*ProfileUseCase) Resolve

Resolve converts a profile name or ID into canonical metadata and its profiled scenario.

type ProviderUseCase

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

ProviderUseCase implements Provider CRUD plus model-list resolution. It holds a *serverconfig.Config directly (not an AppManager — see .design/usecase-layer.md, "Construction").

func NewProviderUseCase

func NewProviderUseCase(cfg *serverconfig.Config) *ProviderUseCase

NewProviderUseCase constructs a ProviderUseCase over the given config.

func (*ProviderUseCase) Add

Add creates a new provider. Provider names are not unique — only UUIDs are — so this never rejects on name collision; a fresh UUID is minted every call.

func (*ProviderUseCase) AvailableModels

AvailableModels resolves the provider's model list through the full cache → vmodel → API → template fallback chain (Config.ResolveProviderModels(forceRefresh=false, ...)). This deliberately replaces the TUI's own hand-written cache → template two-level shortcut (internal/command/tui/rule_mode.go's availableModels), which missed the vmodel level and so could not see virtual providers — see .design/usecase-layer.md, "Known behavioral differences not yet resolved".

func (*ProviderUseCase) Delete

Delete removes a provider by UUID. Confirmation (if any) and the "rules referencing it will be left dangling" warning are caller concerns.

func (*ProviderUseCase) Get

Get returns a provider by UUID, or ErrProviderNotFound.

func (*ProviderUseCase) List

List returns every configured provider.

func (*ProviderUseCase) RefreshModels

RefreshModels forces a re-resolution of the provider's model list, bypassing the cache (ResolveProviderModels(forceRefresh=true, ...)).

func (*ProviderUseCase) Update

Update replaces an existing provider's fields by UUID. Returns ErrProviderNotFound if the UUID doesn't match any provider.

type RefreshModelsRequest

type RefreshModelsRequest struct {
	UUID string `json:"uuid"`
}

RefreshModelsRequest identifies the provider whose model list should be re-fetched from its upstream API.

type RefreshModelsResult

type RefreshModelsResult struct {
	Models []string `json:"models"`
}

RefreshModelsResult is the output of RefreshModels.

type ResolveProfileResult

type ResolveProfileResult struct {
	Profile  typ.ProfileMeta  `json:"profile"`
	Scenario typ.RuleScenario `json:"scenario"`
}

ResolveProfileResult contains the canonical profile identity for a supplied name or ID. Launch callers use this result without paying to assemble rule presentation data.

type ResolveRoutingRequest

type ResolveRoutingRequest struct {
	AgentType agent.AgentType `json:"agent_type"`
}

ResolveRoutingRequest identifies the agent type to resolve routing for.

type ResolveRoutingResult

type ResolveRoutingResult struct {
	RequestModel  string           `json:"request_model"`
	Scenario      typ.RuleScenario `json:"scenario"`
	RuleFound     bool             `json:"rule_found"`
	RuleActive    bool             `json:"rule_active"`
	ResponseModel string           `json:"response_model,omitempty"`
	ServiceUsable bool             `json:"service_usable"`
	ProviderUUID  string           `json:"provider_uuid,omitempty"`
	ProviderName  string           `json:"provider_name,omitempty"`
	Model         string           `json:"model,omitempty"`
}

ResolveRoutingResult reports what routing rule (if any) already exists for the agent type, and whether its configured provider is still valid. RuleFound false means no rule exists yet for this agent's routing key; ServiceUsable false (with RuleFound true) means the rule exists but its primary service has no usable provider — callers decide what to do about either case (prompt, warn, proceed with config-files-only), this method only reports the facts.

type RuleUseCase

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

RuleUseCase implements Rule CRUD. It holds a *serverconfig.Config directly (not an AppManager — see .design/usecase-layer.md, "Construction").

func NewRuleUseCase

func NewRuleUseCase(cfg *serverconfig.Config) *RuleUseCase

NewRuleUseCase constructs a RuleUseCase over the given config.

func (*RuleUseCase) Create

Create adds a new rule. Returns ErrRuleExists if a rule for the same (RequestModel, Scenario) pair already exists — mirrors the pre-check CLI callers do today via GetRuleByRequestModelAndScenario before calling AddRule, made into part of the contract instead of a caller-side convention every surface has to remember to repeat.

func (*RuleUseCase) Delete

func (uc *RuleUseCase) Delete(req DeleteRuleRequest) error

Delete removes a rule by UUID. Returns ErrRuleNotFound if the UUID doesn't match any rule — confirmation (if any) is the caller's concern.

func (*RuleUseCase) Get

Get returns a rule by UUID, or ErrRuleNotFound.

func (*RuleUseCase) List

func (uc *RuleUseCase) List() ListRulesResult

List returns every configured rule.

func (*RuleUseCase) UpdateService

func (uc *RuleUseCase) UpdateService(req UpdateServiceRequest) (UpdateServiceResult, error)

UpdateService replaces the Services on an existing rule. Returns ErrRuleNotFound if the UUID doesn't match any rule.

type ShowRequest

type ShowRequest struct {
	AgentType agent.AgentType `json:"agent_type"`
}

ShowRequest identifies the agent type to show.

type ShowResult

type ShowResult struct {
	Info    agent.AgentInfo      `json:"info"`
	Routing ResolveRoutingResult `json:"routing"`
}

ShowResult is the assembled data for the Show operation — replaces the data-gathering half of showAgentConfig in internal/command/agent_command.go. Rendering (fmt.Printf calls) stays in the caller.

type UpdateProviderRequest

type UpdateProviderRequest struct {
	UUID     string            `json:"uuid"`
	Name     string            `json:"name"`
	APIBase  string            `json:"api_base"`
	Token    string            `json:"token"`
	APIStyle protocol.APIStyle `json:"api_style"`
	ProxyURL string            `json:"proxy_url,omitempty"`
}

UpdateProviderRequest replaces a provider's fields by UUID. There is no partial-update path today in either CLI or TUI.

Token is the one exception to wholesale replace: an empty Token is ignored and the existing token is preserved. This matches the CLI's interactive "press Enter to keep current" behavior (the CLI reloads the stored token before calling Update when the user leaves the field blank). Clearing a token is intentionally unsupported.

type UpdateProviderResult

type UpdateProviderResult struct {
	Provider *typ.Provider `json:"provider"`
}

UpdateProviderResult is the output of Update.

type UpdateServiceRequest

type UpdateServiceRequest struct {
	UUID     string                 `json:"uuid"`
	Services []*loadbalance.Service `json:"services"`
}

UpdateServiceRequest re-points an existing rule at a different service. Everything else on the rule (request model, scenario, flags, tactic) stays as-is — mirrors runRuleUpdateService's scope in config_rule.go.

type UpdateServiceResult

type UpdateServiceResult struct {
	Rule typ.Rule `json:"rule"`
}

UpdateServiceResult is the output of UpdateService.

Jump to

Keyboard shortcuts

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