├── .devcontainer ├── .bashrc ├── Dockerfile ├── README.md ├── devcontainer.json ├── docker-compose.yml └── post-create.sh ├── .dockerignore ├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md ├── SECURITY.md └── workflows │ ├── build.yml │ ├── ci.yml │ └── publish-cli.yml ├── .gitignore ├── .husky └── pre-commit ├── .npmrc ├── LICENSE ├── NOTICE ├── README.md ├── apps ├── docs │ ├── .gitignore │ ├── README.md │ ├── app │ │ ├── (docs) │ │ │ ├── [[...slug]] │ │ │ │ ├── layout.tsx │ │ │ │ └── page.tsx │ │ │ └── layout.tsx │ │ ├── api │ │ │ └── search │ │ │ │ └── route.ts │ │ ├── global.css │ │ ├── layout.config.tsx │ │ └── layout.tsx │ ├── components │ │ ├── icons.tsx │ │ ├── mdx-components.tsx │ │ └── ui │ │ │ ├── block-info-card.tsx │ │ │ ├── block-types.tsx │ │ │ ├── features.tsx │ │ │ └── theme-image.tsx │ ├── content │ │ └── docs │ │ │ ├── blocks │ │ │ ├── agent.mdx │ │ │ ├── api.mdx │ │ │ ├── condition.mdx │ │ │ ├── evaluator.mdx │ │ │ ├── function.mdx │ │ │ ├── index.mdx │ │ │ ├── meta.json │ │ │ └── router.mdx │ │ │ ├── connections │ │ │ ├── accessing-data.mdx │ │ │ ├── basics.mdx │ │ │ ├── best-practices.mdx │ │ │ ├── data-structure.mdx │ │ │ ├── index.mdx │ │ │ ├── meta.json │ │ │ └── tags.mdx │ │ │ ├── execution │ │ │ ├── advanced.mdx │ │ │ ├── basics.mdx │ │ │ ├── index.mdx │ │ │ ├── loops.mdx │ │ │ └── meta.json │ │ │ ├── getting-started │ │ │ └── index.mdx │ │ │ ├── introduction │ │ │ ├── index.mdx │ │ │ └── meta.json │ │ │ ├── meta.json │ │ │ ├── tools │ │ │ ├── airtable.mdx │ │ │ ├── autoblocks.mdx │ │ │ ├── browser_use.mdx │ │ │ ├── clay.mdx │ │ │ ├── confluence.mdx │ │ │ ├── discord.mdx │ │ │ ├── elevenlabs.mdx │ │ │ ├── exa.mdx │ │ │ ├── file.mdx │ │ │ ├── firecrawl.mdx │ │ │ ├── github.mdx │ │ │ ├── gmail.mdx │ │ │ ├── google_docs.mdx │ │ │ ├── google_drive.mdx │ │ │ ├── google_search.mdx │ │ │ ├── google_sheets.mdx │ │ │ ├── guesty.mdx │ │ │ ├── image_generator.mdx │ │ │ ├── index.mdx │ │ │ ├── jina.mdx │ │ │ ├── jira.mdx │ │ │ ├── linear.mdx │ │ │ ├── linkup.mdx │ │ │ ├── mem0.mdx │ │ │ ├── memory.mdx │ │ │ ├── meta.json │ │ │ ├── microsoft_excel.mdx │ │ │ ├── microsoft_teams.mdx │ │ │ ├── mistral_parse.mdx │ │ │ ├── notion.mdx │ │ │ ├── openai.mdx │ │ │ ├── outlook.mdx │ │ │ ├── perplexity.mdx │ │ │ ├── pinecone.mdx │ │ │ ├── reddit.mdx │ │ │ ├── s3.mdx │ │ │ ├── serper.mdx │ │ │ ├── slack.mdx │ │ │ ├── stagehand.mdx │ │ │ ├── stagehand_agent.mdx │ │ │ ├── supabase.mdx │ │ │ ├── tavily.mdx │ │ │ ├── telegram.mdx │ │ │ ├── thinking.mdx │ │ │ ├── translate.mdx │ │ │ ├── twilio_sms.mdx │ │ │ ├── typeform.mdx │ │ │ ├── vision.mdx │ │ │ ├── whatsapp.mdx │ │ │ ├── x.mdx │ │ │ └── youtube.mdx │ │ │ └── variables │ │ │ ├── index.mdx │ │ │ └── meta.json │ ├── lib │ │ ├── source.ts │ │ └── utils.ts │ ├── next.config.ts │ ├── package.json │ ├── postcss.config.mjs │ ├── public │ │ ├── connections.mp4 │ │ ├── favicon │ │ │ ├── android-chrome-192x192.png │ │ │ ├── android-chrome-512x512.png │ │ │ ├── apple-touch-icon.png │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-32x32.png │ │ │ ├── favicon.ico │ │ │ └── site.webmanifest │ │ ├── loops.mp4 │ │ └── static │ │ │ ├── dark │ │ │ ├── agent-dark.png │ │ │ ├── api-dark.png │ │ │ ├── condition-dark.png │ │ │ ├── evaluator-dark.png │ │ │ ├── function-dark.png │ │ │ ├── router-dark.png │ │ │ ├── tooldropdown-dark.png │ │ │ ├── variabledropdown-dark.png │ │ │ └── variables-dark.png │ │ │ └── light │ │ │ ├── agent-light.png │ │ │ ├── api-light.png │ │ │ ├── condition-light.png │ │ │ ├── evaluator-light.png │ │ │ ├── function-light.png │ │ │ ├── router-light.png │ │ │ ├── tooldropdown-light.png │ │ │ ├── variabledropdown-light.png │ │ │ └── variables-light.png │ ├── source.config.ts │ └── tsconfig.json └── sim │ ├── .env.example │ ├── .gitignore │ ├── app │ ├── (auth) │ │ ├── components │ │ │ ├── oauth-provider-checker.tsx │ │ │ └── social-login-buttons.tsx │ │ ├── layout.tsx │ │ ├── login │ │ │ ├── login-form.test.tsx │ │ │ ├── login-form.tsx │ │ │ └── page.tsx │ │ ├── reset-password │ │ │ ├── page.tsx │ │ │ └── reset-password-form.tsx │ │ ├── signup │ │ │ ├── page.tsx │ │ │ ├── signup-form.test.tsx │ │ │ └── signup-form.tsx │ │ └── verify │ │ │ ├── page.tsx │ │ │ ├── use-verification.ts │ │ │ └── verify-content.tsx │ ├── (landing) │ │ ├── actions │ │ │ └── github.ts │ │ ├── components │ │ │ ├── blog-card.tsx │ │ │ ├── dot-pattern.tsx │ │ │ ├── github-stars-client.tsx │ │ │ ├── github-stars.tsx │ │ │ ├── grid-pattern.tsx │ │ │ ├── hero-block.tsx │ │ │ ├── hero-edge.tsx │ │ │ ├── hero-workflow.tsx │ │ │ ├── hooks │ │ │ │ └── use-is-mobile.tsx │ │ │ ├── magicui │ │ │ │ ├── marquee.tsx │ │ │ │ └── orbiting-circles.tsx │ │ │ ├── nav-client.tsx │ │ │ ├── nav-wrapper.tsx │ │ │ ├── sections │ │ │ │ ├── blogs.tsx │ │ │ │ ├── features.tsx │ │ │ │ ├── footer.tsx │ │ │ │ ├── hero.tsx │ │ │ │ ├── integrations.tsx │ │ │ │ └── testimonials.tsx │ │ │ ├── use-window-size.ts │ │ │ └── waitlist-form.tsx │ │ ├── contributors │ │ │ └── page.tsx │ │ ├── landing.tsx │ │ ├── privacy │ │ │ └── page.tsx │ │ ├── terms │ │ │ └── page.tsx │ │ └── utils │ │ │ ├── github.ts │ │ │ └── prefetch.ts │ ├── api │ │ ├── __test-utils__ │ │ │ ├── setup.ts │ │ │ └── utils.ts │ │ ├── auth │ │ │ ├── [...all] │ │ │ │ └── route.ts │ │ │ ├── forget-password │ │ │ │ ├── route.test.ts │ │ │ │ └── route.ts │ │ │ ├── oauth │ │ │ │ ├── connections │ │ │ │ │ ├── route.test.ts │ │ │ │ │ └── route.ts │ │ │ │ ├── credentials │ │ │ │ │ ├── route.test.ts │ │ │ │ │ └── route.ts │ │ │ │ ├── disconnect │ │ │ │ │ ├── route.test.ts │ │ │ │ │ └── route.ts │ │ │ │ ├── microsoft │ │ │ │ │ ├── file │ │ │ │ │ │ └── route.ts │ │ │ │ │ └── files │ │ │ │ │ │ └── route.ts │ │ │ │ ├── token │ │ │ │ │ ├── route.test.ts │ │ │ │ │ └── route.ts │ │ │ │ ├── utils.test.ts │ │ │ │ └── utils.ts │ │ │ ├── reset-password │ │ │ │ └── route.ts │ │ │ └── verify-waitlist-token │ │ │ │ └── route.ts │ │ ├── chat │ │ │ ├── [subdomain] │ │ │ │ ├── otp │ │ │ │ │ └── route.ts │ │ │ │ ├── route.test.ts │ │ │ │ └── route.ts │ │ │ ├── edit │ │ │ │ └── [id] │ │ │ │ │ └── route.ts │ │ │ ├── route.test.ts │ │ │ ├── route.ts │ │ │ ├── subdomains │ │ │ │ └── validate │ │ │ │ │ ├── route.test.ts │ │ │ │ │ └── route.ts │ │ │ ├── utils.test.ts │ │ │ └── utils.ts │ │ ├── codegen │ │ │ ├── route.test.ts │ │ │ └── route.ts │ │ ├── copilot │ │ │ └── route.ts │ │ ├── environment │ │ │ └── route.ts │ │ ├── files │ │ │ ├── delete │ │ │ │ ├── route.test.ts │ │ │ │ └── route.ts │ │ │ ├── parse │ │ │ │ ├── route.test.ts │ │ │ │ └── route.ts │ │ │ ├── presigned │ │ │ │ └── route.ts │ │ │ ├── serve │ │ │ │ └── [...path] │ │ │ │ │ ├── route.test.ts │ │ │ │ │ └── route.ts │ │ │ ├── upload │ │ │ │ ├── route.test.ts │ │ │ │ └── route.ts │ │ │ └── utils.ts │ │ ├── function │ │ │ └── execute │ │ │ │ └── route.ts │ │ ├── help │ │ │ └── route.ts │ │ ├── knowledge │ │ │ ├── [id] │ │ │ │ ├── documents │ │ │ │ │ ├── [documentId] │ │ │ │ │ │ ├── chunks │ │ │ │ │ │ │ ├── [chunkId] │ │ │ │ │ │ │ │ └── route.ts │ │ │ │ │ │ │ └── route.ts │ │ │ │ │ │ └── route.ts │ │ │ │ │ └── route.ts │ │ │ │ ├── process-documents │ │ │ │ │ └── route.ts │ │ │ │ └── route.ts │ │ │ ├── route.ts │ │ │ └── search │ │ │ │ └── route.ts │ │ ├── logs │ │ │ ├── cleanup │ │ │ │ └── route.ts │ │ │ ├── route.test.ts │ │ │ └── route.ts │ │ ├── marketplace │ │ │ ├── [id] │ │ │ │ ├── info │ │ │ │ │ └── route.ts │ │ │ │ ├── unpublish │ │ │ │ │ └── route.ts │ │ │ │ └── view │ │ │ │ │ └── route.ts │ │ │ ├── publish │ │ │ │ └── route.ts │ │ │ └── workflows │ │ │ │ └── route.ts │ │ ├── memory │ │ │ ├── [id] │ │ │ │ └── route.ts │ │ │ └── route.ts │ │ ├── providers │ │ │ └── route.ts │ │ ├── proxy │ │ │ ├── image │ │ │ │ └── route.ts │ │ │ ├── route.ts │ │ │ └── tts │ │ │ │ └── route.ts │ │ ├── schedules │ │ │ ├── [id] │ │ │ │ ├── route.ts │ │ │ │ └── status │ │ │ │ │ ├── route.test.ts │ │ │ │ │ └── route.ts │ │ │ ├── execute │ │ │ │ ├── route.test.ts │ │ │ │ └── route.ts │ │ │ ├── route.test.ts │ │ │ └── route.ts │ │ ├── telemetry │ │ │ └── route.ts │ │ ├── tools │ │ │ ├── confluence │ │ │ │ ├── page │ │ │ │ │ └── route.ts │ │ │ │ └── pages │ │ │ │ │ └── route.ts │ │ │ ├── custom │ │ │ │ ├── route.test.ts │ │ │ │ └── route.ts │ │ │ ├── discord │ │ │ │ ├── channels │ │ │ │ │ └── route.ts │ │ │ │ └── servers │ │ │ │ │ └── route.ts │ │ │ ├── drive │ │ │ │ ├── file │ │ │ │ │ └── route.ts │ │ │ │ └── files │ │ │ │ │ └── route.ts │ │ │ ├── gmail │ │ │ │ ├── label │ │ │ │ │ └── route.ts │ │ │ │ └── labels │ │ │ │ │ └── route.ts │ │ │ ├── jira │ │ │ │ ├── issue │ │ │ │ │ └── route.ts │ │ │ │ ├── issues │ │ │ │ │ └── route.ts │ │ │ │ └── projects │ │ │ │ │ └── route.ts │ │ │ ├── linear │ │ │ │ ├── projects │ │ │ │ │ └── route.ts │ │ │ │ └── teams │ │ │ │ │ └── route.ts │ │ │ ├── microsoft-teams │ │ │ │ ├── channels │ │ │ │ │ └── route.ts │ │ │ │ ├── chats │ │ │ │ │ └── route.ts │ │ │ │ └── teams │ │ │ │ │ └── route.ts │ │ │ ├── outlook │ │ │ │ └── folders │ │ │ │ │ └── route.ts │ │ │ ├── slack │ │ │ │ └── channels │ │ │ │ │ └── route.ts │ │ │ └── stagehand │ │ │ │ ├── agent │ │ │ │ └── route.ts │ │ │ │ ├── extract │ │ │ │ └── route.ts │ │ │ │ └── utils.ts │ │ ├── user │ │ │ ├── api-keys │ │ │ │ ├── [id] │ │ │ │ │ └── route.ts │ │ │ │ └── route.ts │ │ │ ├── settings │ │ │ │ └── route.ts │ │ │ ├── stats │ │ │ │ └── route.ts │ │ │ ├── subscription │ │ │ │ ├── [id] │ │ │ │ │ ├── seats │ │ │ │ │ │ ├── route.test.ts │ │ │ │ │ │ └── route.ts │ │ │ │ │ └── transfer │ │ │ │ │ │ ├── route.test.ts │ │ │ │ │ │ └── route.ts │ │ │ │ ├── enterprise │ │ │ │ │ └── route.ts │ │ │ │ └── route.ts │ │ │ └── usage │ │ │ │ └── route.ts │ │ ├── waitlist │ │ │ └── route.ts │ │ ├── webhooks │ │ │ ├── [id] │ │ │ │ └── route.ts │ │ │ ├── poll │ │ │ │ └── gmail │ │ │ │ │ └── route.ts │ │ │ ├── route.ts │ │ │ ├── test │ │ │ │ └── route.ts │ │ │ └── trigger │ │ │ │ └── [path] │ │ │ │ ├── route.test.ts │ │ │ │ └── route.ts │ │ ├── workflows │ │ │ ├── [id] │ │ │ │ ├── chat │ │ │ │ │ └── status │ │ │ │ │ │ └── route.ts │ │ │ │ ├── deploy │ │ │ │ │ ├── route.test.ts │ │ │ │ │ └── route.ts │ │ │ │ ├── deployed │ │ │ │ │ └── route.ts │ │ │ │ ├── execute │ │ │ │ │ ├── route.test.ts │ │ │ │ │ └── route.ts │ │ │ │ ├── log │ │ │ │ │ └── route.ts │ │ │ │ ├── stats │ │ │ │ │ └── route.ts │ │ │ │ ├── status │ │ │ │ │ └── route.ts │ │ │ │ └── variables │ │ │ │ │ └── route.ts │ │ │ ├── middleware.ts │ │ │ ├── public │ │ │ │ └── [id] │ │ │ │ │ └── route.ts │ │ │ ├── sync │ │ │ │ └── route.ts │ │ │ └── utils.ts │ │ └── workspaces │ │ │ ├── [id] │ │ │ └── route.ts │ │ │ ├── invitations │ │ │ ├── accept │ │ │ │ └── route.ts │ │ │ ├── details │ │ │ │ └── route.ts │ │ │ └── route.ts │ │ │ ├── members │ │ │ ├── [id] │ │ │ │ └── route.ts │ │ │ └── route.ts │ │ │ └── route.ts │ ├── chat │ │ └── [subdomain] │ │ │ ├── chat-client.tsx │ │ │ ├── components │ │ │ ├── auth │ │ │ │ ├── email │ │ │ │ │ └── email-auth.tsx │ │ │ │ └── password │ │ │ │ │ └── password-auth.tsx │ │ │ ├── chat-client.tsx │ │ │ ├── components │ │ │ │ ├── header-links │ │ │ │ │ └── header-links.tsx │ │ │ │ └── markdown-renderer │ │ │ │ │ └── markdown-renderer.tsx │ │ │ ├── error-state │ │ │ │ └── error-state.tsx │ │ │ ├── header │ │ │ │ └── header.tsx │ │ │ ├── input │ │ │ │ └── input.tsx │ │ │ ├── loading-state │ │ │ │ └── loading-state.tsx │ │ │ ├── message-container │ │ │ │ └── message-container.tsx │ │ │ └── message │ │ │ │ ├── components │ │ │ │ └── markdown-renderer.tsx │ │ │ │ └── message.tsx │ │ │ ├── hooks │ │ │ └── use-chat-streaming.ts │ │ │ └── page.tsx │ ├── favicon.ico │ ├── global-error.tsx │ ├── globals.css │ ├── invite │ │ ├── [id] │ │ │ ├── invite.tsx │ │ │ └── page.tsx │ │ └── invite-error │ │ │ ├── invite-error.tsx │ │ │ └── page.tsx │ ├── layout.tsx │ ├── page.tsx │ ├── telemetry-consent-dialog.tsx │ ├── w │ │ ├── [id] │ │ │ ├── components │ │ │ │ ├── code-prompt-bar │ │ │ │ │ └── code-prompt-bar.tsx │ │ │ │ ├── control-bar │ │ │ │ │ ├── components │ │ │ │ │ │ ├── deploy-modal │ │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ │ ├── chat-deploy │ │ │ │ │ │ │ │ │ └── chat-deploy.tsx │ │ │ │ │ │ │ │ ├── deploy-form │ │ │ │ │ │ │ │ │ └── deploy-form.tsx │ │ │ │ │ │ │ │ └── deployment-info │ │ │ │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ │ │ ├── api-endpoint │ │ │ │ │ │ │ │ │ │ └── api-endpoint.tsx │ │ │ │ │ │ │ │ │ ├── api-key │ │ │ │ │ │ │ │ │ │ └── api-key.tsx │ │ │ │ │ │ │ │ │ ├── deploy-status │ │ │ │ │ │ │ │ │ │ └── deploy-status.tsx │ │ │ │ │ │ │ │ │ └── example-command │ │ │ │ │ │ │ │ │ │ └── example-command.tsx │ │ │ │ │ │ │ │ │ └── deployment-info.tsx │ │ │ │ │ │ │ └── deploy-modal.tsx │ │ │ │ │ │ ├── deployment-controls │ │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ │ ├── deployed-workflow-card.tsx │ │ │ │ │ │ │ │ └── deployed-workflow-modal.tsx │ │ │ │ │ │ │ └── deployment-controls.tsx │ │ │ │ │ │ ├── history-dropdown-item │ │ │ │ │ │ │ └── history-dropdown-item.tsx │ │ │ │ │ │ ├── marketplace-modal │ │ │ │ │ │ │ └── marketplace-modal.tsx │ │ │ │ │ │ └── notification-dropdown-item │ │ │ │ │ │ │ └── notification-dropdown-item.tsx │ │ │ │ │ └── control-bar.tsx │ │ │ │ ├── copilot │ │ │ │ │ └── copilot.tsx │ │ │ │ ├── error │ │ │ │ │ └── index.tsx │ │ │ │ ├── loop-node │ │ │ │ │ ├── components │ │ │ │ │ │ ├── loop-badges.test.tsx │ │ │ │ │ │ └── loop-badges.tsx │ │ │ │ │ ├── loop-config.ts │ │ │ │ │ ├── loop-node.test.tsx │ │ │ │ │ └── loop-node.tsx │ │ │ │ ├── notifications │ │ │ │ │ └── notifications.tsx │ │ │ │ ├── panel │ │ │ │ │ ├── components │ │ │ │ │ │ ├── chat │ │ │ │ │ │ │ ├── chat.tsx │ │ │ │ │ │ │ └── components │ │ │ │ │ │ │ │ ├── chat-message │ │ │ │ │ │ │ │ └── chat-message.tsx │ │ │ │ │ │ │ │ ├── chat-modal │ │ │ │ │ │ │ │ └── chat-modal.tsx │ │ │ │ │ │ │ │ └── output-select │ │ │ │ │ │ │ │ └── output-select.tsx │ │ │ │ │ │ ├── console │ │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ │ ├── audio-player │ │ │ │ │ │ │ │ │ └── audio-player.tsx │ │ │ │ │ │ │ │ ├── console-entry │ │ │ │ │ │ │ │ │ └── console-entry.tsx │ │ │ │ │ │ │ │ └── json-view │ │ │ │ │ │ │ │ │ └── json-view.tsx │ │ │ │ │ │ │ └── console.tsx │ │ │ │ │ │ └── variables │ │ │ │ │ │ │ └── variables.tsx │ │ │ │ │ └── panel.tsx │ │ │ │ ├── parallel-node │ │ │ │ │ ├── components │ │ │ │ │ │ └── parallel-badges.tsx │ │ │ │ │ ├── parallel-config.ts │ │ │ │ │ ├── parallel-node.test.tsx │ │ │ │ │ └── parallel-node.tsx │ │ │ │ ├── toolbar │ │ │ │ │ ├── components │ │ │ │ │ │ ├── toolbar-block │ │ │ │ │ │ │ └── toolbar-block.tsx │ │ │ │ │ │ ├── toolbar-loop-block │ │ │ │ │ │ │ └── toolbar-loop-block.tsx │ │ │ │ │ │ ├── toolbar-parallel-block │ │ │ │ │ │ │ └── toolbar-parallel-block.tsx │ │ │ │ │ │ └── toolbar-tabs │ │ │ │ │ │ │ └── toolbar-tabs.tsx │ │ │ │ │ └── toolbar.tsx │ │ │ │ ├── workflow-block │ │ │ │ │ ├── components │ │ │ │ │ │ ├── action-bar │ │ │ │ │ │ │ └── action-bar.tsx │ │ │ │ │ │ ├── connection-blocks │ │ │ │ │ │ │ └── connection-blocks.tsx │ │ │ │ │ │ └── sub-block │ │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ ├── channel-selector │ │ │ │ │ │ │ │ ├── channel-selector-input.tsx │ │ │ │ │ │ │ │ └── components │ │ │ │ │ │ │ │ │ └── slack-channel-selector.tsx │ │ │ │ │ │ │ ├── checkbox-list.tsx │ │ │ │ │ │ │ ├── code.tsx │ │ │ │ │ │ │ ├── condition-input.tsx │ │ │ │ │ │ │ ├── credential-selector │ │ │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ │ │ └── oauth-required-modal.tsx │ │ │ │ │ │ │ │ └── credential-selector.tsx │ │ │ │ │ │ │ ├── date-input.tsx │ │ │ │ │ │ │ ├── dropdown.tsx │ │ │ │ │ │ │ ├── eval-input.tsx │ │ │ │ │ │ │ ├── file-selector │ │ │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ │ │ ├── confluence-file-selector.tsx │ │ │ │ │ │ │ │ │ ├── discord-channel-selector.tsx │ │ │ │ │ │ │ │ │ ├── google-drive-picker.tsx │ │ │ │ │ │ │ │ │ ├── jira-issue-selector.tsx │ │ │ │ │ │ │ │ │ ├── microsoft-file-selector.tsx │ │ │ │ │ │ │ │ │ └── teams-message-selector.tsx │ │ │ │ │ │ │ │ └── file-selector-input.tsx │ │ │ │ │ │ │ ├── file-upload.tsx │ │ │ │ │ │ │ ├── folder-selector │ │ │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ │ │ └── folder-selector-input.tsx │ │ │ │ │ │ │ │ └── folder-selector.tsx │ │ │ │ │ │ │ ├── long-input.tsx │ │ │ │ │ │ │ ├── project-selector │ │ │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ │ │ ├── discord-server-selector.tsx │ │ │ │ │ │ │ │ │ ├── jira-project-selector.tsx │ │ │ │ │ │ │ │ │ ├── linear-project-selector.tsx │ │ │ │ │ │ │ │ │ └── linear-team-selector.tsx │ │ │ │ │ │ │ │ └── project-selector-input.tsx │ │ │ │ │ │ │ ├── schedule │ │ │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ │ │ └── schedule-modal.tsx │ │ │ │ │ │ │ │ └── schedule-config.tsx │ │ │ │ │ │ │ ├── short-input.tsx │ │ │ │ │ │ │ ├── slider-input.tsx │ │ │ │ │ │ │ ├── starter │ │ │ │ │ │ │ │ └── input-format.tsx │ │ │ │ │ │ │ ├── switch.tsx │ │ │ │ │ │ │ ├── table.tsx │ │ │ │ │ │ │ ├── time-input.tsx │ │ │ │ │ │ │ ├── tool-input │ │ │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ │ │ ├── code-editor │ │ │ │ │ │ │ │ │ │ └── code-editor.tsx │ │ │ │ │ │ │ │ │ ├── custom-tool-modal │ │ │ │ │ │ │ │ │ │ └── custom-tool-modal.tsx │ │ │ │ │ │ │ │ │ └── tool-command │ │ │ │ │ │ │ │ │ │ └── tool-command.tsx │ │ │ │ │ │ │ │ └── tool-input.tsx │ │ │ │ │ │ │ └── webhook │ │ │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ │ ├── providers │ │ │ │ │ │ │ │ │ ├── airtable.tsx │ │ │ │ │ │ │ │ │ ├── discord.tsx │ │ │ │ │ │ │ │ │ ├── generic.tsx │ │ │ │ │ │ │ │ │ ├── github.tsx │ │ │ │ │ │ │ │ │ ├── gmail.tsx │ │ │ │ │ │ │ │ │ ├── slack.tsx │ │ │ │ │ │ │ │ │ ├── stripe.tsx │ │ │ │ │ │ │ │ │ ├── telegram.tsx │ │ │ │ │ │ │ │ │ └── whatsapp.tsx │ │ │ │ │ │ │ │ ├── ui │ │ │ │ │ │ │ │ │ ├── config-field.tsx │ │ │ │ │ │ │ │ │ ├── config-section.tsx │ │ │ │ │ │ │ │ │ ├── confirmation.tsx │ │ │ │ │ │ │ │ │ ├── copyable.tsx │ │ │ │ │ │ │ │ │ ├── instructions-section.tsx │ │ │ │ │ │ │ │ │ ├── test-result.tsx │ │ │ │ │ │ │ │ │ ├── webhook-config-field.tsx │ │ │ │ │ │ │ │ │ ├── webhook-footer.tsx │ │ │ │ │ │ │ │ │ └── webhook-url.tsx │ │ │ │ │ │ │ │ └── webhook-modal.tsx │ │ │ │ │ │ │ │ └── webhook.tsx │ │ │ │ │ │ │ ├── hooks │ │ │ │ │ │ │ └── use-sub-block-value.ts │ │ │ │ │ │ │ └── sub-block.tsx │ │ │ │ │ └── workflow-block.tsx │ │ │ │ └── workflow-edge │ │ │ │ │ └── workflow-edge.tsx │ │ │ ├── hooks │ │ │ │ ├── use-block-connections.ts │ │ │ │ ├── use-code-generation.ts │ │ │ │ ├── use-deployment-change-detection.ts │ │ │ │ └── use-workflow-execution.ts │ │ │ ├── layout.tsx │ │ │ ├── page.tsx │ │ │ ├── utils.ts │ │ │ └── workflow.tsx │ │ ├── components │ │ │ ├── providers │ │ │ │ ├── providers.tsx │ │ │ │ └── theme-provider.tsx │ │ │ ├── sidebar │ │ │ │ ├── components │ │ │ │ │ ├── help-modal │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ └── help-form │ │ │ │ │ │ │ │ └── help-form.tsx │ │ │ │ │ │ └── help-modal.tsx │ │ │ │ │ ├── invite-modal │ │ │ │ │ │ ├── invite-modal.tsx │ │ │ │ │ │ └── invites-sent │ │ │ │ │ │ │ └── invites-sent.tsx │ │ │ │ │ ├── nav-section │ │ │ │ │ │ └── nav-section.tsx │ │ │ │ │ ├── settings-modal │ │ │ │ │ │ ├── components │ │ │ │ │ │ │ ├── account │ │ │ │ │ │ │ │ └── account.tsx │ │ │ │ │ │ │ ├── api-keys │ │ │ │ │ │ │ │ └── api-keys.tsx │ │ │ │ │ │ │ ├── credentials │ │ │ │ │ │ │ │ └── credentials.tsx │ │ │ │ │ │ │ ├── environment │ │ │ │ │ │ │ │ └── environment.tsx │ │ │ │ │ │ │ ├── general │ │ │ │ │ │ │ │ └── general.tsx │ │ │ │ │ │ │ ├── privacy │ │ │ │ │ │ │ │ └── privacy.tsx │ │ │ │ │ │ │ ├── settings-navigation │ │ │ │ │ │ │ │ └── settings-navigation.tsx │ │ │ │ │ │ │ ├── subscription │ │ │ │ │ │ │ │ └── subscription.tsx │ │ │ │ │ │ │ └── team-management │ │ │ │ │ │ │ │ └── team-management.tsx │ │ │ │ │ │ └── settings-modal.tsx │ │ │ │ │ ├── sidebar-control │ │ │ │ │ │ └── sidebar-control.tsx │ │ │ │ │ ├── workflow-list │ │ │ │ │ │ └── workflow-list.tsx │ │ │ │ │ └── workspace-header │ │ │ │ │ │ └── workspace-header.tsx │ │ │ │ └── sidebar.tsx │ │ │ └── workflow-preview │ │ │ │ └── generic-workflow-preview.tsx │ │ ├── error.tsx │ │ ├── global-error.tsx │ │ ├── hooks │ │ │ ├── use-keyboard-shortcuts.ts │ │ │ └── use-registry-loading.ts │ │ ├── knowledge │ │ │ ├── [id] │ │ │ │ ├── [documentId] │ │ │ │ │ ├── components │ │ │ │ │ │ ├── document-loading.tsx │ │ │ │ │ │ └── edit-chunk-modal.tsx │ │ │ │ │ ├── document.tsx │ │ │ │ │ └── page.tsx │ │ │ │ ├── base.tsx │ │ │ │ ├── components │ │ │ │ │ └── knowledge-base-loading.tsx │ │ │ │ └── page.tsx │ │ │ ├── components │ │ │ │ ├── base-overview │ │ │ │ │ └── base-overview.tsx │ │ │ │ ├── create-modal │ │ │ │ │ ├── components │ │ │ │ │ │ └── create-form │ │ │ │ │ │ │ └── create-form.tsx │ │ │ │ │ └── create-modal.tsx │ │ │ │ ├── empty-state-card │ │ │ │ │ └── empty-state-card.tsx │ │ │ │ ├── icons │ │ │ │ │ └── document-icons.tsx │ │ │ │ └── skeletons │ │ │ │ │ ├── knowledge-base-card-skeleton.tsx │ │ │ │ │ └── table-skeleton.tsx │ │ │ ├── knowledge.tsx │ │ │ ├── loading.tsx │ │ │ └── page.tsx │ │ ├── layout.tsx │ │ ├── logs │ │ │ ├── components │ │ │ │ ├── control-bar │ │ │ │ │ └── control-bar.tsx │ │ │ │ ├── filters │ │ │ │ │ ├── components │ │ │ │ │ │ ├── filter-section.tsx │ │ │ │ │ │ ├── level.tsx │ │ │ │ │ │ ├── timeline.tsx │ │ │ │ │ │ ├── trigger.tsx │ │ │ │ │ │ └── workflow.tsx │ │ │ │ │ └── filters.tsx │ │ │ │ ├── sidebar │ │ │ │ │ ├── components │ │ │ │ │ │ └── markdown-renderer.tsx │ │ │ │ │ └── sidebar.tsx │ │ │ │ ├── tool-calls │ │ │ │ │ └── tool-calls-display.tsx │ │ │ │ └── trace-spans │ │ │ │ │ └── trace-spans-display.tsx │ │ │ ├── logs.tsx │ │ │ ├── page.tsx │ │ │ ├── stores │ │ │ │ ├── store.ts │ │ │ │ └── types.ts │ │ │ └── utils │ │ │ │ └── format-date.ts │ │ └── marketplace │ │ │ ├── components │ │ │ ├── control-bar │ │ │ │ └── control-bar.tsx │ │ │ ├── error-message.tsx │ │ │ ├── section.tsx │ │ │ ├── toolbar │ │ │ │ └── toolbar.tsx │ │ │ ├── workflow-card-skeleton.tsx │ │ │ └── workflow-card.tsx │ │ │ ├── constants │ │ │ └── categories.tsx │ │ │ ├── marketplace.tsx │ │ │ └── page.tsx │ └── zoom-prevention.tsx │ ├── blocks │ ├── blocks │ │ ├── agent.test.ts │ │ ├── agent.ts │ │ ├── airtable.ts │ │ ├── api.ts │ │ ├── autoblocks.ts │ │ ├── browser_use.ts │ │ ├── clay.ts │ │ ├── condition.ts │ │ ├── confluence.ts │ │ ├── discord.ts │ │ ├── elevenlabs.ts │ │ ├── evaluator.ts │ │ ├── exa.ts │ │ ├── file.ts │ │ ├── firecrawl.ts │ │ ├── function.ts │ │ ├── github.ts │ │ ├── gmail.ts │ │ ├── google.ts │ │ ├── google_docs.ts │ │ ├── google_drive.ts │ │ ├── google_sheets.ts │ │ ├── guesty.ts │ │ ├── image_generator.ts │ │ ├── jina.ts │ │ ├── jira.ts │ │ ├── knowledge.ts │ │ ├── linear.ts │ │ ├── linkup.ts │ │ ├── mem0.ts │ │ ├── memory.ts │ │ ├── microsoft_excel.ts │ │ ├── microsoft_teams.ts │ │ ├── mistral_parse.ts │ │ ├── notion.ts │ │ ├── openai.ts │ │ ├── outlook.ts │ │ ├── perplexity.ts │ │ ├── pinecone.ts │ │ ├── reddit.ts │ │ ├── router.ts │ │ ├── s3.ts │ │ ├── serper.ts │ │ ├── slack.ts │ │ ├── stagehand.ts │ │ ├── stagehand_agent.ts │ │ ├── starter.ts │ │ ├── supabase.ts │ │ ├── tavily.ts │ │ ├── telegram.ts │ │ ├── thinking.ts │ │ ├── translate.ts │ │ ├── twilio.ts │ │ ├── typeform.ts │ │ ├── vision.ts │ │ ├── whatsapp.ts │ │ ├── x.ts │ │ └── youtube.ts │ ├── index.ts │ ├── registry.ts │ ├── types.ts │ └── utils.ts │ ├── components.json │ ├── components │ ├── emails │ │ ├── base-styles.ts │ │ ├── footer.tsx │ │ ├── invitation-email.tsx │ │ ├── otp-verification-email.tsx │ │ ├── render-email.ts │ │ ├── reset-password-email.tsx │ │ ├── waitlist-approval-email.tsx │ │ ├── waitlist-confirmation-email.tsx │ │ └── workspace-invitation.tsx │ ├── icons.tsx │ ├── icons │ │ └── document-icons.tsx │ └── ui │ │ ├── alert-dialog.tsx │ │ ├── alert.tsx │ │ ├── avatar.tsx │ │ ├── badge.tsx │ │ ├── breadcrumb.tsx │ │ ├── button.tsx │ │ ├── calendar.tsx │ │ ├── card.tsx │ │ ├── checkbox.tsx │ │ ├── code-block.tsx │ │ ├── collapsible.tsx │ │ ├── command.tsx │ │ ├── copy-button.tsx │ │ ├── dialog.tsx │ │ ├── dropdown-menu.tsx │ │ ├── env-var-dropdown.tsx │ │ ├── form.tsx │ │ ├── formatted-text.tsx │ │ ├── input-otp-form.tsx │ │ ├── input-otp.tsx │ │ ├── input.tsx │ │ ├── label.tsx │ │ ├── loading-agent.tsx │ │ ├── notice.tsx │ │ ├── popover.tsx │ │ ├── progress.tsx │ │ ├── radio-group.tsx │ │ ├── scroll-area.tsx │ │ ├── select.tsx │ │ ├── separator.tsx │ │ ├── sheet.tsx │ │ ├── skeleton.tsx │ │ ├── slider.tsx │ │ ├── switch.tsx │ │ ├── table.tsx │ │ ├── tabs.tsx │ │ ├── tag-dropdown.test.tsx │ │ ├── tag-dropdown.tsx │ │ ├── textarea.tsx │ │ ├── toggle.tsx │ │ └── tooltip.tsx │ ├── db │ ├── index.ts │ ├── migrations │ │ ├── 0000_careless_black_knight.sql │ │ ├── 0001_foamy_dakota_north.sql │ │ ├── 0002_previous_xavin.sql │ │ ├── 0003_smiling_hammerhead.sql │ │ ├── 0004_nasty_mesmero.sql │ │ ├── 0005_shocking_domino.sql │ │ ├── 0006_plain_zzzax.sql │ │ ├── 0007_mute_stepford_cuckoos.sql │ │ ├── 0008_quick_paladin.sql │ │ ├── 0009_cynical_bullseye.sql │ │ ├── 0009_far_sharon_ventura.sql │ │ ├── 0010_flashy_nebula.sql │ │ ├── 0011_youthful_iron_lad.sql │ │ ├── 0012_minor_dexter_bennett.sql │ │ ├── 0013_dusty_aaron_stack.sql │ │ ├── 0014_nice_dragon_lord.sql │ │ ├── 0015_brief_martin_li.sql │ │ ├── 0016_cultured_butterfly.sql │ │ ├── 0017_curious_ink.sql │ │ ├── 0018_sleepy_champions.sql │ │ ├── 0019_even_lorna_dane.sql │ │ ├── 0020_clear_skreet.sql │ │ ├── 0021_shocking_korath.sql │ │ ├── 0022_gray_galactus.sql │ │ ├── 0023_nervous_tyger_tiger.sql │ │ ├── 0024_next_whizzer.sql │ │ ├── 0025_curved_jubilee.sql │ │ ├── 0026_daily_killraven.sql │ │ ├── 0027_careless_gamora.sql │ │ ├── 0028_absent_triton.sql │ │ ├── 0030_happy_joseph.sql │ │ ├── 0031_lively_nico_minoru.sql │ │ ├── 0032_rare_nico_minoru.sql │ │ ├── 0033_solid_stellaris.sql │ │ ├── 0034_brainy_revanche.sql │ │ ├── 0035_slim_energizer.sql │ │ ├── 0036_married_skreet.sql │ │ ├── 0037_outgoing_madame_hydra.sql │ │ ├── 0038_shocking_thor.sql │ │ ├── 0039_tranquil_speed.sql │ │ ├── 0040_silky_monster_badoon.sql │ │ ├── meta │ │ │ ├── 0000_snapshot.json │ │ │ ├── 0001_snapshot.json │ │ │ ├── 0002_snapshot.json │ │ │ ├── 0003_snapshot.json │ │ │ ├── 0004_snapshot.json │ │ │ ├── 0005_snapshot.json │ │ │ ├── 0006_snapshot.json │ │ │ ├── 0007_snapshot.json │ │ │ ├── 0008_snapshot.json │ │ │ ├── 0009_snapshot.json │ │ │ ├── 0010_snapshot.json │ │ │ ├── 0011_snapshot.json │ │ │ ├── 0012_snapshot.json │ │ │ ├── 0013_snapshot.json │ │ │ ├── 0014_snapshot.json │ │ │ ├── 0015_snapshot.json │ │ │ ├── 0016_snapshot.json │ │ │ ├── 0017_snapshot.json │ │ │ ├── 0018_snapshot.json │ │ │ ├── 0019_snapshot.json │ │ │ ├── 0020_snapshot.json │ │ │ ├── 0021_snapshot.json │ │ │ ├── 0022_snapshot.json │ │ │ ├── 0023_snapshot.json │ │ │ ├── 0024_snapshot.json │ │ │ ├── 0025_snapshot.json │ │ │ ├── 0026_snapshot.json │ │ │ ├── 0027_snapshot.json │ │ │ ├── 0028_snapshot.json │ │ │ ├── 0030_snapshot.json │ │ │ ├── 0031_snapshot.json │ │ │ ├── 0032_snapshot.json │ │ │ ├── 0033_snapshot.json │ │ │ ├── 0034_snapshot.json │ │ │ ├── 0035_snapshot.json │ │ │ ├── 0036_snapshot.json │ │ │ ├── 0037_snapshot.json │ │ │ ├── 0038_snapshot.json │ │ │ ├── 0039_snapshot.json │ │ │ ├── 0040_snapshot.json │ │ │ └── _journal.json │ │ ├── relations.ts │ │ └── schema.ts │ └── schema.ts │ ├── drizzle.config.ts │ ├── executor │ ├── __test-utils__ │ │ ├── executor-mocks.ts │ │ ├── mock-dependencies.ts │ │ └── test-executor.ts │ ├── handlers │ │ ├── agent │ │ │ ├── agent-handler.test.ts │ │ │ ├── agent-handler.ts │ │ │ └── types.ts │ │ ├── api │ │ │ ├── api-handler.test.ts │ │ │ └── api-handler.ts │ │ ├── condition │ │ │ ├── condition-handler.test.ts │ │ │ └── condition-handler.ts │ │ ├── evaluator │ │ │ ├── evaluator-handler.test.ts │ │ │ └── evaluator-handler.ts │ │ ├── function │ │ │ ├── function-handler.test.ts │ │ │ └── function-handler.ts │ │ ├── generic │ │ │ ├── generic-handler.test.ts │ │ │ └── generic-handler.ts │ │ ├── index.ts │ │ ├── loop │ │ │ ├── loop-handler.test.ts │ │ │ └── loop-handler.ts │ │ ├── parallel │ │ │ ├── parallel-handler.test.ts │ │ │ └── parallel-handler.ts │ │ └── router │ │ │ ├── router-handler.test.ts │ │ │ └── router-handler.ts │ ├── index.test.ts │ ├── index.ts │ ├── loops.test.ts │ ├── loops.ts │ ├── parallels.test.ts │ ├── parallels.ts │ ├── path.test.ts │ ├── path.ts │ ├── resolver.test.ts │ ├── resolver.ts │ └── types.ts │ ├── hooks │ ├── use-debounce.ts │ └── use-user-subscription.ts │ ├── instrumentation-client.ts │ ├── instrumentation-server.ts │ ├── instrumentation.ts │ ├── lib │ ├── auth-client.ts │ ├── auth.ts │ ├── document-processor.ts │ ├── env.ts │ ├── environment.ts │ ├── file-parsers │ │ ├── csv-parser.ts │ │ ├── docx-parser.ts │ │ ├── index.test.ts │ │ ├── index.ts │ │ ├── pdf-parser.ts │ │ ├── raw-pdf-parser.ts │ │ └── types.ts │ ├── freestyle.ts │ ├── generate-chat-title.ts │ ├── logs │ │ ├── console-logger.ts │ │ ├── execution-logger.ts │ │ └── trace-spans.ts │ ├── mailer.ts │ ├── oauth.ts │ ├── redis.ts │ ├── schedules │ │ ├── utils.test.ts │ │ └── utils.ts │ ├── subscription.ts │ ├── subscription │ │ ├── subscription.ts │ │ ├── utils.test.ts │ │ └── utils.ts │ ├── telemetry.ts │ ├── uploads │ │ ├── s3-client.test.ts │ │ ├── s3-client.ts │ │ ├── setup.server.ts │ │ └── setup.ts │ ├── urls │ │ └── utils.ts │ ├── usage-monitor.ts │ ├── utils.test.ts │ ├── utils.ts │ ├── variables │ │ ├── variable-manager.test.ts │ │ └── variable-manager.ts │ ├── waitlist │ │ ├── rate-limiter.ts │ │ ├── service.ts │ │ └── token.ts │ ├── webhooks │ │ ├── gmail-polling-service.ts │ │ └── utils.ts │ └── workflows │ │ └── utils.ts │ ├── middleware.ts │ ├── next.config.ts │ ├── package.json │ ├── postcss.config.mjs │ ├── providers │ ├── anthropic │ │ └── index.ts │ ├── cerebras │ │ ├── index.ts │ │ └── types.ts │ ├── deepseek │ │ └── index.ts │ ├── google │ │ └── index.ts │ ├── groq │ │ └── index.ts │ ├── index.ts │ ├── model-capabilities.test.ts │ ├── model-capabilities.ts │ ├── ollama │ │ ├── index.ts │ │ └── types.ts │ ├── openai │ │ └── index.ts │ ├── pricing.ts │ ├── types.ts │ ├── utils.test.ts │ ├── utils.ts │ └── xai │ │ └── index.ts │ ├── public │ ├── favicon │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon.ico │ │ └── site.webmanifest │ ├── icon.svg │ ├── logo-sim.svg │ ├── sim.png │ ├── sim.svg │ ├── social │ │ ├── facebook.png │ │ ├── instagram.png │ │ └── twitter.png │ ├── static │ │ ├── automate-blocks.svg │ │ ├── demo.gif │ │ ├── discord-icon.png │ │ ├── github-icon.png │ │ ├── preview.png │ │ ├── sim.png │ │ ├── sync-blocks.svg │ │ └── x-icon.png │ └── twitter │ │ ├── daniel.jpg │ │ ├── github-projects.jpg │ │ ├── hasan.jpg │ │ ├── lazukars.png │ │ ├── nizzy.jpg │ │ ├── samarth.jpg │ │ ├── syamrajk.jpg │ │ └── xyflow.jpg │ ├── scripts │ └── ollama_docker.sh │ ├── serializer │ ├── __test-utils__ │ │ └── test-workflows.ts │ ├── index.test.ts │ ├── index.ts │ └── types.ts │ ├── stores │ ├── constants.ts │ ├── copilot │ │ ├── store.ts │ │ ├── types.ts │ │ └── utils.ts │ ├── custom-tools │ │ ├── store.ts │ │ └── types.ts │ ├── execution │ │ ├── store.ts │ │ └── types.ts │ ├── index.ts │ ├── notifications │ │ ├── store.ts │ │ └── types.ts │ ├── ollama │ │ ├── store.ts │ │ └── types.ts │ ├── panel │ │ ├── chat │ │ │ ├── store.ts │ │ │ └── types.ts │ │ ├── console │ │ │ ├── store.ts │ │ │ └── types.ts │ │ ├── store.ts │ │ ├── types.ts │ │ └── variables │ │ │ ├── store.ts │ │ │ └── types.ts │ ├── settings │ │ ├── environment │ │ │ ├── store.ts │ │ │ └── types.ts │ │ └── general │ │ │ ├── store.ts │ │ │ └── types.ts │ ├── sidebar │ │ └── store.ts │ ├── sync-core.ts │ ├── sync-registry.ts │ ├── sync.ts │ └── workflows │ │ ├── index.ts │ │ ├── middleware.ts │ │ ├── persistence.ts │ │ ├── registry │ │ ├── store.ts │ │ ├── types.ts │ │ └── utils.ts │ │ ├── subblock │ │ ├── store.ts │ │ ├── types.ts │ │ └── utils.ts │ │ ├── sync.ts │ │ ├── utils.ts │ │ └── workflow │ │ ├── store.test.ts │ │ ├── store.ts │ │ ├── types.ts │ │ ├── utils.test.ts │ │ └── utils.ts │ ├── tailwind.config.ts │ ├── telemetry.config.ts │ ├── tools │ ├── __test-utils__ │ │ ├── mock-data.ts │ │ └── test-tools.ts │ ├── airtable │ │ ├── create_records.ts │ │ ├── get_record.ts │ │ ├── index.test.ts │ │ ├── index.ts │ │ ├── list_records.ts │ │ ├── types.ts │ │ ├── update_multiple_records.ts │ │ └── update_record.ts │ ├── autoblocks │ │ ├── index.ts │ │ ├── prompt_manager.ts │ │ └── types.ts │ ├── browser_use │ │ ├── index.ts │ │ ├── run_task.ts │ │ └── types.ts │ ├── clay │ │ ├── index.ts │ │ ├── populate.ts │ │ └── types.ts │ ├── confluence │ │ ├── index.ts │ │ ├── retrieve.ts │ │ ├── types.ts │ │ ├── update.ts │ │ └── utils.ts │ ├── discord │ │ ├── get_messages.ts │ │ ├── get_server.ts │ │ ├── get_user.ts │ │ ├── index.ts │ │ ├── send_message.ts │ │ └── types.ts │ ├── elevenlabs │ │ ├── index.ts │ │ ├── tts.ts │ │ └── types.ts │ ├── exa │ │ ├── answer.ts │ │ ├── find_similar_links.ts │ │ ├── get_contents.ts │ │ ├── index.ts │ │ ├── search.ts │ │ └── types.ts │ ├── file │ │ ├── index.ts │ │ ├── parser.ts │ │ └── types.ts │ ├── firecrawl │ │ ├── index.ts │ │ ├── scrape.ts │ │ └── types.ts │ ├── function │ │ ├── execute.test.ts │ │ ├── execute.ts │ │ ├── index.ts │ │ └── types.ts │ ├── github │ │ ├── comment.ts │ │ ├── index.ts │ │ ├── latest_commit.ts │ │ ├── pr.test.ts │ │ ├── pr.ts │ │ ├── repo_info.test.ts │ │ ├── repo_info.ts │ │ └── types.ts │ ├── gmail │ │ ├── index.ts │ │ ├── read.test.ts │ │ ├── read.ts │ │ ├── search.ts │ │ ├── send.ts │ │ └── types.ts │ ├── google │ │ ├── index.ts │ │ ├── search.ts │ │ └── types.ts │ ├── google_docs │ │ ├── create.ts │ │ ├── index.ts │ │ ├── read.ts │ │ ├── types.ts │ │ └── write.ts │ ├── google_drive │ │ ├── create_folder.ts │ │ ├── get_content.ts │ │ ├── index.ts │ │ ├── list.ts │ │ ├── types.ts │ │ ├── upload.ts │ │ └── utils.ts │ ├── google_sheets │ │ ├── append.ts │ │ ├── index.ts │ │ ├── read.ts │ │ ├── types.ts │ │ ├── update.ts │ │ └── write.ts │ ├── guesty │ │ ├── guest.ts │ │ ├── index.ts │ │ ├── reservation.ts │ │ └── types.ts │ ├── http │ │ ├── index.ts │ │ ├── request.test.ts │ │ ├── request.ts │ │ └── types.ts │ ├── hubspot │ │ └── contacts.ts │ ├── index.test.ts │ ├── index.ts │ ├── jina │ │ ├── index.ts │ │ ├── read_url.ts │ │ └── types.ts │ ├── jira │ │ ├── bulk_read.ts │ │ ├── index.ts │ │ ├── retrieve.ts │ │ ├── types.ts │ │ ├── update.ts │ │ ├── utils.ts │ │ └── write.ts │ ├── knowledge │ │ ├── index.ts │ │ ├── search.ts │ │ └── types.ts │ ├── linear │ │ ├── create_issue.ts │ │ ├── index.ts │ │ ├── read_issues.ts │ │ └── types.ts │ ├── linkup │ │ ├── index.ts │ │ ├── search.ts │ │ └── types.ts │ ├── mem0 │ │ ├── add_memories.ts │ │ ├── get_memories.ts │ │ ├── index.ts │ │ ├── search_memories.ts │ │ └── types.ts │ ├── memory │ │ ├── add.ts │ │ ├── delete.ts │ │ ├── get.ts │ │ ├── get_all.ts │ │ ├── index.ts │ │ └── types.ts │ ├── microsoft_excel │ │ ├── index.ts │ │ ├── read.ts │ │ ├── table_add.ts │ │ ├── types.ts │ │ └── write.ts │ ├── microsoft_teams │ │ ├── attachment-utils.ts │ │ ├── index.ts │ │ ├── read_channel.ts │ │ ├── read_chat.ts │ │ ├── types.ts │ │ ├── write_channel.ts │ │ └── write_chat.ts │ ├── mistral │ │ ├── index.ts │ │ ├── parser.ts │ │ └── types.ts │ ├── notion │ │ ├── create_page.ts │ │ ├── index.ts │ │ ├── read.ts │ │ ├── types.ts │ │ ├── update_page.ts │ │ └── write.ts │ ├── openai │ │ ├── embeddings.ts │ │ ├── image.ts │ │ ├── index.ts │ │ └── types.ts │ ├── outlook │ │ ├── draft.ts │ │ ├── index.ts │ │ ├── read.ts │ │ ├── send.ts │ │ └── types.ts │ ├── perplexity │ │ ├── chat.ts │ │ ├── index.ts │ │ └── types.ts │ ├── pinecone │ │ ├── fetch.ts │ │ ├── generate_embeddings.ts │ │ ├── index.ts │ │ ├── search_text.ts │ │ ├── search_vector.ts │ │ ├── types.ts │ │ └── upsert_text.ts │ ├── reddit │ │ ├── get_comments.ts │ │ ├── get_posts.ts │ │ ├── hot_posts.ts │ │ ├── index.ts │ │ └── types.ts │ ├── registry.ts │ ├── s3 │ │ ├── get_object.ts │ │ ├── index.ts │ │ └── types.ts │ ├── salesforce │ │ └── opportunities.ts │ ├── serper │ │ ├── index.ts │ │ ├── search.ts │ │ └── types.ts │ ├── slack │ │ ├── index.ts │ │ ├── message.ts │ │ └── types.ts │ ├── stagehand │ │ ├── agent.ts │ │ ├── extract.ts │ │ ├── index.ts │ │ └── types.ts │ ├── supabase │ │ ├── index.ts │ │ ├── insert.ts │ │ ├── query.ts │ │ └── types.ts │ ├── tavily │ │ ├── extract.ts │ │ ├── index.ts │ │ ├── search.ts │ │ └── types.ts │ ├── telegram │ │ ├── index.ts │ │ ├── message.ts │ │ └── types.ts │ ├── thinking │ │ ├── index.ts │ │ ├── tool.ts │ │ └── types.ts │ ├── twilio │ │ ├── index.ts │ │ ├── send_sms.ts │ │ └── types.ts │ ├── typeform │ │ ├── files.test.ts │ │ ├── files.ts │ │ ├── index.test.ts │ │ ├── index.ts │ │ ├── insights.test.ts │ │ ├── insights.ts │ │ ├── responses.test.ts │ │ ├── responses.ts │ │ └── types.ts │ ├── types.ts │ ├── utils.test.ts │ ├── utils.ts │ ├── vision │ │ ├── index.ts │ │ ├── tool.ts │ │ └── types.ts │ ├── whatsapp │ │ ├── index.ts │ │ ├── send_message.ts │ │ └── types.ts │ ├── x │ │ ├── index.ts │ │ ├── read.ts │ │ ├── search.ts │ │ ├── types.ts │ │ ├── user.ts │ │ └── write.ts │ └── youtube │ │ ├── index.ts │ │ ├── search.ts │ │ └── types.ts │ ├── tsconfig.json │ ├── vercel.json │ ├── vitest.config.ts │ └── vitest.setup.ts ├── biome.json ├── bun.lock ├── bunfig.toml ├── docker-compose.local.yml ├── docker-compose.ollama.yml ├── docker-compose.prod.yml ├── docker ├── app.Dockerfile └── db.Dockerfile ├── package.json ├── packages └── simstudio │ ├── README.md │ ├── package.json │ ├── src │ └── index.ts │ └── tsconfig.json ├── scripts ├── README.md ├── generate-block-docs.ts ├── generate-docs.sh ├── package-lock.json ├── package.json ├── setup-doc-generator.sh └── tsconfig.json └── turbo.json /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | # Use the latest Bun canary image for development 2 | FROM oven/bun:canary 3 | 4 | # Avoid warnings by switching to noninteractive 5 | ENV DEBIAN_FRONTEND=noninteractive 6 | 7 | # Install necessary packages for development 8 | RUN apt-get update \ 9 | && apt-get -y install --no-install-recommends \ 10 | git curl wget jq sudo postgresql-client vim nano \ 11 | bash-completion ca-certificates lsb-release gnupg \ 12 | && apt-get clean -y \ 13 | && rm -rf /var/lib/apt/lists/* 14 | 15 | # Create a non-root user 16 | ARG USERNAME=bun 17 | ARG USER_UID=1000 18 | ARG USER_GID=$USER_UID 19 | 20 | # Add sudo support 21 | RUN echo "$USERNAME ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$USERNAME \ 22 | && chmod 0440 /etc/sudoers.d/$USERNAME 23 | 24 | # Install global packages for development 25 | RUN bun install -g turbo drizzle-kit typescript @types/node 26 | 27 | # Install bun completions 28 | RUN bun completions > /etc/bash_completion.d/bun 29 | 30 | # Set up shell environment 31 | RUN echo "export PATH=$PATH:/home/$USERNAME/.bun/bin" >> /etc/profile 32 | RUN echo "source /etc/profile" >> /etc/bash.bashrc 33 | 34 | # Switch back to dialog for any ad-hoc use of apt-get 35 | ENV DEBIAN_FRONTEND=dialog 36 | 37 | WORKDIR /workspace 38 | 39 | # Expose the ports we're interested in 40 | EXPOSE 3000 41 | EXPOSE 3001 -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | LICENSE 2 | NOTICE 3 | .prettierrc 4 | .prettierignore 5 | README.md 6 | .gitignore 7 | .husky 8 | .github 9 | .devcontainer 10 | .env.example 11 | node_modules -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '[BUG]' 5 | labels: bug 6 | assignees: '' 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior: 14 | 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Additional context** 27 | Add any other context about the problem here. 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '[REQUEST]' 5 | labels: feature 6 | assignees: '' 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | ------- | ------------------ | 7 | | 0.1.x | :white_check_mark: | 8 | 9 | ## Reporting a Vulnerability 10 | 11 | We take the security of Sim Studio seriously. If you believe you've found a security vulnerability, please follow these steps: 12 | 13 | 1. **Do not disclose the vulnerability publicly** or to any third parties. 14 | 15 | 2. **Email us directly** at security@simstudio.ai with details of the vulnerability. 16 | 17 | 3. **Include the following information** in your report: 18 | 19 | - Description of the vulnerability 20 | - Steps to reproduce 21 | - Potential impact 22 | - Any suggestions for mitigation 23 | 24 | 4. We will acknowledge receipt of your vulnerability report within 48 hours and provide an estimated timeline for a fix. 25 | 26 | 5. Once the vulnerability is fixed, we will notify you and publicly acknowledge your contribution (unless you prefer to remain anonymous). 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /apps/**/node_modules 6 | /packages/**/node_modules 7 | /scripts/node_modules 8 | 9 | # bun specific 10 | bun-debug.log* 11 | 12 | # testing 13 | /coverage 14 | /apps/**/coverage 15 | 16 | # next.js 17 | /.next/ 18 | /apps/**/out/ 19 | /apps/**/.next/ 20 | /apps/**/build 21 | 22 | # production 23 | /build 24 | /dist 25 | **/dist/ 26 | **/standalone/ 27 | sim-standalone.tar.gz 28 | 29 | # misc 30 | .DS_Store 31 | *.pem 32 | 33 | # env files 34 | .env 35 | *.env 36 | .env.local 37 | .env.development 38 | .env.test 39 | .env.production 40 | 41 | # vercel 42 | .vercel 43 | 44 | # typescript 45 | *.tsbuildinfo 46 | next-env.d.ts 47 | 48 | # cursorrules 49 | .cursorrules 50 | 51 | # docs 52 | /apps/docs/.source 53 | /apps/docs/.contentlayer 54 | /apps/docs/.content-collections 55 | 56 | # database instantiation 57 | **/postgres_data/ 58 | 59 | # collector configuration 60 | collector-config.yaml 61 | docker-compose.collector.yml 62 | start-collector.sh 63 | 64 | # Turborepo 65 | .turbo -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | bunx lint-staged -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | ignore-scripts=true 2 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Sim Studio 2 | Copyright 2025 Sim Studio 3 | 4 | This product includes software developed for the Sim Studio project. -------------------------------------------------------------------------------- /apps/docs/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # bun specific 7 | .bun 8 | bun.lockb 9 | bun-debug.log* 10 | 11 | # testing 12 | /coverage 13 | 14 | # next.js 15 | /.next/ 16 | /out/ 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # env files 24 | .env 25 | *.env 26 | .env.local 27 | .env.development 28 | .env.test 29 | .env.production 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | 38 | # Fumadocs 39 | /.source/ -------------------------------------------------------------------------------- /apps/docs/README.md: -------------------------------------------------------------------------------- 1 | # docs 2 | 3 | This is a Next.js application generated with 4 | [Create Fumadocs](https://github.com/fuma-nama/fumadocs). 5 | 6 | Run development server: 7 | 8 | ```bash 9 | bun run dev 10 | ``` 11 | 12 | Open http://localhost:3000 with your browser to see the result. 13 | 14 | ## Learn More 15 | 16 | To learn more about Next.js and Fumadocs, take a look at the following 17 | resources: 18 | 19 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js 20 | features and API. 21 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 22 | - [Fumadocs](https://fumadocs.vercel.app) - learn about Fumadocs 23 | - [Bun Documentation](https://bun.sh/docs) - learn about Bun features and API 24 | -------------------------------------------------------------------------------- /apps/docs/app/(docs)/[[...slug]]/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react' 2 | 3 | export default function SlugLayout({ children }: { children: ReactNode }) { 4 | return children 5 | } 6 | -------------------------------------------------------------------------------- /apps/docs/app/(docs)/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react' 2 | import { DocsLayout } from 'fumadocs-ui/layouts/docs' 3 | import { ExternalLink, GithubIcon } from 'lucide-react' 4 | import Link from 'next/link' 5 | import { source } from '@/lib/source' 6 | 7 | const GitHubLink = () => ( 8 |
9 | 15 | 16 | 17 |
18 | ) 19 | 20 | export default function Layout({ children }: { children: ReactNode }) { 21 | return ( 22 | <> 23 | Sim Studio, 27 | }} 28 | links={[ 29 | { 30 | text: 'Visit Sim Studio', 31 | url: 'https://simstudio.ai', 32 | icon: , 33 | }, 34 | ]} 35 | sidebar={{ 36 | defaultOpenLevel: 1, 37 | collapsible: true, 38 | footer: null, 39 | }} 40 | > 41 | {children} 42 | 43 | 44 | 45 | ) 46 | } 47 | -------------------------------------------------------------------------------- /apps/docs/app/api/search/route.ts: -------------------------------------------------------------------------------- 1 | import { createFromSource } from 'fumadocs-core/search/server' 2 | import { source } from '@/lib/source' 3 | 4 | export const { GET } = createFromSource(source) 5 | -------------------------------------------------------------------------------- /apps/docs/app/global.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | @import "fumadocs-ui/css/neutral.css"; 3 | @import "fumadocs-ui/css/preset.css"; 4 | :root { 5 | --color-fd-primary: #802fff; /* Purple from control-bar component */ 6 | } 7 | 8 | /* Custom text highlighting styles */ 9 | .text-highlight { 10 | color: var(--color-fd-primary); 11 | } 12 | 13 | /* Override marker color for highlighted lists */ 14 | .highlight-markers li::marker { 15 | color: var(--color-fd-primary); 16 | } 17 | 18 | @source '../node_modules/fumadocs-ui/dist/**/*.js'; 19 | -------------------------------------------------------------------------------- /apps/docs/app/layout.config.tsx: -------------------------------------------------------------------------------- 1 | import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared' 2 | 3 | /** 4 | * Shared layout configurations 5 | * 6 | * you can customise layouts individually from: 7 | * Home Layout: app/(home)/layout.tsx 8 | * Docs Layout: app/docs/layout.tsx 9 | */ 10 | export const baseOptions: BaseLayoutProps = { 11 | nav: { 12 | title: ( 13 | <> 14 | 15 | 16 | 17 | My App 18 | 19 | ), 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /apps/docs/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { ReactNode } from 'react' 2 | import { RootProvider } from 'fumadocs-ui/provider' 3 | import { Inter } from 'next/font/google' 4 | import './global.css' 5 | import { Analytics } from '@vercel/analytics/next' 6 | 7 | const inter = Inter({ 8 | subsets: ['latin'], 9 | }) 10 | 11 | export default function Layout({ children }: { children: ReactNode }) { 12 | return ( 13 | 14 | 15 | 16 | {children} 17 | 18 | 19 | 20 | 21 | ) 22 | } 23 | 24 | export const metadata = { 25 | title: 'Sim Studio', 26 | description: 27 | 'Build agents in seconds with a drag and drop workflow builder. Access comprehensive documentation to help you create efficient workflows and maximize your automation capabilities.', 28 | manifest: '/favicon/site.webmanifest', 29 | icons: { 30 | icon: [ 31 | { url: '/favicon/favicon-16x16.png', sizes: '16x16', type: 'image/png' }, 32 | { url: '/favicon/favicon-32x32.png', sizes: '32x32', type: 'image/png' }, 33 | ], 34 | apple: '/favicon/apple-touch-icon.png', 35 | shortcut: '/favicon/favicon.ico', 36 | }, 37 | appleWebApp: { 38 | capable: true, 39 | statusBarStyle: 'default', 40 | title: 'Sim Studio Docs', 41 | }, 42 | } 43 | -------------------------------------------------------------------------------- /apps/docs/components/mdx-components.tsx: -------------------------------------------------------------------------------- 1 | import defaultMdxComponents from 'fumadocs-ui/mdx' 2 | import { ThemeImage } from './ui/theme-image' 3 | 4 | // Extend the default MDX components with our custom components 5 | const mdxComponents = { 6 | ...defaultMdxComponents, 7 | ThemeImage, 8 | } 9 | 10 | export default mdxComponents 11 | -------------------------------------------------------------------------------- /apps/docs/components/ui/block-info-card.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import type * as React from 'react' 4 | 5 | interface BlockInfoCardProps { 6 | type: string 7 | color: string 8 | icon?: boolean 9 | iconSvg?: string 10 | } 11 | 12 | export function BlockInfoCard({ 13 | type, 14 | color, 15 | icon = false, 16 | iconSvg, 17 | }: BlockInfoCardProps): React.ReactNode { 18 | return ( 19 |
20 |
21 |
25 | {iconSvg ? ( 26 |
27 | ) : ( 28 |
{type.substring(0, 2)}
29 | )} 30 |
31 |
32 | {icon && ( 33 | 41 | )} 42 |
43 | ) 44 | } 45 | -------------------------------------------------------------------------------- /apps/docs/components/ui/theme-image.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { useEffect, useState } from 'react' 4 | import Image from 'next/image' 5 | import { useTheme } from 'next-themes' 6 | 7 | interface ThemeImageProps { 8 | lightSrc: string 9 | darkSrc: string 10 | alt: string 11 | width?: number 12 | height?: number 13 | className?: string 14 | } 15 | 16 | export function ThemeImage({ 17 | lightSrc, 18 | darkSrc, 19 | alt, 20 | width = 600, 21 | height = 400, 22 | className = 'rounded-lg border border-border my-6', 23 | }: ThemeImageProps) { 24 | const { resolvedTheme } = useTheme() 25 | const [imageSrc, setImageSrc] = useState(lightSrc) 26 | const [mounted, setMounted] = useState(false) 27 | 28 | // Wait until component is mounted to avoid hydration mismatch 29 | useEffect(() => { 30 | setMounted(true) 31 | }, []) 32 | 33 | useEffect(() => { 34 | if (mounted) { 35 | setImageSrc(resolvedTheme === 'dark' ? darkSrc : lightSrc) 36 | } 37 | }, [resolvedTheme, lightSrc, darkSrc, mounted]) 38 | 39 | if (!mounted) { 40 | return null 41 | } 42 | 43 | return ( 44 |
45 | {alt} 46 |
47 | ) 48 | } 49 | -------------------------------------------------------------------------------- /apps/docs/content/docs/blocks/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Blocks", 3 | "pages": ["agent", "api", "condition", "function", "evaluator", "router"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/docs/content/docs/connections/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Connections", 3 | "pages": ["basics", "tags", "data-structure", "accessing-data", "best-practices"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/docs/content/docs/execution/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Execution", 3 | "pages": ["basics", "loops", "advanced"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/docs/content/docs/introduction/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Introduction", 3 | "pages": ["index"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/docs/content/docs/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Sim Studio Documentation", 3 | "pages": [ 4 | "---Introduction---", 5 | "./introduction/index", 6 | "./getting-started/index", 7 | "---Create---", 8 | "blocks", 9 | "tools", 10 | "---Connections---", 11 | "connections", 12 | "---Execution---", 13 | "execution", 14 | "---Advanced---", 15 | "./variables/index" 16 | ], 17 | "defaultOpen": true 18 | } 19 | -------------------------------------------------------------------------------- /apps/docs/content/docs/tools/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": [ 3 | "index", 4 | "airtable", 5 | "autoblocks", 6 | "browser_use", 7 | "clay", 8 | "confluence", 9 | "discord", 10 | "elevenlabs", 11 | "exa", 12 | "file", 13 | "firecrawl", 14 | "github", 15 | "gmail", 16 | "google_docs", 17 | "google_drive", 18 | "google_search", 19 | "google_sheets", 20 | "guesty", 21 | "image_generator", 22 | "jina", 23 | "jira", 24 | "linear", 25 | "linkup", 26 | "mem0", 27 | "memory", 28 | "microsoft_excel", 29 | "microsoft_teams", 30 | "mistral_parse", 31 | "notion", 32 | "openai", 33 | "outlook", 34 | "perplexity", 35 | "pinecone", 36 | "reddit", 37 | "s3", 38 | "serper", 39 | "slack", 40 | "stagehand", 41 | "stagehand_agent", 42 | "supabase", 43 | "tavily", 44 | "telegram", 45 | "thinking", 46 | "translate", 47 | "twilio_sms", 48 | "typeform", 49 | "vision", 50 | "whatsapp", 51 | "x", 52 | "youtube" 53 | ] 54 | } 55 | -------------------------------------------------------------------------------- /apps/docs/content/docs/variables/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Variables", 3 | "pages": ["index"] 4 | } 5 | -------------------------------------------------------------------------------- /apps/docs/lib/source.ts: -------------------------------------------------------------------------------- 1 | import { loader } from 'fumadocs-core/source' 2 | import { docs } from '@/.source' 3 | 4 | // `loader()` also assign a URL to your pages 5 | // See https://fumadocs.vercel.app/docs/headless/source-api for more info 6 | export const source = loader({ 7 | baseUrl: '/', 8 | source: docs.toFumadocsSource(), 9 | }) 10 | -------------------------------------------------------------------------------- /apps/docs/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { type ClassValue, clsx } from 'clsx' 2 | import { twMerge } from 'tailwind-merge' 3 | 4 | /** 5 | * Combines multiple class names into a single string, merging Tailwind classes properly 6 | */ 7 | export function cn(...inputs: ClassValue[]) { 8 | return twMerge(clsx(inputs)) 9 | } 10 | -------------------------------------------------------------------------------- /apps/docs/next.config.ts: -------------------------------------------------------------------------------- 1 | import { createMDX } from 'fumadocs-mdx/next' 2 | 3 | const withMDX = createMDX() 4 | 5 | /** @type {import('next').NextConfig} */ 6 | const config = { 7 | reactStrictMode: true, 8 | async redirects() { 9 | return [ 10 | { 11 | source: '/', 12 | destination: '/introduction', 13 | permanent: true, 14 | }, 15 | ] 16 | }, 17 | } 18 | 19 | export default withMDX(config) 20 | -------------------------------------------------------------------------------- /apps/docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "license": "Apache-2.0", 6 | "scripts": { 7 | "dev": "next dev --port 3001", 8 | "build": "next build", 9 | "start": "next start", 10 | "postinstall": "fumadocs-mdx", 11 | "type-check": "tsc --noEmit" 12 | }, 13 | "dependencies": { 14 | "@tabler/icons-react": "^3.31.0", 15 | "@vercel/analytics": "1.5.0", 16 | "@vercel/og": "^0.6.5", 17 | "clsx": "^2.1.1", 18 | "fumadocs-core": "^15.0.16", 19 | "fumadocs-mdx": "^11.5.6", 20 | "fumadocs-ui": "^15.0.16", 21 | "lucide-react": "^0.511.0", 22 | "next": "^15.2.3", 23 | "next-themes": "^0.4.6", 24 | "react": "19.1.0", 25 | "react-dom": "19.1.0", 26 | "tailwind-merge": "^3.0.2" 27 | }, 28 | "devDependencies": { 29 | "@tailwindcss/postcss": "^4.0.12", 30 | "@types/mdx": "^2.0.13", 31 | "@types/node": "^22.14.1", 32 | "@types/react": "^19.1.2", 33 | "@types/react-dom": "^19.0.4", 34 | "dotenv-cli": "^8.0.0", 35 | "postcss": "^8.5.3", 36 | "tailwindcss": "^4.0.12", 37 | "typescript": "^5.8.2" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /apps/docs/postcss.config.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | '@tailwindcss/postcss': {}, 4 | }, 5 | } 6 | -------------------------------------------------------------------------------- /apps/docs/public/connections.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/connections.mp4 -------------------------------------------------------------------------------- /apps/docs/public/favicon/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/favicon/android-chrome-192x192.png -------------------------------------------------------------------------------- /apps/docs/public/favicon/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/favicon/android-chrome-512x512.png -------------------------------------------------------------------------------- /apps/docs/public/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /apps/docs/public/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /apps/docs/public/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /apps/docs/public/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/favicon/favicon.ico -------------------------------------------------------------------------------- /apps/docs/public/favicon/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Sim Studio", 3 | "short_name": "Sim Studio", 4 | "icons": [ 5 | { 6 | "src": "/favicon/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/favicon/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /apps/docs/public/loops.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/loops.mp4 -------------------------------------------------------------------------------- /apps/docs/public/static/dark/agent-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/static/dark/agent-dark.png -------------------------------------------------------------------------------- /apps/docs/public/static/dark/api-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/static/dark/api-dark.png -------------------------------------------------------------------------------- /apps/docs/public/static/dark/condition-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/static/dark/condition-dark.png -------------------------------------------------------------------------------- /apps/docs/public/static/dark/evaluator-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/static/dark/evaluator-dark.png -------------------------------------------------------------------------------- /apps/docs/public/static/dark/function-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/static/dark/function-dark.png -------------------------------------------------------------------------------- /apps/docs/public/static/dark/router-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/static/dark/router-dark.png -------------------------------------------------------------------------------- /apps/docs/public/static/dark/tooldropdown-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/static/dark/tooldropdown-dark.png -------------------------------------------------------------------------------- /apps/docs/public/static/dark/variabledropdown-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/static/dark/variabledropdown-dark.png -------------------------------------------------------------------------------- /apps/docs/public/static/dark/variables-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/static/dark/variables-dark.png -------------------------------------------------------------------------------- /apps/docs/public/static/light/agent-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/static/light/agent-light.png -------------------------------------------------------------------------------- /apps/docs/public/static/light/api-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/static/light/api-light.png -------------------------------------------------------------------------------- /apps/docs/public/static/light/condition-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/static/light/condition-light.png -------------------------------------------------------------------------------- /apps/docs/public/static/light/evaluator-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/static/light/evaluator-light.png -------------------------------------------------------------------------------- /apps/docs/public/static/light/function-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/static/light/function-light.png -------------------------------------------------------------------------------- /apps/docs/public/static/light/router-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/static/light/router-light.png -------------------------------------------------------------------------------- /apps/docs/public/static/light/tooldropdown-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/static/light/tooldropdown-light.png -------------------------------------------------------------------------------- /apps/docs/public/static/light/variabledropdown-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/static/light/variabledropdown-light.png -------------------------------------------------------------------------------- /apps/docs/public/static/light/variables-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/docs/public/static/light/variables-light.png -------------------------------------------------------------------------------- /apps/docs/source.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, defineDocs } from 'fumadocs-mdx/config' 2 | 3 | export const docs = defineDocs({ 4 | dir: 'content/docs', 5 | }) 6 | 7 | export default defineConfig({ 8 | mdxOptions: { 9 | // MDX options 10 | }, 11 | }) 12 | -------------------------------------------------------------------------------- /apps/docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ESNext", 5 | "lib": ["dom", "dom.iterable", "esnext"], 6 | "allowJs": true, 7 | "skipLibCheck": true, 8 | "strict": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "noEmit": true, 11 | "esModuleInterop": true, 12 | "module": "esnext", 13 | "moduleResolution": "bundler", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "jsx": "preserve", 17 | "incremental": true, 18 | "paths": { 19 | "@/.source": ["./.source/index.ts"], 20 | "@/*": ["./*"] 21 | }, 22 | "plugins": [ 23 | { 24 | "name": "next" 25 | } 26 | ] 27 | }, 28 | "include": [ 29 | "next-env.d.ts", 30 | "**/*.ts", 31 | "**/*.tsx", 32 | ".next/types/**/*.ts", 33 | "content/docs/execution/index.mdx", 34 | "content/docs/connections/index.mdx" 35 | ], 36 | "exclude": ["node_modules"] 37 | } 38 | -------------------------------------------------------------------------------- /apps/sim/.env.example: -------------------------------------------------------------------------------- 1 | # Database (Required) 2 | DATABASE_URL="postgresql://postgres:password@localhost:5432/postgres" 3 | 4 | # Authentication (Required) 5 | BETTER_AUTH_SECRET=your_secret_key # Use `openssl rand -hex 32` to generate, or visit https://www.better-auth.com/docs/installation 6 | BETTER_AUTH_URL=http://localhost:3000 7 | 8 | ## Security (Required) 9 | ENCRYPTION_KEY=your_encryption_key # Use `openssl rand -hex 32` to generate 10 | 11 | # Email Provider (Optional) 12 | # RESEND_API_KEY= # Uncomment and add your key from https://resend.com to send actual emails 13 | # If left commented out, emails will be logged to console instead 14 | 15 | # Freestyle API Key (Required for sandboxed code execution for functions/custom-tools) 16 | # FREESTYLE_API_KEY= # Uncomment and add your key from https://docs.freestyle.sh/Getting-Started/run 17 | -------------------------------------------------------------------------------- /apps/sim/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /packages/**/node_modules 6 | 7 | # bun specific 8 | .bun 9 | bun.lockb 10 | bun-debug.log* 11 | 12 | # testing 13 | /coverage 14 | 15 | # next.js 16 | /.next/ 17 | /out/ 18 | 19 | # production 20 | /build 21 | /dist 22 | **/dist/ 23 | **/standalone/ 24 | sim-standalone.tar.gz 25 | 26 | # misc 27 | .DS_Store 28 | *.pem 29 | 30 | # env files 31 | .env 32 | *.env 33 | .env.local 34 | .env.development 35 | .env.test 36 | .env.production 37 | 38 | # vercel 39 | .vercel 40 | 41 | # typescript 42 | *.tsbuildinfo 43 | next-env.d.ts 44 | 45 | # cursorrules 46 | .cursorrules 47 | 48 | # Sentry Config File 49 | .env.sentry-build-plugin 50 | 51 | # Uploads 52 | /uploads 53 | -------------------------------------------------------------------------------- /apps/sim/app/(auth)/components/oauth-provider-checker.tsx: -------------------------------------------------------------------------------- 1 | 'use server' 2 | 3 | import { env } from '@/lib/env' 4 | import { isProd } from '@/lib/environment' 5 | 6 | export async function getOAuthProviderStatus() { 7 | const githubAvailable = !!( 8 | env.GITHUB_CLIENT_ID && 9 | env.GITHUB_CLIENT_SECRET && 10 | env.GITHUB_CLIENT_ID !== 'placeholder' && 11 | env.GITHUB_CLIENT_SECRET !== 'placeholder' 12 | ) 13 | 14 | const googleAvailable = !!( 15 | env.GOOGLE_CLIENT_ID && 16 | env.GOOGLE_CLIENT_SECRET && 17 | env.GOOGLE_CLIENT_ID !== 'placeholder' && 18 | env.GOOGLE_CLIENT_SECRET !== 'placeholder' 19 | ) 20 | 21 | return { githubAvailable, googleAvailable, isProduction: isProd } 22 | } 23 | -------------------------------------------------------------------------------- /apps/sim/app/(auth)/layout.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import Image from 'next/image' 4 | import Link from 'next/link' 5 | import { GridPattern } from '../(landing)/components/grid-pattern' 6 | import { NotificationList } from '../w/[id]/components/notifications/notifications' 7 | 8 | export default function AuthLayout({ children }: { children: React.ReactNode }) { 9 | return ( 10 |
11 | {/* Background pattern */} 12 |
40 | ) 41 | } 42 | -------------------------------------------------------------------------------- /apps/sim/app/(auth)/login/page.tsx: -------------------------------------------------------------------------------- 1 | import { getOAuthProviderStatus } from '../components/oauth-provider-checker' 2 | import LoginForm from './login-form' 3 | 4 | // Force dynamic rendering to avoid prerender errors with search params 5 | export const dynamic = 'force-dynamic' 6 | 7 | export default async function LoginPage() { 8 | const { githubAvailable, googleAvailable, isProduction } = await getOAuthProviderStatus() 9 | 10 | return ( 11 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /apps/sim/app/(auth)/signup/page.tsx: -------------------------------------------------------------------------------- 1 | import { getOAuthProviderStatus } from '../components/oauth-provider-checker' 2 | import SignupForm from './signup-form' 3 | 4 | // Force dynamic rendering to avoid prerender errors with search params 5 | export const dynamic = 'force-dynamic' 6 | 7 | export default async function SignupPage() { 8 | const { githubAvailable, googleAvailable, isProduction } = await getOAuthProviderStatus() 9 | 10 | return ( 11 | 16 | ) 17 | } 18 | -------------------------------------------------------------------------------- /apps/sim/app/(auth)/verify/page.tsx: -------------------------------------------------------------------------------- 1 | import { env } from '@/lib/env' 2 | import { isProd } from '@/lib/environment' 3 | import { getBaseUrl } from '@/lib/urls/utils' 4 | import { VerifyContent } from './verify-content' 5 | 6 | // Force dynamic rendering to avoid prerender errors with search params 7 | export const dynamic = 'force-dynamic' 8 | 9 | export default function VerifyPage() { 10 | const baseUrl = getBaseUrl() 11 | const hasResendKey = Boolean(env.RESEND_API_KEY && env.RESEND_API_KEY !== 'placeholder') 12 | 13 | return 14 | } 15 | -------------------------------------------------------------------------------- /apps/sim/app/(landing)/components/github-stars-client.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { motion } from 'framer-motion' 4 | import { GithubIcon } from '@/components/icons' 5 | 6 | interface GitHubStarsClientProps { 7 | stars: string 8 | } 9 | 10 | export default function GitHubStarsClient({ stars }: GitHubStarsClientProps) { 11 | return ( 12 | 22 | 23 | {stars} 24 | 25 | ) 26 | } 27 | -------------------------------------------------------------------------------- /apps/sim/app/(landing)/components/hero-edge.tsx: -------------------------------------------------------------------------------- 1 | import { BaseEdge, type EdgeProps, getSmoothStepPath } from 'reactflow' 2 | 3 | export const HeroEdge = ({ 4 | id, 5 | sourceX, 6 | sourceY, 7 | targetX, 8 | targetY, 9 | sourcePosition, 10 | targetPosition, 11 | style = {}, 12 | markerEnd, 13 | }: EdgeProps) => { 14 | const isHorizontal = sourcePosition === 'right' || sourcePosition === 'left' 15 | 16 | const [edgePath] = getSmoothStepPath({ 17 | sourceX, 18 | sourceY, 19 | sourcePosition, 20 | targetX, 21 | targetY, 22 | targetPosition, 23 | borderRadius: 8, 24 | offset: isHorizontal ? 30 : 20, 25 | }) 26 | 27 | return ( 28 | 39 | ) 40 | } 41 | -------------------------------------------------------------------------------- /apps/sim/app/(landing)/components/hooks/use-is-mobile.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react' 2 | 3 | export default function useIsMobile() { 4 | const [isMobile, setIsMobile] = useState(false) 5 | const [mounted, setMounted] = useState(false) 6 | 7 | useEffect(() => { 8 | setMounted(true) 9 | const checkMobile = () => setIsMobile(window.innerWidth < 768) 10 | checkMobile() 11 | 12 | window.addEventListener('resize', checkMobile) 13 | return () => window.removeEventListener('resize', checkMobile) 14 | }, []) 15 | 16 | return { isMobile, mounted } 17 | } 18 | -------------------------------------------------------------------------------- /apps/sim/app/(landing)/components/use-window-size.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react' 2 | 3 | interface WindowSize { 4 | width: number | undefined 5 | height: number | undefined 6 | } 7 | 8 | export function useWindowSize(): WindowSize { 9 | const [windowSize, setWindowSize] = useState({ 10 | width: undefined, 11 | height: undefined, 12 | }) 13 | 14 | useEffect(() => { 15 | // Handler to call on window resize 16 | function handleResize() { 17 | setWindowSize({ 18 | width: window.innerWidth, 19 | height: window.innerHeight, 20 | }) 21 | } 22 | 23 | // Add event listener 24 | window.addEventListener('resize', handleResize) 25 | 26 | // Call handler right away so state gets updated with initial window size 27 | handleResize() 28 | 29 | // Remove event listener on cleanup 30 | return () => window.removeEventListener('resize', handleResize) 31 | }, []) 32 | 33 | return windowSize 34 | } 35 | -------------------------------------------------------------------------------- /apps/sim/app/(landing)/landing.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import NavWrapper from './components/nav-wrapper' 4 | import Footer from './components/sections/footer' 5 | import Hero from './components/sections/hero' 6 | import Integrations from './components/sections/integrations' 7 | import Testimonials from './components/sections/testimonials' 8 | 9 | export default function Landing() { 10 | const handleOpenTypeformLink = () => { 11 | window.open('https://form.typeform.com/to/jqCO12pF', '_blank') 12 | } 13 | 14 | return ( 15 |
16 | 17 | 18 | 19 | 20 | {/* */} 21 | 22 | {/* */} 23 | 24 | {/* Footer */} 25 |
26 |
27 | ) 28 | } 29 | -------------------------------------------------------------------------------- /apps/sim/app/api/__test-utils__/setup.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * API Test Setup 3 | */ 4 | import { afterEach, beforeEach, vi } from 'vitest' 5 | 6 | // Mock Next.js implementations 7 | vi.mock('next/headers', () => ({ 8 | cookies: () => ({ 9 | get: vi.fn().mockReturnValue({ value: 'test-session-token' }), 10 | }), 11 | headers: () => ({ 12 | get: vi.fn().mockReturnValue('test-value'), 13 | }), 14 | })) 15 | 16 | // Mock auth utilities 17 | vi.mock('@/lib/auth/session', () => ({ 18 | getSession: vi.fn().mockResolvedValue({ 19 | user: { 20 | id: 'user-id', 21 | email: 'test@example.com', 22 | }, 23 | sessionToken: 'test-session-token', 24 | }), 25 | })) 26 | 27 | // Configure Vitest environment 28 | beforeEach(() => { 29 | // Clear all mocks before each test 30 | vi.clearAllMocks() 31 | }) 32 | 33 | afterEach(() => { 34 | // Ensure all mocks are restored after each test 35 | vi.restoreAllMocks() 36 | }) 37 | -------------------------------------------------------------------------------- /apps/sim/app/api/auth/[...all]/route.ts: -------------------------------------------------------------------------------- 1 | import { toNextJsHandler } from 'better-auth/next-js' 2 | import { auth } from '@/lib/auth' 3 | 4 | export const dynamic = 'force-dynamic' 5 | 6 | export const { GET, POST } = toNextJsHandler(auth.handler) 7 | -------------------------------------------------------------------------------- /apps/sim/app/api/auth/forget-password/route.ts: -------------------------------------------------------------------------------- 1 | import { type NextRequest, NextResponse } from 'next/server' 2 | import { auth } from '@/lib/auth' 3 | import { createLogger } from '@/lib/logs/console-logger' 4 | 5 | export const dynamic = 'force-dynamic' 6 | 7 | const logger = createLogger('ForgetPasswordAPI') 8 | 9 | export async function POST(request: NextRequest) { 10 | try { 11 | const body = await request.json() 12 | const { email, redirectTo } = body 13 | 14 | if (!email) { 15 | return NextResponse.json({ message: 'Email is required' }, { status: 400 }) 16 | } 17 | 18 | await auth.api.forgetPassword({ 19 | body: { 20 | email, 21 | redirectTo, 22 | }, 23 | method: 'POST', 24 | }) 25 | 26 | return NextResponse.json({ success: true }) 27 | } catch (error) { 28 | logger.error('Error requesting password reset:', { error }) 29 | 30 | return NextResponse.json( 31 | { 32 | message: 33 | error instanceof Error 34 | ? error.message 35 | : 'Failed to send password reset email. Please try again later.', 36 | }, 37 | { status: 500 } 38 | ) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /apps/sim/app/api/auth/reset-password/route.ts: -------------------------------------------------------------------------------- 1 | import { type NextRequest, NextResponse } from 'next/server' 2 | import { auth } from '@/lib/auth' 3 | import { createLogger } from '@/lib/logs/console-logger' 4 | 5 | export const dynamic = 'force-dynamic' 6 | 7 | const logger = createLogger('PasswordReset') 8 | 9 | export async function POST(request: NextRequest) { 10 | try { 11 | const body = await request.json() 12 | const { token, newPassword } = body 13 | 14 | if (!token || !newPassword) { 15 | return NextResponse.json({ message: 'Token and new password are required' }, { status: 400 }) 16 | } 17 | 18 | await auth.api.resetPassword({ 19 | body: { 20 | newPassword, 21 | token, 22 | }, 23 | method: 'POST', 24 | }) 25 | 26 | return NextResponse.json({ success: true }) 27 | } catch (error) { 28 | logger.error('Error during password reset:', { error }) 29 | 30 | return NextResponse.json( 31 | { 32 | message: 33 | error instanceof Error 34 | ? error.message 35 | : 'Failed to reset password. Please try again or request a new reset link.', 36 | }, 37 | { status: 500 } 38 | ) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /apps/sim/app/api/user/subscription/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from 'next/server' 2 | import { getSession } from '@/lib/auth' 3 | import { createLogger } from '@/lib/logs/console-logger' 4 | import { getHighestPrioritySubscription } from '@/lib/subscription/subscription' 5 | import { checkEnterprisePlan, checkTeamPlan } from '@/lib/subscription/utils' 6 | 7 | const logger = createLogger('UserSubscriptionAPI') 8 | 9 | export async function GET() { 10 | try { 11 | const session = await getSession() 12 | 13 | if (!session?.user?.id) { 14 | return NextResponse.json({ error: 'Authentication required' }, { status: 401 }) 15 | } 16 | 17 | const activeSub = await getHighestPrioritySubscription(session.user.id) 18 | 19 | const isPaid = 20 | activeSub?.status === 'active' && 21 | ['pro', 'team', 'enterprise'].includes(activeSub?.plan ?? '') 22 | 23 | const isPro = isPaid 24 | 25 | const isTeam = checkTeamPlan(activeSub) 26 | 27 | const isEnterprise = checkEnterprisePlan(activeSub) 28 | 29 | return NextResponse.json({ 30 | isPaid, 31 | isPro, 32 | isTeam, 33 | isEnterprise, 34 | plan: activeSub?.plan || 'free', 35 | status: activeSub?.status || null, 36 | seats: activeSub?.seats || null, 37 | metadata: activeSub?.metadata || null, 38 | }) 39 | } catch (error) { 40 | logger.error('Error fetching subscription:', error) 41 | return NextResponse.json({ error: 'Failed to fetch subscription data' }, { status: 500 }) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /apps/sim/app/api/user/usage/route.ts: -------------------------------------------------------------------------------- 1 | import { type NextRequest, NextResponse } from 'next/server' 2 | import { getSession } from '@/lib/auth' 3 | import { createLogger } from '@/lib/logs/console-logger' 4 | import { checkUsageStatus } from '@/lib/usage-monitor' 5 | 6 | const logger = createLogger('UserUsageAPI') 7 | 8 | export async function GET(request: NextRequest) { 9 | try { 10 | // Get the authenticated user 11 | const session = await getSession() 12 | 13 | if (!session?.user?.id) { 14 | logger.warn('Unauthorized usage data access attempt') 15 | return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) 16 | } 17 | 18 | // Get usage data using our monitor utility 19 | const usageData = await checkUsageStatus(session.user.id) 20 | 21 | // Set appropriate caching headers 22 | const response = NextResponse.json(usageData) 23 | 24 | // Cache for 5 minutes, private (user-specific data), must revalidate 25 | response.headers.set('Cache-Control', 'private, max-age=300, must-revalidate') 26 | // Add date header for age calculation 27 | response.headers.set('Date', new Date().toUTCString()) 28 | 29 | return response 30 | } catch (error) { 31 | logger.error('Error checking usage data:', error) 32 | return NextResponse.json({ error: 'Failed to check usage data' }, { status: 500 }) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /apps/sim/app/api/workflows/utils.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from 'next/server' 2 | 3 | export function createErrorResponse(error: string, status: number, code?: string) { 4 | return NextResponse.json( 5 | { 6 | error, 7 | code: code || error.toUpperCase().replace(/\s+/g, '_'), 8 | }, 9 | { status } 10 | ) 11 | } 12 | 13 | export function createSuccessResponse(data: any) { 14 | return NextResponse.json(data) 15 | } 16 | -------------------------------------------------------------------------------- /apps/sim/app/chat/[subdomain]/components/components/header-links/header-links.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { motion } from 'framer-motion' 4 | import { GithubIcon } from '@/components/icons' 5 | 6 | interface HeaderLinksProps { 7 | stars: string 8 | } 9 | 10 | export default function HeaderLinks({ stars }: HeaderLinksProps) { 11 | return ( 12 |
13 | 23 | 24 | {stars} 25 | 26 |
27 | ) 28 | } 29 | -------------------------------------------------------------------------------- /apps/sim/app/chat/[subdomain]/components/loading-state/loading-state.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | export function ChatLoadingState() { 4 | return ( 5 |
6 |
7 |
8 |
9 |
10 |
11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /apps/sim/app/chat/[subdomain]/page.tsx: -------------------------------------------------------------------------------- 1 | import ChatClient from './chat-client' 2 | 3 | export default async function ChatPage({ params }: { params: Promise<{ subdomain: string }> }) { 4 | const { subdomain } = await params 5 | return 6 | } 7 | -------------------------------------------------------------------------------- /apps/sim/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simstudioai/sim/dcf6e10b5bcdb426dd36fb8143281a4c2aa6596f/apps/sim/app/favicon.ico -------------------------------------------------------------------------------- /apps/sim/app/global-error.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { useEffect } from 'react' 4 | import * as Sentry from '@sentry/nextjs' 5 | import NextError from 'next/error' 6 | 7 | export default function GlobalError({ error }: { error: Error & { digest?: string } }) { 8 | useEffect(() => { 9 | Sentry.captureException(error) 10 | }, [error]) 11 | 12 | return ( 13 | 14 | 15 | {/* `NextError` is the default Next.js error page component. Its type 16 | definition requires a `statusCode` prop. However, since the App Router 17 | does not expose status codes for errors, we simply pass 0 to render a 18 | generic error message. */} 19 | 20 | 21 | 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /apps/sim/app/invite/[id]/page.tsx: -------------------------------------------------------------------------------- 1 | import Invite from './invite' 2 | 3 | export default Invite 4 | -------------------------------------------------------------------------------- /apps/sim/app/invite/invite-error/page.tsx: -------------------------------------------------------------------------------- 1 | import InviteError from './invite-error' 2 | 3 | // Generate this page on-demand instead of at build time 4 | export const dynamic = 'force-dynamic' 5 | 6 | export default function InviteErrorPage() { 7 | return 8 | } 9 | -------------------------------------------------------------------------------- /apps/sim/app/page.tsx: -------------------------------------------------------------------------------- 1 | import Landing from './(landing)/landing' 2 | 3 | export default Landing 4 | -------------------------------------------------------------------------------- /apps/sim/app/w/[id]/components/control-bar/components/deploy-modal/components/deployment-info/components/api-endpoint/api-endpoint.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { CopyButton } from '@/components/ui/copy-button' 4 | import { Label } from '@/components/ui/label' 5 | 6 | interface ApiEndpointProps { 7 | endpoint: string 8 | showLabel?: boolean 9 | } 10 | 11 | export function ApiEndpoint({ endpoint, showLabel = true }: ApiEndpointProps) { 12 | return ( 13 |
14 | {showLabel && ( 15 |
16 | 17 |
18 | )} 19 |
20 |
{endpoint}
21 | 22 |
23 |
24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /apps/sim/app/w/[id]/components/loop-node/loop-config.ts: -------------------------------------------------------------------------------- 1 | import { RepeatIcon } from 'lucide-react' 2 | 3 | export const LoopTool = { 4 | id: 'loop', 5 | type: 'loop', 6 | name: 'Loop', 7 | description: 'Create a Loop', 8 | icon: RepeatIcon, 9 | bgColor: '#2FB3FF', 10 | data: { 11 | label: 'Loop', 12 | loopType: 'for', 13 | count: 5, 14 | collection: '', 15 | width: 500, 16 | height: 300, 17 | extent: 'parent', 18 | executionState: { 19 | currentIteration: 0, 20 | isExecuting: false, 21 | startTime: null, 22 | endTime: null, 23 | }, 24 | }, 25 | style: { 26 | width: 500, 27 | height: 300, 28 | }, 29 | // Specify that this should be rendered as a ReactFlow group node 30 | isResizable: true, 31 | } 32 | -------------------------------------------------------------------------------- /apps/sim/app/w/[id]/components/panel/components/console/console.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { useMemo } from 'react' 4 | import { ScrollArea } from '@/components/ui/scroll-area' 5 | import { useConsoleStore } from '@/stores/panel/console/store' 6 | import { useWorkflowRegistry } from '@/stores/workflows/registry/store' 7 | import { ConsoleEntry } from './components/console-entry/console-entry' 8 | 9 | interface ConsoleProps { 10 | panelWidth: number 11 | } 12 | 13 | export function Console({ panelWidth }: ConsoleProps) { 14 | const entries = useConsoleStore((state) => state.entries) 15 | const { activeWorkflowId } = useWorkflowRegistry() 16 | 17 | const filteredEntries = useMemo(() => { 18 | return entries.filter((entry) => entry.workflowId === activeWorkflowId) 19 | }, [entries, activeWorkflowId]) 20 | 21 | return ( 22 | 23 |
24 | {filteredEntries.length === 0 ? ( 25 |
26 | No console entries 27 |
28 | ) : ( 29 | filteredEntries.map((entry) => ( 30 | 31 | )) 32 | )} 33 |
34 |
35 | ) 36 | } 37 | -------------------------------------------------------------------------------- /apps/sim/app/w/[id]/components/parallel-node/parallel-config.ts: -------------------------------------------------------------------------------- 1 | import { SplitIcon } from 'lucide-react' 2 | 3 | export const ParallelTool = { 4 | id: 'parallel', 5 | type: 'parallel', 6 | name: 'Parallel', 7 | description: 'Parallel Execution', 8 | icon: SplitIcon, 9 | bgColor: '#8BC34A', 10 | data: { 11 | label: 'Parallel', 12 | parallelType: 'collection' as 'collection' | 'count', 13 | count: 5, 14 | collection: '', 15 | extent: 'parent', 16 | executionState: { 17 | currentExecution: 0, 18 | isExecuting: false, 19 | startTime: null, 20 | endTime: null, 21 | }, 22 | }, 23 | style: { 24 | width: 500, 25 | height: 300, 26 | }, 27 | // Specify that this should be rendered as a ReactFlow group node 28 | isResizable: true, 29 | } 30 | -------------------------------------------------------------------------------- /apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx: -------------------------------------------------------------------------------- 1 | import { Checkbox } from '@/components/ui/checkbox' 2 | import { Label } from '@/components/ui/label' 3 | import { cn } from '@/lib/utils' 4 | import { useSubBlockValue } from '../hooks/use-sub-block-value' 5 | 6 | interface CheckboxListProps { 7 | blockId: string 8 | subBlockId: string 9 | title: string 10 | options: { label: string; id: string }[] 11 | layout?: 'full' | 'half' 12 | } 13 | 14 | export function CheckboxList({ blockId, subBlockId, title, options, layout }: CheckboxListProps) { 15 | return ( 16 |
17 | {options.map((option) => { 18 | const [value, setValue] = useSubBlockValue(blockId, option.id) 19 | return ( 20 |
21 | setValue(checked as boolean)} 25 | /> 26 | 32 |
33 | ) 34 | })} 35 |
36 | ) 37 | } 38 | -------------------------------------------------------------------------------- /apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/switch.tsx: -------------------------------------------------------------------------------- 1 | import { Label } from '@/components/ui/label' 2 | import { Switch as UISwitch } from '@/components/ui/switch' 3 | import { useSubBlockValue } from '../hooks/use-sub-block-value' 4 | 5 | interface SwitchProps { 6 | blockId: string 7 | subBlockId: string 8 | title: string 9 | } 10 | 11 | export function Switch({ blockId, subBlockId, title }: SwitchProps) { 12 | const [value, setValue] = useSubBlockValue(blockId, subBlockId) 13 | 14 | return ( 15 |
16 | 19 | setValue(checked)} /> 20 |
21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/config-section.tsx: -------------------------------------------------------------------------------- 1 | import type React from 'react' 2 | import { cn } from '@/lib/utils' 3 | 4 | interface ConfigSectionProps { 5 | title?: string 6 | children: React.ReactNode 7 | className?: string 8 | } 9 | 10 | export function ConfigSection({ title, children, className }: ConfigSectionProps) { 11 | return ( 12 |
15 | {children} 16 |
17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/webhook/components/ui/instructions-section.tsx: -------------------------------------------------------------------------------- 1 | import type React from 'react' 2 | import { cn } from '@/lib/utils' 3 | 4 | interface InstructionsSectionProps { 5 | title?: string 6 | children: React.ReactNode 7 | tip?: string 8 | className?: string 9 | } 10 | 11 | export function InstructionsSection({ 12 | title = 'Setup Instructions', 13 | children, 14 | tip, 15 | className, 16 | }: InstructionsSectionProps) { 17 | return ( 18 |
19 |

{title}

20 |
21 | {children} {/* Instructions list goes here */} 22 |
23 |
24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /apps/sim/app/w/[id]/layout.tsx: -------------------------------------------------------------------------------- 1 | import { ErrorBoundary } from './components/error' 2 | 3 | export default function WorkflowLayout({ children }: { children: React.ReactNode }) { 4 | return ( 5 |
6 | {children} 7 |
8 | ) 9 | } 10 | -------------------------------------------------------------------------------- /apps/sim/app/w/[id]/page.tsx: -------------------------------------------------------------------------------- 1 | import WorkFlow from './workflow' 2 | 3 | export default WorkFlow 4 | -------------------------------------------------------------------------------- /apps/sim/app/w/components/providers/providers.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { TooltipProvider } from '@/components/ui/tooltip' 4 | import { ThemeProvider } from './theme-provider' 5 | 6 | export default function Providers({ children }: { children: React.ReactNode }) { 7 | return ( 8 | 9 | 10 | {children} 11 | 12 | 13 | ) 14 | } 15 | -------------------------------------------------------------------------------- /apps/sim/app/w/components/providers/theme-provider.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { useEffect } from 'react' 4 | import { useGeneralStore } from '@/stores/settings/general/store' 5 | 6 | export function ThemeProvider({ children }: { children: React.ReactNode }) { 7 | const theme = useGeneralStore((state) => state.theme) 8 | 9 | useEffect(() => { 10 | const root = window.document.documentElement 11 | root.classList.remove('light', 'dark') 12 | 13 | // If theme is system, check system preference 14 | if (theme === 'system') { 15 | const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches 16 | root.classList.add(prefersDark ? 'dark' : 'light') 17 | } else { 18 | root.classList.add(theme) 19 | } 20 | }, [theme]) 21 | 22 | return children 23 | } 24 | -------------------------------------------------------------------------------- /apps/sim/app/w/error.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { NextError } from './[id]/components/error' 4 | 5 | export default NextError 6 | -------------------------------------------------------------------------------- /apps/sim/app/w/global-error.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { NextGlobalError } from './[id]/components/error' 4 | 5 | export default NextGlobalError 6 | -------------------------------------------------------------------------------- /apps/sim/app/w/hooks/use-registry-loading.ts: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { useEffect } from 'react' 4 | import { useWorkflowRegistry } from '@/stores/workflows/registry/store' 5 | 6 | /** 7 | * Custom hook to manage workflow registry loading state 8 | * 9 | * This hook initializes the loading state and automatically clears it 10 | * when workflows are loaded or after a timeout 11 | */ 12 | export function useRegistryLoading() { 13 | const { workflows, setLoading } = useWorkflowRegistry() 14 | 15 | useEffect(() => { 16 | // Set loading state initially 17 | setLoading(true) 18 | 19 | // If workflows are already loaded, clear loading state 20 | if (Object.keys(workflows).length > 0) { 21 | setTimeout(() => setLoading(false), 300) 22 | return 23 | } 24 | 25 | // Create a timeout to clear loading state after max time 26 | const timeout = setTimeout(() => { 27 | setLoading(false) 28 | }, 3000) // 3 second maximum loading time 29 | 30 | // Listen for workflows to be loaded 31 | const checkInterval = setInterval(() => { 32 | const currentWorkflows = useWorkflowRegistry.getState().workflows 33 | if (Object.keys(currentWorkflows).length > 0) { 34 | setLoading(false) 35 | clearInterval(checkInterval) 36 | } 37 | }, 200) 38 | 39 | return () => { 40 | clearTimeout(timeout) 41 | clearInterval(checkInterval) 42 | } 43 | }, [setLoading, workflows]) 44 | } 45 | -------------------------------------------------------------------------------- /apps/sim/app/w/knowledge/[id]/[documentId]/page.tsx: -------------------------------------------------------------------------------- 1 | import { Document } from './document' 2 | 3 | interface DocumentPageProps { 4 | params: Promise<{ 5 | id: string 6 | documentId: string 7 | }> 8 | searchParams: Promise<{ 9 | kbName?: string 10 | docName?: string 11 | }> 12 | } 13 | 14 | export default async function DocumentChunksPage({ params, searchParams }: DocumentPageProps) { 15 | const { id, documentId } = await params 16 | const { kbName, docName } = await searchParams 17 | 18 | return ( 19 | 25 | ) 26 | } 27 | -------------------------------------------------------------------------------- /apps/sim/app/w/knowledge/[id]/page.tsx: -------------------------------------------------------------------------------- 1 | import { KnowledgeBase } from './base' 2 | 3 | interface PageProps { 4 | params: Promise<{ 5 | id: string 6 | }> 7 | searchParams: Promise<{ 8 | kbName?: string 9 | }> 10 | } 11 | 12 | export default async function KnowledgeBasePage({ params, searchParams }: PageProps) { 13 | const { id } = await params 14 | const { kbName } = await searchParams 15 | 16 | return 17 | } 18 | -------------------------------------------------------------------------------- /apps/sim/app/w/knowledge/components/empty-state-card/empty-state-card.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { LibraryBig } from 'lucide-react' 4 | 5 | interface EmptyStateCardProps { 6 | title: string 7 | description: string 8 | buttonText: string 9 | onClick: () => void 10 | icon?: React.ReactNode 11 | } 12 | 13 | export function EmptyStateCard({ 14 | title, 15 | description, 16 | buttonText, 17 | onClick, 18 | icon, 19 | }: EmptyStateCardProps) { 20 | return ( 21 |
25 |
26 | {icon || } 27 |

{title}

28 |
29 | 30 |
31 |
32 | Get started 33 |
34 | 35 |

{description}

36 |
37 |
38 | ) 39 | } 40 | -------------------------------------------------------------------------------- /apps/sim/app/w/knowledge/page.tsx: -------------------------------------------------------------------------------- 1 | import { Knowledge } from './knowledge' 2 | 3 | export default function KnowledgePage() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /apps/sim/app/w/layout.tsx: -------------------------------------------------------------------------------- 1 | import Providers from './components/providers/providers' 2 | import { Sidebar } from './components/sidebar/sidebar' 3 | 4 | export default function WorkspaceLayout({ children }: { children: React.ReactNode }) { 5 | return ( 6 | 7 |
8 |
9 | 10 |
11 |
{children}
12 |
13 |
14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /apps/sim/app/w/logs/components/filters/components/filter-section.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react' 2 | import { ChevronDown } from 'lucide-react' 3 | import { Button } from '@/components/ui/button' 4 | import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible' 5 | 6 | export default function FilterSection({ 7 | title, 8 | defaultOpen = false, 9 | content, 10 | }: { 11 | title: string 12 | defaultOpen?: boolean 13 | content?: React.ReactNode 14 | }) { 15 | const [isOpen, setIsOpen] = useState(defaultOpen) 16 | 17 | return ( 18 | 19 | 20 | 31 | 32 | 33 | {content || ( 34 |
35 | Filter options for {title} will go here 36 |
37 | )} 38 |
39 |
40 | ) 41 | } 42 | -------------------------------------------------------------------------------- /apps/sim/app/w/logs/page.tsx: -------------------------------------------------------------------------------- 1 | import Logs from './logs' 2 | 3 | export default Logs 4 | -------------------------------------------------------------------------------- /apps/sim/app/w/logs/utils/format-date.ts: -------------------------------------------------------------------------------- 1 | import { format } from 'date-fns' 2 | 3 | /** 4 | * Helper function to format date in various formats 5 | */ 6 | export const formatDate = (dateString: string) => { 7 | const date = new Date(dateString) 8 | return { 9 | full: date.toLocaleDateString('en-US', { 10 | month: 'short', 11 | day: 'numeric', 12 | year: 'numeric', 13 | hour: '2-digit', 14 | minute: '2-digit', 15 | second: '2-digit', 16 | hour12: false, 17 | }), 18 | time: date.toLocaleTimeString([], { 19 | hour: '2-digit', 20 | minute: '2-digit', 21 | second: '2-digit', 22 | hour12: false, 23 | }), 24 | formatted: format(date, 'HH:mm:ss'), 25 | relative: (() => { 26 | const now = new Date() 27 | const diffMs = now.getTime() - date.getTime() 28 | const diffMins = Math.floor(diffMs / 60000) 29 | 30 | if (diffMins < 1) return 'just now' 31 | if (diffMins < 60) return `${diffMins}m ago` 32 | 33 | const diffHours = Math.floor(diffMins / 60) 34 | if (diffHours < 24) return `${diffHours}h ago` 35 | 36 | const diffDays = Math.floor(diffHours / 24) 37 | if (diffDays === 1) return 'yesterday' 38 | if (diffDays < 7) return `${diffDays}d ago` 39 | 40 | return format(date, 'MMM d') 41 | })(), 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /apps/sim/app/w/marketplace/components/error-message.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { motion } from 'framer-motion' 4 | import { AlertCircle } from 'lucide-react' 5 | 6 | /** 7 | * ErrorMessageProps interface - defines the properties for the ErrorMessage component 8 | * @property {string | null} message - The error message to display, or null if no error 9 | */ 10 | interface ErrorMessageProps { 11 | message: string | null 12 | } 13 | 14 | /** 15 | * ErrorMessage component - Displays an error message with animation 16 | * Only renders when a message is provided, otherwise returns null 17 | * Uses Framer Motion for smooth entrance animation 18 | */ 19 | export function ErrorMessage({ message }: ErrorMessageProps) { 20 | // Don't render anything if there's no message 21 | if (!message) return null 22 | 23 | return ( 24 | 30 |

31 | 32 | {message} 33 |

34 |
35 | ) 36 | } 37 | -------------------------------------------------------------------------------- /apps/sim/app/w/marketplace/components/section.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { forwardRef, type ReactNode } from 'react' 4 | 5 | /** 6 | * SectionProps interface - defines the properties for the Section component 7 | * @property {string} title - The heading text for the section 8 | * @property {string} id - The ID for the section (used for scroll targeting) 9 | * @property {ReactNode} children - The content to be rendered inside the section 10 | */ 11 | interface SectionProps { 12 | title: string 13 | id: string 14 | children: ReactNode 15 | } 16 | 17 | /** 18 | * Section component - Renders a section with a title and content 19 | * Used to organize different categories of workflows in the marketplace 20 | * Implements forwardRef to allow parent components to access the DOM node for scrolling 21 | */ 22 | export const Section = forwardRef(({ title, id, children }, ref) => { 23 | return ( 24 |
25 |

{title}

26 | {children} 27 |
28 | ) 29 | }) 30 | 31 | Section.displayName = 'Section' 32 | -------------------------------------------------------------------------------- /apps/sim/app/w/marketplace/page.tsx: -------------------------------------------------------------------------------- 1 | import Marketplace from './marketplace' 2 | 3 | export default Marketplace 4 | -------------------------------------------------------------------------------- /apps/sim/app/zoom-prevention.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { useEffect } from 'react' 4 | 5 | export function ZoomPrevention() { 6 | useEffect(() => { 7 | const preventZoom = (e: KeyboardEvent | WheelEvent) => { 8 | // Prevent zoom on ctrl/cmd + wheel 9 | if (e instanceof WheelEvent && (e.ctrlKey || e.metaKey)) { 10 | e.preventDefault() 11 | } 12 | 13 | // Prevent zoom on ctrl/cmd + plus/minus/zero 14 | if (e instanceof KeyboardEvent && (e.ctrlKey || e.metaKey)) { 15 | if (e.key === '=' || e.key === '-' || e.key === '0') { 16 | e.preventDefault() 17 | } 18 | } 19 | } 20 | 21 | // Add event listeners 22 | document.addEventListener('wheel', preventZoom, { passive: false }) 23 | document.addEventListener('keydown', preventZoom) 24 | 25 | // Cleanup 26 | return () => { 27 | document.removeEventListener('wheel', preventZoom) 28 | document.removeEventListener('keydown', preventZoom) 29 | } 30 | }, []) 31 | 32 | return null 33 | } 34 | -------------------------------------------------------------------------------- /apps/sim/blocks/blocks/condition.ts: -------------------------------------------------------------------------------- 1 | import { ConditionalIcon } from '@/components/icons' 2 | import type { BlockConfig } from '../types' 3 | 4 | interface ConditionBlockOutput { 5 | success: boolean 6 | output: { 7 | content: string 8 | conditionResult: boolean 9 | selectedPath: { 10 | blockId: string 11 | blockType: string 12 | blockTitle: string 13 | } 14 | selectedConditionId: string 15 | } 16 | } 17 | 18 | export const ConditionBlock: BlockConfig = { 19 | type: 'condition', 20 | name: 'Condition', 21 | description: 'Add a condition', 22 | longDescription: 23 | 'Add a condition to the workflow to branch the execution path based on a boolean expression.', 24 | docsLink: 'https://docs.simstudio.ai/blocks/condition', 25 | bgColor: '#FF752F', 26 | icon: ConditionalIcon, 27 | category: 'blocks', 28 | subBlocks: [ 29 | { 30 | id: 'conditions', 31 | type: 'condition-input', 32 | layout: 'full', 33 | }, 34 | ], 35 | tools: { 36 | access: [], 37 | }, 38 | inputs: {}, 39 | outputs: { 40 | response: { 41 | type: { 42 | content: 'string', 43 | conditionResult: 'boolean', 44 | selectedPath: 'json', 45 | selectedConditionId: 'string', 46 | }, 47 | }, 48 | }, 49 | } 50 | -------------------------------------------------------------------------------- /apps/sim/blocks/blocks/function.ts: -------------------------------------------------------------------------------- 1 | import { CodeIcon } from '@/components/icons' 2 | import type { CodeExecutionOutput } from '@/tools/function/types' 3 | import type { BlockConfig } from '../types' 4 | 5 | export const FunctionBlock: BlockConfig = { 6 | type: 'function', 7 | name: 'Function', 8 | description: 'Run custom logic', 9 | longDescription: 10 | 'Execute custom JavaScript or TypeScript code within your workflow to transform data or implement complex logic. Create reusable functions to process inputs and generate outputs for other blocks.', 11 | docsLink: 'https://docs.simstudio.ai/blocks/function', 12 | category: 'blocks', 13 | bgColor: '#FF402F', 14 | icon: CodeIcon, 15 | subBlocks: [ 16 | { 17 | id: 'code', 18 | type: 'code', 19 | layout: 'full', 20 | }, 21 | ], 22 | tools: { 23 | access: ['function_execute'], 24 | }, 25 | inputs: { 26 | code: { type: 'string', required: false }, 27 | timeout: { type: 'number', required: false }, 28 | }, 29 | outputs: { 30 | response: { 31 | type: { 32 | result: 'any', 33 | stdout: 'string', 34 | }, 35 | }, 36 | }, 37 | } 38 | -------------------------------------------------------------------------------- /apps/sim/blocks/blocks/thinking.ts: -------------------------------------------------------------------------------- 1 | import { BrainIcon } from '@/components/icons' 2 | import type { ToolResponse } from '@/tools/types' 3 | import type { BlockConfig } from '../types' 4 | 5 | interface ThinkingToolResponse extends ToolResponse { 6 | output: { 7 | acknowledgedThought: string 8 | } 9 | } 10 | 11 | export const ThinkingBlock: BlockConfig = { 12 | type: 'thinking', 13 | name: 'Thinking', 14 | description: 'Forces model to outline its thought process.', 15 | longDescription: 16 | 'Adds a step where the model explicitly outlines its thought process before proceeding. This can improve reasoning quality by encouraging step-by-step analysis.', 17 | docsLink: 'https://docs.simstudio.ai/tools/thinking', 18 | category: 'tools', 19 | bgColor: '#181C1E', 20 | icon: BrainIcon, 21 | hideFromToolbar: true, 22 | 23 | subBlocks: [ 24 | { 25 | id: 'thought', 26 | title: 'Thought Process / Instruction', 27 | type: 'long-input', 28 | layout: 'full', 29 | placeholder: 'Describe the step-by-step thinking process here...', 30 | hidden: true, 31 | }, 32 | ], 33 | 34 | inputs: { 35 | thought: { type: 'string', required: true }, 36 | }, 37 | 38 | outputs: { 39 | response: { 40 | type: { 41 | acknowledgedThought: 'string', 42 | }, 43 | }, 44 | }, 45 | 46 | tools: { 47 | access: ['thinking_tool'], 48 | }, 49 | } 50 | -------------------------------------------------------------------------------- /apps/sim/blocks/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | getAllBlocks, 3 | getAllBlockTypes, 4 | getBlock, 5 | getBlocksByCategory, 6 | isValidBlockType, 7 | registry, 8 | } from './registry' 9 | 10 | export { registry, getBlock, getBlocksByCategory, getAllBlockTypes, isValidBlockType, getAllBlocks } 11 | 12 | export type { BlockConfig } from './types' 13 | -------------------------------------------------------------------------------- /apps/sim/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": true, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.ts", 8 | "css": "app/globals.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks", 19 | "blocks": "@/blocks" 20 | }, 21 | "iconLibrary": "lucide" 22 | } 23 | -------------------------------------------------------------------------------- /apps/sim/components/ui/badge.tsx: -------------------------------------------------------------------------------- 1 | import type * as React from 'react' 2 | import { cva, type VariantProps } from 'class-variance-authority' 3 | import { cn } from '@/lib/utils' 4 | 5 | const badgeVariants = cva( 6 | 'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', 7 | { 8 | variants: { 9 | variant: { 10 | default: 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80', 11 | secondary: 12 | 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80', 13 | destructive: 14 | 'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80', 15 | outline: 'text-foreground', 16 | }, 17 | }, 18 | defaultVariants: { 19 | variant: 'default', 20 | }, 21 | } 22 | ) 23 | 24 | export interface BadgeProps 25 | extends React.HTMLAttributes, 26 | VariantProps {} 27 | 28 | function Badge({ className, variant, ...props }: BadgeProps) { 29 | return
30 | } 31 | 32 | export { Badge, badgeVariants } 33 | -------------------------------------------------------------------------------- /apps/sim/components/ui/checkbox.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as React from 'react' 4 | import * as CheckboxPrimitive from '@radix-ui/react-checkbox' 5 | import { Check } from 'lucide-react' 6 | import { cn } from '@/lib/utils' 7 | 8 | const Checkbox = React.forwardRef< 9 | React.ElementRef, 10 | React.ComponentPropsWithoutRef 11 | >(({ className, ...props }, ref) => ( 12 | 20 | 21 | 22 | 23 | 24 | )) 25 | Checkbox.displayName = CheckboxPrimitive.Root.displayName 26 | 27 | export { Checkbox } 28 | -------------------------------------------------------------------------------- /apps/sim/components/ui/code-block.tsx: -------------------------------------------------------------------------------- 1 | import type React from 'react' 2 | import { CopyButton } from '@/components/ui/copy-button' 3 | import { cn } from '@/lib/utils' 4 | 5 | interface CodeBlockProps extends React.HTMLAttributes { 6 | code: string 7 | language?: string 8 | } 9 | 10 | export function CodeBlock({ code, language, className, ...props }: CodeBlockProps) { 11 | return ( 12 |
13 |
14 |         {code}
15 |       
16 | 17 |
18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /apps/sim/components/ui/collapsible.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as CollapsiblePrimitive from '@radix-ui/react-collapsible' 4 | 5 | const Collapsible = CollapsiblePrimitive.Root 6 | 7 | const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger 8 | 9 | const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent 10 | 11 | export { Collapsible, CollapsibleTrigger, CollapsibleContent } 12 | -------------------------------------------------------------------------------- /apps/sim/components/ui/copy-button.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import { useState } from 'react' 4 | import { Check, Copy } from 'lucide-react' 5 | import { Button } from '@/components/ui/button' 6 | 7 | interface CopyButtonProps { 8 | text: string 9 | className?: string 10 | showLabel?: boolean 11 | } 12 | 13 | export function CopyButton({ text, className = '', showLabel = true }: CopyButtonProps) { 14 | const [copied, setCopied] = useState(false) 15 | 16 | const copyToClipboard = () => { 17 | navigator.clipboard.writeText(text) 18 | setCopied(true) 19 | setTimeout(() => setCopied(false), 2000) 20 | } 21 | 22 | return ( 23 |
24 | {showLabel && ( 25 |
26 | {copied ? 'Copied!' : 'Click to copy'} 27 |
28 | )} 29 | 46 |
47 | ) 48 | } 49 | -------------------------------------------------------------------------------- /apps/sim/components/ui/input.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { cn } from '@/lib/utils' 3 | 4 | const Input = React.forwardRef>( 5 | ({ className, type, autoComplete = 'off', ...props }, ref) => { 6 | return ( 7 | 20 | ) 21 | } 22 | ) 23 | Input.displayName = 'Input' 24 | 25 | export { Input } 26 | -------------------------------------------------------------------------------- /apps/sim/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as React from 'react' 4 | import * as LabelPrimitive from '@radix-ui/react-label' 5 | import { cva, type VariantProps } from 'class-variance-authority' 6 | import { cn } from '@/lib/utils' 7 | 8 | const labelVariants = cva( 9 | 'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70' 10 | ) 11 | 12 | const Label = React.forwardRef< 13 | React.ElementRef, 14 | React.ComponentPropsWithoutRef & VariantProps 15 | >(({ className, ...props }, ref) => ( 16 | 17 | )) 18 | Label.displayName = LabelPrimitive.Root.displayName 19 | 20 | export { Label } 21 | -------------------------------------------------------------------------------- /apps/sim/components/ui/popover.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as React from 'react' 4 | import * as PopoverPrimitive from '@radix-ui/react-popover' 5 | import { cn } from '@/lib/utils' 6 | 7 | const Popover = PopoverPrimitive.Root 8 | 9 | const PopoverTrigger = PopoverPrimitive.Trigger 10 | 11 | const PopoverContent = React.forwardRef< 12 | React.ElementRef, 13 | React.ComponentPropsWithoutRef 14 | >(({ className, align = 'center', sideOffset = 4, ...props }, ref) => ( 15 | 16 | 26 | 27 | )) 28 | PopoverContent.displayName = PopoverPrimitive.Content.displayName 29 | 30 | export { Popover, PopoverTrigger, PopoverContent } 31 | -------------------------------------------------------------------------------- /apps/sim/components/ui/progress.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as React from 'react' 4 | import * as ProgressPrimitive from '@radix-ui/react-progress' 5 | import { cn } from '@/lib/utils' 6 | 7 | const Progress = React.forwardRef< 8 | React.ElementRef, 9 | React.ComponentPropsWithoutRef 10 | >(({ className, value, ...props }, ref) => ( 11 | 16 | 20 | 21 | )) 22 | Progress.displayName = ProgressPrimitive.Root.displayName 23 | 24 | export { Progress } 25 | -------------------------------------------------------------------------------- /apps/sim/components/ui/separator.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as React from 'react' 4 | import * as SeparatorPrimitive from '@radix-ui/react-separator' 5 | import { cn } from '@/lib/utils' 6 | 7 | const Separator = React.forwardRef< 8 | React.ElementRef, 9 | React.ComponentPropsWithoutRef 10 | >(({ className, orientation = 'horizontal', decorative = true, ...props }, ref) => ( 11 | 22 | )) 23 | Separator.displayName = SeparatorPrimitive.Root.displayName 24 | 25 | export { Separator } 26 | -------------------------------------------------------------------------------- /apps/sim/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from '@/lib/utils' 2 | 3 | function Skeleton({ className, ...props }: React.HTMLAttributes) { 4 | return
5 | } 6 | 7 | export { Skeleton } 8 | -------------------------------------------------------------------------------- /apps/sim/components/ui/slider.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as React from 'react' 4 | import * as SliderPrimitive from '@radix-ui/react-slider' 5 | import { cn } from '@/lib/utils' 6 | 7 | const Slider = React.forwardRef< 8 | React.ElementRef, 9 | React.ComponentPropsWithoutRef 10 | >(({ className, ...props }, ref) => ( 11 | 16 | 17 | 18 | 19 | 20 | 21 | )) 22 | Slider.displayName = SliderPrimitive.Root.displayName 23 | 24 | export { Slider } 25 | -------------------------------------------------------------------------------- /apps/sim/components/ui/switch.tsx: -------------------------------------------------------------------------------- 1 | 'use client' 2 | 3 | import * as React from 'react' 4 | import * as SwitchPrimitives from '@radix-ui/react-switch' 5 | import { cn } from '@/lib/utils' 6 | 7 | const Switch = React.forwardRef< 8 | React.ElementRef, 9 | React.ComponentPropsWithoutRef 10 | >(({ className, ...props }, ref) => ( 11 | 19 | 24 | 25 | )) 26 | Switch.displayName = SwitchPrimitives.Root.displayName 27 | 28 | export { Switch } 29 | -------------------------------------------------------------------------------- /apps/sim/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { cn } from '@/lib/utils' 3 | 4 | const Textarea = React.forwardRef>( 5 | ({ className, ...props }, ref) => { 6 | return ( 7 |