// // Copyright 2026 The InfiniFlow Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package cli import ( "fmt" "os" "strings" "github.com/peterh/liner" ) // HistoryFile returns the path to the history file func HistoryFile() string { return os.Getenv("HOME") + "/" + historyFileName } const historyFileName = ".ragflow_cli_history" // CLI represents the command line interface type CLI struct { client *RAGFlowClient prompt string running bool line *liner.State } // NewCLI creates a new CLI instance func NewCLI() (*CLI, error) { // Create liner first line := liner.NewLiner() // Create client with password prompt using liner client := NewRAGFlowClient("user") // Default to user mode client.PasswordPrompt = line.PasswordPrompt return &CLI{ prompt: "RAGFlow> ", client: client, line: line, }, nil } // Run starts the interactive CLI func (c *CLI) Run() error { c.running = true // Load history from file histFile := HistoryFile() if f, err := os.Open(histFile); err == nil { c.line.ReadHistory(f) f.Close() } // Save history on exit defer func() { if f, err := os.Create(histFile); err == nil { c.line.WriteHistory(f) f.Close() } c.line.Close() }() fmt.Println("Welcome to RAGFlow CLI") fmt.Println("Type \\? for help, \\q to quit") fmt.Println() for c.running { input, err := c.line.Prompt(c.prompt) if err != nil { fmt.Printf("Error reading input: %v\n", err) continue } input = strings.TrimSpace(input) if input == "" { continue } // Add to history (skip meta commands) if !strings.HasPrefix(input, "\\") { c.line.AppendHistory(input) } if err := c.execute(input); err != nil { fmt.Printf("Error: %v\n", err) } } return nil } func (c *CLI) execute(input string) error { p := NewParser(input) cmd, err := p.Parse() if err != nil { return err } if cmd == nil { return nil } // Handle meta commands if cmd.Type == "meta" { return c.handleMetaCommand(cmd) } // Execute the command using the client _, err = c.client.ExecuteCommand(cmd) return err } func (c *CLI) handleMetaCommand(cmd *Command) error { command := cmd.Params["command"].(string) switch command { case "q", "quit", "exit": fmt.Println("Goodbye!") c.running = false case "?", "h", "help": c.printHelp() case "c", "clear": // Clear screen (simple approach) fmt.Print("\033[H\033[2J") default: return fmt.Errorf("unknown meta command: \\%s", command) } return nil } func (c *CLI) printHelp() { help := ` RAGFlow CLI Help ================ SQL Commands: LOGIN USER 'email'; - Login as user REGISTER USER 'name' AS 'nickname' PASSWORD 'pwd'; - Register new user SHOW VERSION; - Show version info SHOW CURRENT USER; - Show current user LIST USERS; - List all users LIST SERVICES; - List services PING; - Ping server ... and many more Meta Commands: \? or \h - Show this help \q or \quit - Exit CLI \c or \clear - Clear screen For more information, see documentation. ` fmt.Println(help) } // Cleanup performs cleanup before exit func (c *CLI) Cleanup() { fmt.Println("\nCleaning up...") }