66import multiprocessing
77import queue # <-- FIX: Added missing import for queue.Empty
88import sys
9+ import time
910from asyncio import Lock , Queue
1011from contextlib import asynccontextmanager
1112from typing import Any , Awaitable , Callable
@@ -62,7 +63,7 @@ def _initialize_globals() -> None:
6263 state .model_switching_lock = Lock ()
6364 state .params_cache_lock = Lock ()
6465 auth_utils .initialize_keys ()
65- state .logger .info ("API keys and global locks initialized." )
66+ state .logger .debug ("API keys and global locks initialized." )
6667
6768
6869def _initialize_proxy_settings () -> None :
@@ -79,11 +80,11 @@ def _initialize_proxy_settings() -> None:
7980 state .PLAYWRIGHT_PROXY_SETTINGS = {"server" : proxy_server_env }
8081 if NO_PROXY_ENV :
8182 state .PLAYWRIGHT_PROXY_SETTINGS ["bypass" ] = NO_PROXY_ENV .replace ("," , ";" )
82- state .logger .info (
83- f"Playwright proxy settings configured : { state .PLAYWRIGHT_PROXY_SETTINGS } "
83+ state .logger .debug (
84+ f"[代理] 已配置 : { state .PLAYWRIGHT_PROXY_SETTINGS . get ( 'server' , 'N/A' ) } "
8485 )
8586 else :
86- state .logger .info ( "No proxy configured for Playwright. " )
87+ state .logger .debug ( "[代理] 未配置 " )
8788
8889
8990async def _start_stream_proxy () -> None :
@@ -96,24 +97,24 @@ async def _start_stream_proxy() -> None:
9697 or get_environment_variable ("HTTPS_PROXY" )
9798 or get_environment_variable ("HTTP_PROXY" )
9899 )
99- state .logger .info (
100- f"Starting STREAM proxy on port { port } with upstream proxy: { STREAM_PROXY_SERVER_ENV } "
101- )
100+ state .logger .info (f"[系统] 启动流式代理服务 (端口: { port } )" )
102101 state .STREAM_QUEUE = multiprocessing .Queue ()
103102 state .STREAM_PROCESS = multiprocessing .Process (
104103 target = stream .start ,
105104 args = (state .STREAM_QUEUE , port , STREAM_PROXY_SERVER_ENV ),
106105 )
107106 state .STREAM_PROCESS .start ()
108- state .logger .info ("STREAM proxy process started. Waiting for 'READY' signal..." )
107+ state .logger .debug (
108+ "STREAM proxy process started. Waiting for 'READY' signal..."
109+ )
109110
110111 # Wait for the proxy to be ready
111112 try :
112113 # Use asyncio.to_thread to wait for the blocking queue.get()
113114 # Set a timeout to avoid waiting forever
114115 ready_signal = await asyncio .to_thread (state .STREAM_QUEUE .get , timeout = 15 )
115116 if ready_signal == "READY" :
116- state .logger .info ("Received 'READY' signal from STREAM proxy. " )
117+ state .logger .info ("[系统] 流式代理就绪 " )
117118 else :
118119 state .logger .warning (
119120 f"Received unexpected signal from proxy: { ready_signal } "
@@ -129,10 +130,9 @@ async def _initialize_browser_and_page() -> None:
129130 """Initialize Playwright browser connection and page."""
130131 from playwright .async_api import async_playwright
131132
132- state .logger .info ( "Starting Playwright..." )
133+ state .logger .debug ( "[内核] 正在启动 Playwright..." )
133134 state .playwright_manager = await async_playwright ().start ()
134135 state .is_playwright_ready = True
135- state .logger .info ("Playwright started." )
136136
137137 ws_endpoint = get_environment_variable ("CAMOUFOX_WS_ENDPOINT" )
138138 launch_mode = get_environment_variable ("LAUNCH_MODE" , "unknown" )
@@ -141,20 +141,20 @@ async def _initialize_browser_and_page() -> None:
141141 raise ValueError ("CAMOUFOX_WS_ENDPOINT environment variable is missing." )
142142
143143 if ws_endpoint :
144- state .logger .info (f"Connecting to browser at: { ws_endpoint } " )
144+ state .logger .debug (f"Connecting to browser at: { ws_endpoint } " )
145145 state .browser_instance = await state .playwright_manager .firefox .connect (
146146 ws_endpoint , timeout = 30000
147147 )
148148 state .is_browser_connected = True
149- state .logger .info (f"Connected to browser : { state .browser_instance .version } " )
149+ state .logger .info (f"[浏览器] 已连接 (版本 : { state .browser_instance .version } ) " )
150150
151151 state .page_instance , state .is_page_ready = await _initialize_page_logic (
152152 state .browser_instance
153153 )
154154 if state .is_page_ready :
155155 await _handle_initial_model_state_and_storage (state .page_instance )
156156 await enable_temporary_chat_mode (state .page_instance )
157- state .logger .info ("Page initialized successfully. " )
157+ state .logger .info ("[系统] 页面初始化成功 " )
158158 else :
159159 state .logger .error ("Page initialization failed." )
160160
@@ -165,7 +165,7 @@ async def _initialize_browser_and_page() -> None:
165165async def _shutdown_resources () -> None :
166166 """Gracefully shut down all resources."""
167167 logger = state .logger
168- logger .info ( "Shutting down resources ..." )
168+ logger .debug ( "[系统] 正在关闭资源 ..." )
169169
170170 # Signal all streaming generators to exit immediately
171171 state .should_exit = True
@@ -185,29 +185,29 @@ async def _shutdown_resources() -> None:
185185 state .STREAM_QUEUE .join_thread ()
186186 except Exception :
187187 pass
188- logger .info ("STREAM proxy terminated." )
188+ logger .debug ("STREAM proxy terminated." )
189189
190190 if state .worker_task and not state .worker_task .done ():
191- logger .info ("Cancelling worker task..." )
191+ logger .debug ("Cancelling worker task..." )
192192 state .worker_task .cancel ()
193193 try :
194194 await asyncio .wait_for (state .worker_task , timeout = 2.0 )
195- logger .info ("Worker task cancelled." )
195+ logger .debug ("Worker task cancelled." )
196196 except asyncio .TimeoutError :
197197 logger .warning ("Worker task did not respond to cancellation within 2s." )
198198 except asyncio .CancelledError :
199- logger .info ("Worker task cancelled." )
199+ logger .debug ("Worker task cancelled." )
200200
201201 if state .page_instance :
202202 await _close_page_logic ()
203203
204204 if state .browser_instance and state .browser_instance .is_connected ():
205205 await state .browser_instance .close ()
206- logger .info ("Browser connection closed." )
206+ logger .debug ("Browser connection closed." )
207207
208208 if state .playwright_manager :
209209 await state .playwright_manager .stop ()
210- logger .info ("Playwright stopped." )
210+ logger .debug ("Playwright stopped." )
211211
212212
213213@asynccontextmanager
@@ -225,7 +225,8 @@ async def lifespan(app: FastAPI):
225225 load_excluded_models (EXCLUDED_MODELS_FILENAME )
226226
227227 state .is_initializing = True
228- logger .info ("Starting AI Studio Proxy Server..." )
228+ startup_start_time = time .time ()
229+ logger .info ("[系统] AI Studio 代理服务器启动中..." )
229230
230231 try :
231232 await _start_stream_proxy ()
@@ -234,11 +235,12 @@ async def lifespan(app: FastAPI):
234235 launch_mode = get_environment_variable ("LAUNCH_MODE" , "unknown" )
235236 if state .is_page_ready or launch_mode == "direct_debug_no_browser" :
236237 state .worker_task = asyncio .create_task (queue_worker ())
237- logger .info ("Request processing worker started." )
238+ logger .debug ("Request processing worker started." )
238239 else :
239240 raise RuntimeError ("Failed to initialize browser/page, worker not started." )
240241
241- logger .info ("Server startup complete." )
242+ startup_duration = time .time () - startup_start_time
243+ logger .info (f"[系统] 服务器启动完成 (耗时: { startup_duration :.2f} 秒)" )
242244 state .is_initializing = False
243245 yield
244246 except asyncio .CancelledError :
@@ -248,11 +250,11 @@ async def lifespan(app: FastAPI):
248250 await _shutdown_resources ()
249251 raise RuntimeError (f"Application startup failed: { e } " ) from e
250252 finally :
251- logger .info ("Shutting down server ..." )
253+ logger .info ("[系统] 服务器关闭中 ..." )
252254 await _shutdown_resources ()
253255 restore_original_streams (initial_stdout , initial_stderr )
254256 restore_original_streams (* original_streams )
255- logger .info ("Server shutdown complete. " )
257+ logger .info ("[系统] 服务器已关闭 " )
256258
257259
258260class APIKeyAuthMiddleware (BaseHTTPMiddleware ):
@@ -330,24 +332,26 @@ def create_app() -> FastAPI:
330332
331333 from .routers import (
332334 add_api_key ,
335+ auth_files_router ,
333336 cancel_request ,
334337 chat_completions ,
335338 delete_api_key ,
336339 get_api_info ,
337340 get_api_keys ,
338- get_css ,
339- get_js ,
340341 get_queue_status ,
341342 health_check ,
342343 list_models ,
344+ model_capabilities_router ,
345+ ports_router ,
346+ proxy_router ,
343347 read_index ,
348+ serve_react_assets ,
344349 test_api_key ,
345350 websocket_log_endpoint ,
346351 )
347352
348353 app .get ("/" , response_class = FileResponse )(read_index )
349- app .get ("/webui.css" )(get_css )
350- app .get ("/webui.js" )(get_js )
354+ app .get ("/assets/{filename:path}" )(serve_react_assets ) # React built assets
351355 app .get ("/api/info" )(get_api_info )
352356 app .get ("/health" )(health_check )
353357 app .get ("/v1/models" )(list_models )
@@ -356,6 +360,20 @@ def create_app() -> FastAPI:
356360 app .get ("/v1/queue" )(get_queue_status )
357361 app .websocket ("/ws/logs" )(websocket_log_endpoint )
358362
363+ # Model capabilities endpoint (single source of truth)
364+ app .include_router (model_capabilities_router )
365+
366+ # Proxy, auth, and port management routers
367+ app .include_router (proxy_router )
368+ app .include_router (auth_files_router )
369+ app .include_router (ports_router )
370+
371+ # Server control and helper routers
372+ from api_utils .routers import helper_router , server_router
373+
374+ app .include_router (server_router )
375+ app .include_router (helper_router )
376+
359377 # API密钥管理端点
360378 app .get ("/api/keys" )(get_api_keys )
361379 app .post ("/api/keys" )(add_api_key )
0 commit comments