mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-09-21 17:38:00 +00:00
feat(auto): quota-aware AUTO slot scheduling (model tiers, hour/week/month resets) + key scope periods; fix key/slot create/delete UX
This commit is contained in:
@ -3,6 +3,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
@ -120,18 +121,55 @@ func (c *Config) ApplyDefaults() error {
|
||||
|
||||
// RuntimeConfig is the persisted web-UI editable slice (sources added/edited).
|
||||
type RuntimeConfig struct {
|
||||
Sources []Source `json:"sources"`
|
||||
Keys []GWKey `json:"keys,omitempty"`
|
||||
Sources []Source `json:"sources"`
|
||||
Keys []GWKey `json:"keys,omitempty"`
|
||||
Auto []ModelScope `json:"auto,omitempty"`
|
||||
}
|
||||
|
||||
// GWKey is a gateway API key persisted in the runtime store. Role is "admin"
|
||||
// (full management) or "user" (sees only its own key); Models is the allowed
|
||||
// model whitelist (nil/empty = all models).
|
||||
// model scope with per-model token quota (0 = unlimited).
|
||||
type GWKey struct {
|
||||
Key string `json:"key"`
|
||||
Role string `json:"role"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Models []string `json:"models,omitempty"`
|
||||
Note string `json:"note,omitempty"`
|
||||
CreatedAt int64 `json:"created_at,omitempty"`
|
||||
Key string `json:"key"`
|
||||
Role string `json:"role"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Models []ModelScope `json:"models,omitempty"`
|
||||
Note string `json:"note,omitempty"`
|
||||
CreatedAt int64 `json:"created_at,omitempty"`
|
||||
}
|
||||
|
||||
// ModelScope is one allowed model for a key, or one AUTO scheduling slot,
|
||||
// with an optional token quota and reset period. TokenQuota 0 = unlimited;
|
||||
// Period "" = never resets; "hour"/"week"/"month" are fixed windows; "nhour"
|
||||
// uses Hours as the window length in hours.
|
||||
type ModelScope struct {
|
||||
Model string `json:"model"`
|
||||
TokenQuota int64 `json:"token_quota"`
|
||||
Period string `json:"period,omitempty"`
|
||||
Hours int64 `json:"hours,omitempty"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON accepts both the legacy "model-id" string form and the
|
||||
// {"model":"...","token_quota":N} object form so old runtime files keep
|
||||
// loading.
|
||||
func (m *ModelScope) UnmarshalJSON(b []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(b, &s); err == nil {
|
||||
m.Model = s
|
||||
return nil
|
||||
}
|
||||
var o struct {
|
||||
Model string `json:"model"`
|
||||
TokenQuota int64 `json:"token_quota"`
|
||||
Period string `json:"period"`
|
||||
Hours int64 `json:"hours"`
|
||||
}
|
||||
if err := json.Unmarshal(b, &o); err != nil {
|
||||
return err
|
||||
}
|
||||
m.Model = o.Model
|
||||
m.TokenQuota = o.TokenQuota
|
||||
m.Period = o.Period
|
||||
m.Hours = o.Hours
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -137,4 +137,21 @@ func (s *Store) DeleteKey(key string) (bool, error) {
|
||||
}
|
||||
s.data.Keys = kept
|
||||
return true, s.persistLocked()
|
||||
}
|
||||
|
||||
// AutoRules returns the persisted AUTO scheduling slots.
|
||||
func (s *Store) AutoRules() []ModelScope {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
out := make([]ModelScope, len(s.data.Auto))
|
||||
copy(out, s.data.Auto)
|
||||
return out
|
||||
}
|
||||
|
||||
// SaveAutoRules persists the AUTO scheduling slots.
|
||||
func (s *Store) SaveAutoRules(entries []ModelScope) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.data.Auto = entries
|
||||
return s.persistLocked()
|
||||
}
|
||||
Reference in New Issue
Block a user