backend: add unified restart-required signature logic
- Add bootConfigSignature to gateway state for tracking restart-sensitive config - Implement computeConfigSignature() to capture model and tool enabled states - Add gatewayRestartRequiredBySignature() for unified restart detection - Update gatewayStatusData() to use signature-based comparison - Preserve backward compatibility with existing boot_default_model field
This commit is contained in:
parent
5f50ae5e76
commit
538415bca5
1 changed files with 108 additions and 12 deletions
|
|
@ -25,13 +25,14 @@ import (
|
|||
|
||||
// gateway holds the state for the managed gateway process.
|
||||
var gateway = struct {
|
||||
mu sync.Mutex
|
||||
cmd *exec.Cmd
|
||||
owned bool // true if we started the process, false if we attached to an existing one
|
||||
bootDefaultModel string
|
||||
runtimeStatus string
|
||||
startupDeadline time.Time
|
||||
logs *LogBuffer
|
||||
mu sync.Mutex
|
||||
cmd *exec.Cmd
|
||||
owned bool // true if we started the process, false if we attached to an existing one
|
||||
bootDefaultModel string
|
||||
bootConfigSignature string
|
||||
runtimeStatus string
|
||||
startupDeadline time.Time
|
||||
logs *LogBuffer
|
||||
}{
|
||||
runtimeStatus: "stopped",
|
||||
logs: NewLogBuffer(200),
|
||||
|
|
@ -187,6 +188,95 @@ func gatewayRestartRequired(configDefaultModel, bootDefaultModel, gatewayStatus
|
|||
return configDefaultModel != bootDefaultModel
|
||||
}
|
||||
|
||||
func computeConfigSignature(cfg *config.Config) string {
|
||||
if cfg == nil {
|
||||
return ""
|
||||
}
|
||||
var parts []string
|
||||
defaultModel := strings.TrimSpace(cfg.Agents.Defaults.GetModelName())
|
||||
if defaultModel != "" {
|
||||
parts = append(parts, "model:"+defaultModel)
|
||||
}
|
||||
toolSignatures := []string{}
|
||||
if cfg.Tools.ReadFile.Enabled {
|
||||
toolSignatures = append(toolSignatures, "read_file")
|
||||
}
|
||||
if cfg.Tools.WriteFile.Enabled {
|
||||
toolSignatures = append(toolSignatures, "write_file")
|
||||
}
|
||||
if cfg.Tools.ListDir.Enabled {
|
||||
toolSignatures = append(toolSignatures, "list_dir")
|
||||
}
|
||||
if cfg.Tools.EditFile.Enabled {
|
||||
toolSignatures = append(toolSignatures, "edit_file")
|
||||
}
|
||||
if cfg.Tools.AppendFile.Enabled {
|
||||
toolSignatures = append(toolSignatures, "append_file")
|
||||
}
|
||||
if cfg.Tools.Exec.Enabled {
|
||||
toolSignatures = append(toolSignatures, "exec")
|
||||
}
|
||||
if cfg.Tools.Cron.Enabled {
|
||||
toolSignatures = append(toolSignatures, "cron")
|
||||
}
|
||||
if cfg.Tools.Web.Enabled {
|
||||
toolSignatures = append(toolSignatures, "web")
|
||||
}
|
||||
if cfg.Tools.WebFetch.Enabled {
|
||||
toolSignatures = append(toolSignatures, "web_fetch")
|
||||
}
|
||||
if cfg.Tools.Message.Enabled {
|
||||
toolSignatures = append(toolSignatures, "message")
|
||||
}
|
||||
if cfg.Tools.SendFile.Enabled {
|
||||
toolSignatures = append(toolSignatures, "send_file")
|
||||
}
|
||||
if cfg.Tools.FindSkills.Enabled {
|
||||
toolSignatures = append(toolSignatures, "find_skills")
|
||||
}
|
||||
if cfg.Tools.InstallSkill.Enabled {
|
||||
toolSignatures = append(toolSignatures, "install_skill")
|
||||
}
|
||||
if cfg.Tools.Spawn.Enabled {
|
||||
toolSignatures = append(toolSignatures, "spawn")
|
||||
}
|
||||
if cfg.Tools.SpawnStatus.Enabled {
|
||||
toolSignatures = append(toolSignatures, "spawn_status")
|
||||
}
|
||||
if cfg.Tools.I2C.Enabled {
|
||||
toolSignatures = append(toolSignatures, "i2c")
|
||||
}
|
||||
if cfg.Tools.SPI.Enabled {
|
||||
toolSignatures = append(toolSignatures, "spi")
|
||||
}
|
||||
if cfg.Tools.MCP.Enabled {
|
||||
toolSignatures = append(toolSignatures, "mcp")
|
||||
}
|
||||
if cfg.Tools.MCP.Discovery.Enabled {
|
||||
toolSignatures = append(toolSignatures, "mcp_discovery")
|
||||
}
|
||||
if cfg.Tools.MCP.Discovery.UseRegex {
|
||||
toolSignatures = append(toolSignatures, "mcp_discovery_regex")
|
||||
}
|
||||
if cfg.Tools.MCP.Discovery.UseBM25 {
|
||||
toolSignatures = append(toolSignatures, "mcp_discovery_bm25")
|
||||
}
|
||||
if len(toolSignatures) > 0 {
|
||||
parts = append(parts, "tools:"+strings.Join(toolSignatures, ","))
|
||||
}
|
||||
return strings.Join(parts, ";")
|
||||
}
|
||||
|
||||
func gatewayRestartRequiredBySignature(bootSignature, currentSignature, gatewayStatus string) bool {
|
||||
if gatewayStatus != "running" {
|
||||
return false
|
||||
}
|
||||
if bootSignature == "" || currentSignature == "" {
|
||||
return false
|
||||
}
|
||||
return bootSignature != currentSignature
|
||||
}
|
||||
|
||||
func isCmdProcessAliveLocked(cmd *exec.Cmd) bool {
|
||||
if cmd == nil || cmd.Process == nil {
|
||||
return false
|
||||
|
|
@ -228,10 +318,11 @@ func attachToGatewayProcessLocked(pid int, cfg *config.Config) error {
|
|||
gateway.owned = false // We didn't start this process
|
||||
setGatewayRuntimeStatusLocked("running")
|
||||
|
||||
// Update bootDefaultModel from config
|
||||
// Update bootDefaultModel and bootConfigSignature from config
|
||||
if cfg != nil {
|
||||
defaultModelName := strings.TrimSpace(cfg.Agents.Defaults.GetModelName())
|
||||
gateway.bootDefaultModel = defaultModelName
|
||||
gateway.bootConfigSignature = computeConfigSignature(cfg)
|
||||
}
|
||||
|
||||
logger.InfoC("gateway", fmt.Sprintf("Attached to gateway process (PID: %d)", pid))
|
||||
|
|
@ -419,6 +510,7 @@ func (h *Handler) startGatewayLocked(initialStatus string, existingPid int) (int
|
|||
gateway.cmd = cmd
|
||||
gateway.owned = true // We started this process
|
||||
gateway.bootDefaultModel = defaultModelName
|
||||
gateway.bootConfigSignature = computeConfigSignature(cfg)
|
||||
setGatewayRuntimeStatusLocked(initialStatus)
|
||||
pid = cmd.Process.Pid
|
||||
logger.InfoC("gateway", fmt.Sprintf("Started picoclaw gateway (PID: %d) from %s", pid, execPath))
|
||||
|
|
@ -439,6 +531,7 @@ func (h *Handler) startGatewayLocked(initialStatus string, existingPid int) (int
|
|||
if gateway.cmd == cmd {
|
||||
gateway.cmd = nil
|
||||
gateway.bootDefaultModel = ""
|
||||
gateway.bootConfigSignature = ""
|
||||
if gateway.runtimeStatus != "restarting" {
|
||||
setGatewayRuntimeStatusLocked("stopped")
|
||||
}
|
||||
|
|
@ -784,11 +877,14 @@ func (h *Handler) gatewayStatusData() map[string]any {
|
|||
}
|
||||
}
|
||||
|
||||
bootDefaultModel, _ := data["boot_default_model"].(string)
|
||||
gatewayStatus, _ := data["gateway_status"].(string)
|
||||
data["gateway_restart_required"] = gatewayRestartRequired(
|
||||
configDefaultModel,
|
||||
bootDefaultModel,
|
||||
currentConfigSignature := computeConfigSignature(cfg)
|
||||
gateway.mu.Lock()
|
||||
bootConfigSignature := gateway.bootConfigSignature
|
||||
gateway.mu.Unlock()
|
||||
data["gateway_restart_required"] = gatewayRestartRequiredBySignature(
|
||||
bootConfigSignature,
|
||||
currentConfigSignature,
|
||||
gatewayStatus,
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue