122 lines
3.4 KiB
Go
122 lines
3.4 KiB
Go
package cli
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"reasonix/internal/config"
|
|
"reasonix/internal/control"
|
|
"reasonix/internal/memorycompiler"
|
|
)
|
|
|
|
func (m *chatTUI) runMemoryV5Command(input string) {
|
|
args := tokenizeArgs(input)
|
|
if len(args) > 2 {
|
|
m.notice("usage: /memory-v5 off|observe|compact|on|status|learnings")
|
|
return
|
|
}
|
|
if len(args) == 2 && strings.EqualFold(args[1], "learnings") {
|
|
m.notice(memoryV5LearningsText(m.ctrl))
|
|
return
|
|
}
|
|
if len(args) < 2 || strings.EqualFold(args[1], "status") {
|
|
cfg, err := config.Load()
|
|
if err != nil {
|
|
m.notice("memory-v5: " + err.Error())
|
|
return
|
|
}
|
|
m.notice(fmt.Sprintf("memory-v5: %s (usage: /memory-v5 off|observe|compact|on|status|learnings)", cliMemoryV5Mode(cfg.MemoryCompilerEnabled(), cfg.MemoryCompilerVerbosity())))
|
|
return
|
|
}
|
|
if m.ctrl != nil && m.ctrl.Running() {
|
|
m.notice("finish or cancel the current turn before changing memory-v5")
|
|
return
|
|
}
|
|
setting, err := parseCLIMemoryV5Setting(args[1])
|
|
if err != nil {
|
|
m.notice("memory-v5: " + err.Error())
|
|
return
|
|
}
|
|
|
|
path := config.UserConfigPath()
|
|
if path == "" {
|
|
m.notice("memory-v5: cannot resolve config path")
|
|
return
|
|
}
|
|
// Lock only the load-modify-save cycle; the controller updates below run
|
|
// off-lock.
|
|
edit, err := func() (*config.Config, error) {
|
|
unlock := config.LockUserConfigEdits()
|
|
defer unlock()
|
|
edit := config.LoadForEdit(path)
|
|
if err := edit.SetMemoryCompilerEnabled(setting.enabled); err != nil {
|
|
return nil, err
|
|
}
|
|
if setting.setVerbosity {
|
|
if err := edit.SetMemoryCompilerVerbosity(setting.verbosity); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
if err := edit.SaveTo(path); err != nil {
|
|
return nil, err
|
|
}
|
|
return edit, nil
|
|
}()
|
|
if err != nil {
|
|
m.notice("memory-v5: " + err.Error())
|
|
return
|
|
}
|
|
|
|
if m.ctrl != nil {
|
|
m.ctrl.SetMemoryCompilerEnabled(setting.enabled)
|
|
if setting.setVerbosity {
|
|
m.ctrl.SetMemoryCompilerVerbosity(setting.verbosity)
|
|
}
|
|
}
|
|
m.notice(fmt.Sprintf("memory-v5 set to %s", cliMemoryV5Mode(edit.MemoryCompilerEnabled(), edit.MemoryCompilerVerbosity())))
|
|
}
|
|
|
|
type cliMemoryV5Setting struct {
|
|
enabled bool
|
|
verbosity string
|
|
setVerbosity bool
|
|
}
|
|
|
|
func parseCLIMemoryV5Setting(mode string) (cliMemoryV5Setting, error) {
|
|
switch strings.ToLower(strings.TrimSpace(mode)) {
|
|
case "off":
|
|
return cliMemoryV5Setting{enabled: false}, nil
|
|
case "observe", "silent", "minimal":
|
|
return cliMemoryV5Setting{enabled: true, verbosity: config.MemoryCompilerVerbosityObserve, setVerbosity: true}, nil
|
|
case "on", "compact", "inject", "contract":
|
|
return cliMemoryV5Setting{enabled: true, verbosity: config.MemoryCompilerVerbosityCompact, setVerbosity: true}, nil
|
|
default:
|
|
return cliMemoryV5Setting{}, fmt.Errorf("memory-v5 %q: must be off|observe|compact|on|status|learnings", mode)
|
|
}
|
|
}
|
|
|
|
// memoryV5LearningsText renders the project's learned Memory v5 state. It is a
|
|
// read-only local view; nothing here reaches a provider.
|
|
func memoryV5LearningsText(ctrl control.SessionAPI) string {
|
|
root := ""
|
|
if ctrl != nil {
|
|
root = ctrl.WorkspaceRoot()
|
|
}
|
|
rt := memorycompiler.New(config.MemoryCompilerDir(root))
|
|
if rt == nil {
|
|
return "memory-v5: no project state directory"
|
|
}
|
|
rep, ok := rt.LearningsReport(0)
|
|
if !ok {
|
|
return "memory-v5: no learned state yet"
|
|
}
|
|
return memorycompiler.FormatLearningsReport(rep)
|
|
}
|
|
|
|
func cliMemoryV5Mode(enabled bool, verbosity string) string {
|
|
if !enabled {
|
|
return "off"
|
|
}
|
|
return config.NormalizeMemoryCompilerVerbosity(verbosity)
|
|
}
|