mirror of
https://github.com/esengine/DeepSeek-Reasonix.git
synced 2026-11-07 10:45:59 -10:00
fix(config): move RemovePluginModelRefs into its own file (follow-up to #8198)
RemovePluginModelRefs pushed edit.go past its file-size budget and its doc comment, like the two in repairPluginModelRefs, ran past the comment budget. The method moves unchanged into plugin_model_refs.go and the three comments are cut to state the constraint only. No behaviour change.
This commit is contained in:
1 parent
7e5643d380
commit
a233e8b13f
3 files changed
+58
-72
No files matched your search
@@ -603,62 +603,6 @@ func (c *Config) providerRemovalFallback(name string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// RemovePluginModelRefs migrates model references that name models of the
|
||||
// plugin id off that plugin, and reports whether anything changed.
|
||||
//
|
||||
// Plugin-namespaced refs (plugin/<plugin>/<provider>/<model>) resolve through
|
||||
// boot's merged resolver rather than the config catalog, so SetDefaultModel
|
||||
// accepts them without proof. That trade means removing the plugin strands
|
||||
// every ref that named it: the next launch fails with "unknown model" and no
|
||||
// session can start until the file is edited by hand. Removal calls this to
|
||||
// close that gap the way RemoveProvider does for a deleted provider.
|
||||
//
|
||||
// References move to the first remaining configured provider. Unlike provider
|
||||
// removal this never refuses: the plugin is already gone by the time it runs,
|
||||
// so with no fallback the refs are cleared and the keyless-default policy in
|
||||
// ResolveNewSessionChatModel picks the boot model instead.
|
||||
func (c *Config) RemovePluginModelRefs(pluginID string) bool {
|
||||
pluginID = strings.TrimSpace(pluginID)
|
||||
if pluginID == "" {
|
||||
return false
|
||||
}
|
||||
ownedByPlugin := func(ref string) bool {
|
||||
return protocol.PluginRefOwner(strings.TrimSpace(ref)) == pluginID
|
||||
}
|
||||
|
||||
defaultOwned := ownedByPlugin(c.DefaultModel)
|
||||
plannerOwned := ownedByPlugin(c.Agent.PlannerModel)
|
||||
subagentOwned := ownedByPlugin(c.Agent.SubagentModel)
|
||||
subagentModelsOwned := map[string]bool{}
|
||||
for skill, ref := range c.Agent.SubagentModels {
|
||||
if ownedByPlugin(ref) {
|
||||
subagentModelsOwned[skill] = true
|
||||
}
|
||||
}
|
||||
if !defaultOwned && !plannerOwned && !subagentOwned && len(subagentModelsOwned) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
fallback := c.providerRemovalFallback("")
|
||||
if defaultOwned {
|
||||
c.DefaultModel = fallback
|
||||
}
|
||||
if plannerOwned {
|
||||
c.Agent.PlannerModel = fallback
|
||||
}
|
||||
if subagentOwned {
|
||||
c.Agent.SubagentModel = fallback
|
||||
}
|
||||
for skill := range subagentModelsOwned {
|
||||
if fallback != "" {
|
||||
c.Agent.SubagentModels[skill] = fallback
|
||||
} else {
|
||||
delete(c.Agent.SubagentModels, skill)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// validateProvider checks the fields a provider can't function without.
|
||||
func validateProvider(e ProviderEntry) error {
|
||||
switch {
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"reasonix/internal/extension/protocol"
|
||||
)
|
||||
|
||||
// RemovePluginModelRefs moves every model ref owned by pluginID to the first
|
||||
// remaining configured provider, or clears it when none is left, and reports
|
||||
// whether anything changed. Plugin refs resolve outside the config catalog, so
|
||||
// a removed plugin would otherwise strand them and fail the next boot.
|
||||
func (c *Config) RemovePluginModelRefs(pluginID string) bool {
|
||||
pluginID = strings.TrimSpace(pluginID)
|
||||
if pluginID == "" {
|
||||
return false
|
||||
}
|
||||
ownedByPlugin := func(ref string) bool {
|
||||
return protocol.PluginRefOwner(strings.TrimSpace(ref)) == pluginID
|
||||
}
|
||||
|
||||
defaultOwned := ownedByPlugin(c.DefaultModel)
|
||||
plannerOwned := ownedByPlugin(c.Agent.PlannerModel)
|
||||
subagentOwned := ownedByPlugin(c.Agent.SubagentModel)
|
||||
subagentModelsOwned := map[string]bool{}
|
||||
for skill, ref := range c.Agent.SubagentModels {
|
||||
if ownedByPlugin(ref) {
|
||||
subagentModelsOwned[skill] = true
|
||||
}
|
||||
}
|
||||
if !defaultOwned && !plannerOwned && !subagentOwned && len(subagentModelsOwned) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
fallback := c.providerRemovalFallback("")
|
||||
if defaultOwned {
|
||||
c.DefaultModel = fallback
|
||||
}
|
||||
if plannerOwned {
|
||||
c.Agent.PlannerModel = fallback
|
||||
}
|
||||
if subagentOwned {
|
||||
c.Agent.SubagentModel = fallback
|
||||
}
|
||||
for skill := range subagentModelsOwned {
|
||||
if fallback != "" {
|
||||
c.Agent.SubagentModels[skill] = fallback
|
||||
} else {
|
||||
delete(c.Agent.SubagentModels, skill)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -717,15 +717,9 @@ func (t *installSourceTool) applyRemovePluginPackage(_ request, act *action) err
|
||||
return nil
|
||||
}
|
||||
|
||||
// repairPluginModelRefs moves default_model and the optional agent model refs
|
||||
// off a plugin that has just been removed. Its models stop resolving the
|
||||
// moment the package is gone, and boot rejects an unknown default_model, so
|
||||
// leaving the ref in place locks the user out of every session until they edit
|
||||
// the file by hand.
|
||||
//
|
||||
// Only the user config is repaired: plugin packages install globally, so a
|
||||
// project reasonix.toml that names a plugin model is the project's own choice
|
||||
// to make and to undo.
|
||||
// repairPluginModelRefs moves user-config model refs off a removed plugin,
|
||||
// since boot rejects an unknown default_model. Project configs are left alone:
|
||||
// a project naming a plugin model made that choice itself.
|
||||
func repairPluginModelRefs(pluginID string) error {
|
||||
path := config.UserConfigPath()
|
||||
if strings.TrimSpace(path) == "" {
|
||||
@@ -734,13 +728,8 @@ func repairPluginModelRefs(pluginID string) error {
|
||||
if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) {
|
||||
return nil
|
||||
}
|
||||
// Probe a throwaway copy first. A config with no ref to this plugin is left
|
||||
// byte-for-byte alone, and a malformed one is left for the user to recover:
|
||||
// rewriting it here would trade a stale ref for a lost file.
|
||||
//
|
||||
// Credentials load with it: the fallback provider must be one the user can
|
||||
// actually reach, and Configured() reports false for every provider when
|
||||
// the keys are absent.
|
||||
// A strict read-only probe leaves an unaffected or malformed file untouched;
|
||||
// credentials load so the fallback is a provider the user can reach.
|
||||
probe, err := config.LoadForEditReadOnlyStrict(path)
|
||||
if err != nil || probe == nil || !probe.RemovePluginModelRefs(pluginID) {
|
||||
return nil
|
||||
|
||||
Reference in new issue
Block a user