Coverage for aipyapp/__main__.py: 0%
133 statements
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-11 12:02 +0200
« prev ^ index » next coverage.py v7.10.3, created at 2025-08-11 12:02 +0200
1#!/usr/bin/env python
2# coding: utf-8
4import os
5import sys
7if "pythonw" in sys.executable.lower():
8 sys.stdout = open(os.devnull, "w", encoding='utf-8')
9 sys.stderr = open(os.devnull, "w", encoding='utf-8')
11from loguru import logger
13logger.remove()
14from .i18n import set_lang, T
15from .aipy import CONFIG_DIR, ConfigManager
16logger.add(CONFIG_DIR / "aipyapp.log", format="{time:HH:mm:ss} | {level} | {message} | {extra}", level='INFO')
18def parse_args():
19 import argparse
20 config_help_message = (
21 f"Specify the configuration directory.\nDefaults to {CONFIG_DIR} if not provided."
22 )
24 parser = argparse.ArgumentParser(description="Python use - AIPython", formatter_class=argparse.RawTextHelpFormatter)
25 parser.add_argument("-c", '--config-dir', default=CONFIG_DIR, type=str, help=config_help_message)
26 parser.add_argument('--debug', default=False, action='store_true', help="Debug mode")
28 modes = parser.add_mutually_exclusive_group(required=False)
29 modes.add_argument('-u', '--update', default=False, action='store_true', help="Update aipyapp to latest version")
30 modes.add_argument('-s', '--sync', default=False, action='store_true', help="Sync content from trustoken")
31 modes.add_argument('-p', '--python', default=False, action='store_true', help="Python mode")
32 modes.add_argument('-i', '--ipython', default=False, action='store_true', help="IPython mode")
33 modes.add_argument('-g', '--gui', default=False, action='store_true', help="GUI mode")
34 modes.add_argument('-e', '--exec', default=None, help="CMD mode - execute an instruction")
35 modes.add_argument('-a', '--agent', default=False, action='store_true', help='Agent mode - HTTP API server for n8n integration')
36 parser.add_argument('--port', type=int, default=8848, help="Port for agent mode HTTP server (default: 8848)")
37 parser.add_argument('--host', default='127.0.0.1', help="Host for agent mode HTTP server (default: 127.0.0.1)")
38 parser.add_argument('--style', default=None, help="Style of the display, e.g. 'classic' or 'modern'")
39 parser.add_argument('--role', default=None, help="Role to use")
40 parser.add_argument('--beta', action='store_true', help='Include beta versions in update')
42 return parser.parse_args()
44def ensure_pkg(pkg):
45 try:
46 if pkg == 'wxpython':
47 import wx
48 elif pkg == 'ipython':
49 import IPython
50 elif pkg == 'fastapi':
51 import fastapi
52 elif pkg == 'uvicorn':
53 import uvicorn
54 except ImportError:
55 import subprocess
56 print(f"Installing required package: {pkg}")
57 cp = subprocess.run([sys.executable, "-m", "pip", "install", pkg])
58 assert cp.returncode == 0
60def handle_update(args):
61 """处理 update 命令"""
62 import subprocess
63 from . import __version__
65 package_name = 'aipyapp'
66 print(f"当前版本: {__version__}")
68 if args.beta:
69 print(f"更新到最新版本 (包括测试版): {package_name}")
70 cmd = [sys.executable, "-m", "pip", "install", "--upgrade", "--pre", package_name]
71 else:
72 print(f"更新到最新稳定版本: {package_name}")
73 cmd = [sys.executable, "-m", "pip", "install", "--upgrade", package_name]
75 try:
76 result = subprocess.run(cmd, check=True, capture_output=True, text=True)
77 print("更新完成!")
78 if result.stdout.strip():
79 print(result.stdout)
80 except subprocess.CalledProcessError as e:
81 print(f"更新失败: {e.stderr}")
82 sys.exit(1)
83 except Exception as e:
84 print(f"更新失败: {str(e)}")
85 sys.exit(1)
87def handle_sync(conf, args):
88 """处理 sync 命令"""
89 conf.fetch_config()
91def init_settings(conf, args):
92 settings = conf.get_config()
93 lang = settings.get('lang')
94 if lang: set_lang(lang)
95 settings.gui = args.gui
96 settings.debug = args.debug
97 settings.config_dir = args.config_dir
98 if args.role:
99 settings['role'] = args.role.lower()
100 if args.style:
101 display_config = settings.setdefault('display', {})
102 display_config['style'] = args.style
103 if args.agent:
104 settings['agent'] = {'port': args.port, 'host': args.host}
106 #TODO: remove these lines
107 if conf.check_config(gui=True) == 'TrustToken':
108 from .config import LLMConfig
109 llm_config = LLMConfig(CONFIG_DIR / "config")
110 if llm_config.need_config():
111 settings['llm_need_config'] = True
112 if not args.gui:
113 from .aipy.wizard import show_provider_config
114 show_provider_config(llm_config)
115 if llm_config.need_config():
116 print(f"❌ {T('LLM configuration required')}")
117 sys.exit(1)
118 settings["llm"] = llm_config.config
120 settings['config_manager'] = conf
121 return settings
123def get_aipy_main(args, settings):
124 """根据参数获取对应的 aipy_main 函数"""
125 if args.agent:
126 ensure_pkg('fastapi')
127 ensure_pkg('uvicorn')
128 from .cli.cli_agent import main as aipy_main
129 elif args.python:
130 from .cli.cli_python import main as aipy_main
131 elif args.ipython:
132 ensure_pkg('ipython')
133 from .cli.cli_ipython import main as aipy_main
134 elif args.gui:
135 settings['gui'] = True
136 ensure_pkg('wxpython')
137 from .gui.main import main as aipy_main
138 else:
139 if args.exec:
140 settings['exec_cmd'] = args.exec
141 from .cli.cli_task import main as aipy_main
142 return aipy_main
144def main():
145 args = parse_args()
147 # 处理 update 子命令
148 if args.update:
149 handle_update(args)
150 return
152 conf = ConfigManager(args.config_dir)
153 if args.sync:
154 handle_sync(conf, args)
155 return
157 settings = init_settings(conf, args)
158 aipy_main = get_aipy_main(args, settings)
159 aipy_main(settings)
161def mainw():
162 args = parse_args()
163 ensure_pkg('wxpython')
164 from .gui.main import main as aipy_main
165 aipy_main(args)
167if __name__ == '__main__':
168 main()