mirror of https://github.com/kortix-ai/suna.git
Compare commits
8 Commits
0d6ae9e43b
...
653e98475d
Author | SHA1 | Date |
---|---|---|
|
653e98475d | |
|
63f2d8e5ec | |
|
0fc3c4a573 | |
|
b77243d69d | |
|
38dd730bbc | |
|
f6dd36d08a | |
|
d7b95b24a7 | |
|
034ea37745 |
|
@ -179,3 +179,5 @@ state.json
|
|||
.DS_Store
|
||||
**/.DS_Store
|
||||
.aider*
|
||||
**/.prompts/
|
||||
**/__pycache__/
|
||||
|
|
40
README.md
40
README.md
|
@ -52,45 +52,29 @@ Handles data persistence with authentication, user management, conversation hist
|
|||
|
||||
## Use Cases
|
||||
|
||||
1. **Competitor Analysis** ([Watch](https://suna.so/use-case/competitor-analysis)) - *"Analyze the market for my next company in the healthcare industry, located in the UK. Give me the major players, their market size, strengths, and weaknesses, and add their website URLs. Once done, generate a PDF report."*
|
||||
1. **Competitor Analysis** ([Watch](https://www.suna.so/share/5ee791ac-e19c-4986-a61c-6d0659d0e5bc)) - *"Analyze the market for my next company in the healthcare industry, located in the UK. Give me the major players, their market size, strengths, and weaknesses, and add their website URLs. Once done, generate a PDF report."*
|
||||
|
||||
2. **VC List** ([Watch](https://suna.so/use-case/vc-list)) - *"Give me the list of the most important VC Funds in the United States based on Assets Under Management. Give me website URLs, and if possible an email to reach them out."*
|
||||
2. **VC List** ([Watch](https://www.suna.so/share/804d20a3-cf1c-4adb-83bb-0e77cc6adeac)) - *"Give me the list of the most important VC Funds in the United States based on Assets Under Management. Give me website URLs, and if possible an email to reach them out."*
|
||||
|
||||
3. **Insurance Policies** ([Watch](https://suna.so/use-case/insurance-policies)) - *"Find me the best insurance policy per pricing for my house, located in Milan, Italy. Scrape Italian companies in the insurance market for houses."*
|
||||
3. **Looking for Candidates** ([Watch](https://www.suna.so/share/3ae581b0-2db8-4c63-b324-3b8d29762e74)) - *"Go on LinkedIn, and find me 10 profiles available - they are not working right now - for a junior software engineer position, who are located in Munich, Germany. They should have at least one bachelor's degree in Computer Science or anything related to it, and 1-year of experience in any field/role."*
|
||||
|
||||
4. **Looking for Candidates** ([Watch](https://suna.so/use-case/looking-for-candidates)) - *"Go on LinkedIn, and find me 10 profiles available - they are not working right now - for a junior software engineer position, who are located in Munich, Germany. They should have at least one bachelor's degree in Computer Science or anything related to it, and 1-year of experience in any field/role."*
|
||||
4. **Planning Company Trip** ([Watch](https://www.suna.so/share/725e64a0-f1e2-4bb6-8a1f-703c2833fd72)) - *"Generate me a route plan for my company. We should go to California. We'll be in 8 people. Compose the trip from the departure (Paris, France) to the activities we can do considering that the trip will be 7 days long - departure on the 21st of Apr 2025. Check the weather forecast and temperature for the upcoming days, and based on that, you can plan our activities (outdoor vs indoor)."*
|
||||
|
||||
5. **Writing Report** ([Watch](https://suna.so/use-case/writing-report)) - *"Write me a detailed report about what's happened in the US stock market in the last 2 weeks. Analyze the S&P 500 trend, and tell me what the market is expecting to see in the upcoming weeks. This is a report analysis for a Bank CFO."*
|
||||
5. **Working on Excel** ([Watch](https://www.suna.so/share/128f23a4-51cd-42a6-97a0-0b458b32010e)) - *"My company asked me to set up an Excel spreadsheet with all the information about Italian lottery games (Lotto, 10eLotto, and Million Day). Based on that, generate and send me a spreadsheet with all the basic information (public ones)."*
|
||||
|
||||
6. **Product Reviews** ([Watch](https://suna.so/use-case/product-reviews)) - *"Go on Amazon, and find me the most common product issues related to the Nespresso Machine - you can find them by reading the reviews. Once done, write me a short report about common issues that could be converted into competitive advantage for a new Nespresso Machine."*
|
||||
6. **Automate Event Speaker Prospecting** ([Watch](https://www.suna.so/share/7a7592ea-ed44-4c69-bcb5-5f9bb88c188c)) - *"Find 20 AI ethics speakers from Europe who've spoken at conferences in the past year. Scrapes conference sites, cross-references LinkedIn and YouTube, and outputs contact info + talk summaries."*
|
||||
|
||||
7. **Game Generation** ([Watch](https://suna.so/use-case/game-generation)) - *"Generate a Mini Game where the Player needs to drive a spaceship and fight against interstellar aliens. The aliens should be green, while the main player should be white. Make it with a 90' style."*
|
||||
7. **Summarize and Cross-Reference Scientific Papers** ([Watch](https://www.suna.so/share/c2081b3c-786e-4e7c-9bf4-46e9b23bb662)) - *"Research and compare scientific papers talking about Alcohol effects on our bodies during the last 5 years. Generate a report about the most important scientific papers talking about the topic I wrote before."*
|
||||
|
||||
8. **Planning Company Trip** ([Watch](https://suna.so/use-case/planning-company-trip)) - *"Generate me a route plan for my company. We should go to California. We'll be in 8 people. Compose the trip from the departure (Paris, France) to the activities we can do considering that the trip will be 7 days long - departure on the 21st of Apr 2025. Check the weather forecast and temperature for the upcoming days, and based on that, you can plan our activities (outdoor vs indoor)."*
|
||||
8. **Research + First Contact Draft** ([Watch](https://www.suna.so/share/6b6296a6-8683-49e5-9ad0-a32952d12c44)) - *"Research my potential customers (B2B) on LinkedIn. They should be in the clean tech industry. Find their websites and their email addresses. After that, based on the company profile, generate a personalized first contact email where I present my company which is offering consulting services to cleantech companies to maximize their profits and reduce their costs."*
|
||||
|
||||
9. **Working on Excel** ([Watch](https://suna.so/use-case/working-on-excel)) - *"My company asked me to set up an Excel spreadsheet with all the information about Italian lottery games (Lotto, 10eLotto, and Million Day). Based on that, generate and send me a spreadsheet with all the basic information (public ones)."*
|
||||
9. **SEO Analysis** ([Watch](https://www.suna.so/share/43491cb0-cd6c-45f0-880c-66ddc8c4b842)) - *"Based on my website suna.so, generate an SEO report analysis, find top-ranking pages by keyword clusters, and identify topics I'm missing."*
|
||||
|
||||
10. **Scraping Databases** ([Watch](https://suna.so/use-case/scraping-databases)) - *"Search for open tender databases (e.g. EU TED, US SAM.gov), find relevant procurement calls in the clean tech industry, summarize requirements, and generate a report about it."*
|
||||
10. **Generate a Personal Trip** ([Watch](https://www.suna.so/share/37b31907-8349-4f63-b0e5-27ca597ed02a)) - *"Generate a personal trip to London, with departure from Bangkok on the 1st of May. The trip will last 10 days. Find an accommodation in the center of London, with a rating on Google reviews of at least 4.5. Find me interesting outdoor activities to do during the journey. Generate a detailed itinerary plan."*
|
||||
|
||||
11. **Automate Event Speaker Prospecting** ([Watch](https://suna.so/use-case/automate-event-speaker-prospecting)) - *"Find 20 AI ethics speakers from Europe who've spoken at conferences in the past year. Scrapes conference sites, cross-references LinkedIn and YouTube, and outputs contact info + talk summaries."*
|
||||
11. **Recently Funded Startups** ([Watch](https://www.suna.so/share/8b2a897e-985a-4d5e-867b-15239274f764)) - *"Go on Crunchbase, Dealroom, and TechCrunch, filter by Series A funding rounds in the SaaS Finance Space, and build a report with company data, founders, and contact info for outbound sales."*
|
||||
|
||||
12. **Summarize and Cross-Reference Scientific Papers** ([Watch](https://suna.so/use-case/summarize-cross-reference-scientific-papers)) - *"Research and compare scientific papers talking about Alcohol effects on our bodies during the last 5 years. Generate a report about the most important scientific papers talking about the topic I wrote before."*
|
||||
|
||||
13. **Generating Leads** ([Watch](https://suna.so/use-case/generating-leads)) - *"I need to generate at least 20 B2B leads to reach out for my new AI tool. It's a customer support tool, then I'll need to have companies located in Spain, Barcelona, with 10-50 employees (find a way to get the number of employees). List me their names, websites, size (employees), and contact information if public."*
|
||||
|
||||
14. **Research + First Contact Draft** ([Watch](https://suna.so/use-case/research-first-contact-draft)) - *"Research my potential customers (B2B) on LinkedIn. They should be in the clean tech industry. Find their websites and their email addresses. After that, based on the company profile, generate a personalized first contact email where I present my company which is offering consulting services to cleantech companies to maximize their profits and reduce their costs."*
|
||||
|
||||
15. **SEO Analysis** ([Watch](https://suna.so/use-case/seo-analysis)) - *"Based on my website suna.so, generate an SEO report analysis, find top-ranking pages by keyword clusters, and identify topics I'm missing."*
|
||||
|
||||
16. **Clustering Public Reviews** ([Watch](https://suna.so/use-case/clustering-public-reviews)) - *"Clusterize public reviews for McDonald's by scraping them on public pages like Google Reviews, then generate a detailed report about the most common feedback and reviews (from 5 to 1 star), generate cluster to obtain insights about what can be improved and what is producing good results for the McDonald's brand."*
|
||||
|
||||
17. **Generate a Personal Trip** ([Watch](https://suna.so/use-case/generate-personal-trip)) - *"Generate a personal trip to London, with departure from Bangkok on the 1st of May. The trip will last 10 days. Find an accommodation in the center of London, with a rating on Google reviews of at least 4.5. Find me interesting outdoor activities to do during the journey. Generate a detailed itinerary plan."*
|
||||
|
||||
18. **Scrape and Monitor Stocks** ([Watch](https://suna.so/use-case/scrape-monitor-stocks)) - *"I want to monitor the 10 biggest public companies in Portugal. Scrape them on the internet, and find the public ones with the price/share available in the last 30 trading days. Generate a report based on the data you find."*
|
||||
|
||||
19. **Recently Funded Startups** ([Watch](https://suna.so/use-case/recently-funded-startups)) - *"Go on Crunchbase, Dealroom, and TechCrunch, filter by Series A funding rounds in the SaaS Finance Space, and build a report with company data, founders, and contact info for outbound sales."*
|
||||
|
||||
20. **Scrape Forum Discussions** ([Watch](https://suna.so/use-case/scrape-forum-discussions)) - *"I need to find the best beauty centers in Rome, but I want to find them by using open forums that speak about this topic. Go on Google, and scrape the forums by looking for beauty center discussions located in Rome. Then generate a list of 5 beauty centers with the best comments about them."*
|
||||
12. **Scrape Forum Discussions** ([Watch](https://www.suna.so/share/7d7a5d93-a20d-48b0-82cc-e9a876e9fd04)) - *"I need to find the best beauty centers in Rome, but I want to find them by using open forums that speak about this topic. Go on Google, and scrape the forums by looking for beauty center discussions located in Rome. Then generate a list of 5 beauty centers with the best comments about them."*
|
||||
|
||||
## Run Locally / Self-Hosting
|
||||
|
||||
|
|
|
@ -34,6 +34,9 @@ MODEL_NAME_ALIASES = {
|
|||
"sonnet-3.7": "anthropic/claude-3-7-sonnet-latest",
|
||||
"gpt-4.1": "openai/gpt-4.1-2025-04-14",
|
||||
"gemini-flash-2.5": "openrouter/google/gemini-2.5-flash-preview",
|
||||
"grok-3": "xai/grok-3-fast-latest",
|
||||
"deepseek": "deepseek/deepseek-chat",
|
||||
"grok-3-mini": "xai/grok-3-mini-fast-beta",
|
||||
}
|
||||
|
||||
class AgentStartRequest(BaseModel):
|
||||
|
@ -293,7 +296,7 @@ async def get_or_create_project_sandbox(client, project_id: str):
|
|||
|
||||
logger.info(f"Creating new sandbox for project {project_id}")
|
||||
sandbox_pass = str(uuid.uuid4())
|
||||
sandbox = create_sandbox(sandbox_pass)
|
||||
sandbox = create_sandbox(sandbox_pass, project_id)
|
||||
sandbox_id = sandbox.id
|
||||
logger.info(f"Created new sandbox {sandbox_id}")
|
||||
|
||||
|
|
|
@ -123,6 +123,7 @@ class ResponseProcessor:
|
|||
finish_reason = None
|
||||
last_assistant_message_object = None # Store the final saved assistant message object
|
||||
tool_result_message_objects = {} # tool_index -> full saved message object
|
||||
has_printed_thinking_prefix = False # Flag for printing thinking prefix only once
|
||||
|
||||
logger.info(f"Streaming Config: XML={config.xml_tool_calling}, Native={config.native_tool_calling}, "
|
||||
f"Execute on stream={config.execute_on_stream}, Strategy={config.tool_execution_strategy}")
|
||||
|
@ -156,13 +157,17 @@ class ResponseProcessor:
|
|||
|
||||
# Check for and log Anthropic thinking content
|
||||
if delta and hasattr(delta, 'reasoning_content') and delta.reasoning_content:
|
||||
logger.info(f"[THINKING]: {delta.reasoning_content}")
|
||||
if not has_printed_thinking_prefix:
|
||||
# print("[THINKING]: ", end='', flush=True)
|
||||
has_printed_thinking_prefix = True
|
||||
# print(delta.reasoning_content, end='', flush=True)
|
||||
# Append reasoning to main content to be saved in the final message
|
||||
accumulated_content += delta.reasoning_content
|
||||
|
||||
# Process content chunk
|
||||
if delta and hasattr(delta, 'content') and delta.content:
|
||||
chunk_content = delta.content
|
||||
# print(chunk_content, end='', flush=True)
|
||||
accumulated_content += chunk_content
|
||||
current_xml_content += chunk_content
|
||||
|
||||
|
@ -281,6 +286,8 @@ class ResponseProcessor:
|
|||
logger.info("Stopping stream processing after loop due to XML tool call limit")
|
||||
break
|
||||
|
||||
# print() # Add a final newline after the streaming loop finishes
|
||||
|
||||
# --- After Streaming Loop ---
|
||||
|
||||
# Wait for pending tool executions from streaming phase
|
||||
|
|
|
@ -113,7 +113,7 @@ app = FastAPI(lifespan=lifespan)
|
|||
# return await call_next(request)
|
||||
|
||||
# Define allowed origins based on environment
|
||||
allowed_origins = ["https://www.suna.so", "https://suna.so", "https://staging.suna.so"]
|
||||
allowed_origins = ["https://www.suna.so", "https://suna.so", "https://staging.suna.so", "http://localhost:3000"] #"http://localhost:3000"
|
||||
|
||||
# Add staging-specific origins
|
||||
if config.ENV_MODE == EnvMode.STAGING:
|
||||
|
|
|
@ -86,16 +86,16 @@ def start_supervisord_session(sandbox: Sandbox):
|
|||
logger.error(f"Error starting supervisord session: {str(e)}")
|
||||
raise e
|
||||
|
||||
def create_sandbox(password: str, sandbox_id: str = None):
|
||||
def create_sandbox(password: str, project_id: str = None):
|
||||
"""Create a new sandbox with all required services configured and running."""
|
||||
|
||||
logger.debug("Creating new Daytona sandbox environment")
|
||||
logger.debug("Configuring sandbox with browser-use image and environment variables")
|
||||
|
||||
labels = None
|
||||
if sandbox_id:
|
||||
logger.debug(f"Using sandbox_id as label: {sandbox_id}")
|
||||
labels = {'id': sandbox_id}
|
||||
if project_id:
|
||||
logger.debug(f"Using sandbox_id as label: {project_id}")
|
||||
labels = {'id': project_id}
|
||||
|
||||
params = CreateSandboxParams(
|
||||
image="adamcohenhillel/kortix-suna:0.0.20",
|
||||
|
@ -114,14 +114,6 @@ def create_sandbox(password: str, sandbox_id: str = None):
|
|||
"CHROME_DEBUGGING_HOST": "localhost",
|
||||
"CHROME_CDP": ""
|
||||
},
|
||||
ports=[
|
||||
6080, # noVNC web interface
|
||||
5900, # VNC port
|
||||
5901, # VNC port
|
||||
9222, # Chrome remote debugging port
|
||||
8080, # HTTP website port
|
||||
8002, # The browser api port
|
||||
],
|
||||
resources={
|
||||
"cpu": 2,
|
||||
"memory": 4,
|
||||
|
|
|
@ -5,7 +5,7 @@ from utils.config import config, EnvMode
|
|||
|
||||
# Define subscription tiers and their monthly limits (in minutes)
|
||||
SUBSCRIPTION_TIERS = {
|
||||
'price_1RGJ9GG6l1KZGqIroxSqgphC': {'name': 'free', 'minutes': 0},
|
||||
'price_1RGJ9GG6l1KZGqIroxSqgphC': {'name': 'free', 'minutes': 8},
|
||||
'price_1RGJ9LG6l1KZGqIrd9pwzeNW': {'name': 'base', 'minutes': 300},
|
||||
'price_1RGJ9JG6l1KZGqIrVUU4ZRv6': {'name': 'extra', 'minutes': 2400}
|
||||
}
|
||||
|
@ -91,11 +91,11 @@ async def check_billing_status(client, account_id: str) -> Tuple[bool, str, Opti
|
|||
if not subscription:
|
||||
subscription = {
|
||||
'price_id': 'price_1RGJ9GG6l1KZGqIroxSqgphC', # Free tier
|
||||
'plan_name': 'Free'
|
||||
'plan_name': 'free'
|
||||
}
|
||||
|
||||
if not subscription or subscription.get('price_id') is None or subscription.get('price_id') == 'price_1RGJ9GG6l1KZGqIroxSqgphC':
|
||||
return False, "You are not subscribed to any plan. Please upgrade your plan to continue.", subscription
|
||||
# if not subscription or subscription.get('price_id') is None or subscription.get('price_id') == 'price_1RGJ9GG6l1KZGqIroxSqgphC':
|
||||
# return False, "You are not subscribed to any plan. Please upgrade your plan to continue.", subscription
|
||||
|
||||
# Get tier info
|
||||
tier_info = SUBSCRIPTION_TIERS.get(subscription['price_id'])
|
||||
|
|
|
@ -67,12 +67,6 @@ def setup_logger(name: str = 'agentpress') -> logging.Logger:
|
|||
"""
|
||||
logger = logging.getLogger(name)
|
||||
|
||||
# Set console logging level based on environment
|
||||
if config.ENV_MODE == EnvMode.PRODUCTION:
|
||||
logger.setLevel(logging.WARNING)
|
||||
else:
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
# Create logs directory if it doesn't exist
|
||||
log_dir = 'logs'
|
||||
if not os.path.exists(log_dir):
|
||||
|
@ -91,9 +85,8 @@ def setup_logger(name: str = 'agentpress') -> logging.Logger:
|
|||
# Console handler
|
||||
console_handler = logging.StreamHandler(sys.stdout)
|
||||
|
||||
# Set console logging level based on environment
|
||||
if config.ENV_MODE == EnvMode.PRODUCTION:
|
||||
console_handler.setLevel(logging.INFO)
|
||||
console_handler.setLevel(logging.WARNING)
|
||||
else:
|
||||
console_handler.setLevel(logging.DEBUG)
|
||||
|
||||
|
|
|
@ -42,3 +42,5 @@ next-env.d.ts
|
|||
supabase/.branches
|
||||
supabase/.temp
|
||||
supabase/**/*.env
|
||||
**/.prompts/
|
||||
**/__pycache__/
|
||||
|
|
|
@ -5,7 +5,8 @@ import { Skeleton } from "@/components/ui/skeleton";
|
|||
import { useRouter } from 'next/navigation';
|
||||
import { Menu } from "lucide-react";
|
||||
import { ChatInput, ChatInputHandles } from '@/components/thread/chat-input';
|
||||
import { initiateAgent, createThread, addUserMessage, startAgent } from "@/lib/api";
|
||||
import { initiateAgent, createThread, addUserMessage, startAgent, createProject } from "@/lib/api";
|
||||
import { generateThreadName } from "@/lib/actions/threads";
|
||||
import { useIsMobile } from "@/hooks/use-mobile";
|
||||
import { useSidebar } from "@/components/ui/sidebar";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
@ -32,7 +33,7 @@ function DashboardContent() {
|
|||
const chatInputRef = useRef<ChatInputHandles>(null);
|
||||
|
||||
const handleSubmit = async (message: string, options?: { model_name?: string; enable_thinking?: boolean }) => {
|
||||
if (!message.trim() && !chatInputRef.current?.getPendingFiles().length || isSubmitting) return;
|
||||
if ((!message.trim() && !(chatInputRef.current?.getPendingFiles().length)) || isSubmitting) return;
|
||||
|
||||
setIsSubmitting(true);
|
||||
|
||||
|
@ -62,26 +63,38 @@ function DashboardContent() {
|
|||
|
||||
// Call initiateAgent API
|
||||
const result = await initiateAgent(formData);
|
||||
console.log('Agent initiated:', result);
|
||||
console.log('Agent initiated with files:', result);
|
||||
|
||||
// Navigate to the thread
|
||||
if (result.thread_id) {
|
||||
router.push(`/agents/${result.thread_id}`);
|
||||
}
|
||||
} else {
|
||||
// For text-only messages, first create a thread
|
||||
const thread = await createThread("");
|
||||
// ---- Text-only messages ----
|
||||
// 1. Generate a project name
|
||||
const projectName = await generateThreadName(message);
|
||||
|
||||
// Then add the user message
|
||||
// 2. Create the project
|
||||
// Assuming createProject gets the account_id from the logged-in user
|
||||
const newProject = await createProject({
|
||||
name: projectName,
|
||||
description: "", // Or derive a description if desired
|
||||
});
|
||||
|
||||
// 3. Create the thread using the new project ID
|
||||
const thread = await createThread(newProject.id); // <-- Pass the actual project ID
|
||||
|
||||
// 4. Then add the user message
|
||||
await addUserMessage(thread.thread_id, message);
|
||||
|
||||
// Start the agent on this thread with the options
|
||||
// 5. Start the agent on this thread with the options
|
||||
await startAgent(thread.thread_id, options);
|
||||
|
||||
// Navigate to thread
|
||||
// 6. Navigate to thread
|
||||
router.push(`/agents/${thread.thread_id}`);
|
||||
}
|
||||
} catch (error: any) {
|
||||
// Log line 85 might be here if createThread or initiateAgent fails
|
||||
console.error('Error creating thread or initiating agent:', error);
|
||||
|
||||
// Skip billing error checks in local development mode
|
||||
|
@ -163,17 +176,18 @@ function DashboardContent() {
|
|||
}
|
||||
|
||||
// Don't rethrow - we've handled this error with the billing alert
|
||||
setIsSubmitting(false);
|
||||
setIsSubmitting(false); // Stop submission process on billing error
|
||||
return; // Exit handleSubmit
|
||||
}
|
||||
}
|
||||
|
||||
// Handle other errors or rethrow
|
||||
// The second log (line 174) might happen here if startAgent fails, for example
|
||||
toast.error(error.message || "An error occurred");
|
||||
|
||||
console.error("Error creating agent:", error);
|
||||
setIsSubmitting(false);
|
||||
setIsSubmitting(false); // Reset submitting state on other errors too
|
||||
}
|
||||
// Removed finally block as catch now handles resetting isSubmitting
|
||||
};
|
||||
|
||||
// Check for pending prompt in localStorage on mount
|
||||
|
|
|
@ -9,6 +9,9 @@ import {
|
|||
import { PricingAlert } from "@/components/billing/pricing-alert"
|
||||
import { MaintenanceAlert } from "@/components/maintenance-alert"
|
||||
import { useAccounts } from "@/hooks/use-accounts"
|
||||
import { useAuth } from "@/components/AuthProvider"
|
||||
import { useRouter } from "next/navigation"
|
||||
import { Loader2 } from "lucide-react"
|
||||
|
||||
interface DashboardLayoutProps {
|
||||
children: React.ReactNode
|
||||
|
@ -21,12 +24,35 @@ export default function DashboardLayout({
|
|||
const [showMaintenanceAlert, setShowMaintenanceAlert] = useState(false)
|
||||
const { data: accounts } = useAccounts()
|
||||
const personalAccount = accounts?.find(account => account.personal_account)
|
||||
const { user, isLoading } = useAuth()
|
||||
const router = useRouter()
|
||||
|
||||
useEffect(() => {
|
||||
setShowPricingAlert(true)
|
||||
setShowPricingAlert(false)
|
||||
setShowMaintenanceAlert(false)
|
||||
}, [])
|
||||
|
||||
// Check authentication status
|
||||
useEffect(() => {
|
||||
if (!isLoading && !user) {
|
||||
router.push('/auth')
|
||||
}
|
||||
}, [user, isLoading, router])
|
||||
|
||||
// Show loading state while checking auth
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-screen">
|
||||
<Loader2 className="h-8 w-8 animate-spin text-primary" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Don't render anything if not authenticated
|
||||
if (!user) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<SidebarProvider>
|
||||
<SidebarLeft />
|
||||
|
|
|
@ -14,7 +14,7 @@ export default function Home() {
|
|||
<main className="flex flex-col items-center justify-center min-h-screen w-full">
|
||||
<div className="w-full divide-y divide-border">
|
||||
<HeroSection />
|
||||
{/* <UseCasesSection /> */}
|
||||
<UseCasesSection />
|
||||
{/* <CompanyShowcase /> */}
|
||||
{/* <BentoSection /> */}
|
||||
{/* <QuoteSection /> */}
|
||||
|
|
|
@ -20,8 +20,7 @@ interface UseCase {
|
|||
export function UseCasesSection() {
|
||||
// Get featured use cases from siteConfig and limit to 8
|
||||
const featuredUseCases: UseCase[] = (siteConfig.useCases || [])
|
||||
.filter((useCase: UseCase) => useCase.featured)
|
||||
.slice(0, 8);
|
||||
.filter((useCase: UseCase) => useCase.featured);
|
||||
|
||||
return (
|
||||
<section
|
||||
|
|
|
@ -72,6 +72,12 @@ export function NavAgents() {
|
|||
const projects = await getProjects() as Project[]
|
||||
console.log("Projects loaded:", projects.length, projects.map(p => ({ id: p.id, name: p.name })));
|
||||
|
||||
// If no projects are found, the user might not be logged in
|
||||
if (projects.length === 0) {
|
||||
setThreads([])
|
||||
return
|
||||
}
|
||||
|
||||
// Create a map of projects by ID for faster lookups
|
||||
const projectsById = new Map<string, Project>();
|
||||
projects.forEach(project => {
|
||||
|
@ -113,6 +119,8 @@ export function NavAgents() {
|
|||
setThreads(sortThreads(threadsWithProjects))
|
||||
} catch (err) {
|
||||
console.error("Error loading threads with projects:", err)
|
||||
// Set empty threads array on error
|
||||
setThreads([])
|
||||
} finally {
|
||||
if (showLoading) {
|
||||
setIsLoading(false)
|
||||
|
|
|
@ -294,8 +294,25 @@ export const deleteProject = async (projectId: string): Promise<void> => {
|
|||
// Thread APIs
|
||||
export const getThreads = async (projectId?: string): Promise<Thread[]> => {
|
||||
const supabase = createClient();
|
||||
|
||||
// Get the current user's ID to filter threads
|
||||
const { data: userData, error: userError } = await supabase.auth.getUser();
|
||||
if (userError) {
|
||||
console.error('Error getting current user:', userError);
|
||||
return [];
|
||||
}
|
||||
|
||||
// If no user is logged in, return an empty array
|
||||
if (!userData.user) {
|
||||
console.log('[API] No user logged in, returning empty threads array');
|
||||
return [];
|
||||
}
|
||||
|
||||
let query = supabase.from('threads').select('*');
|
||||
|
||||
// Always filter by the current user's account ID
|
||||
query = query.eq('account_id', userData.user.id);
|
||||
|
||||
if (projectId) {
|
||||
console.log('[API] Filtering threads by project_id:', projectId);
|
||||
query = query.eq('project_id', projectId);
|
||||
|
|
|
@ -83,9 +83,9 @@ export const siteConfig = {
|
|||
buttonText: "Hire Suna",
|
||||
buttonColor: "bg-secondary text-white",
|
||||
isPopular: false,
|
||||
hours: "no free usage at this time",
|
||||
hours: "10 min",
|
||||
features: [
|
||||
"no free usage",
|
||||
"10 minutes",
|
||||
// "Community support",
|
||||
// "Single user",
|
||||
// "Standard response time",
|
||||
|
@ -1088,26 +1088,10 @@ export const siteConfig = {
|
|||
},
|
||||
],
|
||||
useCases: [
|
||||
{
|
||||
id: "lead-enrichment",
|
||||
title: "Enrich company leads with LinkedIn data",
|
||||
description: "Enriched a list of company leads by automatically finding LinkedIn profiles, identifying CEOs and Heads of Sales/Marketing, and generating clear one-line company descriptions.",
|
||||
category: "research",
|
||||
featured: true,
|
||||
icon: (
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9 6.75H7.75C6.64543 6.75 5.75 7.64543 5.75 8.75V17.25C5.75 18.3546 6.64543 19.25 7.75 19.25H16.25C17.3546 19.25 18.25 18.3546 18.25 17.25V8.75C18.25 7.64543 17.3546 6.75 16.25 6.75H15" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M14 8.25H10C9.44772 8.25 9 7.80228 9 7.25V5.75C9 5.19772 9.44772 4.75 10 4.75H14C14.5523 4.75 15 5.19772 15 5.75V7.25C15 7.80228 14.5523 8.25 14 8.25Z" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M9 12H12M9 15H15" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
),
|
||||
image: "https://images.unsplash.com/photo-1522204523234-8729aa6e3d5f?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2400&q=80",
|
||||
url: "https://www.suna.so/share/b289e34f-68af-40aa-8b46-62c2dcefa58a"
|
||||
},
|
||||
{
|
||||
id: "competitor-analysis",
|
||||
title: "Healthcare market competitor analysis",
|
||||
description: "Analyze the UK healthcare industry market, identifying major players with their market size, strengths, weaknesses, and website URLs, compiled into a comprehensive PDF report.",
|
||||
title: "Competitor Analysis",
|
||||
description: "Analyze the market for my next company in the healthcare industry, located in the UK. Give me the major players, their market size, strengths, and weaknesses, and add their website URLs. Once done, generate a PDF report.",
|
||||
category: "research",
|
||||
featured: true,
|
||||
icon: (
|
||||
|
@ -1118,12 +1102,12 @@ export const siteConfig = {
|
|||
</svg>
|
||||
),
|
||||
image: "https://images.unsplash.com/photo-1576091160550-2173dba999ef?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2400&q=80",
|
||||
url: "https://www.suna.so/share/792ab3ea-ab8e-4b26-b7b5-a19e2ea4c96b"
|
||||
url: "https://www.suna.so/share/5ee791ac-e19c-4986-a61c-6d0659d0e5bc"
|
||||
},
|
||||
{
|
||||
id: "vc-list",
|
||||
title: "Top US VC funds by AUM",
|
||||
description: "Comprehensive listing of the most significant venture capital funds in the United States ranked by Assets Under Management, including website URLs and contact information.",
|
||||
title: "VC List",
|
||||
description: "Give me the list of the most important VC Funds in the United States based on Assets Under Management. Give me website URLs, and if possible an email to reach them out.",
|
||||
category: "finance",
|
||||
featured: true,
|
||||
icon: (
|
||||
|
@ -1133,29 +1117,14 @@ export const siteConfig = {
|
|||
</svg>
|
||||
),
|
||||
image: "https://images.unsplash.com/photo-1444653614773-995cb1ef9efa?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2400&q=80",
|
||||
url: "https://www.suna.so/share/5645e4ea-3989-4977-8898-30a7e1d3c449"
|
||||
},
|
||||
{
|
||||
id: "insurance-policy",
|
||||
title: "Best home insurance in Milan",
|
||||
description: "Research and comparison of the most cost-effective home insurance policies in Milan, Italy, by comprehensively analyzing offerings from multiple Italian insurance providers.",
|
||||
category: "research",
|
||||
featured: false,
|
||||
icon: (
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M19.25 5.75C19.25 5.19772 18.8023 4.75 18.25 4.75H14C12.8954 4.75 12 5.64543 12 6.75V19.25L12.8284 18.4216C13.5786 17.6714 14.596 17.25 15.6569 17.25H18.25C18.8023 17.25 19.25 16.8023 19.25 16.25V5.75Z" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M4.75 5.75C4.75 5.19772 5.19772 4.75 5.75 4.75H10C11.1046 4.75 12 5.64543 12 6.75V19.25L11.1716 18.4216C10.4214 17.6714 9.40401 17.25 8.34315 17.25H5.75C5.19772 17.25 4.75 16.8023 4.75 16.25V5.75Z" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
),
|
||||
image: "https://images.unsplash.com/photo-1560518883-ce09059eeffa?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2400&q=80",
|
||||
url: "https://www.suna.so/share/1cf18fc9-3b74-4a76-a654-2d20d48c35ce"
|
||||
url: "https://www.suna.so/share/804d20a3-cf1c-4adb-83bb-0e77cc6adeac"
|
||||
},
|
||||
{
|
||||
id: "candidate-search",
|
||||
title: "Find available software engineers",
|
||||
description: "Search for 10 available junior software engineers in Munich with Computer Science degrees and at least 1 year of experience by scanning LinkedIn profiles.",
|
||||
title: "Looking for Candidates",
|
||||
description: "Go on LinkedIn, and find me 10 profiles available - they are not working right now - for a junior software engineer position, who are located in Munich, Germany. They should have at least one bachelor's degree in Computer Science or anything related to it, and 1-year of experience in any field/role.",
|
||||
category: "recruitment",
|
||||
featured: false,
|
||||
featured: true,
|
||||
icon: (
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M17.25 10C17.25 12.8995 14.8995 15.25 12 15.25C9.10051 15.25 6.75 12.8995 6.75 10C6.75 7.10051 9.10051 4.75 12 4.75C14.8995 4.75 17.25 7.10051 17.25 10Z" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
|
@ -1164,29 +1133,12 @@ export const siteConfig = {
|
|||
</svg>
|
||||
),
|
||||
image: "https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2400&q=80",
|
||||
url: "https://www.suna.so/share/2d76dff7-d7fa-4504-b685-befb0b11dd68"
|
||||
},
|
||||
{
|
||||
id: "stock-market-report",
|
||||
title: "US stock market analysis report",
|
||||
description: "Detailed report on US stock market performance over the past two weeks, including S&P 500 trend analysis and market predictions for a Bank CFO.",
|
||||
category: "finance",
|
||||
featured: true,
|
||||
icon: (
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.75 11.75L10.25 6.25L14.75 10.75L19.25 6.25" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M19.25 6.25V19.25" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M4.75 6.25V19.25" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M4.75 19.25H19.25" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
),
|
||||
image: "https://images.unsplash.com/photo-1611974789855-9c2a0a7236a3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2400&q=80",
|
||||
url: "https://www.suna.so/share/e343e2fb-55d5-4fe2-a6e3-f9e1655eb8e6"
|
||||
url: "https://www.suna.so/share/3ae581b0-2db8-4c63-b324-3b8d29762e74"
|
||||
},
|
||||
{
|
||||
id: "company-trip",
|
||||
title: "Plan company trip to California",
|
||||
description: "Comprehensive 7-day itinerary for 8 people traveling from Paris to California, including weather-dependent indoor and outdoor activities from April 21-28, 2025.",
|
||||
title: "Planning Company Trip",
|
||||
description: "Generate me a route plan for my company. We should go to California. We'll be in 8 people. Compose the trip from the departure (Paris, France) to the activities we can do considering that the trip will be 7 days long - departure on the 21st of Apr 2025.",
|
||||
category: "travel",
|
||||
featured: true,
|
||||
icon: (
|
||||
|
@ -1198,12 +1150,28 @@ export const siteConfig = {
|
|||
</svg>
|
||||
),
|
||||
image: "https://images.unsplash.com/photo-1507525428034-b723cf961d3e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2400&q=80",
|
||||
url: "https://www.suna.so/share/da71b44e-cd20-42d2-8084-f03861376eab"
|
||||
url: "https://www.suna.so/share/725e64a0-f1e2-4bb6-8a1f-703c2833fd72"
|
||||
},
|
||||
{
|
||||
id: "excel-spreadsheet",
|
||||
title: "Working on Excel",
|
||||
description: "My company asked me to set up an Excel spreadsheet with all the information about Italian lottery games (Lotto, 10eLotto, and Million Day). Based on that, generate and send me a spreadsheet with all the basic information (public ones).",
|
||||
category: "data",
|
||||
featured: true,
|
||||
icon: (
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.75 6.75C4.75 5.64543 5.64543 4.75 6.75 4.75H17.25C18.3546 4.75 19.25 5.64543 19.25 6.75V17.25C19.25 18.3546 18.3546 19.25 17.25 19.25H6.75C5.64543 19.25 4.75 18.3546 4.75 17.25V6.75Z" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M9.75 8.75V19" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M5 8.25H19" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
),
|
||||
image: "https://images.unsplash.com/photo-1532153975070-2e9ab71f1b14?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2400&q=80",
|
||||
url: "https://www.suna.so/share/128f23a4-51cd-42a6-97a0-0b458b32010e"
|
||||
},
|
||||
{
|
||||
id: "speaker-prospecting",
|
||||
title: "Find AI ethics conference speakers",
|
||||
description: "Discover 20 AI ethics speakers from Europe who have presented at conferences in the past year by scraping event sites and cross-referencing with LinkedIn and YouTube.",
|
||||
title: "Automate Event Speaker Prospecting",
|
||||
description: "Find 20 AI ethics speakers from Europe who've spoken at conferences in the past year. Scrapes conference sites, cross-references LinkedIn and YouTube, and outputs contact info + talk summaries.",
|
||||
category: "research",
|
||||
featured: true,
|
||||
icon: (
|
||||
|
@ -1214,12 +1182,12 @@ export const siteConfig = {
|
|||
</svg>
|
||||
),
|
||||
image: "https://images.unsplash.com/photo-1523580494863-6f3031224c94?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2400&q=80",
|
||||
url: "https://www.suna.so/share/08a65777-41d8-44a7-95a1-ebd979ebb16e"
|
||||
url: "https://www.suna.so/share/7a7592ea-ed44-4c69-bcb5-5f9bb88c188c"
|
||||
},
|
||||
{
|
||||
id: "scientific-papers",
|
||||
title: "Research alcohol effects scientific papers",
|
||||
description: "Comprehensive analysis and comparison of scientific research papers from the last 5 years on alcohol's effects on the human body, presented as a detailed report.",
|
||||
title: "Summarize and Cross-Reference Scientific Papers",
|
||||
description: "Research and compare scientific papers talking about Alcohol effects on our bodies during the last 5 years. Generate a report about the most important scientific papers talking about the topic I wrote before.",
|
||||
category: "research",
|
||||
featured: true,
|
||||
icon: (
|
||||
|
@ -1230,12 +1198,12 @@ export const siteConfig = {
|
|||
</svg>
|
||||
),
|
||||
image: "https://images.unsplash.com/photo-1532153975070-2e9ab71f1b14?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2400&q=80",
|
||||
url: "https://www.suna.so/share/aa414558-bfdf-4d7c-9b56-37dee72e4610"
|
||||
url: "https://www.suna.so/share/c2081b3c-786e-4e7c-9bf4-46e9b23bb662"
|
||||
},
|
||||
{
|
||||
id: "lead-generation",
|
||||
title: "Generate B2B leads in Barcelona",
|
||||
description: "Identify at least 20 potential B2B leads for an AI customer support tool, specifically targeting companies in Barcelona with 10-50 employees, including company names, websites, size, and contact information.",
|
||||
title: "Research + First Contact Draft",
|
||||
description: "Research my potential customers (B2B) on LinkedIn. They should be in the clean tech industry. Find their websites and their email addresses. After that, based on the company profile, generate a personalized first contact email.",
|
||||
category: "sales",
|
||||
featured: true,
|
||||
icon: (
|
||||
|
@ -1246,7 +1214,72 @@ export const siteConfig = {
|
|||
</svg>
|
||||
),
|
||||
image: "https://images.unsplash.com/photo-1552581234-26160f608093?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2400&q=80",
|
||||
url: "https://www.suna.so/share/cfd491ea-f3cd-42a9-a775-baff938edcef"
|
||||
url: "https://www.suna.so/share/6b6296a6-8683-49e5-9ad0-a32952d12c44"
|
||||
},
|
||||
{
|
||||
id: "seo-analysis",
|
||||
title: "SEO Analysis",
|
||||
description: "Based on my website suna.so, generate an SEO report analysis, find top-ranking pages by keyword clusters, and identify topics I'm missing.",
|
||||
category: "marketing",
|
||||
featured: true,
|
||||
icon: (
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.75 11.75L10.25 6.25L14.75 10.75L19.25 6.25" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M19.25 6.25V19.25" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M4.75 6.25V19.25" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M4.75 19.25H19.25" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
),
|
||||
image: "https://images.unsplash.com/photo-1611974789855-9c2a0a7236a3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2400&q=80",
|
||||
url: "https://www.suna.so/share/43491cb0-cd6c-45f0-880c-66ddc8c4b842"
|
||||
},
|
||||
{
|
||||
id: "personal-trip",
|
||||
title: "Generate a Personal Trip",
|
||||
description: "Generate a personal trip to London, with departure from Bangkok on the 1st of May. The trip will last 10 days. Find an accommodation in the center of London, with a rating on Google reviews of at least 4.5.",
|
||||
category: "travel",
|
||||
featured: true,
|
||||
icon: (
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.75 8.75C4.75 7.64543 5.64543 6.75 6.75 6.75H17.25C18.3546 6.75 19.25 7.64543 19.25 8.75V17.25C19.25 18.3546 18.3546 19.25 17.25 19.25H6.75C5.64543 19.25 4.75 18.3546 4.75 17.25V8.75Z" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M8 4.75V8.25" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M16 4.75V8.25" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M7.75 10.75H16.25" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
),
|
||||
image: "https://images.unsplash.com/photo-1507525428034-b723cf961d3e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2400&q=80",
|
||||
url: "https://www.suna.so/share/37b31907-8349-4f63-b0e5-27ca597ed02a"
|
||||
},
|
||||
{
|
||||
id: "funded-startups",
|
||||
title: "Recently Funded Startups",
|
||||
description: "Go on Crunchbase, Dealroom, and TechCrunch, filter by Series A funding rounds in the SaaS Finance Space, and build a report with company data, founders, and contact info for outbound sales.",
|
||||
category: "finance",
|
||||
featured: true,
|
||||
icon: (
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 4.75L19.25 9L12 13.25L4.75 9L12 4.75Z" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M9.25 11.5L4.75 14L12 18.25L19.25 14L14.6722 11.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
),
|
||||
image: "https://images.unsplash.com/photo-1444653614773-995cb1ef9efa?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2400&q=80",
|
||||
url: "https://www.suna.so/share/8b2a897e-985a-4d5e-867b-15239274f764"
|
||||
},
|
||||
{
|
||||
id: "scrape-forums",
|
||||
title: "Scrape Forum Discussions",
|
||||
description: "I need to find the best beauty centers in Rome, but I want to find them by using open forums that speak about this topic. Go on Google, and scrape the forums by looking for beauty center discussions located in Rome.",
|
||||
category: "research",
|
||||
featured: true,
|
||||
icon: (
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.75 19.2502H18.25C18.8023 19.2502 19.25 18.8025 19.25 18.2502V5.75C19.25 5.19772 18.8023 4.75 18.25 4.75H5.75C5.19772 4.75 4.75 5.19772 4.75 5.75V18.2502C4.75 18.8025 5.19772 19.2502 5.75 19.2502Z" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M9.75 8.75C9.75 9.44036 9.19036 10 8.5 10C7.80964 10 7.25 9.44036 7.25 8.75C7.25 8.05964 7.80964 7.5 8.5 7.5C9.19036 7.5 9.75 8.05964 9.75 8.75Z" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
<path d="M19.25 13.75L14.75 9.25L7.25 16.75" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
),
|
||||
image: "https://images.unsplash.com/photo-1523580494863-6f3031224c94?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2400&q=80",
|
||||
url: "https://www.suna.so/share/7d7a5d93-a20d-48b0-82cc-e9a876e9fd04"
|
||||
}
|
||||
],
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue