diff --git a/internal/cli/context_command.go b/internal/cli/context_command.go index ef30773322..353601e033 100644 --- a/internal/cli/context_command.go +++ b/internal/cli/context_command.go @@ -114,15 +114,15 @@ func (c *RAGFlowClient) ContextSearch(cmd *Command) (ResponseIf, error) { } } - threshold := 0.0 - if cmd.Params["threshold"] != nil { - threshold, ok = cmd.Params["threshold"].(float64) - if !ok { - return nil, fmt.Errorf("fail to convert 'threshold' to float64") - } - } + //threshold := 0.0 + //if cmd.Params["threshold"] != nil { + // threshold, ok = cmd.Params["threshold"].(float64) + // if !ok { + // return nil, fmt.Errorf("fail to convert 'threshold' to float64") + // } + //} - fmt.Printf("search query: %s, path: %s, threshold: %f, number: %d\n", query, path, threshold, number) + fmt.Printf("search query: %s, path: %s, number: %d\n", query, path, number) // Convert to response var response ContextSearchResponse diff --git a/internal/cli/context_parser.go b/internal/cli/context_parser.go new file mode 100644 index 0000000000..57ce897b95 --- /dev/null +++ b/internal/cli/context_parser.go @@ -0,0 +1,178 @@ +// +// 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" + "strings" +) + +func (p *Parser) parseContextListCommand() (*Command, error) { + p.nextToken() // consume LS + + cmd := NewCommand("context_list") + + if p.curToken.Type == TokenEOF { + cmd.Params["path"] = "." + return cmd, nil + } + + for p.curToken.Type != TokenEOF { + if p.curToken.Type == TokenDash { + p.nextToken() // skip dash + if p.curToken.Type != TokenIdentifier { + return nil, fmt.Errorf("expect identifier") + } + if cmd.Params["parameter"] == nil { + cmd.Params["parameter"] = p.curToken.Value + } else { + cmd.Params["parameter"] = fmt.Sprintf("%s%s", cmd.Params["parameter"], p.curToken.Value) + } + p.nextToken() // skip parameter + } else if p.curToken.Type == TokenIdentifier { + if cmd.Params["path"] == nil { + cmd.Params["path"] = p.curToken.Value + } else { + err := fmt.Errorf("ls: cannot access '%s': No such file or directory", p.curToken.Value) + return nil, err + } + p.nextToken() // skip path + } else { + return nil, fmt.Errorf("syntax error") + } + } + + return cmd, nil +} + +func (p *Parser) parseContextCatCommand() (*Command, error) { + p.nextToken() // consume CAT + + if p.curToken.Type == TokenEOF { + return nil, fmt.Errorf("expect a filename") + } + + if p.curToken.Type != TokenIdentifier && p.curToken.Type != TokenQuotedString { + return nil, fmt.Errorf("expect a filename") + } + + cmd := NewCommand("context_cat") + if p.curToken.Type == TokenIdentifier { + for p.curToken.Type != TokenEOF { + if p.curToken.Type != TokenIdentifier { + return nil, fmt.Errorf("expect a identifier") + } + + if cmd.Params["filename"] == nil { + cmd.Params["filename"] = p.curToken.Value + } else { + cmd.Params["filename"] = fmt.Sprintf("%s/%s", cmd.Params["filename"], p.curToken.Value) + } + p.nextToken() + if p.curToken.Type == TokenEOF { + break + } + if p.curToken.Type != TokenSlash { + return nil, fmt.Errorf("expect a slash") + } + p.nextToken() + if p.curToken.Type == TokenEOF { + return nil, fmt.Errorf("error format") + } + } + + } else if p.curToken.Type == TokenQuotedString { + var err error + cmd.Params["filename"], err = p.parseQuotedString() + if err != nil { + return nil, err + } + } + p.nextToken() + + if p.curToken.Type != TokenEOF { + return nil, fmt.Errorf("syntax error") + } + + return cmd, nil +} + +func (p *Parser) parseContextSearchCommand() (*Command, error) { + p.nextToken() // consume SEARCH + + cmd := NewCommand("context_search") + + for p.curToken.Type != TokenEOF { + if p.curToken.Type == TokenDash { + p.nextToken() // skip dash + if p.curToken.Type != TokenIdentifier { + return nil, fmt.Errorf("expect identifier") + } + + if strings.ToLower(p.curToken.Value) == "n" { + p.nextToken() + var err error + if p.curToken.Type != TokenNumber { + return nil, fmt.Errorf("expect number") + } + cmd.Params["number"], err = p.parseNumber() + if err != nil { + return nil, err + } + p.nextToken() + continue + } + + if strings.ToLower(p.curToken.Value) == "t" { + p.nextToken() + var err error + if p.curToken.Type != TokenNumber { + return nil, fmt.Errorf("expect number") + } + cmd.Params["threshold"], err = p.parseFloat() + if err != nil { + return nil, err + } + p.nextToken() + continue + } + + return nil, fmt.Errorf("unknow parameter: %s", p.curToken.Value) + } else if p.curToken.Type == TokenIdentifier { + if cmd.Params["path"] == nil { + cmd.Params["path"] = p.curToken.Value + } else { + cmd.Params["path"] = fmt.Sprintf("%s %s", cmd.Params["path"], p.curToken.Value) + } + p.nextToken() // skip path + } else if p.curToken.Type == TokenQuotedString { + if cmd.Params["query"] == nil { + var err error + cmd.Params["query"], err = p.parseQuotedString() + if err != nil { + return nil, err + } + p.nextToken() + } else { + return nil, fmt.Errorf("Query phrase exists") + } + } + return nil, fmt.Errorf("syntax error") + } + + return cmd, nil +} diff --git a/internal/cli/user_parser.go b/internal/cli/user_parser.go index 32882a7fa3..41090217e1 100644 --- a/internal/cli/user_parser.go +++ b/internal/cli/user_parser.go @@ -1859,10 +1859,23 @@ func (p *Parser) parseInsertMetadataFromFile() (*Command, error) { func (p *Parser) parseSearchCommand() (*Command, error) { p.nextToken() // consume SEARCH - question, err := p.parseQuotedString() - if err != nil { - return nil, err + + var err error + var question string + if p.curToken.Type == TokenQuotedString { + question, err = p.parseQuotedString() + if err != nil { + return nil, err + } + } else if p.curToken.Type == TokenIdentifier { + question, err = p.parseIdentifier() + if err != nil { + return nil, err + } + } else { + return nil, fmt.Errorf("expected quoted string or identifier") } + p.nextToken() if p.curToken.Type == TokenOn { @@ -1920,31 +1933,42 @@ func (p *Parser) parseSearchCommand() (*Command, error) { continue } - if strings.ToLower(p.curToken.Value) == "t" { - p.nextToken() - var err error - if p.curToken.Type != TokenNumber { - return nil, fmt.Errorf("expect number") - } - cmd.Params["threshold"], err = p.parseFloat() - if err != nil { - return nil, err - } - p.nextToken() - continue - } + //if strings.ToLower(p.curToken.Value) == "t" { + // p.nextToken() + // var err error + // if p.curToken.Type != TokenNumber { + // return nil, fmt.Errorf("expect number") + // } + // cmd.Params["threshold"], err = p.parseFloat() + // if err != nil { + // return nil, err + // } + // p.nextToken() + // continue + //} return nil, fmt.Errorf("unknow parameter: %s", p.curToken.Value) } else if p.curToken.Type == TokenIdentifier { if cmd.Params["path"] == nil { cmd.Params["path"] = p.curToken.Value } else { - cmd.Params["path"] = fmt.Sprintf("%s %s", cmd.Params["path"], p.curToken.Value) + cmd.Params["path"] = fmt.Sprintf("%s%s", cmd.Params["path"], p.curToken.Value) } p.nextToken() // skip path continue + } else if p.curToken.Type == TokenSlash { + if cmd.Params["path"] == nil { + cmd.Params["path"] = "/" + } else { + cmd.Params["path"] = fmt.Sprintf("%s/", cmd.Params["path"]) + } + p.nextToken() // skip slash + if p.curToken.Type == TokenIdentifier { + cmd.Params["path"] = fmt.Sprintf("%s%s", cmd.Params["path"], p.curToken.Value) + p.nextToken() + } + continue } - return nil, fmt.Errorf("syntax error") } return cmd, nil }