chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:04:19 +08:00
commit 46c3330e28
212 changed files with 65282 additions and 0 deletions
+225
View File
@@ -0,0 +1,225 @@
"""
ga_cli/cli.py - GenericAgent 命令行分发系统
通过 python -m ga_cli <命令> 或 ga <命令> 调用
"""
import os, sys, subprocess, argparse, textwrap
# Windows GBK 终端兼容
if sys.platform == "win32" and sys.stdout.encoding and sys.stdout.encoding.lower() in ("gbk", "gb2312"):
sys.stdout.reconfigure(errors="replace") if hasattr(sys.stdout, "reconfigure") else None
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
PROJECT_DIR = os.path.dirname(SCRIPT_DIR)
def _frontends():
return os.path.join(PROJECT_DIR, "frontends")
def _reflect():
return os.path.join(PROJECT_DIR, "reflect")
def launch_frontend(cmd_parts, args=None):
"""启动前端/工具进程"""
full_cmd = []
for part in cmd_parts:
part = part.replace("{PROJECT_DIR}", PROJECT_DIR)
part = part.replace("{FRONTENDS}", _frontends())
part = part.replace("{REFLECT}", _reflect())
full_cmd.append(part)
# 插入额外参数
if args:
full_cmd.extend(args)
print(f"🚀 {' '.join(full_cmd)}")
sys.stdout.flush()
os.chdir(PROJECT_DIR)
proc = subprocess.Popen(full_cmd)
try:
proc.wait()
except KeyboardInterrupt:
proc.terminate()
sys.exit(0)
COMMANDS = {
"gui": {
"help": "启动桌面GUI (qtapp)",
"desc": "启动基于 PyQt5 的完整桌面聊天界面(气泡代码高亮、文件拖拽、历史搜索)",
"cmd": ["python", "{FRONTENDS}/qtapp.py"],
},
"configure": {
"help": "运行初始配置向导 (configure_mykey.py)",
"desc": "首次安装后配置 API Key、模型参数等基础设置",
"cmd": ["python", "{PROJECT_DIR}/assets/configure_mykey.py"],
},
"hub": {
"help": "启动 Hub 管理器 (launcher)",
"desc": "启动 hub 前端管理面板(系统托盘 + 浏览器界面)",
"cmd": ["python", "{PROJECT_DIR}/hub.pyw"],
},
"tui": {
"help": "启动终端 TUI (tuiapp)",
"desc": "启动终端图形界面(Textual),适合纯终端环境或 SSH",
"cmd": ["python", "{FRONTENDS}/tuiapp.py"],
},
"tui2": {
"help": "启动终端 TUI v2 (tuiapp_v2)",
"desc": "启动增强版终端图形界面(Textual v2),更多功能更好的体验",
"cmd": ["python", "{FRONTENDS}/tuiapp_v2.py"],
},
"cli": {
"help": "启动 CLI 对话 (agentmain)",
"desc": "启动命令行交互对话模式,最轻量的使用方式",
"cmd": ["python", "{PROJECT_DIR}/agentmain.py"],
},
"launch": {
"help": "启动 webview 桌面壳 (launch.pyw)",
"desc": "以原生窗口形式包装 stapp Web 界面(基于 pywebview",
"cmd": ["python", "{PROJECT_DIR}/launch.pyw"],
},
"status": {
"help": "检查运行状态",
"desc": "检查当前是否已有 GenericAgent 进程在运行",
"cmd": None,
"internal": True,
},
"update": {
"help": "更新项目 (git pull + pip install)",
"desc": "从 Git 拉取最新代码并更新依赖",
"cmd": None,
"internal": True,
},
"list": {
"help": "列出所有可用前端/服务",
"desc": "显示所有注册的命令",
"cmd": None,
"internal": True,
},
}
def cmd_list():
"""展示所有可用命令"""
print()
frontend_cmds = [(k, v) for k, v in sorted(COMMANDS.items()) if v["cmd"] is not None]
internal_cmds = [(k, v) for k, v in sorted(COMMANDS.items()) if v["cmd"] is None]
print(f" {'命令':20s} {'说明'}")
print(f" {''*20} {''*40}")
for name, info in frontend_cmds:
print(f" {name:20s} {info.get('help', info['desc'][:40])}")
print()
for name, info in internal_cmds:
print(f" {name:20s} {info.get('help', info['desc'][:40])}")
print()
def cmd_status():
"""检查进程状态"""
import psutil
running = [p for p in psutil.process_iter(['pid', 'name', 'cmdline'])
if p.info['cmdline'] and any('agentmain' in c for c in p.info['cmdline'])]
if running:
print(f"🟢 运行中: {len(running)} 个进程")
for p in running:
print(f" PID {p.info['pid']}{' '.join(p.info['cmdline'][:3])}")
else:
print("⚫ GenericAgent 进程未运行")
def cmd_update():
"""git pull + pip install"""
os.chdir(PROJECT_DIR)
print("🔄 git pull...")
r = subprocess.run(["git", "pull"], capture_output=True, text=True)
print(r.stdout)
if r.returncode != 0:
print(r.stderr)
print("📦 pip install...")
r2 = subprocess.run([sys.executable, "-m", "pip", "install", "-e", "."],
capture_output=True, text=True)
print(r2.stdout[-500:] if r2.stdout else "")
if r2.returncode != 0:
print(r2.stderr[-500:])
def main():
parser = argparse.ArgumentParser(
prog="ga",
description="GenericAgent 全局命令入口",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=textwrap.dedent("""\
示例:
ga gui 启动桌面 GUI
ga web 启动 Web 增强版
ga web --native 启动 Web 基础版(桌面壳)
ga tui 启动终端 TUI (v1)
ga tui2 启动终端 TUI (v2 增强版)
ga pet 启动桌面宠物 v2
ga launch 启动 webview 桌面壳
ga list 列出所有命令
"""),
)
parser.add_argument("command", nargs="?", help="命令名")
parser.add_argument("args", nargs="*", help="子命令参数")
parser.add_argument("-v", "--version", action="store_true", help="显示版本")
args, unknown = parser.parse_known_args()
if args.version:
print("GenericAgent v0.1.0")
return
cmd = args.command
if not cmd or cmd == "help":
parser.print_help()
print("\n--- 命令列表 ---")
cmd_list()
return
if cmd == "list":
cmd_list()
return
if cmd == "status":
cmd_status()
return
if cmd == "update":
cmd_update()
return
if cmd not in COMMANDS:
print(f"❌ 未知命令: {cmd}")
print(f" 使用 'ga list' 查看可用命令")
sys.exit(1)
info = COMMANDS[cmd]
# 内置命令走内部逻辑
if info.get("internal"):
print(f"❌ 命令 {cmd} 没有配置启动命令")
sys.exit(1)
extra = list(args.args) + unknown
# === 处理命令特有 flags ===
cmd_parts = list(info["cmd"])
# 处理 flags (如 --native)
flags = info.get("flags", {})
for flag_name, flag_info in flags.items():
if flag_name in extra:
cmd_parts = list(flag_info["cmd"])
extra.remove(flag_name)
break
launch_frontend(cmd_parts, extra if extra else None)
if __name__ == "__main__":
main()