|
7 | 7 | from kirara_ai.im.adapter import BotProfileAdapter |
8 | 8 | from kirara_ai.im.im_registry import IMRegistry |
9 | 9 | from kirara_ai.im.manager import IMManager |
| 10 | +from kirara_ai.logger import get_logger |
10 | 11 |
|
11 | 12 | from ...auth.middleware import require_auth |
12 | 13 | from .models import (IMAdapterConfig, IMAdapterConfigSchema, IMAdapterList, IMAdapterResponse, IMAdapterStatus, |
13 | 14 | IMAdapterTypes) |
14 | 15 |
|
15 | 16 | im_bp = Blueprint("im", __name__) |
16 | 17 |
|
| 18 | +logger = get_logger("Web.IM") |
| 19 | + |
17 | 20 | def _create_adapter(manager: IMManager, name: str, adapter: str, config: dict): |
18 | 21 | registry: IMRegistry = g.container.resolve(IMRegistry) |
19 | 22 | adapter_info = registry.get_all_adapters()[adapter] |
@@ -123,48 +126,76 @@ async def create_adapter(): |
123 | 126 | @im_bp.route("/adapters/<adapter_id>", methods=["PUT"]) |
124 | 127 | @require_auth |
125 | 128 | async def update_adapter(adapter_id: str): |
126 | | - """更新适配器配置""" |
| 129 | + """更新适配器配置 (支持重命名)""" |
127 | 130 | data = await request.get_json() |
128 | | - adapter_info = IMAdapterConfig(**data) |
129 | | - registry: IMRegistry = g.container.resolve(IMRegistry) |
130 | | - |
131 | | - if adapter_id != adapter_info.name: |
132 | | - return jsonify({"error": "Adapter ID mismatch"}), 400 |
| 131 | + try: |
| 132 | + adapter_info = IMAdapterConfig(**data) |
| 133 | + except Exception as e: |
| 134 | + return jsonify({"error": f"Invalid request data: {e}"}), 400 |
133 | 135 |
|
134 | 136 | config: GlobalConfig = g.container.resolve(GlobalConfig) |
135 | 137 | manager: IMManager = g.container.resolve(IMManager) |
| 138 | + registry: IMRegistry = g.container.resolve(IMRegistry) |
136 | 139 | loop = asyncio.get_event_loop() |
137 | 140 |
|
138 | | - # 检查适配器是否存在 |
| 141 | + # 1. 检查原始适配器是否存在 |
139 | 142 | if not manager.has_adapter(adapter_id): |
140 | 143 | return jsonify({"error": "Adapter not found"}), 404 |
141 | 144 |
|
142 | | - # 更新配置 |
143 | | - adapter_config_class = registry.get_config_class(adapter_info.adapter) |
144 | | - adapter_config = adapter_config_class(**adapter_info.config) |
145 | | - manager.update_adapter_config(adapter_id, adapter_config) |
| 145 | + # 2. 如果名称改变,检查新名称是否冲突 |
| 146 | + if adapter_id != adapter_info.name and manager.has_adapter(adapter_info.name): |
| 147 | + return jsonify({"error": f"Adapter name '{adapter_info.name}' already exists"}), 400 |
146 | 148 |
|
147 | | - # 保存配置到文件 |
148 | | - ConfigLoader.save_config_with_backup(CONFIG_FILE, config) |
| 149 | + # 3. 检查适配器类型是否有效 |
| 150 | + if adapter_info.adapter not in registry.get_all_adapters(): |
| 151 | + return jsonify({"error": "Invalid adapter type specified"}), 400 |
149 | 152 |
|
150 | | - # 如果适配器正在运行,需要重启 |
151 | | - is_running = manager.is_adapter_running(adapter_id) |
152 | | - if is_running: |
153 | | - await manager.stop_adapter(adapter_id, loop) |
154 | | - |
155 | | - _create_adapter(manager, adapter_id, adapter_info.adapter, adapter_info.config) |
156 | | - |
| 153 | + # --- 停止旧适配器 (如果正在运行) --- |
| 154 | + if manager.is_adapter_running(adapter_id): |
| 155 | + try: |
| 156 | + await manager.stop_adapter(adapter_id, loop) |
| 157 | + except Exception as e: |
| 158 | + logger.error(f"Error stopping adapter {adapter_id}: {e}") |
| 159 | + |
| 160 | + # --- 更新 IMManager --- |
| 161 | + # 从管理器中删除旧的实例 |
| 162 | + manager.delete_adapter(adapter_id) |
| 163 | + |
| 164 | + # 使用新名称和配置创建新的实例 |
| 165 | + _create_adapter(manager, adapter_info.name, adapter_info.adapter, adapter_info.config) |
| 166 | + config.ims.append(adapter_info) |
| 167 | + |
| 168 | + # --- 尝试启动新适配器 (如果启用) --- |
| 169 | + is_now_running = False |
157 | 170 | if adapter_info.enable: |
158 | | - await manager.start_adapter(adapter_id, loop) |
| 171 | + try: |
| 172 | + await manager.start_adapter(adapter_info.name, loop) |
| 173 | + is_now_running = True |
| 174 | + except Exception as e: |
| 175 | + logger.error(f"Failed to start adapter '{adapter_info.name}' after update: {e}") |
159 | 176 |
|
160 | | - return IMAdapterResponse( |
161 | | - adapter=IMAdapterStatus( |
162 | | - name=adapter_id, |
163 | | - adapter=adapter_info.adapter, |
164 | | - is_running=is_running, |
165 | | - config=adapter_info.config, |
166 | | - ) |
167 | | - ).model_dump() |
| 177 | + # --- 保存配置到文件 --- |
| 178 | + # 无论是否启动成功,都保存更新后的配置 |
| 179 | + ConfigLoader.save_config_with_backup(CONFIG_FILE, config) |
| 180 | + |
| 181 | + # --- 准备并返回响应 --- |
| 182 | + bot_profile = None |
| 183 | + if is_now_running: # 仅在成功启动后尝试获取 profile |
| 184 | + adapter_instance = manager.get_adapter(adapter_info.name) |
| 185 | + if isinstance(adapter_instance, BotProfileAdapter): |
| 186 | + try: |
| 187 | + # 添加超时以防卡住 |
| 188 | + bot_profile = await asyncio.wait_for(adapter_instance.get_bot_profile(), timeout=5.0) |
| 189 | + except Exception as e: |
| 190 | + logger.error(f"Failed to get bot profile for {adapter_info.name} after update: {e}") |
| 191 | + |
| 192 | + return IMAdapterResponse(adapter=IMAdapterStatus( |
| 193 | + name=adapter_info.name, # 使用新名称 |
| 194 | + adapter=adapter_info.adapter, |
| 195 | + is_running=is_now_running, # 反映当前实际运行状态 |
| 196 | + config=adapter_info.config, |
| 197 | + bot_profile=bot_profile |
| 198 | + )).model_dump() |
168 | 199 |
|
169 | 200 |
|
170 | 201 | @im_bp.route("/adapters/<adapter_id>", methods=["DELETE"]) |
|
0 commit comments