DEV Community

Ramu Narasinga
Ramu Narasinga

Posted on • Edited on • Originally published at thinkthroo.com

FileViewerModal component in Suna, an open source generalist AI agent.

In this article, we review a component named FileViewerModal in Suna codebase. Suna is an Open Source Generalist AI Agent.

Where is FileViewerModal component used?

I explored Suna by creating an account and created few chats. As part of the conversation response, there are tags and list of files responded as shown in the below image.

When you click on any file here, the below modal appears.

This is rendered by the FileViewerModal component. If you look at this page’s url, it looks something like this — https://www.suna.so/agents/{id}

Suna does not use any monorepo setup, it contains backend and frontend folders. Frontend is built using Next.js app router, so we can expect a folder named “agents” and a dynamic route.

As you can see, the [threadId] folder is used for dynamic routing in app router based Next.js project. At line 1548 in [threadId]/page.tsx, you will find the below code:

{sandboxId && (
  <FileViewerModal
    open={fileViewerOpen}
    onOpenChange={setFileViewerOpen}
    sandboxId={sandboxId}
    initialFilePath={fileToView}
    project={project || undefined}
  />
)}
Enter fullscreen mode Exit fullscreen mode

FileViewerModal component

This component is defined in components/thread/file-viewer-modal.tsx. At the time of writing this article, this FileViewerModal component has 905 LOC.

Below code is response to fetch the file that should be loaded in the viewer.

// Load files when modal opens or path changes - Refined
  useEffect(() => {
    if (!open || !sandboxId) {
      return; // Don't load if modal is closed or no sandbox ID
    }

    const loadFiles = async () => {
      setIsLoadingFiles(true);
      console.log(`[FILE VIEWER] useEffect[currentPath]: Triggered. Loading files for path: ${currentPath}`);
      try {
        const filesData = await listSandboxFiles(sandboxId, currentPath);
        console.log(`[FILE VIEWER] useEffect[currentPath]: API returned ${filesData.length} files.`);
        setFiles(filesData);
      } catch (error) {
        console.error("Failed to load files:", error);
        toast.error("Failed to load files");
        setFiles([]);
      } finally {
        setIsLoadingFiles(false);
      }
    };

    loadFiles();
    // Dependency: Only re-run when open, sandboxId, or currentPath changes
  }, [open, sandboxId, currentPath]);
Enter fullscreen mode Exit fullscreen mode

Dialog component used is a Shadcn/ui component, located at components/ui/dialog.tsx.

File is rendered using another component called FileRenderer.

<div className="h-full w-full relative">
  <FileRenderer
    key={selectedFilePath}
    content={textContentForRenderer}
    binaryUrl={blobUrlForRenderer}
    fileName={selectedFilePath}
    className="h-full w-full"
    project={projectWithSandbox}
    markdownRef={isMarkdownFile(selectedFilePath) ? markdownRef : undefined}
  />
</div>
Enter fullscreen mode Exit fullscreen mode

About me:

Hey, my name is Ramu Narasinga. I study large open-source projects and create content about their codebase architecture and best practices, sharing it through articles, videos.

Want me to review your codebase architecture? book a meeting —https://thinkthroo.com/consultation/codebase-architecture-review

Business enquiries — [email protected]

My Github —  https://github.com/ramu-narasinga

My website —  https://ramunarasinga.com

My YouTube channel —  https://www.youtube.com/@ramu-narasinga

Learning platform —  https://thinkthroo.com

Codebase Architecture —  https://app.thinkthroo.com/architecture

Best practices —  https://app.thinkthroo.com/best-practices

Production-grade projects —  https://app.thinkthroo.com/production-grade-projects

References:

  1. https://github.com/kortix-ai/suna/blob/main/frontend/src/app/(dashboard)/agents/%5BthreadId%5D/page.tsx#L1610

  2. https://github.com/kortix-ai/suna/blob/main/frontend/src/components/thread/file-viewer-modal.tsx#L39

Top comments (2)

Collapse
 
nevodavid profile image
Nevo David

gotta say, digging into stuff like this helps me learn way more than docs ever do - you think actually building your own tools makes stuff click faster or would you rather just study how others do it?

Collapse
 
ramunarasinga-11 profile image
Ramu Narasinga • Edited

Hey David, thanks for your comment.

I’m actually building a learning platform where I teach these hidden patterns in the OSS - github.com/ramu-narasinga/thinkthroo

Products I am building right now:

  1. thinkthroo CLI - lets you configure commonly used engineering capabilities like changesets, renovate.json, kodiak etc., I will expand this to features like auth etc.,

  2. Animate code - I already use an OSS code hike based example. Check out thinkthroo on IG