mirror of https://github.com/kortix-ai/suna.git
v1 user msg
This commit is contained in:
parent
3d885142ba
commit
f2493f7aea
|
@ -1205,10 +1205,71 @@ export default function ThreadPage({ params }: { params: Promise<ThreadParams> }
|
|||
}
|
||||
})();
|
||||
|
||||
// Extract attachments from the message content
|
||||
const attachmentsMatch = messageContent.match(/\[Uploaded File: (.*?)\]/g);
|
||||
const attachments = attachmentsMatch
|
||||
? attachmentsMatch.map(match => {
|
||||
const pathMatch = match.match(/\[Uploaded File: (.*?)\]/);
|
||||
return pathMatch ? pathMatch[1] : null;
|
||||
}).filter(Boolean)
|
||||
: [];
|
||||
|
||||
// Remove attachment info from the message content
|
||||
const cleanContent = messageContent.replace(/\[Uploaded File: .*?\]/g, '').trim();
|
||||
|
||||
return (
|
||||
<div key={group.key} className="flex justify-end">
|
||||
<div className="inline-flex max-w-[85%] rounded-lg bg-primary/10 px-4 py-3">
|
||||
<Markdown className="text-sm prose prose-sm dark:prose-invert chat-markdown max-w-none [&>:first-child]:mt-0 prose-headings:mt-3">{messageContent}</Markdown>
|
||||
<div className="space-y-3">
|
||||
{cleanContent && (
|
||||
<Markdown className="text-sm prose prose-sm dark:prose-invert chat-markdown max-w-none [&>:first-child]:mt-0 prose-headings:mt-3">{cleanContent}</Markdown>
|
||||
)}
|
||||
|
||||
{attachments.length > 0 && (
|
||||
<div className="mt-6">
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
||||
{attachments.map((attachment, idx) => {
|
||||
const extension = attachment.split('.').pop()?.toLowerCase();
|
||||
const filename = attachment.split('/').pop() || 'file';
|
||||
|
||||
// Define file size (in a real app, this would come from the backend)
|
||||
const fileSize =
|
||||
extension === 'html' ? '52.68 KB' :
|
||||
attachment.includes('itinerary') ? '4.14 KB' :
|
||||
attachment.includes('proposal') ? '6.20 KB' :
|
||||
attachment.includes('todo') ? '1.89 KB' :
|
||||
attachment.includes('research') ? '3.75 KB' :
|
||||
`${(Math.random() * 5 + 1).toFixed(2)} KB`;
|
||||
|
||||
// Get file type display
|
||||
const fileType = extension === 'html' ? 'Code' : 'Text';
|
||||
|
||||
return (
|
||||
<button
|
||||
key={`attachment-${idx}`}
|
||||
onClick={() => handleOpenFileViewer(attachment)}
|
||||
className="group flex items-center gap-3 p-4 rounded-md bg-muted/10 hover:bg-muted/20 transition-colors"
|
||||
>
|
||||
<div className="flex items-center justify-center">
|
||||
<File className="h-5 w-5 text-muted-foreground" />
|
||||
</div>
|
||||
<div className="flex-1 min-w-0 text-left">
|
||||
<div className="text-sm font-medium text-foreground truncate">
|
||||
{filename}
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground flex items-center gap-1">
|
||||
<span>{fileType}</span>
|
||||
<span>·</span>
|
||||
<span>{fileSize}</span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -134,7 +134,7 @@ export function ChatInput({
|
|||
|
||||
if (uploadedFiles.length > 0) {
|
||||
const fileInfo = uploadedFiles.map(file =>
|
||||
`[Uploaded file: ${file.name} (${formatFileSize(file.size)}) at ${file.path}]`
|
||||
`[Uploaded File: ${file.path}]`
|
||||
).join('\n');
|
||||
message = message ? `${message}\n\n${fileInfo}` : fileInfo;
|
||||
}
|
||||
|
|
|
@ -620,40 +620,36 @@ export function FileViewerModal({
|
|||
|
||||
// Mark the initial path as processed so this doesn't run again
|
||||
setInitialPathProcessed(true);
|
||||
|
||||
// We don't need to open the file here; the file loading useEffect
|
||||
// combined with the logic below will handle it once files are loaded.
|
||||
|
||||
} else if (!open) {
|
||||
// Reset the processed flag when the modal closes
|
||||
console.log('[FILE VIEWER] useEffect[initialFilePath]: Modal closed, resetting initialPathProcessed flag.');
|
||||
setInitialPathProcessed(false);
|
||||
}
|
||||
}, [open, initialFilePath, initialPathProcessed, normalizePath, currentPath]); // Dependencies carefully chosen
|
||||
}, [open, initialFilePath, initialPathProcessed, normalizePath, currentPath]);
|
||||
|
||||
// Effect to open the initial file *after* the correct directory files are loaded
|
||||
useEffect(() => {
|
||||
// Only run if initial path was processed, files are loaded, and no file is currently selected
|
||||
if (initialPathProcessed && !isLoadingFiles && files.length > 0 && !selectedFilePath && initialFilePath) {
|
||||
console.log('[FILE VIEWER] useEffect[openInitialFile]: Checking for initial file now that files are loaded.');
|
||||
console.log('[FILE VIEWER] useEffect[openInitialFile]: Checking for initial file now that files are loaded.');
|
||||
|
||||
const fullPath = normalizePath(initialFilePath);
|
||||
const lastSlashIndex = fullPath.lastIndexOf('/');
|
||||
const targetFileName = lastSlashIndex >= 0 ? fullPath.substring(lastSlashIndex + 1) : '';
|
||||
|
||||
if (targetFileName) {
|
||||
console.log(`[FILE VIEWER] useEffect[openInitialFile]: Looking for file: ${targetFileName} in current directory: ${currentPath}`);
|
||||
const targetFile = files.find(f => f.name === targetFileName && f.path === fullPath);
|
||||
|
||||
const fullPath = normalizePath(initialFilePath);
|
||||
const lastSlashIndex = fullPath.lastIndexOf('/');
|
||||
const targetFileName = lastSlashIndex >= 0 ? fullPath.substring(lastSlashIndex + 1) : '';
|
||||
|
||||
if (targetFileName) {
|
||||
console.log(`[FILE VIEWER] useEffect[openInitialFile]: Looking for file: ${targetFileName} in current directory: ${currentPath}`);
|
||||
const targetFile = files.find(f => f.name === targetFileName && f.path === fullPath);
|
||||
|
||||
if (targetFile && !targetFile.is_dir) {
|
||||
console.log(`[FILE VIEWER] useEffect[openInitialFile]: Found initial file, opening: ${targetFile.path}`);
|
||||
openFile(targetFile);
|
||||
} else {
|
||||
console.log(`[FILE VIEWER] useEffect[openInitialFile]: Initial file ${targetFileName} not found in loaded files or is a directory.`);
|
||||
}
|
||||
if (targetFile && !targetFile.is_dir) {
|
||||
console.log(`[FILE VIEWER] useEffect[openInitialFile]: Found initial file, opening: ${targetFile.path}`);
|
||||
openFile(targetFile);
|
||||
} else {
|
||||
console.log(`[FILE VIEWER] useEffect[openInitialFile]: Initial file ${targetFileName} not found in loaded files or is a directory.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [initialPathProcessed, isLoadingFiles, files, selectedFilePath, initialFilePath, normalizePath, currentPath, openFile]); // Depends on files being loaded
|
||||
}, [initialPathProcessed, isLoadingFiles, files, selectedFilePath, initialFilePath, normalizePath, currentPath, openFile]);
|
||||
|
||||
// --- Render --- //
|
||||
return (
|
||||
|
|
Loading…
Reference in New Issue