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:
103
frontend-v2/app/api/chat/route.ts
Normal file
103
frontend-v2/app/api/chat/route.ts
Normal 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' } }
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user