feat: 添加 Next.js API Route 使用容器环境变量

- 新增 /api/chat/route.ts 使用 Vercel AI SDK + MCP
- 使用容器环境变量 ANTHROPIC_AUTH_TOKEN 和 ANTHROPIC_BASE_URL
- 默认使用 Haiku 模型 (glm-4.5-air) 降低成本

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude AI
2026-03-24 23:25:33 +00:00
parent 2677c2c23e
commit ad4dc6e089

View File

@@ -0,0 +1,103 @@
/**
* Next.js API Route - 聊天接口
*
* 使用 Vercel AI SDK + MCP 实现流式响应
* 集成 json-render 官方 useChatUI hook
*/
import { streamText } from 'ai';
import { createAnthropic } from '@ai-sdk/anthropic';
import { createMCPClient } from '@ai-sdk/mcp';
import catalog from '@/lib/catalog/catalog';
// MCP 服务器配置
const MCP_SERVERS = {
'novel-translator': process.env.MCP_TRANSLATOR_URL || 'https://d8d-ai-vscode-8080-223-236-template-6-group.dev.d8d.fun/mcp',
'novel-platform-user': process.env.MCP_USER_URL || 'https://d8d-ai-vscode-8080-223-238-template-6-group.dev.d8d.fun/mcp/',
'novel-platform-admin': process.env.MCP_ADMIN_URL || 'https://d8d-ai-vscode-8080-223-238-template-6-group.dev.d8d.fun/admin-mcp/',
};
// 运行时配置:使用 Node.js 运行时(支持 HTTP 请求)
export const runtime = 'nodejs';
export async function POST(req: Request) {
try {
const { messages } = await req.json();
// 验证 API 配置
const authToken = process.env.ANTHROPIC_AUTH_TOKEN;
const baseUrl = process.env.ANTHROPIC_BASE_URL;
if (!authToken) {
return new Response(
JSON.stringify({ error: 'ANTHROPIC_AUTH_TOKEN not configured' }),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
}
// 创建 MCP 客户端并获取工具
const mcpClients = await Promise.all(
Object.entries(MCP_SERVERS).map(async ([name, url]) => {
try {
const client = await createMCPClient({
name,
version: '1.0.0',
transport: {
type: 'http',
url,
},
});
return { name, client };
} catch (error) {
console.error(`[API] Failed to connect to MCP ${name}:`, error);
return null;
}
})
);
// 合并所有 MCP 工具
const allTools: Record<string, any> = {};
for (const mcp of mcpClients) {
if (mcp) {
try {
const tools = await mcp.client.tools();
Object.assign(allTools, tools);
} catch (error) {
console.error(`[API] Failed to get tools from ${mcp.name}:`, error);
}
}
}
console.log(`[API] Available tools: ${Object.keys(allTools).length}`);
// 创建 Anthropic provider使用容器内环境变量
const anthropicProvider = createAnthropic({
baseURL: baseUrl,
apiKey: authToken,
});
// 创建模型实例
const modelName = process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL || 'glm-4.5-air';
const anthropicModel = anthropicProvider(modelName);
// 使用 streamText 创建流式响应
const result = streamText({
model: anthropicModel,
system: catalog.prompt({ mode: 'inline' }),
messages,
tools: allTools,
temperature: 0.7,
});
// 返回流式响应
return result.toTextStreamResponse();
} catch (error) {
console.error('[API] Error in POST /api/chat:', error);
return new Response(
JSON.stringify({
error: 'Internal server error',
details: error instanceof Error ? error.message : String(error),
}),
{ status: 500, headers: { 'Content-Type': 'application/json' } }
);
}
}