diff --git a/app.py b/app.py index d4833195..2e1dbeb0 100644 --- a/app.py +++ b/app.py @@ -14,7 +14,7 @@ async def main(): # 启动 HTTP 配置服务器 http_runner = None - if config['server'].get('http', {}).get('enabled', False): + if config['manager'].get('enabled', False): config_server = ConfigServer(config) try: http_runner = await config_server.start() diff --git a/config.yaml b/config.yaml index a4bd0e02..0ed2084d 100644 --- a/config.yaml +++ b/config.yaml @@ -17,11 +17,11 @@ server: # 可选:设备白名单,如果设置了白名单,那么白名单的机器无论是什么token都可以连接。 #allowed_devices: # - "24:0A:C4:1D:3B:F0" # MAC地址列表 - http: - enabled: false - ip: 0.0.0.0 - port: 8001 - token: password +manager: + enabled: false + ip: 0.0.0.0 + port: 8001 + token: password xiaozhi: type: hello diff --git a/core/http_server.py b/core/http_server.py index 1cee536b..185de82e 100644 --- a/core/http_server.py +++ b/core/http_server.py @@ -1,135 +1,51 @@ import logging -import yaml +import os from aiohttp import web -from core.utils.util import get_project_dir +from core.utils.util import get_local_ip, get_project_dir +from manager.api.prompt import PromptHandler logger = logging.getLogger(__name__) + +async def handle_options(request): + headers = { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type, Authorization' + } + return web.Response(headers=headers) + + class ConfigServer: def __init__(self, config: dict): self.config = config self.app = web.Application() + + # 初始化接口处理器 + self.prompt_handler = PromptHandler(config) self.setup_routes() def setup_routes(self): - self.app.router.add_get('/', self.index) - self.app.router.add_get('/api/prompt', self.get_prompt) - self.app.router.add_post('/api/prompt', self.update_prompt) - self.app.router.add_options('/api/prompt', self.handle_options) + # 注册prompt接口 + self.app.router.add_get('/api/prompt', self.prompt_handler.get_prompt) + self.app.router.add_post('/api/prompt', self.prompt_handler.update_prompt) + self.app.router.add_options('/api/prompt', handle_options) - async def index(self, request): - html = ''' - - - - 小智提示词配置 - - - - -

小智提示词配置

- -
- - -
- - - - ''' - return web.Response(text=html, content_type='text/html') - - async def handle_options(self, request): - headers = { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', - 'Access-Control-Allow-Headers': 'Content-Type, Authorization' - } - return web.Response(headers=headers) - - async def verify_token(self, request): - if 'token' not in self.config['server']['http']: - return True - - expected_token = self.config['server']['http']['token'] - token = request.headers.get('Authorization', '').replace('Bearer ', '') - - if not token or token != expected_token: - return False - return True - - async def get_prompt(self, request): - if not await self.verify_token(request): - return web.json_response({'error': 'Unauthorized'}, status=401) - - headers = {'Access-Control-Allow-Origin': '*'} - return web.json_response({ - 'prompt': self.config['prompt'] - }, headers=headers) - - async def update_prompt(self, request): - if not await self.verify_token(request): - return web.json_response({'error': 'Unauthorized'}, status=401) - - try: - data = await request.json() - if 'prompt' not in data: - return web.json_response({'error': 'Missing prompt field'}, status=400) - - # 更新内存中的配置 - self.config['prompt'] = data['prompt'] - - # 更新配置文件 - config_path = get_project_dir() + 'config.yaml' - with open(config_path, 'w', encoding='utf-8') as f: - yaml.dump(self.config, f, allow_unicode=True) - - headers = {'Access-Control-Allow-Origin': '*'} - return web.json_response({'success': True}, headers=headers) - - except Exception as e: - logger.error(f"Failed to update prompt: {e}") - return web.json_response({'error': str(e)}, status=500) + async def redirect_to_index(self, _): + raise web.HTTPFound('/manager/') async def start(self): try: - http_config = self.config['server']['http'] + http_config = self.config['manager'] if not http_config.get('enabled', False): logger.info("HTTP server is disabled") return @@ -138,7 +54,8 @@ class ConfigServer: await runner.setup() site = web.TCPSite(runner, http_config['ip'], http_config['port']) await site.start() - logger.info(f"Config HTTP server is running at http://{http_config['ip']}:{http_config['port']}") + logger.info( + f"Config HTTP server is running at http://{get_local_ip()}:{http_config['port']}/manager/index.html") return runner # 返回runner以便后续清理 except Exception as e: logger.error(f"Failed to start HTTP server: {e}") diff --git a/manager/api/auth.py b/manager/api/auth.py new file mode 100644 index 00000000..96f303b2 --- /dev/null +++ b/manager/api/auth.py @@ -0,0 +1,10 @@ +async def verify_token(config, request): + if 'token' not in config['manager']: + return True + + expected_token = config['manager']['token'] + token = request.headers.get('Authorization', '').replace('Bearer ', '') + + if not token or token != expected_token: + return False + return True diff --git a/manager/api/prompt.py b/manager/api/prompt.py new file mode 100644 index 00000000..25b28c35 --- /dev/null +++ b/manager/api/prompt.py @@ -0,0 +1,36 @@ +import logging +from aiohttp import web +from manager.api.auth import verify_token + +logger = logging.getLogger(__name__) + + +class PromptHandler: + def __init__(self, config): + self.config = config + + async def get_prompt(self, request): + if not await verify_token(self.config, request): + return web.json_response({'error': 'Unauthorized'}, status=401) + + return web.json_response({ + 'prompt': self.config['prompt'], + 'Access-Control-Allow-Origin': '*' + }) + + async def update_prompt(self, request): + if not await verify_token(self.config, request): + return web.json_response({'error': 'Unauthorized'}, status=401) + + try: + data = await request.json() + if 'prompt' not in data: + return web.json_response({'error': 'Missing prompt field'}, status=400) + + # 通过config参数回传修改能力 + self.config['prompt'] = data['prompt'] + return web.json_response({'success': True}, headers={'Access-Control-Allow-Origin': '*'}) + + except Exception as e: + logger.error(f"Failed to update prompt: {e}") + return web.json_response({'error': str(e)}, status=500) diff --git a/manager/static/index.html b/manager/static/index.html new file mode 100644 index 00000000..8c32c57c --- /dev/null +++ b/manager/static/index.html @@ -0,0 +1,53 @@ + + + + 小智提示词配置 + + + + +

小智提示词配置

+ +
+ + +
+ + + \ No newline at end of file diff --git a/manager/static/login.html b/manager/static/login.html new file mode 100644 index 00000000..9f6d80d9 --- /dev/null +++ b/manager/static/login.html @@ -0,0 +1,13 @@ + + + + login + + + + +login + + \ No newline at end of file diff --git a/static/index.html b/static/index.html new file mode 100644 index 00000000..8c32c57c --- /dev/null +++ b/static/index.html @@ -0,0 +1,53 @@ + + + + 小智提示词配置 + + + + +

小智提示词配置

+ +
+ + +
+ + + \ No newline at end of file