(args []string)
| 37 | fmt.Fprintln(os.Stderr, "Error:", err) |
| 38 | os.Exit(1) |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | func runMemoryCLI(args []string) error { |
| 43 | if len(args) == 0 { |
| 44 | return fmt.Errorf("usage: lumina-backend memory <search|remember|forget|doctor|seal|flush>") |
| 45 | } |
| 46 | cfg := config.NewConfig() |
| 47 | if len(cfg.PathErrors) > 0 { |
| 48 | return fmt.Errorf("invalid AppRoot configuration: %s", strings.Join(cfg.PathErrors, "; ")) |
| 49 | } |
| 50 | if err := apppaths.PrepareRuntime(cfg.Paths, "dev"); err != nil { |
| 51 | return err |
| 52 | } |
| 53 | if err := apppaths.EnsureProjectManifest(cfg.ProjectPaths, time.Now()); err != nil { |
| 54 | return err |
| 55 | } |
| 56 | if !cfg.LongTermMemoryEnabled { |
| 57 | return fmt.Errorf("long-term memory is disabled") |
| 58 | } |
| 59 | if !cfg.UsesMemoryFabric() { |
| 60 | return fmt.Errorf("Memory Fabric is required") |
| 61 | } |
| 62 | ctx := context.Background() |
| 63 | fabric, err := agent.OpenConfiguredMemoryFabric(ctx, cfg, false) |
| 64 | if err != nil { |
| 65 | return err |
| 66 | } |
| 67 | if fabric == nil { |
| 68 | return fmt.Errorf("Memory Fabric is unavailable") |
| 69 | } |
| 70 | defer fabric.Close() |
| 71 | space := agent.MemoryFabricSpace(cfg) |
| 72 | switch args[0] { |
| 73 | case "search": |
| 74 | flags := flag.NewFlagSet("memory search", flag.ContinueOnError) |
| 75 | limit := flags.Int("limit", cfg.MemoryRecallMaxItems, "max evidence items") |
| 76 | maxTokens := flags.Int("max-context-tokens", cfg.MemoryContextMaxTokens, "maximum evidence context tokens") |
| 77 | contextID := flags.String("context", "", "current context/session ID") |
| 78 | at := flags.String("at", "", "reference time (RFC3339 or YYYY-MM-DD)") |
| 79 | diagnostics := flags.Bool("diagnostics", false, "include local retrieval diagnostics") |
| 80 | if err := flags.Parse(args[1:]); err != nil { |
| 81 | return err |
| 82 | } |
| 83 | query := strings.TrimSpace(strings.Join(flags.Args(), " ")) |
| 84 | if query == "" { |
| 85 | return fmt.Errorf("memory search requires a query") |
| 86 | } |
| 87 | result, err := fabric.Search(ctx, memory.SearchRequest{Space: space, Query: query, |
| 88 | ContextID: *contextID, ReferenceTime: parseMemoryCLITime(*at), MaxEvidence: *limit, |
| 89 | MaxContextTokens: *maxTokens, IncludeDiagnostics: *diagnostics}) |
| 90 | if err != nil { |
| 91 | return err |
| 92 | } |
| 93 | return writeJSON(os.Stdout, result) |
| 94 | case "remember": |
| 95 | flags := flag.NewFlagSet("memory remember", flag.ContinueOnError) |
| 96 | mode := flags.String("mode", string(memory.WriteExplicit), "explicit|correction|preference|constraint|critical_result") |
no test coverage detected