feat: 画布聊天自动使用最近图片
当用户发送文字请求但没有附带图片时,自动按以下优先级获取图片: 1. 画布中选中的图片 2. 画布中最近添加的图片 3. 历史对话中的图片 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
1f26ec911c
commit
ddf49cb329
@ -356,6 +356,43 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
|
||||
// 标记是否已经为当前画布设置过标题(避免重复调用)
|
||||
const hasSetCanvasTitle = useRef(false);
|
||||
|
||||
// 获取最近的图片 URL(用于自动附加)
|
||||
const getRecentImageUrl = useCallback((): string | null => {
|
||||
// 1. 优先使用画布中选中的图片
|
||||
if (selectedImageNodes.length > 0) {
|
||||
return (selectedImageNodes[0].data as any)?.src || null;
|
||||
}
|
||||
|
||||
// 2. 其次使用画布中最近添加的图片
|
||||
const imageNodes = nodes.filter(n => n.type === 'image' && (n.data as any)?.src);
|
||||
if (imageNodes.length > 0) {
|
||||
// 返回最后一个添加的图片(假设数组末尾是最新的)
|
||||
return (imageNodes[imageNodes.length - 1].data as any)?.src || null;
|
||||
}
|
||||
|
||||
// 3. 最后从历史对话中查找图片
|
||||
for (let i = messages.length - 1; i >= 0; i--) {
|
||||
const msg = messages[i];
|
||||
// 检查用户消息的附件
|
||||
if (msg.role === 'user' && (msg as any).attachments?.length > 0) {
|
||||
const attachment = (msg as any).attachments[0];
|
||||
if (attachment.url && attachment.contentType?.startsWith('image/')) {
|
||||
return attachment.url;
|
||||
}
|
||||
}
|
||||
// 检查用户消息的 parts
|
||||
if (msg.role === 'user' && (msg as any).parts) {
|
||||
for (const part of (msg as any).parts) {
|
||||
if (part.type === 'file' && part.url && part.mediaType?.startsWith('image/')) {
|
||||
return part.url;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}, [selectedImageNodes, nodes, messages]);
|
||||
|
||||
// 处理发送(图片已在上传时添加到画布,这里只发送消息)
|
||||
const handleSend = useCallback(async () => {
|
||||
if (!input.trim() && attachments.length === 0) return;
|
||||
@ -367,8 +404,23 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
|
||||
// 构建 parts 数组:文件在前,文本在后(与 multimodal-input 一致)
|
||||
const parts: any[] = [];
|
||||
|
||||
// 🆕 如果没有附件,自动使用最近的图片
|
||||
let effectiveAttachments = [...attachments];
|
||||
if (effectiveAttachments.length === 0 && input.trim()) {
|
||||
const recentImageUrl = getRecentImageUrl();
|
||||
if (recentImageUrl) {
|
||||
// 自动添加最近的图片作为附件
|
||||
effectiveAttachments.push({
|
||||
url: recentImageUrl,
|
||||
name: '最近图片',
|
||||
contentType: 'image/jpeg',
|
||||
});
|
||||
console.log('[CanvasChat] 自动使用最近图片:', recentImageUrl);
|
||||
}
|
||||
}
|
||||
|
||||
// 添加文件部分(作为 file 类型的 part)
|
||||
attachments.forEach((a) => {
|
||||
effectiveAttachments.forEach((a) => {
|
||||
parts.push({
|
||||
type: "file" as const,
|
||||
mediaType: a.contentType,
|
||||
@ -378,7 +430,7 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
|
||||
});
|
||||
|
||||
// 添加文本部分
|
||||
const textContent = input.trim() || (attachments.length > 0 ? "请处理这张图片" : "");
|
||||
const textContent = input.trim() || (effectiveAttachments.length > 0 ? "请处理这张图片" : "");
|
||||
if (textContent) {
|
||||
parts.push({ type: "text" as const, text: textContent });
|
||||
}
|
||||
@ -391,7 +443,7 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
|
||||
|
||||
setInput("");
|
||||
setAttachments([]);
|
||||
}, [input, attachments, selectedModelId, sendMessage]);
|
||||
}, [input, attachments, selectedModelId, sendMessage, getRecentImageUrl]);
|
||||
|
||||
// 处理文件选择 - 上传后立即添加到画布
|
||||
const handleFileSelect = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user