补全注释

This commit is contained in:
h88782481 2026-03-10 08:43:07 +08:00
parent 96fbc4da80
commit f193c48ce1
13 changed files with 115 additions and 14 deletions

View file

@ -27,11 +27,13 @@ bp = Blueprint('admin', __name__)
@bp.route('/admin')
@bp.route('/admin/')
def admin_page():
"""返回管理面板首页 HTML 页面,供浏览器进入配置界面。"""
return send_from_directory(_STATIC_DIR, 'admin.html')
@bp.route('/static/<path:filename>')
def static_files(filename):
"""提供管理面板所需的静态资源文件。"""
return send_from_directory(_STATIC_DIR, filename)
@ -40,6 +42,7 @@ def static_files(filename):
@bp.route('/v1/models', methods=['GET'])
def list_models():
"""返回当前配置的模型列表,供 Cursor 拉取可用模型。"""
mappings = settings.get().get('model_mappings', {})
models = [{
'id': name,
@ -61,6 +64,7 @@ def list_models():
@bp.route('/api/admin/login', methods=['POST'])
def admin_login():
"""校验管理面板登录密钥,并返回是否允许进入后台。"""
data = request.get_json(force=True)
if not Config.ACCESS_API_KEY:
return jsonify({'ok': True, 'message': '未配置鉴权'})
@ -74,6 +78,7 @@ def admin_login():
@bp.route('/api/admin/settings', methods=['GET'])
def get_settings():
"""读取当前生效的全局代理配置。"""
err = _check_auth()
if err:
return err
@ -88,6 +93,7 @@ def get_settings():
@bp.route('/api/admin/settings', methods=['PUT'])
def update_settings():
"""更新全局上游地址与密钥配置。"""
err = _check_auth()
if err:
return err
@ -104,6 +110,7 @@ def update_settings():
@bp.route('/api/admin/mappings', methods=['GET'])
def list_mappings():
"""列出所有模型映射配置,供管理面板读取和展示。"""
err = _check_auth()
if err:
return err
@ -112,6 +119,7 @@ def list_mappings():
@bp.route('/api/admin/mappings', methods=['POST'])
def add_mapping():
"""新增一条模型映射,并写入持久化配置。"""
err = _check_auth()
if err:
return err
@ -133,6 +141,7 @@ def add_mapping():
@bp.route('/api/admin/mappings/<path:name>', methods=['PUT'])
def update_mapping(name):
"""更新指定名称的模型映射,必要时支持重命名。"""
err = _check_auth()
if err:
return err
@ -158,6 +167,7 @@ def update_mapping(name):
@bp.route('/api/admin/mappings/<path:name>', methods=['DELETE'])
def delete_mapping(name):
"""删除指定名称的模型映射,并在存在时同步保存配置。"""
err = _check_auth()
if err:
return err
@ -185,7 +195,10 @@ def _check_auth():
def _save_and_respond(data, log_msg):
"""保存配置并返回响应"""
"""保存配置并返回统一成功响应。
当写盘失败时这里也负责把异常转成结构化的 JSON 错误返回
"""
try:
settings.save(data)
except OSError as e:

View file

@ -149,6 +149,7 @@ def _handle_openai_stream(
payload['stream'] = True
def generate():
"""消费上游 OpenAI SSE并逐段产出给 Cursor 的聊天补全流。"""
resp, err = forward_request(url, headers, payload, stream=True)
if err:
yield chat_error_chunk(str(err))
@ -235,6 +236,7 @@ def _handle_responses_stream(
converter = ResponsesToCCStreamConverter(model=ctx.client_model)
def generate():
"""消费上游 Responses 事件,并实时转换成聊天补全 chunk。"""
resp, err = forward_request(url, headers, payload, stream=True)
if err:
yield chat_error_chunk(str(err))
@ -314,6 +316,7 @@ def _handle_anthropic_stream(
converter = AnthropicStreamConverter()
def generate():
"""消费上游 Anthropic 事件流,并逐步映射为聊天补全 SSE。"""
resp, err = forward_request(url, headers, payload, stream=True)
if err:
yield chat_error_chunk(str(err))

View file

@ -19,7 +19,11 @@ logger = logging.getLogger(__name__)
@dataclass(frozen=True)
class RouteContext:
"""数据面路由使用的标准请求上下文。"""
"""数据面路由使用的标准请求上下文。
路由层会先根据客户端模型名解析出统一上下文后续处理函数只需要关心
上游模型后端类型目标地址鉴权信息和流式标记而不必重复访问配置层
"""
client_model: str
upstream_model: str

View file

@ -22,6 +22,7 @@ bp = Blueprint('messages', __name__)
@bp.route('/v1/messages', methods=['POST'])
def messages_passthrough():
"""透传 Anthropic Messages 请求,并在必要时补齐 thinking 兼容层。"""
payload = request.get_json(force=True)
model = payload.get('model', 'unknown')
is_stream = payload.get('stream', False)
@ -43,6 +44,7 @@ def messages_passthrough():
# 流式透传
def generate():
"""建立上游流式连接并逐段回传处理后的 SSE 数据。"""
try:
resp = req_lib.post(
url, headers=headers, json=payload,
@ -132,7 +134,7 @@ def _process_stream(resp):
def _emit_thinking_blocks(text):
"""生成 thinking block 的 SSE 事件序列"""
"""生成一组等价的 Anthropic thinking block SSE 事件。"""
yield (
f'event: content_block_start\n'
f'data: {json.dumps({"type": "content_block_start", "index": 0, "content_block": {"type": "thinking", "thinking": ""}})}\n\n'

View file

@ -126,6 +126,7 @@ def _handle_openai_stream(
converter = ResponsesStreamConverter(model=ctx.client_model)
def generate():
"""消费 OpenAI 聊天补全流,并实时改写为 Responses SSE。"""
yield from converter.start_events()
resp, err = forward_request(url, headers, cc_payload, stream=True)
@ -205,6 +206,7 @@ def _handle_responses_stream(
converter = ResponsesStreamConverter(model=ctx.client_model)
def generate():
"""透传上游原生 Responses 流,并做轻量模型名改写。"""
resp, err = forward_request(url, headers, payload, stream=True)
if err:
yield responses_error_event(str(err))
@ -275,6 +277,7 @@ def _handle_anthropic_stream(
converter = ResponsesStreamConverter(model=ctx.client_model)
def generate():
"""消费 Anthropic SSE并直接映射为 Responses 事件序列。"""
yield from converter.start_events()
resp, err = forward_request(url, headers, anthropic_payload, stream=True)