config: [serve] section for the OpenAI-compatible front door
listen (default :8090, own port so it coexists with [events]), vkey_ref
(the bearer key OpenWebUI connections present; refs only, resolved at
startup), and an optional enabled_models subset of the catalog. Entries
must name a real servable model (mopac-<class> from [models.classes]) so
a typo fails at config load, not mid-request. Example file extended;
once/loop configs without [serve] stay valid.
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
This commit is contained in:
@@ -18,6 +18,7 @@ type Config struct {
|
||||
Bash BashConfig
|
||||
Demo DemoConfig
|
||||
Events EventsConfig
|
||||
Serve ServeConfig
|
||||
KeyProxy KeyProxyConfig
|
||||
Gitea GiteaConfig
|
||||
}
|
||||
@@ -76,6 +77,14 @@ type DemoConfig struct {
|
||||
Class string
|
||||
}
|
||||
|
||||
// ServeConfig is the `harness serve` OpenAI-compatible front door (the
|
||||
// OpenWebUI connection). Own port — coexists with [events].
|
||||
type ServeConfig struct {
|
||||
Listen string // bind address (default ":8090"; publish via docker -p)
|
||||
VKeyRef string // bearer vkey ref; the key OWUI connections present
|
||||
EnabledModels []string // optional subset of the catalog (mopac-<class>); empty = all classes
|
||||
}
|
||||
|
||||
// KeyProxyConfig is the ukrrs/mopac-keyproxy resolve hop: mpk: key refs
|
||||
// POST here. All hosts/paths live in this config, never in code.
|
||||
type KeyProxyConfig struct {
|
||||
@@ -146,6 +155,7 @@ func Default() *Config {
|
||||
SecretHeader: "X-Discourse-Webhook-Secret",
|
||||
},
|
||||
},
|
||||
Serve: ServeConfig{Listen: ":8090"},
|
||||
KeyProxy: KeyProxyConfig{CacheTTLSecs: 60},
|
||||
Demo: DemoConfig{
|
||||
ID: "demo-1",
|
||||
@@ -322,6 +332,17 @@ func (c *Config) apply(doc TOMLDoc) error {
|
||||
applyEventSource(&c.Events.Redmine, doc.Table("events", "redmine"))
|
||||
applyEventSource(&c.Events.Discourse, doc.Table("events", "discourse"))
|
||||
applyEventSource(&c.Events.Gitea, doc.Table("events", "gitea"))
|
||||
|
||||
sv := doc.Table("serve")
|
||||
if v, ok := sv.String("listen"); ok {
|
||||
c.Serve.Listen = v
|
||||
}
|
||||
if v, ok := sv.String("vkey_ref"); ok {
|
||||
c.Serve.VKeyRef = v
|
||||
}
|
||||
if v, ok := sv.StringList("enabled_models"); ok {
|
||||
c.Serve.EnabledModels = v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -410,6 +431,24 @@ func (c *Config) Validate() error {
|
||||
return fmt.Errorf("[events]: listen and state_dir must not be empty")
|
||||
}
|
||||
|
||||
// Serve is optional (`once`/`loop` configs need none); a vkey that IS
|
||||
// set must be well-formed, and enabled_models entries must name real
|
||||
// catalog models (mopac-<class>) so the front door fails at startup.
|
||||
if c.Serve.VKeyRef != "" {
|
||||
if err := CheckKeyRef(c.Serve.VKeyRef); err != nil {
|
||||
return fmt.Errorf("[serve]: %w", err)
|
||||
}
|
||||
}
|
||||
for _, m := range c.Serve.EnabledModels {
|
||||
class := strings.TrimPrefix(m, "mopac-")
|
||||
if !strings.HasPrefix(m, "mopac-") || class == "" || c.Models.Classes[class] == "" {
|
||||
return fmt.Errorf("[serve]: enabled_models entry %q is not servable (must be mopac-<class> from [models.classes])", m)
|
||||
}
|
||||
}
|
||||
if c.Serve.Listen == "" {
|
||||
return fmt.Errorf("[serve]: listen must not be empty")
|
||||
}
|
||||
|
||||
if c.Loop.PollIntervalSecs < 1 {
|
||||
return fmt.Errorf("[loop]: poll_interval_secs must be >= 1")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user