mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-04-22 11:47:47 +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:
2
go.mod
2
go.mod
@ -40,10 +40,12 @@ require (
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.3 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
|
||||
github.com/peterh/liner v1.2.2 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
|
||||
5
go.sum
5
go.sum
@ -75,6 +75,8 @@ github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0V
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4=
|
||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@ -84,6 +86,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
|
||||
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/peterh/liner v1.2.2 h1:aJ4AOodmL+JxOZZEL2u9iJf8omNRpqHc/EbrK+3mAXw=
|
||||
github.com/peterh/liner v1.2.2/go.mod h1:xFwJyiKIXJZUKItq5dGHZSTBRAuG/CpeNpWLyiNRNwI=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
@ -152,6 +156,7 @@ golang.org/x/exp v0.0.0-20231226003508-02704c960a9b h1:kLiC65FbiHWFAOu+lxwNPujcs
|
||||
golang.org/x/exp v0.0.0-20231226003508-02704c960a9b/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
|
||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||
|
||||
@ -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