claude-code-cchui/src/app/api/messages/[messageId]/route.ts
gaoziman 5a6a147bd8 feat(API): 集成秘塔AI工具和工具追踪功能
聊天API (chat/route.ts):
- 添加秘塔API Key解密和传递
- 集成工具使用追踪,记录每次对话使用的工具
- 支持图片搜索结果的流式返回
- 添加 tool_used 和 tool_search_images 事件类型

设置API (settings/route.ts):
- 支持秘塔API Key的加密存储和清除
- 更新默认工具列表包含秘塔工具

消息API (messages/route.ts):
- 支持搜索图片数据的追加保存
2025-12-22 12:22:34 +08:00

172 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { NextResponse } from 'next/server';
import { db } from '@/drizzle/db';
import { messages, type SearchImageData } from '@/drizzle/schema';
import { eq } from 'drizzle-orm';
interface RouteParams {
params: Promise<{ messageId: string }>;
}
/**
* PATCH /api/messages/[messageId] - 更新消息
* 主要用于更新消息的图片数据Pyodide 执行后保存图片)和搜索图片
*/
export async function PATCH(request: Request, { params }: RouteParams) {
try {
const { messageId } = await params;
const body = await request.json();
// 验证 messageId
if (!messageId) {
return NextResponse.json(
{ error: 'Message ID is required' },
{ status: 400 }
);
}
// 查找消息
const existingMessage = await db.query.messages.findFirst({
where: eq(messages.messageId, messageId),
});
if (!existingMessage) {
return NextResponse.json(
{ error: 'Message not found' },
{ status: 404 }
);
}
// 构建更新数据
const updateData: {
images?: string[];
searchImages?: SearchImageData[];
content?: string;
updatedAt: Date;
} = {
updatedAt: new Date(),
};
// 更新图片(追加模式)
if (body.images && Array.isArray(body.images)) {
const existingImages = (existingMessage.images as string[]) || [];
updateData.images = [...existingImages, ...body.images];
}
// 更新搜索图片(追加模式)
if (body.searchImages && Array.isArray(body.searchImages)) {
const existingSearchImages = (existingMessage.searchImages as SearchImageData[]) || [];
updateData.searchImages = [...existingSearchImages, ...body.searchImages];
}
// 更新内容(如果提供)
if (body.content !== undefined) {
updateData.content = body.content;
}
// 执行更新
await db
.update(messages)
.set(updateData)
.where(eq(messages.messageId, messageId));
// 返回更新后的消息
const updatedMessage = await db.query.messages.findFirst({
where: eq(messages.messageId, messageId),
});
return NextResponse.json({
success: true,
message: updatedMessage,
});
} catch (error) {
console.error('Update message error:', error);
return NextResponse.json(
{ error: 'Failed to update message' },
{ status: 500 }
);
}
}
/**
* GET /api/messages/[messageId] - 获取单个消息
*/
export async function GET(request: Request, { params }: RouteParams) {
try {
const { messageId } = await params;
if (!messageId) {
return NextResponse.json(
{ error: 'Message ID is required' },
{ status: 400 }
);
}
const message = await db.query.messages.findFirst({
where: eq(messages.messageId, messageId),
});
if (!message) {
return NextResponse.json(
{ error: 'Message not found' },
{ status: 404 }
);
}
return NextResponse.json({
success: true,
message,
});
} catch (error) {
console.error('Get message error:', error);
return NextResponse.json(
{ error: 'Failed to get message' },
{ status: 500 }
);
}
}
/**
* DELETE /api/messages/[messageId] - 删除消息
* 用于重新生成功能:删除 AI 消息后重新生成
*/
export async function DELETE(request: Request, { params }: RouteParams) {
try {
const { messageId } = await params;
if (!messageId) {
return NextResponse.json(
{ error: 'Message ID is required' },
{ status: 400 }
);
}
// 查找消息
const existingMessage = await db.query.messages.findFirst({
where: eq(messages.messageId, messageId),
});
if (!existingMessage) {
return NextResponse.json(
{ error: 'Message not found' },
{ status: 404 }
);
}
// 删除消息
await db
.delete(messages)
.where(eq(messages.messageId, messageId));
return NextResponse.json({
success: true,
message: 'Message deleted successfully',
});
} catch (error) {
console.error('Delete message error:', error);
return NextResponse.json(
{ error: 'Failed to delete message' },
{ status: 500 }
);
}
}