|
1 | 1 | package main |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "context" |
4 | 5 | "fmt" |
5 | 6 | "os" |
6 | 7 | "path/filepath" |
| 8 | + "sort" |
7 | 9 | "strings" |
| 10 | + "time" |
8 | 11 |
|
| 12 | + "github.com/BackendStack21/odek/internal/config" |
| 13 | + "github.com/BackendStack21/odek/internal/llm" |
9 | 14 | "github.com/BackendStack21/odek/internal/memory" |
10 | 15 | "github.com/BackendStack21/odek/internal/memory/extended" |
11 | 16 | ) |
@@ -70,10 +75,10 @@ func memoryCmd(args []string) error { |
70 | 75 | } |
71 | 76 | } |
72 | 77 |
|
73 | | -// extendedMemoryCmd handles `odek memory extended forget|quarantine|compact`. |
| 78 | +// extendedMemoryCmd handles `odek memory extended <subcommand>`. |
74 | 79 | func extendedMemoryCmd(dir string, args []string) error { |
75 | 80 | if len(args) == 0 { |
76 | | - fmt.Fprintf(os.Stderr, "Usage: odek memory extended <forget|promote|pin|quarantine|compact|pending|confirm|reject> [args]\n") |
| 81 | + fmt.Fprintf(os.Stderr, "Usage: odek memory extended <forget|promote|pin|quarantine|compact|stats|consolidate|pending|confirm|reject> [args]\n") |
77 | 82 | return nil |
78 | 83 | } |
79 | 84 |
|
@@ -144,6 +149,48 @@ func extendedMemoryCmd(dir string, args []string) error { |
144 | 149 | fmt.Println("odek: Extended Memory vector index compaction triggered in the background") |
145 | 150 | return nil |
146 | 151 |
|
| 152 | + case "stats": |
| 153 | + st := em.Stats() |
| 154 | + fmt.Println("Extended Memory stats:") |
| 155 | + fmt.Printf(" live atoms: %d\n", st.LiveAtoms) |
| 156 | + fmt.Printf(" quarantined atoms: %d\n", st.QuarantinedAtoms) |
| 157 | + if len(st.QuarantineReasons) > 0 { |
| 158 | + reasons := make([]string, 0, len(st.QuarantineReasons)) |
| 159 | + for r := range st.QuarantineReasons { |
| 160 | + reasons = append(reasons, r) |
| 161 | + } |
| 162 | + sort.Strings(reasons) |
| 163 | + for _, r := range reasons { |
| 164 | + fmt.Printf(" %-16s %d\n", r+":", st.QuarantineReasons[r]) |
| 165 | + } |
| 166 | + } |
| 167 | + fmt.Printf(" index vectors: %d (dirty: %v)\n", st.IndexVectors, st.IndexDirty) |
| 168 | + fmt.Printf(" store size: %.1f MiB\n", float64(st.StoreSizeBytes)/(1<<20)) |
| 169 | + fmt.Printf(" recall timeouts: %d\n", st.RecallTimeouts) |
| 170 | + fmt.Printf(" recall failures: %d\n", st.RecallFailures) |
| 171 | + if st.RecallTimeouts+st.RecallFailures > 0 { |
| 172 | + fmt.Println(" warning: recall degraded this process — check LLM/embedding backend latency") |
| 173 | + } |
| 174 | + return nil |
| 175 | + |
| 176 | + case "consolidate": |
| 177 | + // Merging near-duplicate atoms needs an LLM; resolve the operator |
| 178 | + // backend the same way the agent does. |
| 179 | + resolved := config.LoadConfig(config.CLIFlags{}) |
| 180 | + if resolved.APIKey == "" { |
| 181 | + return fmt.Errorf("memory extended consolidate requires an LLM backend (no API key resolved)") |
| 182 | + } |
| 183 | + llmClient := llm.New(resolved.BaseURL, resolved.APIKey, resolved.Model, "", 0, 120*time.Second) |
| 184 | + emLLM := extended.New(extDir, llmClient, cfg) |
| 185 | + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) |
| 186 | + defer cancel() |
| 187 | + merged, err := emLLM.ConsolidateAtoms(ctx) |
| 188 | + if err != nil { |
| 189 | + return err |
| 190 | + } |
| 191 | + fmt.Printf("odek: consolidation complete — %d atom(s) merged into existing or new entries\n", merged) |
| 192 | + return nil |
| 193 | + |
147 | 194 | case "pending": |
148 | 195 | pending, err := em.ListPendingReview() |
149 | 196 | if err != nil { |
@@ -186,6 +233,6 @@ func extendedMemoryCmd(dir string, args []string) error { |
186 | 233 | return nil |
187 | 234 |
|
188 | 235 | default: |
189 | | - return fmt.Errorf("unknown extended memory subcommand %q (expected: forget, promote, pin, quarantine, compact, pending, confirm, reject)", sub) |
| 236 | + return fmt.Errorf("unknown extended memory subcommand %q (expected: forget, promote, pin, quarantine, compact, stats, consolidate, pending, confirm, reject)", sub) |
190 | 237 | } |
191 | 238 | } |
0 commit comments