mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
refactor: support explicit provider field in model list entries (#2609)
* refactor: support explicit model list providers * fix(web): preserve explicit model providers * fix(web): preserve legacy provider prefixes on model updates fix(models): normalize explicit provider-prefixed ids fix(api): preserve legacy model updates across providers fix(agent): preserve config identity for explicit provider refs * fix ci
This commit is contained in:
@@ -6,10 +6,12 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/sipeed/picoclaw/pkg/config"
|
||||
"github.com/sipeed/picoclaw/pkg/logger"
|
||||
"github.com/sipeed/picoclaw/pkg/providers"
|
||||
)
|
||||
|
||||
// registerModelRoutes binds model list management endpoints to the ServeMux.
|
||||
@@ -26,6 +28,7 @@ func (h *Handler) registerModelRoutes(mux *http.ServeMux) {
|
||||
type modelResponse struct {
|
||||
Index int `json:"index"`
|
||||
ModelName string `json:"model_name"`
|
||||
Provider string `json:"provider,omitempty"`
|
||||
Model string `json:"model"`
|
||||
APIBase string `json:"api_base,omitempty"`
|
||||
APIKey string `json:"api_key"`
|
||||
@@ -73,10 +76,12 @@ func (h *Handler) handleListModels(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
models := make([]modelResponse, 0, len(cfg.ModelList))
|
||||
for i, m := range cfg.ModelList {
|
||||
provider, modelID := providers.ExtractProtocol(m)
|
||||
models = append(models, modelResponse{
|
||||
Index: i,
|
||||
ModelName: m.ModelName,
|
||||
Model: m.Model,
|
||||
Provider: provider,
|
||||
Model: modelID,
|
||||
APIBase: m.APIBase,
|
||||
APIKey: maskAPIKey(m.APIKey()),
|
||||
Proxy: m.Proxy,
|
||||
@@ -176,6 +181,12 @@ func (h *Handler) handleUpdateModel(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
defer r.Body.Close()
|
||||
|
||||
var rawFields map[string]json.RawMessage
|
||||
if err = json.Unmarshal(body, &rawFields); err != nil {
|
||||
http.Error(w, fmt.Sprintf("Invalid JSON: %v", err), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
type custom struct {
|
||||
config.ModelConfig
|
||||
APIKey string `json:"api_key"`
|
||||
@@ -226,6 +237,35 @@ func (h *Handler) handleUpdateModel(w http.ResponseWriter, r *http.Request) {
|
||||
} else if len(mc.CustomHeaders) == 0 {
|
||||
mc.CustomHeaders = nil
|
||||
}
|
||||
// Preserve the existing Provider when the caller omits it. This keeps the
|
||||
// update API backward-compatible for clients that haven't started sending
|
||||
// the new field yet, while still allowing explicit clearing via "".
|
||||
if _, ok := rawFields["provider"]; !ok {
|
||||
mc.Provider = cfg.ModelList[idx].Provider
|
||||
// Older clients still round-trip the legacy model field only. When the
|
||||
// stored config encodes provider/model in Model and has no explicit
|
||||
// Provider field yet, continue preserving that hidden provider prefix.
|
||||
// This keeps provider-omitted updates backward-compatible even when an
|
||||
// older client edits the visible model ID.
|
||||
if strings.TrimSpace(cfg.ModelList[idx].Provider) == "" {
|
||||
existingProtocol, existingModelID := providers.ExtractProtocol(cfg.ModelList[idx])
|
||||
existingRawModel := strings.TrimSpace(cfg.ModelList[idx].Model)
|
||||
incomingModel := strings.TrimSpace(mc.Model)
|
||||
if existingRawModel != "" && existingRawModel != existingModelID && incomingModel != "" {
|
||||
if incomingModel == existingModelID {
|
||||
mc.Model = existingRawModel
|
||||
} else if strings.Contains(incomingModel, "/") && !strings.Contains(existingModelID, "/") {
|
||||
// Older clients never saw the hidden provider prefix for simple
|
||||
// legacy entries such as "openai/gpt-4o". If they now send an
|
||||
// explicit provider/model string, treat it as the caller's full
|
||||
// intent instead of re-applying the old hidden prefix.
|
||||
mc.Model = incomingModel
|
||||
} else if !strings.HasPrefix(incomingModel, existingProtocol+"/") {
|
||||
mc.Model = existingProtocol + "/" + incomingModel
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg.ModelList[idx] = &mc.ModelConfig
|
||||
|
||||
|
||||
Reference in New Issue
Block a user