mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-19 14:11:04 +08:00
Add command history in ragflow cli (#13538)
### What problem does this PR solve? In ragflow cli, use Up/Down arrows to navigate command history, ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
@@ -17,57 +17,91 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"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 {
|
||||
parser *Parser
|
||||
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: NewRAGFlowClient("user"), // Default to user mode
|
||||
client: client,
|
||||
line: line,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Run starts the interactive CLI
|
||||
func (c *CLI) Run() error {
|
||||
c.running = true
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
|
||||
// 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 {
|
||||
fmt.Print(c.prompt)
|
||||
|
||||
if !scanner.Scan() {
|
||||
break
|
||||
input, err := c.line.Prompt(c.prompt)
|
||||
if err != nil {
|
||||
fmt.Printf("Error reading input: %v\n", err)
|
||||
continue
|
||||
}
|
||||
|
||||
input := scanner.Text()
|
||||
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 scanner.Err()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CLI) execute(input string) error {
|
||||
@@ -125,9 +159,9 @@ SQL Commands:
|
||||
... and many more
|
||||
|
||||
Meta Commands:
|
||||
\\? or \\h - Show this help
|
||||
\\q or \\quit - Exit CLI
|
||||
\\c or \\clear - Clear screen
|
||||
\? or \h - Show this help
|
||||
\q or \quit - Exit CLI
|
||||
\c or \clear - Clear screen
|
||||
|
||||
For more information, see documentation.
|
||||
`
|
||||
|
||||
@@ -26,10 +26,14 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// PasswordPromptFunc is a function type for password input
|
||||
type PasswordPromptFunc func(prompt string) (string, error)
|
||||
|
||||
// RAGFlowClient handles API interactions with the RAGFlow server
|
||||
type RAGFlowClient struct {
|
||||
HTTPClient *HTTPClient
|
||||
ServerType string // "admin" or "user"
|
||||
HTTPClient *HTTPClient
|
||||
ServerType string // "admin" or "user"
|
||||
PasswordPrompt PasswordPromptFunc // Function for password input
|
||||
}
|
||||
|
||||
// NewRAGFlowClient creates a new RAGFlow client
|
||||
@@ -61,10 +65,20 @@ func (c *RAGFlowClient) LoginUser(cmd *Command) error {
|
||||
}
|
||||
|
||||
// Get password from user input (hidden)
|
||||
fmt.Printf("password for %s: ", email)
|
||||
password, err := readPassword()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read password: %w", err)
|
||||
var password string
|
||||
if c.PasswordPrompt != nil {
|
||||
pwd, err := c.PasswordPrompt(fmt.Sprintf("password for %s: ", email))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read password: %w", err)
|
||||
}
|
||||
password = pwd
|
||||
} else {
|
||||
fmt.Printf("password for %s: ", email)
|
||||
pwd, err := readPassword()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read password: %w", err)
|
||||
}
|
||||
password = pwd
|
||||
}
|
||||
password = strings.TrimSpace(password)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user