diff --git a/backend/sandbox/api.py b/backend/sandbox/api.py index 33effa6f..390d44c9 100644 --- a/backend/sandbox/api.py +++ b/backend/sandbox/api.py @@ -53,6 +53,10 @@ async def verify_sandbox_access(client, sandbox_id: str, user_id: str): raise HTTPException(status_code=404, detail="Sandbox not found") project_data = project_result.data[0] + + if project_data.get('is_public'): + return project_data + account_id = project_data.get('account_id') # Verify account membership diff --git a/backend/supabase/migrations/20250416133920_agentpress_schema.sql b/backend/supabase/migrations/20250416133920_agentpress_schema.sql index c0156dd6..f5c92b6c 100644 --- a/backend/supabase/migrations/20250416133920_agentpress_schema.sql +++ b/backend/supabase/migrations/20250416133920_agentpress_schema.sql @@ -6,6 +6,7 @@ CREATE TABLE projects ( description TEXT, account_id UUID NOT NULL REFERENCES basejump.accounts(id) ON DELETE CASCADE, sandbox JSONB DEFAULT '{}'::jsonb, + is_public BOOLEAN DEFAULT FALSE, created_at TIMESTAMP WITH TIME ZONE DEFAULT TIMEZONE('utc'::text, NOW()) NOT NULL, updated_at TIMESTAMP WITH TIME ZONE DEFAULT TIMEZONE('utc'::text, NOW()) NOT NULL ); @@ -96,7 +97,10 @@ ALTER TABLE projects ENABLE ROW LEVEL SECURITY; -- Project policies CREATE POLICY project_select_policy ON projects FOR SELECT - USING (basejump.has_role_on_account(account_id) = true); + USING ( + is_public = TRUE OR + basejump.has_role_on_account(account_id) = true OR + ); CREATE POLICY project_insert_policy ON projects FOR INSERT @@ -274,6 +278,7 @@ CREATE POLICY message_delete_policy ON messages -- Grant permissions to roles GRANT ALL PRIVILEGES ON TABLE projects TO authenticated, service_role; +GRANT SELECT ON TABLE projects TO anon; GRANT SELECT ON TABLE threads TO authenticated, anon, service_role; GRANT SELECT ON TABLE messages TO authenticated, anon, service_role; GRANT ALL PRIVILEGES ON TABLE agent_runs TO authenticated, service_role; diff --git a/frontend/src/app/share/[threadId]/page.tsx b/frontend/src/app/share/[threadId]/page.tsx index 2d1c349f..456a4fc7 100644 --- a/frontend/src/app/share/[threadId]/page.tsx +++ b/frontend/src/app/share/[threadId]/page.tsx @@ -95,6 +95,8 @@ function renderMarkdownContent(content: string, handleToolClick: (assistantMessa let lastIndex = 0; const contentParts: React.ReactNode[] = []; let match; + // Generate a unique timestamp for this render to avoid key conflicts + const timestamp = Date.now(); // If no XML tags found, just return the full content as markdown if (!content.match(xmlRegex)) { @@ -106,7 +108,7 @@ function renderMarkdownContent(content: string, handleToolClick: (assistantMessa if (match.index > lastIndex) { const textBeforeTag = content.substring(lastIndex, match.index); contentParts.push( - {textBeforeTag} + {textBeforeTag} ); } @@ -114,7 +116,7 @@ function renderMarkdownContent(content: string, handleToolClick: (assistantMessa const toolName = match[1] || match[2]; const IconComponent = getToolIcon(toolName); const paramDisplay = extractPrimaryParam(toolName, rawXml); - const toolCallKey = `tool-${match.index}`; + const toolCallKey = `tool-${match.index}-${timestamp}`; if (toolName === 'ask') { // Extract attachments from the XML attributes @@ -129,7 +131,7 @@ function renderMarkdownContent(content: string, handleToolClick: (assistantMessa // Render tag content with attachment UI contentParts.push( -
+
{askContent} {attachments.length > 0 && ( @@ -151,7 +153,7 @@ function renderMarkdownContent(content: string, handleToolClick: (assistantMessa return ( + +
)} @@ -1514,33 +1540,14 @@ export default function ThreadPage({ params }: { params: Promise } renderToolResult={toolViewResult} /> - {sandboxId && ( - - )} - - {/* Show a fallback modal when sandbox is not available */} - {!sandboxId && fileViewerOpen && ( -
-
-

File Unavailable

-

- The file viewer is not available for this shared thread. -

- -
-
- )} + {/* Show FileViewerModal regardless of sandboxId availability */} + ); } diff --git a/frontend/src/components/thread/tool-views/FileOperationToolView.tsx b/frontend/src/components/thread/tool-views/FileOperationToolView.tsx index b3306650..27154aed 100644 --- a/frontend/src/components/thread/tool-views/FileOperationToolView.tsx +++ b/frontend/src/components/thread/tool-views/FileOperationToolView.tsx @@ -144,7 +144,11 @@ export function FileOperationToolView({ ? `${project.sandbox.sandbox_url}/${processedFilePath}` : undefined; - console.log('HTML Preview URL:', htmlPreviewUrl); + // Only log HTML preview URL when it exists + if (htmlPreviewUrl) { + console.log('HTML Preview URL:', htmlPreviewUrl); + } + // Add state for view mode toggle (code or preview) const [viewMode, setViewMode] = useState<'code' | 'preview'>(isHtml || isMarkdown || isCsv ? 'preview' : 'code');