d1f789cc10
新增平台 Anthropic 网关路由 /api/llm/anthropic/{*path},复用账号 Router 凭据边界
OpenAI 侧规范路径改为 /api/llm/v1/responses 与 /api/llm/v1/chat/completions,旧路径保留兼容
baseUrl 不再携带路由与版本段,统一由协议自己拼 v1/<op>
cc 执行器改走平台网关,ANTHROPIC_AUTH_TOKEN 复用平台会话,不再直连 Router
后台模型目录 agentMode 增加 anthropic,管理页与客户端契约同步
补齐三条路由埋点与静态段白名单,新增三条回归测试
同步后端架构文档、模型别名文档与排障记忆
107 lines
3.6 KiB
Rust
107 lines
3.6 KiB
Rust
use axum::{
|
|
Router,
|
|
extract::DefaultBodyLimit,
|
|
middleware,
|
|
routing::{get, post},
|
|
};
|
|
|
|
use crate::{
|
|
auth::require_bearer_auth,
|
|
llm::{
|
|
LLM_REQUEST_MAX_BODY_BYTES, list_llm_models, proxy_llm_chat_completions,
|
|
proxy_llm_messages, proxy_llm_responses,
|
|
},
|
|
state::AppState,
|
|
volcengine_speech::{
|
|
get_volcengine_speech_config, stream_volcengine_asr, stream_volcengine_tts_bidirection,
|
|
stream_volcengine_tts_sse,
|
|
},
|
|
};
|
|
|
|
pub fn router(state: AppState) -> Router<AppState> {
|
|
Router::new()
|
|
.route(
|
|
"/api/llm/models",
|
|
get(list_llm_models).route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_bearer_auth,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/llm/chat/completions",
|
|
post(proxy_llm_chat_completions)
|
|
.route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_bearer_auth,
|
|
))
|
|
.layer(DefaultBodyLimit::max(LLM_REQUEST_MAX_BODY_BYTES)),
|
|
)
|
|
.route(
|
|
"/api/llm/v1/chat/completions",
|
|
post(proxy_llm_chat_completions)
|
|
.route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_bearer_auth,
|
|
))
|
|
.layer(DefaultBodyLimit::max(LLM_REQUEST_MAX_BODY_BYTES)),
|
|
)
|
|
.route(
|
|
"/api/llm/responses",
|
|
post(proxy_llm_responses)
|
|
.route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_bearer_auth,
|
|
))
|
|
.layer(DefaultBodyLimit::max(LLM_REQUEST_MAX_BODY_BYTES)),
|
|
)
|
|
.route(
|
|
"/api/llm/v1/responses",
|
|
post(proxy_llm_responses)
|
|
.route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_bearer_auth,
|
|
))
|
|
.layer(DefaultBodyLimit::max(LLM_REQUEST_MAX_BODY_BYTES)),
|
|
)
|
|
// Anthropic 客户端(Claude Agent SDK / Claude Code CLI)固定请求
|
|
// `{ANTHROPIC_BASE_URL}/v1/messages`,所以这里只声明 Anthropic 自己的
|
|
// 路由前缀,尾段交给上游协议本身,网关不自己发明版本段。
|
|
.route(
|
|
"/api/llm/anthropic/{*path}",
|
|
post(proxy_llm_messages)
|
|
.route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_bearer_auth,
|
|
))
|
|
.layer(DefaultBodyLimit::max(LLM_REQUEST_MAX_BODY_BYTES)),
|
|
)
|
|
.route(
|
|
"/api/speech/volcengine/config",
|
|
get(get_volcengine_speech_config).route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_bearer_auth,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/speech/volcengine/asr/stream",
|
|
get(stream_volcengine_asr).route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_bearer_auth,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/speech/volcengine/tts/bidirection",
|
|
get(stream_volcengine_tts_bidirection).route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_bearer_auth,
|
|
)),
|
|
)
|
|
.route(
|
|
"/api/speech/volcengine/tts/sse",
|
|
post(stream_volcengine_tts_sse).route_layer(middleware::from_fn_with_state(
|
|
state.clone(),
|
|
require_bearer_auth,
|
|
)),
|
|
)
|
|
}
|