22Управление процессом OpenCode (lildax)
33"""
44import asyncio
5+ import json
56import os
67import subprocess
78import socket
89from pathlib import Path
910
10- from config import OPENCODE_BIN , PROVIDER_URL , CLI_MODEL , REQUEST_TIMEOUT
11+ from config import OPENCODE_BIN , OPENCODE_CONFIG_PATH , PROVIDER_URL , CLI_MODEL , MCP_SERVERS
1112from logging_config import logger
1213
1314
15+ def sync_mcp_to_lildax_config () -> bool :
16+ """Синхронизирует MCP сервера из bot/config.json в lildax config.
17+
18+ Читает mcp_servers из bot/config.json и обновляет секцию 'mcp'
19+ в ~/.config/lildax/config.json.
20+
21+ Returns:
22+ True если успешно, иначе False
23+ """
24+ try :
25+ # Путь к lildax config (OPENCODE_CONFIG_PATH)
26+ lildax_config_path = Path (OPENCODE_CONFIG_PATH ).expanduser ()
27+
28+ if not MCP_SERVERS :
29+ logger .debug ("No mcp_servers in bot config, skipping sync" )
30+ return True
31+
32+ # Читаем текущий lildax config
33+ try :
34+ with open (lildax_config_path , "r" , encoding = "utf-8" ) as f :
35+ lildax_config = json .load (f )
36+ except FileNotFoundError :
37+ logger .warning (f"Lildax config not found at { lildax_config_path } , creating new" )
38+ lildax_config = {}
39+ except json .JSONDecodeError as e :
40+ logger .error (f"Invalid JSON in lildax config: { e } " )
41+ return False
42+
43+ # Обновляем или создаём секцию mcp
44+ if "mcp" not in lildax_config :
45+ lildax_config ["mcp" ] = {}
46+
47+ # Формат: { "server-name": { "type": "local", "command": [...], "enabled": true } }
48+ for server_name , server_config in MCP_SERVERS .items ():
49+ if isinstance (server_config , dict ) and server_config .get ("enabled" , True ):
50+ lildax_config ["mcp" ][server_name ] = {
51+ "type" : server_config .get ("type" , "local" ),
52+ "command" : server_config .get ("command" , []),
53+ }
54+ if "cwd" in server_config :
55+ lildax_config ["mcp" ][server_name ]["cwd" ] = server_config ["cwd" ]
56+ if "environment" in server_config :
57+ lildax_config ["mcp" ][server_name ]["environment" ] = server_config ["environment" ]
58+
59+ # Сохраняем обновлённый config
60+ lildax_config_path .parent .mkdir (parents = True , exist_ok = True )
61+ with open (lildax_config_path , "w" , encoding = "utf-8" ) as f :
62+ json .dump (lildax_config , f , indent = 2 , ensure_ascii = False )
63+
64+ logger .info (f"Synced { len (MCP_SERVERS )} MCP servers to { lildax_config_path } " )
65+ return True
66+
67+ except Exception as e :
68+ logger .error (f"Failed to sync MCP to lildax config: { e } " )
69+ return False
70+
71+
1472class OpenCodeProcess :
1573 """Управление процессом lildax serve."""
1674
17- def __init__ (self , model : str = None , provider_url : str = None , workdir : Path = None , timeout : int = None ):
75+ def __init__ (self , model : str = None , provider_url : str = None , workdir : Path = None ):
1876 self .logger = logger
1977 self .process = None
2078 self .opencode_port = 4098
2179 self .model = model or CLI_MODEL
2280 self .provider_url = provider_url or PROVIDER_URL
23- self .timeout = timeout or REQUEST_TIMEOUT
2481 self .workdir = workdir or Path .cwd ()
2582 self .logger .debug (
26- f"OpenCodeProcess initialized: workdir={ self .workdir } , model={ self .model } , provider_url={ self .provider_url } , timeout= { self . timeout } "
83+ f"OpenCodeProcess initialized: workdir={ self .workdir } , model={ self .model } , provider_url={ self .provider_url } "
2784 )
2885
2986 def _remove_password_file (self ):
3087 """Удаляет файл password, чтобы lildax не требовал аутентификацию."""
31- password_file = Path .home () / ".local" / "state" / "opencode " / "password"
88+ password_file = Path .home () / ".local" / "state" / "lildax " / "password"
3289 if password_file .exists ():
3390 try :
3491 os .remove (password_file )
@@ -42,8 +99,6 @@ def _build_args(self) -> list[str]:
4299 args .extend (["--provider-url" , self .provider_url ])
43100 if self .model :
44101 args .extend (["--model" , self .model ])
45- if self .timeout :
46- args .extend (["--timeout" , str (self .timeout )])
47102 return args
48103
49104 async def start (self ):
@@ -66,6 +121,9 @@ async def start(self):
66121 break
67122 await asyncio .sleep (0.5 )
68123
124+ # Синхронизируем MCP сервера в lildax config (после убийства, до старта)
125+ sync_mcp_to_lildax_config ()
126+
69127 # Логирование в файл для отладки
70128 log_file_path = f"/tmp/lildax_{ self .opencode_port } .log"
71129 log_file = None
@@ -103,13 +161,11 @@ async def start(self):
103161 if log_file :
104162 log_file .close ()
105163
106- async def restart (self , model : str = None , provider_url : str = None , workdir : Path = None , timeout : int = None ):
164+ async def restart (self , model : str = None , provider_url : str = None , workdir : Path = None ):
107165 if model :
108166 self .model = model
109167 if provider_url :
110168 self .provider_url = provider_url
111- if timeout :
112- self .timeout = timeout
113169 if workdir :
114170 self .logger .info (
115171 f"restart: updating workdir from { self .workdir } to { workdir } "
0 commit comments