From 5b387b68ba71d14cc82a46daec870e8749ed325b Mon Sep 17 00:00:00 2001 From: Jin Hai Date: Tue, 14 Oct 2025 14:53:00 +0800 Subject: [PATCH] The 'cmd' module is introduced to make the CLI easy to use. (#10542) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …pdate comand ### What problem does this PR solve? To make the CLI easy to use. ### Type of change - [x] New Feature (non-breaking change which adds functionality) --------- Signed-off-by: Jin Hai --- admin/admin_client.py | 70 +++++++++++++++++++++++++++++++------------ admin/services.py | 1 - 2 files changed, 51 insertions(+), 20 deletions(-) diff --git a/admin/admin_client.py b/admin/admin_client.py index dc368eb5e..5e9113725 100644 --- a/admin/admin_client.py +++ b/admin/admin_client.py @@ -16,14 +16,14 @@ import argparse import base64 +from cmd import Cmd from Cryptodome.PublicKey import RSA from Cryptodome.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5 from typing import Dict, List, Any -from lark import Lark, Transformer, Tree +from lark import Lark, Transformer, Tree, Token import requests from requests.auth import HTTPBasicAuth -from api.common.base64 import encode_to_base64 GRAMMAR = r""" start: command @@ -100,7 +100,6 @@ NUMBER: /[0-9]+/ %ignore WS """ - class AdminTransformer(Transformer): def start(self, items): @@ -183,7 +182,6 @@ class AdminTransformer(Transformer): def meta_args(self, items): return items - def encrypt(input_string): pub = '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArq9XTUSeYr2+N1h3Afl/z8Dse/2yD0ZGrKwx+EEEcdsBLca9Ynmx3nIB5obmLlSfmskLpBo0UACBmB5rEjBp2Q2f3AG3Hjd4B+gNCG6BDaawuDlgANIhGnaTLrIqWrrcm4EMzJOnAOI1fgzJRsOOUEfaS318Eq9OVO3apEyCCt0lOQK6PuksduOjVxtltDav+guVAA068NrPYmRNabVKRNLJpL8w4D44sfth5RvZ3q9t+6RTArpEtc5sh5ChzvqPOzKGMXW83C95TxmXqpbK6olN4RevSfVjEAgCydH6HN6OhtOQEcnrU97r9H0iZOWwbw3pVrZiUkuRD1R56Wzs2wIDAQAB\n-----END PUBLIC KEY-----' pub_key = RSA.importKey(pub) @@ -191,13 +189,50 @@ def encrypt(input_string): cipher_text = cipher.encrypt(base64.b64encode(input_string.encode('utf-8'))) return base64.b64encode(cipher_text).decode("utf-8") +def encode_to_base64(input_string): + base64_encoded = base64.b64encode(input_string.encode('utf-8')) + return base64_encoded.decode('utf-8') -class AdminCommandParser: +class AdminCLI(Cmd): def __init__(self): + super().__init__() self.parser = Lark(GRAMMAR, start='start', parser='lalr', transformer=AdminTransformer()) self.command_history = [] + self.is_interactive = False + self.admin_account = "admin@ragflow.io" + self.admin_password: str = "admin" + self.host: str = "" + self.port: int = 0 - def parse_command(self, command_str: str) -> Dict[str, Any]: + intro = r"""Type "\h" for help.""" + prompt = "admin> " + + def onecmd(self, command: str) -> bool: + try: + print(f"command: {command}") + result = self.parse_command(command) + self.execute_command(result) + + if isinstance(result, Tree): + return False + + if result.get('type') == 'meta' and result.get('command') in ['q', 'quit', 'exit']: + return True + + except KeyboardInterrupt: + print("\nUse '\\q' to quit") + except EOFError: + print("\nGoodbye!") + return True + return False + + def emptyline(self) -> bool: + return False + + def default(self, line: str) -> bool: + return self.onecmd(line) + + def parse_command(self, command_str: str) -> dict[str, str] | Tree[Token]: if not command_str.strip(): return {'type': 'empty'} @@ -209,16 +244,6 @@ class AdminCommandParser: except Exception as e: return {'type': 'error', 'message': f'Parse error: {str(e)}'} - -class AdminCLI: - def __init__(self): - self.parser = AdminCommandParser() - self.is_interactive = False - self.admin_account = "admin@ragflow.io" - self.admin_password: str = "admin" - self.host: str = "" - self.port: int = 0 - def verify_admin(self, args): conn_info = self._parse_connection_args(args) @@ -323,7 +348,7 @@ class AdminCLI: continue print(f"command: {command}") - result = self.parser.parse_command(command) + result = self.parse_command(command) self.execute_command(result) if isinstance(result, Tree): @@ -610,10 +635,17 @@ def main(): /_/ |_/_/ |_\____/_/ /_/\____/|__/|__/ /_/ |_\__,_/_/ /_/ /_/_/_/ /_/ """) if cli.verify_admin(sys.argv): - cli.run_interactive() + cli.cmdloop() else: + print(r""" + ____ ___ ______________ ___ __ _ + / __ \/ | / ____/ ____/ /___ _ __ / | ____/ /___ ___ (_)___ + / /_/ / /| |/ / __/ /_ / / __ \ | /| / / / /| |/ __ / __ `__ \/ / __ \ + / _, _/ ___ / /_/ / __/ / / /_/ / |/ |/ / / ___ / /_/ / / / / / / / / / / + /_/ |_/_/ |_\____/_/ /_/\____/|__/|__/ /_/ |_\__,_/_/ /_/ /_/_/_/ /_/ + """) if cli.verify_admin(sys.argv): - cli.run_interactive() + cli.cmdloop() # cli.run_single_command(sys.argv[1:]) diff --git a/admin/services.py b/admin/services.py index c3b7d3001..dd1a3c12b 100644 --- a/admin/services.py +++ b/admin/services.py @@ -179,7 +179,6 @@ class ServiceMgr: configs = SERVICE_CONFIGS.configs for service_id, config in enumerate(configs): config_dict = config.to_dict() - service_detail = None try: service_detail = ServiceMgr.get_service_details(service_id) if service_detail['alive']: