Support runtime backend switching via ctl
This commit is contained in:
parent
5a8f7e394e
commit
19971be343
|
|
@ -7,6 +7,7 @@ import (
|
|||
"os"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
|
|
@ -39,17 +40,17 @@ type Agent struct {
|
|||
resultCache resultCache
|
||||
|
||||
// Execution state — owned by the agent, protected by stateMu.
|
||||
state string // "idle", "thinking", "calling: <tool>"
|
||||
reply string // last assistant response
|
||||
getCwd func() string // returns session working directory
|
||||
id string // agent identity (unique principal)
|
||||
parentID string // immutable ID of the agent that spawned this agent
|
||||
depth int // sub-agent depth (0=top-level, 1=sub-agent, 2=sub-sub-agent)
|
||||
activeChildren atomic.Int32 // number of currently-running child sub-agents
|
||||
state string // "idle", "thinking", "calling: <tool>"
|
||||
reply string // last assistant response
|
||||
getCwd func() string // returns session working directory
|
||||
id string // agent identity (unique principal)
|
||||
parentID string // immutable ID of the agent that spawned this agent
|
||||
depth int // sub-agent depth (0=top-level, 1=sub-agent, 2=sub-sub-agent)
|
||||
activeChildren atomic.Int32 // number of currently-running child sub-agents
|
||||
peers map[string]struct{} // peer agent names (same session)
|
||||
peerMu sync.RWMutex
|
||||
fifo Fifo // prompt queue
|
||||
Feed Feed // streaming input gate (change-detecting)
|
||||
fifo Fifo // prompt queue
|
||||
Feed Feed // streaming input gate (change-detecting)
|
||||
toolCallCount atomic.Int64
|
||||
pendingInject atomic.Pointer[string]
|
||||
submitMu sync.Mutex // serializes Submit calls (commands + turns)
|
||||
|
|
@ -298,6 +299,31 @@ func (ag *Agent) ModelName() string {
|
|||
return ag.runtime.Backend.Model()
|
||||
}
|
||||
|
||||
// SwitchBackend replaces the active backend by name. The new backend is fully
|
||||
// constructed before the runtime is changed, so a failed switch leaves the
|
||||
// current backend usable. Backend changes are only safe between turns.
|
||||
func (ag *Agent) SwitchBackend(name string) error {
|
||||
name = strings.TrimSpace(name)
|
||||
if name == "" {
|
||||
return fmt.Errorf("backend requires a name")
|
||||
}
|
||||
if ag.IsRunning() {
|
||||
return fmt.Errorf("cannot switch backend while agent is running")
|
||||
}
|
||||
if ag.newBackend == nil {
|
||||
return fmt.Errorf("backend switching unavailable")
|
||||
}
|
||||
be, err := ag.newBackend(name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("backend %q: %w", name, err)
|
||||
}
|
||||
ag.runtime.Backend = be
|
||||
ag.save()
|
||||
ag.flush()
|
||||
ag.notifyChange()
|
||||
return nil
|
||||
}
|
||||
|
||||
// State returns the agent's current execution state.
|
||||
func (ag *Agent) State() string {
|
||||
ag.stateMu.RLock()
|
||||
|
|
|
|||
|
|
@ -1083,7 +1083,11 @@ func buildAgentChildren(a *agent.Agent, s *session.Session) []virtfs.FsNodeDecl
|
|||
}
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("backend switching not supported via ctl; use cfg")
|
||||
name := strings.Join(args, " ")
|
||||
if err := a.SwitchBackend(name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(name + "\n"), nil
|
||||
},
|
||||
"name": func(args []string) ([]byte, error) {
|
||||
if len(args) == 0 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue