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 ¶
- type AgentUseCase
- func (uc *AgentUseCase) Apply(req *agent.ApplyAgentRequest) (*agent.ApplyAgentResult, error)
- func (uc *AgentUseCase) ResolveRouting(req ResolveRoutingRequest) (ResolveRoutingResult, error)
- func (uc *AgentUseCase) Restore(req *agent.RestoreAgentRequest) (*agent.RestoreAgentResult, error)
- func (uc *AgentUseCase) RoutingKey(agentType agent.AgentType) (requestModel string, scenario typ.RuleScenario, err error)
- func (uc *AgentUseCase) Show(req ShowRequest) (ShowResult, error)
- type AvailableModelsRequest
- type AvailableModelsResult
- type CreateProviderRequest
- type CreateProviderResult
- type CreateRuleRequest
- type CreateRuleResult
- type DeleteProviderRequest
- type DeleteRuleRequest
- type ErrProfileNotFound
- type ErrProviderNotFound
- type ErrRuleExists
- type ErrRuleNotFound
- type ErrUnsupportedAgentType
- type GetProfileRequest
- type GetProfileResult
- type GetProviderRequest
- type GetProviderResult
- type GetRuleRequest
- type GetRuleResult
- type ListProfilesRequest
- type ListProfilesResult
- type ListProvidersResult
- type ListRulesResult
- type ProfileRule
- type ProfileUseCase
- type ProviderUseCase
- func (uc *ProviderUseCase) Add(req CreateProviderRequest) (CreateProviderResult, error)
- func (uc *ProviderUseCase) AvailableModels(req AvailableModelsRequest) (AvailableModelsResult, error)
- func (uc *ProviderUseCase) Delete(req DeleteProviderRequest) error
- func (uc *ProviderUseCase) Get(req GetProviderRequest) (GetProviderResult, error)
- func (uc *ProviderUseCase) List() ListProvidersResult
- func (uc *ProviderUseCase) RefreshModels(req RefreshModelsRequest) (RefreshModelsResult, error)
- func (uc *ProviderUseCase) Update(req UpdateProviderRequest) (UpdateProviderResult, error)
- type RefreshModelsRequest
- type RefreshModelsResult
- type ResolveProfileResult
- type ResolveRoutingRequest
- type ResolveRoutingResult
- type RuleUseCase
- func (uc *RuleUseCase) Create(req CreateRuleRequest) (CreateRuleResult, error)
- func (uc *RuleUseCase) Delete(req DeleteRuleRequest) error
- func (uc *RuleUseCase) Get(req GetRuleRequest) (GetRuleResult, error)
- func (uc *RuleUseCase) List() ListRulesResult
- func (uc *RuleUseCase) UpdateService(req UpdateServiceRequest) (UpdateServiceResult, error)
- type ShowRequest
- type ShowResult
- type UpdateProviderRequest
- type UpdateProviderResult
- type UpdateServiceRequest
- type UpdateServiceResult
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 ¶
func (uc *AgentUseCase) Apply(req *agent.ApplyAgentRequest) (*agent.ApplyAgentResult, error)
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 ¶
func (uc *AgentUseCase) Restore(req *agent.RestoreAgentRequest) (*agent.RestoreAgentResult, error)
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
GetProviderResult is the output of Get.
type GetRuleRequest ¶
type GetRuleRequest struct {
UUID string `json:"uuid"`
}
GetRuleRequest identifies a rule by UUID.
type GetRuleResult ¶
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 ¶
ListProvidersResult is the output of List.
type ListRulesResult ¶
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 ¶
func (uc *ProfileUseCase) Get(req GetProfileRequest) (GetProfileResult, error)
Get resolves a profile name or ID and assembles its routing details.
func (*ProfileUseCase) List ¶
func (uc *ProfileUseCase) List(req ListProfilesRequest) ListProfilesResult
List returns a detached copy of the profiles for a base scenario.
func (*ProfileUseCase) Resolve ¶
func (uc *ProfileUseCase) Resolve(req GetProfileRequest) (ResolveProfileResult, error)
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 ¶
func (uc *ProviderUseCase) Add(req CreateProviderRequest) (CreateProviderResult, error)
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 ¶
func (uc *ProviderUseCase) AvailableModels(req AvailableModelsRequest) (AvailableModelsResult, error)
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 ¶
func (uc *ProviderUseCase) Delete(req DeleteProviderRequest) error
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 ¶
func (uc *ProviderUseCase) Get(req GetProviderRequest) (GetProviderResult, error)
Get returns a provider by UUID, or ErrProviderNotFound.
func (*ProviderUseCase) List ¶
func (uc *ProviderUseCase) List() ListProvidersResult
List returns every configured provider.
func (*ProviderUseCase) RefreshModels ¶
func (uc *ProviderUseCase) RefreshModels(req RefreshModelsRequest) (RefreshModelsResult, error)
RefreshModels forces a re-resolution of the provider's model list, bypassing the cache (ResolveProviderModels(forceRefresh=true, ...)).
func (*ProviderUseCase) Update ¶
func (uc *ProviderUseCase) Update(req UpdateProviderRequest) (UpdateProviderResult, error)
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 ¶
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 ¶
func (uc *RuleUseCase) Create(req CreateRuleRequest) (CreateRuleResult, error)
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 ¶
func (uc *RuleUseCase) Get(req GetRuleRequest) (GetRuleResult, error)
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 ¶
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 ¶
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 ¶
UpdateServiceResult is the output of UpdateService.