mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-17 21:27:23 +08:00
Go: refactor CLI (#15898)
### What problem does this PR solve? 1. remove unused code 2. fix login issue ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) - [x] Refactoring Signed-off-by: Jin Hai <haijin.chn@gmail.com>
This commit is contained in:
@@ -64,23 +64,6 @@ const (
|
||||
OutputFormatJSON OutputFormat = "json" // JSON format (reserved for future use)
|
||||
)
|
||||
|
||||
// ConnectionArgs holds the parsed command line arguments
|
||||
type ConnectionArgs struct {
|
||||
Host string
|
||||
Port int
|
||||
Password string
|
||||
APIToken string
|
||||
UserName string
|
||||
ConfigFilePath string // Path to the config file (e.g., rf.yml)
|
||||
Command *string // Original command string (for SQL mode)
|
||||
CommandArgs []string // Split command arguments (for ContextEngine mode)
|
||||
IsSQLMode bool // true=SQL mode (quoted), false= ContextEngine mode (unquoted)
|
||||
ShowHelp bool
|
||||
AdminMode bool
|
||||
OutputFormat OutputFormat // Output format: table, plain, json
|
||||
Verbose bool // Enable verbose logging
|
||||
}
|
||||
|
||||
type CommandLineMode string
|
||||
|
||||
const (
|
||||
@@ -516,12 +499,8 @@ const historyFileName = ".ragflow_cli_history"
|
||||
|
||||
// CLI represents the command line interface
|
||||
type CLI struct {
|
||||
//client *RAGFlowClient
|
||||
//contextEngine *filesystem.Engine
|
||||
running bool
|
||||
line *liner.State
|
||||
args *ConnectionArgs
|
||||
outputFormat OutputFormat // Output format
|
||||
running bool
|
||||
line *liner.State
|
||||
|
||||
APIServerClientMap map[string]*HTTPClient
|
||||
AdminServerClient *HTTPClient
|
||||
@@ -541,9 +520,8 @@ func NewCLIWithConfig(commandLineConfig *CommandLineConfig) (*CLI, error) {
|
||||
line := liner.NewLiner()
|
||||
|
||||
cli := &CLI{
|
||||
line: line,
|
||||
Config: commandLineConfig,
|
||||
outputFormat: commandLineConfig.OutputFormat,
|
||||
line: line,
|
||||
Config: commandLineConfig,
|
||||
}
|
||||
|
||||
if commandLineConfig.CLIMode == APIMode {
|
||||
@@ -608,7 +586,7 @@ func (c *CLI) NewRun() error {
|
||||
// provider username but no password or api token
|
||||
maxAttempts := 3
|
||||
for attempt := 1; attempt <= maxAttempts; attempt++ {
|
||||
fmt.Printf("Please input your password for '%s': ", *apiConfig.UserName)
|
||||
fmt.Printf("Please input your password: ")
|
||||
|
||||
password, err := ReadPassword()
|
||||
|
||||
@@ -622,12 +600,12 @@ func (c *CLI) NewRun() error {
|
||||
|
||||
apiConfig.UserPassword = &password
|
||||
|
||||
if err = c.VerifyAuth(); err != nil {
|
||||
if err = c.VerifyAuth(*apiConfig.UserName, *apiConfig.UserPassword); err != nil {
|
||||
if attempt < maxAttempts {
|
||||
fmt.Printf("Authentication failed: %v (%d/%d attempts)\n", err, attempt, maxAttempts)
|
||||
fmt.Printf("Authentication failed (%d/%d attempts)\n", attempt, maxAttempts)
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("authentication failed after %d attempts: %v", maxAttempts, err)
|
||||
return fmt.Errorf("authentication failed after %d attempts", maxAttempts)
|
||||
}
|
||||
|
||||
break
|
||||
@@ -635,39 +613,41 @@ func (c *CLI) NewRun() error {
|
||||
}
|
||||
|
||||
case AdminMode:
|
||||
adminConfig := c.Config.AdminClientConfig
|
||||
if adminConfig.AdminName != nil && adminConfig.AdminPassword == nil {
|
||||
// provider username but no password or api token
|
||||
maxAttempts := 3
|
||||
for attempt := 1; attempt <= maxAttempts; attempt++ {
|
||||
fmt.Printf("Please input your password: ")
|
||||
|
||||
password, err := ReadPassword()
|
||||
|
||||
if password == "" {
|
||||
if attempt < maxAttempts {
|
||||
fmt.Println("Password cannot be empty, please try again")
|
||||
continue
|
||||
}
|
||||
return errors.New("no password provided after 3 attempts")
|
||||
}
|
||||
|
||||
adminConfig.AdminPassword = &password
|
||||
|
||||
if err = c.VerifyAuth(*adminConfig.AdminName, *adminConfig.AdminPassword); err != nil {
|
||||
if attempt < maxAttempts {
|
||||
fmt.Printf("Authentication failed (%d/%d attempts)\n", attempt, maxAttempts)
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("authentication failed after %d attempts", maxAttempts)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unexpected CLI mode: %s", cliConfig.CLIMode)
|
||||
}
|
||||
|
||||
if c.args != nil && c.args.UserName != "" && c.args.Password == "" && c.args.APIToken == "" {
|
||||
maxAttempts := 3
|
||||
for attempt := 1; attempt <= maxAttempts; attempt++ {
|
||||
fmt.Print("Please input your password: ")
|
||||
|
||||
password, err := ReadPassword()
|
||||
|
||||
if password == "" {
|
||||
if attempt < maxAttempts {
|
||||
fmt.Println("Password cannot be empty, please try again")
|
||||
continue
|
||||
}
|
||||
return errors.New("no password provided after 3 attempts")
|
||||
}
|
||||
|
||||
c.args.Password = password
|
||||
|
||||
if err = c.VerifyAuth(); err != nil {
|
||||
if attempt < maxAttempts {
|
||||
fmt.Printf("Authentication failed: %v (%d/%d attempts)\n", err, attempt, maxAttempts)
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("authentication failed after %d attempts: %v", maxAttempts, err)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
c.running = true
|
||||
|
||||
// Load history from file
|
||||
@@ -750,62 +730,6 @@ func (c *CLI) executeNew(input string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *CLI) execute(input string) error {
|
||||
// Determine execution mode based on input and args
|
||||
input = strings.TrimSpace(input)
|
||||
|
||||
// Handle meta commands (start with \)
|
||||
if strings.HasPrefix(input, "\\") {
|
||||
p := NewParser(input)
|
||||
cmd, err := p.Parse(c.Config.CLIMode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if cmd != nil && cmd.Type == "meta" {
|
||||
return c.handleMetaCommand(cmd)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we should use SQL mode or Filesystem mode
|
||||
isSQLMode := false
|
||||
if c.args != nil && len(c.args.CommandArgs) > 0 {
|
||||
// Non-interactive mode: use pre-determined mode from args
|
||||
isSQLMode = c.args.IsSQLMode
|
||||
} else {
|
||||
// Interactive mode: determine based on input
|
||||
isSQLMode = looksLikeSQL(input)
|
||||
}
|
||||
|
||||
if isSQLMode {
|
||||
// SQL mode: use parser
|
||||
p := NewParser(input)
|
||||
cmd, err := p.Parse(c.Config.CLIMode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if cmd == nil {
|
||||
return nil
|
||||
}
|
||||
// Execute SQL command using the client
|
||||
var result ResponseIf
|
||||
result, err = c.ExecuteCommand(cmd)
|
||||
if result != nil {
|
||||
result.SetOutputFormat(c.outputFormat)
|
||||
result.PrintOut()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Filesystem mode: execute filesystem command
|
||||
cmd := NewCommand("file_system_command")
|
||||
cmd.Params["command"] = input
|
||||
resp, ceErr := c.executeFilesystem(cmd)
|
||||
if resp != nil {
|
||||
resp.PrintOut()
|
||||
}
|
||||
return ceErr
|
||||
}
|
||||
|
||||
// executeFilesystem executes a Filesystem command and returns a ResponseIf.
|
||||
func (c *CLI) executeFilesystem(cmd *Command) (ResponseIf, error) {
|
||||
rawInput, _ := cmd.Params["command"].(string)
|
||||
@@ -843,13 +767,8 @@ func (c *CLI) executeFilesystem(cmd *Command) (ResponseIf, error) {
|
||||
func (c *CLI) executeFilesystemInner(input string) error {
|
||||
// Parse input into arguments
|
||||
var args []string
|
||||
if c.args != nil && len(c.args.CommandArgs) > 0 {
|
||||
// Non-interactive mode: use pre-parsed args
|
||||
args = c.args.CommandArgs
|
||||
} else {
|
||||
// Interactive mode: parse input
|
||||
args = parseFilesystemArgs(input)
|
||||
}
|
||||
// Interactive mode: parse input
|
||||
args = parseFilesystemArgs(input)
|
||||
|
||||
if len(args) == 0 {
|
||||
return fmt.Errorf("no command provided")
|
||||
@@ -936,7 +855,7 @@ func (c *CLI) executeFilesystemInner(input string) error {
|
||||
return err
|
||||
}
|
||||
// Print skill search results with full details
|
||||
c.printSkillSearchResults(result, c.outputFormat)
|
||||
c.printSkillSearchResults(result, c.Config.OutputFormat)
|
||||
return nil
|
||||
}
|
||||
ceCmd = &filesystem.Command{
|
||||
@@ -1006,7 +925,7 @@ func (c *CLI) executeFilesystemInner(input string) error {
|
||||
|
||||
// Print result
|
||||
// For search command, default to JSON format if not explicitly set to plain/table
|
||||
format := c.outputFormat
|
||||
format := c.Config.OutputFormat
|
||||
if ceCmd.Type == filesystem.CommandSearch && format != OutputFormatPlain && format != OutputFormatTable {
|
||||
format = OutputFormatJSON
|
||||
}
|
||||
@@ -1427,30 +1346,20 @@ func (c *CLI) NewVerifyAuth(username, password *string) error {
|
||||
}
|
||||
|
||||
// VerifyAuth verifies authentication if needed
|
||||
func (c *CLI) VerifyAuth() error {
|
||||
if c.args == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If API token is provided, use it for authentication
|
||||
if c.args.APIToken != "" {
|
||||
// TODO: Implement API token authentication
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *CLI) VerifyAuth(username, password string) error {
|
||||
// Otherwise, use username/password authentication
|
||||
if c.args.UserName == "" {
|
||||
if username == "" {
|
||||
return fmt.Errorf("username is required")
|
||||
}
|
||||
|
||||
if c.args.Password == "" {
|
||||
if password == "" {
|
||||
return fmt.Errorf("password is required")
|
||||
}
|
||||
|
||||
// Create login command with username and password
|
||||
cmd := NewCommand("login_user")
|
||||
cmd.Params["email"] = c.args.UserName
|
||||
cmd.Params["password"] = c.args.Password
|
||||
cmd.Params["email"] = username
|
||||
cmd.Params["password"] = password
|
||||
_, err := c.ExecuteCommand(cmd)
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user