├── .env.example
├── .github
└── workflows
│ ├── check-backend.yml
│ ├── check-console.yml
│ ├── check-frontend.yml
│ ├── publish-deploy.yml
│ ├── publish-npm.yml
│ └── publish-pypi.yml
├── .gitignore
├── .idea
├── .gitignore
├── agentlabs-poc.iml
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── dictionaries
│ └── kevinpiacentini.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── jsLinters
│ └── eslint.xml
├── modules.xml
├── prettier.xml
└── vcs.xml
├── .readme
├── agentlabs-banner.jpg
├── how-it-works.jpg
└── python-sdk-example.jpeg
├── LICENSE
├── Makefile
├── NOTICE
├── README.md
├── caddy
└── config
│ └── Caddyfile
├── cloud-proxy
├── Caddyfile
└── Dockerfile
├── console
├── .dockerignore
├── .eslintignore
├── .eslintrc.cjs
├── .gitignore
├── .idea
│ ├── .gitignore
│ ├── agent-ui.iml
│ ├── inspectionProfiles
│ │ └── Project_Default.xml
│ ├── jsLibraryMappings.xml
│ ├── jsLinters
│ │ └── eslint.xml
│ ├── modules.xml
│ ├── prettier.xml
│ └── vcs.xml
├── .npmrc
├── .prettierignore
├── .prettierrc
├── .storybook
│ ├── main.ts
│ └── preview.ts
├── Dockerfile
├── Dockerfile.dev
├── README.md
├── package-lock.json
├── package.json
├── pnpm-lock.yaml
├── postcss.config.js
├── src
│ ├── app.css
│ ├── app.d.ts
│ ├── app.html
│ ├── index.test.ts
│ ├── lib
│ │ ├── assets
│ │ │ └── img
│ │ │ │ ├── discord-icon.svg
│ │ │ │ ├── github-dark-icon.svg
│ │ │ │ ├── github-icon.svg
│ │ │ │ ├── gitlab-icon.svg
│ │ │ │ ├── google-icon.svg
│ │ │ │ ├── illustrations
│ │ │ │ ├── empty-list.svg
│ │ │ │ ├── no-result.svg
│ │ │ │ ├── not-found.svg
│ │ │ │ └── success.svg
│ │ │ │ ├── logo-dark.svg
│ │ │ │ ├── logo-light.svg
│ │ │ │ └── microsoft-icon.svg
│ │ ├── components
│ │ │ ├── auth
│ │ │ │ ├── GithubIcon.svelte
│ │ │ │ ├── GitlabIcon.svelte
│ │ │ │ ├── GoogleIcon.svelte
│ │ │ │ ├── MicrosoftIcon.svelte
│ │ │ │ ├── button
│ │ │ │ │ └── AuthProviderButton.svelte
│ │ │ │ └── types.ts
│ │ │ ├── common
│ │ │ │ ├── alert
│ │ │ │ │ └── Alert.svelte
│ │ │ │ ├── avatar
│ │ │ │ │ ├── Avatar.stories.ts
│ │ │ │ │ └── Avatar.svelte
│ │ │ │ ├── button
│ │ │ │ │ ├── Button.stories.svelte
│ │ │ │ │ ├── Button.svelte
│ │ │ │ │ └── button.types.ts
│ │ │ │ ├── card
│ │ │ │ │ ├── Card.stories.svelte
│ │ │ │ │ ├── Card.svelte
│ │ │ │ │ └── CardSkeleton.svelte
│ │ │ │ ├── copiable
│ │ │ │ │ └── CopiableTag.svelte
│ │ │ │ ├── empty-state
│ │ │ │ │ ├── EmptyState.svelte
│ │ │ │ │ └── NotResultState.svelte
│ │ │ │ ├── input
│ │ │ │ │ └── Input.svelte
│ │ │ │ ├── intercom
│ │ │ │ │ └── Intercom.svelte
│ │ │ │ ├── loading-frame
│ │ │ │ │ └── LoadingFrame.svelte
│ │ │ │ ├── logo
│ │ │ │ │ └── AgentLabsLogo.svelte
│ │ │ │ ├── markdown
│ │ │ │ │ ├── markdown-code.svelte
│ │ │ │ │ ├── markdown-heading.svelte
│ │ │ │ │ ├── markdown-image.svelte
│ │ │ │ │ ├── markdown-link.svelte
│ │ │ │ │ ├── markdown-list-item.svelte
│ │ │ │ │ ├── markdown-list.svelte
│ │ │ │ │ ├── markdown-paragraph.svelte
│ │ │ │ │ └── markdown-renderer.svelte
│ │ │ │ ├── multi-select
│ │ │ │ │ ├── MultiSelect.svelte
│ │ │ │ │ └── types.ts
│ │ │ │ ├── navigation
│ │ │ │ │ ├── left-nav
│ │ │ │ │ │ └── LeftNav.svelte
│ │ │ │ │ ├── nav-item
│ │ │ │ │ │ ├── NavItem.svelte
│ │ │ │ │ │ └── types.ts
│ │ │ │ │ ├── tab-nav
│ │ │ │ │ │ ├── TabNav.svelte
│ │ │ │ │ │ └── types.ts
│ │ │ │ │ └── top-nav
│ │ │ │ │ │ ├── TopNav.svelte
│ │ │ │ │ │ └── TopNavDropdown.svelte
│ │ │ │ ├── skeleton
│ │ │ │ │ ├── MainTitleSkeleton.svelte
│ │ │ │ │ └── PageSkeleton.svelte
│ │ │ │ ├── spacer
│ │ │ │ │ └── Spacer.svelte
│ │ │ │ ├── switch
│ │ │ │ │ └── Switch.svelte
│ │ │ │ ├── table
│ │ │ │ │ ├── ButtonCell.svelte
│ │ │ │ │ ├── CopiableCell.svelte
│ │ │ │ │ ├── NormalCell.svelte
│ │ │ │ │ ├── Table.svelte
│ │ │ │ │ └── types.ts
│ │ │ │ ├── tabs
│ │ │ │ │ ├── Tabs.svelte
│ │ │ │ │ └── types.ts
│ │ │ │ ├── tag
│ │ │ │ │ └── Tag.svelte
│ │ │ │ ├── theme-switch
│ │ │ │ │ └── ThemeSwitch.svelte
│ │ │ │ ├── top-cover
│ │ │ │ │ └── TopCover.svelte
│ │ │ │ └── typography
│ │ │ │ │ └── Typography.svelte
│ │ │ └── project
│ │ │ │ ├── agents
│ │ │ │ ├── agents-grid
│ │ │ │ │ └── AgentsGrid.svelte
│ │ │ │ └── code-snippets
│ │ │ │ │ └── onboarding.snippet.ts
│ │ │ │ └── secret
│ │ │ │ └── SDKSecretGenerator.svelte
│ │ ├── context
│ │ │ ├── AuthOnly.svelte
│ │ │ ├── IntercomContext.svelte
│ │ │ └── ProjectContext.svelte
│ │ ├── entities
│ │ │ ├── agent
│ │ │ │ ├── agent-connection.ts
│ │ │ │ └── agent.ts
│ │ │ ├── auth-method
│ │ │ │ └── auth-method-list-item.ts
│ │ │ ├── member
│ │ │ │ └── member.ts
│ │ │ ├── project
│ │ │ │ └── project.ts
│ │ │ ├── sdk-secret
│ │ │ │ └── sdk-secret.ts
│ │ │ └── user
│ │ │ │ ├── user.ts
│ │ │ │ └── userConfig.ts
│ │ ├── index.ts
│ │ ├── routes
│ │ │ └── routes.ts
│ │ ├── services
│ │ │ ├── .gitkeep
│ │ │ ├── oauth
│ │ │ │ ├── codeVerifier.ts
│ │ │ │ ├── providers
│ │ │ │ │ └── google.ts
│ │ │ │ ├── randomState.ts
│ │ │ │ ├── signInWithRedirect.ts
│ │ │ │ └── types.ts
│ │ │ └── telemetry
│ │ │ │ ├── index.ts
│ │ │ │ └── types.ts
│ │ ├── stores
│ │ │ ├── agent.ts
│ │ │ ├── auth.ts
│ │ │ ├── organization.ts
│ │ │ ├── project.ts
│ │ │ └── theme.ts
│ │ ├── usecases
│ │ │ ├── agents
│ │ │ │ ├── createAgent.ts
│ │ │ │ ├── deleteAgent.ts
│ │ │ │ ├── fetchAgentDetails.ts
│ │ │ │ ├── fetchAgents.ts
│ │ │ │ └── renameAgent.ts
│ │ │ ├── auth-methods
│ │ │ │ ├── common.ts
│ │ │ │ ├── fetchAuthMethod.ts
│ │ │ │ ├── fetchAvailableAuthMethods.ts
│ │ │ │ └── upsert.ts
│ │ │ ├── common.config.ts
│ │ │ ├── members
│ │ │ │ └── fetchProjectMembers.ts
│ │ │ ├── projects
│ │ │ │ ├── create.ts
│ │ │ │ ├── fetchRealtimeBackendConnections.ts
│ │ │ │ └── retrieveProjectById.ts
│ │ │ ├── sdk-secrets
│ │ │ │ ├── fetchSecrets.ts
│ │ │ │ ├── generateSecret.ts
│ │ │ │ └── revokeSecret.ts
│ │ │ └── users
│ │ │ │ ├── fetchRequiredUserConfig.ts
│ │ │ │ ├── login.ts
│ │ │ │ ├── loginWithOAuthCode.ts
│ │ │ │ ├── register.ts
│ │ │ │ └── signInWithGoogle.ts
│ │ └── utils
│ │ │ ├── buildFrontendUrl.ts
│ │ │ ├── clickOutside.ts
│ │ │ ├── genStoreKey.ts
│ │ │ ├── oauthUtils.ts
│ │ │ ├── time.ts
│ │ │ ├── toast.ts
│ │ │ ├── unique.ts
│ │ │ └── validateEnv.ts
│ └── routes
│ │ ├── +error.svelte
│ │ ├── +layout.svelte
│ │ ├── +page.svelte
│ │ ├── login
│ │ ├── +layout.svelte
│ │ ├── +page.server.ts
│ │ └── +page.svelte
│ │ ├── logout
│ │ └── +page.svelte
│ │ ├── oauth
│ │ └── handler
│ │ │ └── [providerId]
│ │ │ └── +page.svelte
│ │ ├── onboarding
│ │ ├── +layout.svelte
│ │ ├── new
│ │ │ ├── +layout.svelte
│ │ │ ├── +page.server.ts
│ │ │ └── +page.svelte
│ │ └── project
│ │ │ └── [projectId]
│ │ │ ├── +layout.svelte
│ │ │ └── ready
│ │ │ ├── +layout.svelte
│ │ │ └── +page.svelte
│ │ ├── project
│ │ ├── +layout.svelte
│ │ ├── [projectId]
│ │ │ ├── +layout.svelte
│ │ │ ├── agent
│ │ │ │ ├── [agentId]
│ │ │ │ │ ├── +layout.svelte
│ │ │ │ │ ├── +page.svelte
│ │ │ │ │ ├── general
│ │ │ │ │ │ └── +page.svelte
│ │ │ │ │ └── settings
│ │ │ │ │ │ └── +page.svelte
│ │ │ │ └── new
│ │ │ │ │ ├── +page.server.ts
│ │ │ │ │ └── +page.svelte
│ │ │ ├── auth
│ │ │ │ ├── +layout.svelte
│ │ │ │ ├── +page.svelte
│ │ │ │ ├── members
│ │ │ │ │ └── +page.svelte
│ │ │ │ └── methods
│ │ │ │ │ ├── +page.svelte
│ │ │ │ │ └── [providerId]
│ │ │ │ │ ├── +page.svelte
│ │ │ │ │ └── +page.ts
│ │ │ ├── backends
│ │ │ │ ├── +layout.svelte
│ │ │ │ └── +page.svelte
│ │ │ ├── overview
│ │ │ │ └── +page.svelte
│ │ │ └── secrets
│ │ │ │ ├── +layout.svelte
│ │ │ │ └── +page.svelte
│ │ └── overview
│ │ │ └── +page.svelte
│ │ ├── register
│ │ ├── +layout.svelte
│ │ ├── +page.server.ts
│ │ └── +page.svelte
│ │ └── types.ts
├── static
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon.ico
│ └── favicon.png
├── svelte.config.js
├── tailwind.config.js
├── tsconfig.json
└── vite.config.ts
├── docker-compose.cloud.yml
├── docker-compose.dev.yml
├── docker-compose.yml
├── frontend
├── .dockerignore
├── .eslintignore
├── .eslintrc.cjs
├── .gitignore
├── .idea
│ ├── .gitignore
│ ├── agent-ui.iml
│ ├── inspectionProfiles
│ │ └── Project_Default.xml
│ ├── jsLibraryMappings.xml
│ ├── jsLinters
│ │ └── eslint.xml
│ ├── modules.xml
│ ├── prettier.xml
│ └── vcs.xml
├── .npmrc
├── .prettierignore
├── .prettierrc
├── .storybook
│ ├── main.ts
│ └── preview.ts
├── Dockerfile
├── Dockerfile.dev
├── README.md
├── package-lock.json
├── package.json
├── pnpm-lock.yaml
├── postcss.config.js
├── src
│ ├── app.css
│ ├── app.d.ts
│ ├── app.html
│ ├── index.test.ts
│ ├── lib
│ │ ├── assets
│ │ │ └── img
│ │ │ │ ├── agent-icon.svg
│ │ │ │ ├── github-dark-icon.svg
│ │ │ │ ├── github-icon.svg
│ │ │ │ ├── gitlab-icon.svg
│ │ │ │ ├── google-icon.svg
│ │ │ │ ├── illustrations
│ │ │ │ └── not-found.svg
│ │ │ │ ├── logo-dark.svg
│ │ │ │ ├── logo-light.svg
│ │ │ │ └── microsoft-icon.svg
│ │ ├── components
│ │ │ ├── auth
│ │ │ │ ├── GithubIcon.svelte
│ │ │ │ ├── GitlabIcon.svelte
│ │ │ │ ├── GoogleIcon.svelte
│ │ │ │ ├── button
│ │ │ │ │ └── AuthProviderButton.svelte
│ │ │ │ └── types.ts
│ │ │ ├── chat
│ │ │ │ ├── chat-input
│ │ │ │ │ └── ChatInput.svelte
│ │ │ │ ├── chat-message
│ │ │ │ │ ├── AgentChatMessage.svelte
│ │ │ │ │ ├── Attachment.svelte
│ │ │ │ │ ├── ChatMessage.svelte
│ │ │ │ │ ├── DatepickerMessage
│ │ │ │ │ │ ├── Datepicker.svelte
│ │ │ │ │ │ └── DatepickerMessage.svelte
│ │ │ │ │ ├── EChartMessage
│ │ │ │ │ │ ├── EChart.svelte
│ │ │ │ │ │ └── EChartMessage.svelte
│ │ │ │ │ ├── LoginMessage.svelte
│ │ │ │ │ ├── MessageInput.svelte
│ │ │ │ │ ├── MessageInputButton.svelte
│ │ │ │ │ ├── PromptMessage.svelte
│ │ │ │ │ ├── SelectMessage
│ │ │ │ │ │ ├── SelectMessage.svelte
│ │ │ │ │ │ └── multi-select
│ │ │ │ │ │ │ ├── MultiSelect.svelte
│ │ │ │ │ │ │ └── types.ts
│ │ │ │ │ └── TypingLoader.svelte
│ │ │ │ ├── chat.svelte
│ │ │ │ ├── file-uploader
│ │ │ │ │ └── FileUploader.svelte
│ │ │ │ └── processing-status
│ │ │ │ │ ├── ProcessingStatus.stories.ts
│ │ │ │ │ └── ProcessingStatus.svelte
│ │ │ ├── common
│ │ │ │ ├── avatar
│ │ │ │ │ ├── Avatar.stories.ts
│ │ │ │ │ └── Avatar.svelte
│ │ │ │ ├── button
│ │ │ │ │ ├── Button.stories.svelte
│ │ │ │ │ ├── Button.svelte
│ │ │ │ │ └── button.types.ts
│ │ │ │ ├── card
│ │ │ │ │ ├── Card.stories.svelte
│ │ │ │ │ ├── Card.svelte
│ │ │ │ │ ├── CardBody.svelte
│ │ │ │ │ └── CardSkeleton.svelte
│ │ │ │ ├── input
│ │ │ │ │ └── Input.svelte
│ │ │ │ ├── letter-avatar
│ │ │ │ │ └── LetterAvatar.svelte
│ │ │ │ ├── loading-frame
│ │ │ │ │ └── LoadingFrame.svelte
│ │ │ │ ├── logo
│ │ │ │ │ ├── AgentLabsLogo.svelte
│ │ │ │ │ └── PoweredBy.svelte
│ │ │ │ ├── navigation
│ │ │ │ │ ├── left-nav
│ │ │ │ │ │ ├── LeftNav.svelte
│ │ │ │ │ │ └── ProfileMenu.svelte
│ │ │ │ │ ├── nav-item
│ │ │ │ │ │ ├── NavItem.svelte
│ │ │ │ │ │ └── types.ts
│ │ │ │ │ ├── tab-nav
│ │ │ │ │ │ ├── TabNav.svelte
│ │ │ │ │ │ └── types.ts
│ │ │ │ │ └── top-nav
│ │ │ │ │ │ └── TopNav.svelte
│ │ │ │ ├── spacer
│ │ │ │ │ └── Spacer.svelte
│ │ │ │ ├── theme-switch
│ │ │ │ │ └── ThemeSwitch.svelte
│ │ │ │ └── typography
│ │ │ │ │ └── Typography.svelte
│ │ │ ├── markdown
│ │ │ │ ├── markdown-code.svelte
│ │ │ │ ├── markdown-heading.svelte
│ │ │ │ ├── markdown-image.svelte
│ │ │ │ ├── markdown-link.svelte
│ │ │ │ ├── markdown-list-item.svelte
│ │ │ │ ├── markdown-list.svelte
│ │ │ │ ├── markdown-paragraph.svelte
│ │ │ │ └── markdown-renderer.svelte
│ │ │ └── sidebar
│ │ │ │ ├── Sidebar.svelte
│ │ │ │ └── header
│ │ │ │ └── SidebarHeader.svelte
│ │ ├── context
│ │ │ ├── AgentContext.svelte
│ │ │ └── RealtimeContext.svelte
│ │ ├── entities
│ │ │ ├── agent
│ │ │ │ └── agent.ts
│ │ │ ├── conversation
│ │ │ │ └── conversation.ts
│ │ │ ├── member
│ │ │ │ └── member.ts
│ │ │ ├── message
│ │ │ │ └── message.ts
│ │ │ └── project
│ │ │ │ └── public-project-config.ts
│ │ ├── gates
│ │ │ └── AuthOnly.svelte
│ │ ├── index.ts
│ │ ├── routes
│ │ │ └── routes.ts
│ │ ├── services
│ │ │ ├── .gitkeep
│ │ │ └── oauth
│ │ │ │ ├── codeVerifier.ts
│ │ │ │ ├── demoRedirectState.ts
│ │ │ │ ├── providers
│ │ │ │ └── google.ts
│ │ │ │ ├── randomState.ts
│ │ │ │ ├── signInWithRedirect.ts
│ │ │ │ └── types.ts
│ │ ├── store
│ │ │ └── chat
│ │ │ │ └── chat.ts
│ │ ├── stores
│ │ │ ├── agent.ts
│ │ │ ├── auth.ts
│ │ │ ├── chat.ts
│ │ │ ├── conversation.ts
│ │ │ ├── left-nav.ts
│ │ │ ├── main-context.ts
│ │ │ ├── realtime.ts
│ │ │ └── theme.ts
│ │ ├── usecases
│ │ │ ├── agents
│ │ │ │ └── fetch-agents.ts
│ │ │ ├── chat
│ │ │ │ └── fetch-messages.ts
│ │ │ ├── conversations
│ │ │ │ └── fetch-conversations.ts
│ │ │ ├── members
│ │ │ │ ├── initSignInWithRedirect.ts
│ │ │ │ ├── loginWithOAuthCode.ts
│ │ │ │ ├── requestPasswordlessEmail.ts
│ │ │ │ ├── signInAnonymously.ts
│ │ │ │ ├── verifyMemberOrLogout.ts
│ │ │ │ └── verifyPasswordlessEmail.ts
│ │ │ └── project
│ │ │ │ └── retrievePublicConfig.ts
│ │ └── utils
│ │ │ ├── clickOutside.ts
│ │ │ ├── genStoreKey.ts
│ │ │ ├── oauthUtils.ts
│ │ │ ├── toast.ts
│ │ │ ├── unique.ts
│ │ │ └── validateEnv.ts
│ ├── routes
│ │ ├── +layout.svelte
│ │ ├── +layout.ts
│ │ ├── +page.svelte
│ │ ├── chat
│ │ │ ├── +layout.svelte
│ │ │ ├── +page.svelte
│ │ │ └── c
│ │ │ │ └── [conversationId]
│ │ │ │ └── +page.svelte
│ │ ├── logout
│ │ │ └── +page.svelte
│ │ ├── oauth
│ │ │ ├── handler
│ │ │ │ └── [providerId]
│ │ │ │ │ └── +page.svelte
│ │ │ └── sign-in-popup
│ │ │ │ └── [providerId]
│ │ │ │ └── +page.svelte
│ │ ├── project-not-found
│ │ │ └── +page.svelte
│ │ └── types.ts
│ └── services
│ │ ├── agents-service.ts
│ │ ├── agents.types.ts
│ │ └── backend-service.ts
├── static
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ └── favicon.png
├── svelte.config.js
├── tailwind.config.js
├── tsconfig.json
└── vite.config.ts
├── nginx
└── nginx.conf
├── scripts
└── frontend-clients
│ ├── .gitignore
│ ├── build_for_console.sh
│ ├── build_for_frontend.sh
│ └── client.ts
├── sdks
├── node-sdk
│ ├── .dockerignore
│ ├── .eslintrc.cjs
│ ├── .gitignore
│ ├── .npmrc
│ ├── .prettierrc
│ ├── Dockerfile
│ ├── README.md
│ ├── package-lock.json
│ ├── package.json
│ ├── scripts
│ │ ├── build.js
│ │ └── docker-entrypoint.sh
│ ├── src
│ │ ├── agent-message-stream.ts
│ │ ├── agent.ts
│ │ ├── attachment.ts
│ │ ├── const.ts
│ │ ├── constants.ts
│ │ ├── http.ts
│ │ ├── incoming-chat-message.ts
│ │ ├── index.ts
│ │ ├── logger.ts
│ │ ├── message-attachment.ts
│ │ ├── project.ts
│ │ ├── realtime.ts
│ │ ├── types.ts
│ │ ├── types
│ │ │ └── echart.ts
│ │ └── utils
│ │ │ └── chunk.ts
│ └── tsconfig.json
└── python-sdk
│ ├── .gitignore
│ ├── Dockerfile
│ ├── README.md
│ ├── agentlabs
│ ├── __init__.py
│ ├── _internals
│ │ ├── __init__.py
│ │ ├── const.py
│ │ ├── http.py
│ │ ├── logger.py
│ │ ├── realtime.py
│ │ └── utils.py
│ ├── agent.py
│ ├── attachment.py
│ ├── chat.py
│ ├── member.py
│ └── project.py
│ ├── poetry.lock
│ ├── pyproject.toml
│ ├── scripts
│ └── docker-entrypoint.sh
│ └── tests
│ └── __init__.py
└── server
├── .dockerignore
├── .eslintrc.js
├── .gitignore
├── .prettierrc
├── Dockerfile
├── Dockerfile.dev
├── README.md
├── nest-cli.json
├── openapi.yaml
├── openapitools.json
├── package-lock.json
├── package.json
├── print-oas.Dockerfile
├── prisma
├── migrations
│ ├── 20231014115126_init
│ │ └── migration.sql
│ ├── 20231020133514_anonymous_users
│ │ └── migration.sql
│ ├── 20231023224256_add_size_bytes_and_project_id_fields_to_attachment
│ │ └── migration.sql
│ ├── 20231026115736_add_type_and_metadata_fields_to_chat_message
│ │ └── migration.sql
│ └── migration_lock.toml
└── schema.prisma
├── scripts
├── docker-entrypoint.dev.sh
├── docker-entrypoint.sh
└── print-oas-docker-entrypoint.sh
├── src
├── agents
│ ├── agents.constants.ts
│ ├── agents.controller.spec.ts
│ ├── agents.controller.ts
│ ├── agents.errors.ts
│ ├── agents.module.ts
│ ├── agents.service.spec.ts
│ ├── agents.service.ts
│ └── dtos
│ │ ├── agent-connection.dto.ts
│ │ ├── create.agent.dto.ts
│ │ ├── created.agent.dto.ts
│ │ ├── deleted.agent.response.dto.ts
│ │ ├── did-agent-ever-connect.dto.ts
│ │ ├── get.agent.response.dto.ts
│ │ ├── list-agent-connections.response.dto.ts
│ │ ├── list.agents.response.dto.ts
│ │ ├── update.agent.dto.ts
│ │ └── updated.agent.dto.ts
├── app.controller.spec.ts
├── app.controller.ts
├── app.module.ts
├── app.service.ts
├── attachments
│ ├── attachment-storage
│ │ ├── attachment-storage.service.ts
│ │ └── local-attachment-storage
│ │ │ └── local-attachment-storage.service.ts
│ ├── attachments.controller.spec.ts
│ ├── attachments.controller.ts
│ ├── attachments.module.ts
│ ├── attachments.service.ts
│ └── attachments.types.ts
├── auth-methods
│ ├── auth-methods.config.ts
│ ├── auth-methods.controller.spec.ts
│ ├── auth-methods.controller.ts
│ ├── auth-methods.errors.ts
│ ├── auth-methods.module.ts
│ ├── auth-methods.service.spec.ts
│ ├── auth-methods.service.ts
│ └── dtos
│ │ ├── auth-method.item.dto.ts
│ │ ├── create.auth-method.dto.ts
│ │ ├── created.auth-method.dto.ts
│ │ ├── created.demo.auth-method.dto.ts
│ │ ├── list.auth-method.response.dto.ts
│ │ ├── sanitized-auth-method-item.dto.ts
│ │ ├── upsert.auth-method.dto.ts
│ │ └── upserted.auth-method.dto.ts
├── chat-messages
│ ├── chat-messages.controller.ts
│ ├── chat-messages.module.ts
│ ├── chat-messages.service.ts
│ └── chat-messages.types.ts
├── common
│ ├── base-realtime-message.dto.ts
│ ├── list.response.ts
│ ├── mime.ts
│ ├── ms-time.ts
│ ├── mutex.ts
│ ├── paginated.query.dto.ts
│ ├── paginated.response.ts
│ ├── realtime-message.ts
│ ├── result.ts
│ └── tutorial-message-factory.ts
├── config
│ ├── config.module.ts
│ └── validate-env.ts
├── conversations
│ ├── conversations.controller.ts
│ ├── conversations.module.ts
│ ├── conversations.service.ts
│ ├── conversations.types.ts
│ └── dto
│ │ └── get-all-conversations.dto.ts
├── frontend-connection-manager
│ ├── frontend-connection-manager.constants.ts
│ ├── frontend-connection-manager.module.ts
│ ├── frontend-connection-manager.service.ts
│ └── frontend-connection-manager.types.ts
├── frontend-connection
│ ├── dto
│ │ └── frontend-chat-message.dto.ts
│ ├── frontend-connection.gateway.ts
│ └── frontend-connection.module.ts
├── iam
│ ├── iam.decorators.ts
│ ├── iam.guard.ts
│ ├── iam.module.ts
│ ├── iam.types.ts
│ ├── member-auth
│ │ └── member-auth.middleware.ts
│ ├── server-sdk-auth
│ │ ├── server-sdk-auth.middleware.ts
│ │ └── server-sdk-auth.types.ts
│ └── user-auth
│ │ └── user-auth.middleware.ts
├── mailer
│ ├── mailer.config.ts
│ ├── mailer.module.ts
│ ├── mailer.service.spec.ts
│ └── mailer.service.ts
├── main.ts
├── members
│ ├── dtos
│ │ ├── list.members.response.dto.ts
│ │ ├── login.member.response.dto.ts
│ │ ├── member.whoami.result.dto.ts
│ │ ├── oauth.authorize.dto.ts
│ │ ├── register.response.dto.ts
│ │ ├── request.passwordless-email.dto.ts
│ │ ├── sanitized.member.dto.ts
│ │ └── verify-passwordless-email.dto.ts
│ ├── members.config.ts
│ ├── members.controller.spec.ts
│ ├── members.controller.ts
│ ├── members.errors.ts
│ ├── members.module.ts
│ ├── members.service.spec.ts
│ ├── members.service.ts
│ ├── members.types.ts
│ └── templates
│ │ └── passwordless-authentication.hbs
├── oauth-providers
│ ├── google
│ │ ├── google.service.spec.ts
│ │ ├── google.service.ts
│ │ └── types.ts
│ └── oauth-providers.module.ts
├── openapi-tools
│ ├── index.ts
│ ├── openapi-file-generator
│ │ ├── openapi-file-generator.service.spec.ts
│ │ └── openapi-file-generator.service.ts
│ ├── openapi-nest.factory.ts
│ ├── openapi-tools.module.ts
│ └── openapi.service.ts
├── prisma
│ ├── prisma.module.ts
│ └── prisma.service.ts
├── project-backend-connection-manager
│ ├── dto
│ │ ├── register-agent-connection.dto.ts
│ │ └── serialized-project-backend-connection.dto.ts
│ ├── project-backend-connection-manager.constants.ts
│ ├── project-backend-connection-manager.controller.ts
│ ├── project-backend-connection-manager.module.ts
│ ├── project-backend-connection-manager.service.ts
│ └── project-backend-connection-manager.types.ts
├── project-backend-connection
│ ├── agent-stream-manager
│ │ └── agent-stream-manager.service.ts
│ ├── conversation-mutex-manager.ts
│ ├── dto
│ │ ├── agent-message.dto.ts
│ │ └── stream-chat-message-token.dto.ts
│ ├── project-backend-connection.gateway.ts
│ └── project-backend-connection.module.ts
├── projects
│ ├── dtos
│ │ ├── create.project.dto.ts
│ │ ├── created.project.dto.ts
│ │ ├── get-realtime-connections.response.dto.ts
│ │ ├── get.public.config.dto.ts
│ │ ├── list.projects.result.dto.ts
│ │ ├── project.dto.ts
│ │ ├── project.exists.response.dto.ts
│ │ └── public.project.config.dto.ts
│ ├── projects.config.ts
│ ├── projects.controller.ts
│ ├── projects.errors.ts
│ ├── projects.module.ts
│ ├── projects.service.ts
│ └── projects.types.ts
├── sdk-secrets
│ ├── dtos
│ │ ├── create.sdk-secret.dto.ts
│ │ ├── created.sdk-secret.dto.ts
│ │ ├── list.sdk-secret.dto.ts
│ │ ├── revoke.sdk-secret.dto.ts
│ │ └── sanitized.sdk-secret.dto.ts
│ ├── sdk-secrets.controller.ts
│ ├── sdk-secrets.errors.ts
│ ├── sdk-secrets.module.ts
│ └── sdk-secrets.service.ts
├── telemetry
│ ├── telemetry.config.ts
│ ├── telemetry.module.ts
│ ├── telemetry.service.spec.ts
│ ├── telemetry.service.ts
│ └── telemetry.types.ts
└── users
│ ├── dtos
│ ├── login.response.dto.ts
│ ├── login.user.dto.ts
│ ├── login.user.response.dto.ts
│ ├── oauth.authorize.dto.ts
│ ├── oauthlogin.user.response.dto.ts
│ ├── register.user.dto.ts
│ ├── sanitized.user.response.dto.ts
│ ├── user.created.response.dto.ts
│ └── whoami.result.dto.ts
│ ├── templates
│ └── .gitkeep
│ ├── users.config.ts
│ ├── users.controller.ts
│ ├── users.module.ts
│ ├── users.service.errors.ts
│ ├── users.service.ts
│ └── users.types.ts
├── test
├── app.e2e-spec.ts
└── jest-e2e.json
├── tsconfig.build.json
└── tsconfig.json
/.github/workflows/check-backend.yml:
--------------------------------------------------------------------------------
1 | env:
2 | BUILD_CONTEXT: server
3 |
4 | name: Check backend
5 |
6 | on:
7 | workflow_dispatch:
8 | pull_request:
9 | push:
10 | branches:
11 | - main
12 |
13 | jobs:
14 | build:
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@v3
18 |
19 | - name: Build and push
20 | uses: docker/build-push-action@v5
21 | with:
22 | context: ${{ env.BUILD_CONTEXT }}
23 | push: false
24 |
--------------------------------------------------------------------------------
/.github/workflows/check-console.yml:
--------------------------------------------------------------------------------
1 | env:
2 | BUILD_CONTEXT: console
3 |
4 | name: Check console
5 |
6 | on:
7 | workflow_dispatch:
8 | pull_request:
9 | push:
10 | branches:
11 | - main
12 |
13 | jobs:
14 | build:
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@v3
18 |
19 | # Required to compile the client SDKS on runners without built-in node suppot
20 | - uses: actions/setup-node@v3
21 | with:
22 | node-version: '>= 20'
23 |
24 | - name: Compile SDKs
25 | run: |
26 | OPENAPI_BASE=/api make frontend-clients
27 |
28 | - name: Build and push
29 | uses: docker/build-push-action@v5
30 | with:
31 | context: ${{ env.BUILD_CONTEXT }}
32 | push: false
33 |
--------------------------------------------------------------------------------
/.github/workflows/check-frontend.yml:
--------------------------------------------------------------------------------
1 | env:
2 | BUILD_CONTEXT: frontend
3 |
4 | name: Check frontend
5 |
6 | on:
7 | workflow_dispatch:
8 | pull_request:
9 | push:
10 | branches:
11 | - main
12 |
13 | jobs:
14 | build:
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@v3
18 |
19 | # Required to compile the client SDKS on runners without built-in node suppot
20 | - uses: actions/setup-node@v3
21 | with:
22 | node-version: '>= 20'
23 |
24 | - name: Compile SDKs
25 | run: |
26 | OPENAPI_BASE=/api make frontend-clients
27 |
28 | - name: Build and push
29 | uses: docker/build-push-action@v5
30 | with:
31 | context: ${{ env.BUILD_CONTEXT }}
32 | push: false
33 |
--------------------------------------------------------------------------------
/.github/workflows/publish-npm.yml:
--------------------------------------------------------------------------------
1 | name: Publish node sdk
2 | env:
3 | PUBLISHER_IMAGE_TAG: node-sdk-publisher
4 |
5 | on:
6 | push:
7 | tags:
8 | - "v*"
9 | workflow_dispatch:
10 |
11 | jobs:
12 | publish_npm:
13 | runs-on: ubuntu-latest
14 | if: startsWith(github.ref, 'refs/tags/v')
15 | steps:
16 | - uses: actions/checkout@v3
17 | - name: Build node sdk publisher image
18 | run: |
19 | docker build sdks/node-sdk -t $PUBLISHER_IMAGE_TAG
20 | - name: Publish node client
21 | run: >
22 | docker run
23 | --rm
24 | -e NPM_TOKEN="${{ secrets.NPM_TOKEN }}"
25 | -e VERSION="$( echo ${{ github.ref_name }} | tr -d 'v' )"
26 | $PUBLISHER_IMAGE_TAG
27 |
--------------------------------------------------------------------------------
/.github/workflows/publish-pypi.yml:
--------------------------------------------------------------------------------
1 | name: Publish python sdk
2 | env:
3 | PUBLISHER_IMAGE_TAG: python-sdk-publisher
4 |
5 | on:
6 | push:
7 | tags:
8 | - "v*"
9 | workflow_dispatch:
10 |
11 | jobs:
12 | publish_pypi:
13 | runs-on: ubuntu-latest
14 | if: startsWith(github.ref, 'refs/tags/v')
15 | steps:
16 | - uses: actions/checkout@v3
17 | - name: Build python sdk publisher image
18 | run: |
19 | docker build sdks/python-sdk -t $PUBLISHER_IMAGE_TAG
20 | - name: Publish python client (tag version)
21 | run: >
22 | docker run
23 | --rm
24 | -e PYPI_TOKEN="${{ secrets.PYPI_TOKEN }}"
25 | -e VERSION="$( echo ${{ github.ref_name }} | tr -d 'v' )"
26 | $PUBLISHER_IMAGE_TAG
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | .env.local
3 | node_modules
4 |
5 | gen-api
6 | caddy/data
7 |
8 | /attachments
9 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 |
--------------------------------------------------------------------------------
/.idea/agentlabs-poc.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/dictionaries/kevinpiacentini.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/jsLinters/eslint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/prettier.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.readme/agentlabs-banner.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/.readme/agentlabs-banner.jpg
--------------------------------------------------------------------------------
/.readme/how-it-works.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/.readme/how-it-works.jpg
--------------------------------------------------------------------------------
/.readme/python-sdk-example.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/.readme/python-sdk-example.jpeg
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | all:
2 | @echo "make frontend-clients"
3 | @echo "make openapi"
4 |
5 | frontend-clients: openapi
6 | cd scripts/frontend-clients && ./build_for_frontend.sh
7 | cd scripts/frontend-clients && ./build_for_console.sh
8 | .PHONY: build-frontend-clients
9 |
10 | openapi:
11 | docker build -f ./server/print-oas.Dockerfile -t print-oas ./server
12 | docker run --rm print-oas > ./server/openapi.yaml
13 | docker rmi print-oas
14 | .PHONY: gen-oas
15 |
16 | check: check-frontend check-backend check-console
17 | .PHONY: check
18 |
19 | check-frontend:
20 | cd frontend && npm run check
21 | .PHONY: check-frontend
22 |
23 | check-backend:
24 | cd server && npm run build
25 | .PHONY: check-backend
26 |
27 | check-console:
28 | cd console && npm run check
29 | .PHONY: check-console
30 |
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2023 AgentLabs, Inc
2 |
3 | Source code in this repository is licensed under the Apache License
4 | Version 2.0. Please see LICENSE for more information.
5 |
6 | Every file is under copyright (c) 2023 AgentLabs, Inc unless otherwise
7 | specified.
8 |
9 | * For a copy of the Apache License Version 2.0, please see LICENSE
10 | as included in this repository's top-level directory.
11 |
12 | * All third party components incorporated into the AgentLabs Software are licensed
13 | under the original license provided by the owner of the applicable component.
--------------------------------------------------------------------------------
/caddy/config/Caddyfile:
--------------------------------------------------------------------------------
1 | :80 {
2 | handle_path /api {
3 | reverse_proxy server:3000
4 | }
5 |
6 | handle_path /api/* {
7 | reverse_proxy server:3000
8 | }
9 |
10 | handle /socket.io/* {
11 | reverse_proxy server:3000
12 | }
13 |
14 | handle /admin {
15 | reverse_proxy console:3000
16 | }
17 |
18 | handle /admin/* {
19 | reverse_proxy console:3000
20 | }
21 |
22 | handle {
23 | reverse_proxy frontend:3000
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/cloud-proxy/Caddyfile:
--------------------------------------------------------------------------------
1 | {$CLOUD_APP_DOMAIN}:443 {
2 | reverse_proxy gateway
3 | }
4 |
5 | {$CLOUD_APP_WILDCARD_DOMAIN}:443 {
6 | tls {
7 | dns godaddy {$CLOUD_APP_WILDCARD_DOMAIN_DNS_API_KEY}
8 | }
9 |
10 | reverse_proxy gateway
11 | }
12 |
13 | {$CLOUD_CONSOLE_DOMAIN}:443 {
14 | @console {
15 | path /admin/*
16 | }
17 |
18 | @api {
19 | path /api/*
20 | }
21 |
22 | handle @console {
23 | reverse_proxy gateway
24 | }
25 |
26 | handle @api {
27 | reverse_proxy gateway
28 | }
29 |
30 | handle {
31 | redir * /admin{path}
32 | reverse_proxy gateway
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/cloud-proxy/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM caddy:2.7.4-builder-alpine as builder
2 |
3 | RUN xcaddy build \
4 | --with github.com/caddy-dns/godaddy
5 |
6 | FROM caddy:2.7.4-alpine
7 |
8 | COPY --from=builder /usr/bin/caddy /usr/bin/caddy
9 |
--------------------------------------------------------------------------------
/console/.dockerignore:
--------------------------------------------------------------------------------
1 | Dockerfile
2 | .dockerignore
3 | .git
4 | .gitignore
5 | .gitattributes
6 | README.md
7 | .npmrc
8 | .prettierrc
9 | .eslintrc.cjs
10 | .graphqlrc
11 | .editorconfig
12 | .svelte-kit
13 | .vscode
14 | node_modules
15 | build
16 | package
17 | **/.env
18 |
--------------------------------------------------------------------------------
/console/.eslintignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 |
10 | # Ignore files for PNPM, NPM and YARN
11 | pnpm-lock.yaml
12 | package-lock.json
13 | yarn.lock
14 |
--------------------------------------------------------------------------------
/console/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: [
4 | "eslint:recommended",
5 | "plugin:@typescript-eslint/recommended",
6 | "plugin:svelte/recommended",
7 | "prettier",
8 | "plugin:storybook/recommended",
9 | "plugin:storybook/recommended"
10 | ],
11 | parser: '@typescript-eslint/parser',
12 | plugins: ['@typescript-eslint'],
13 | parserOptions: {
14 | sourceType: 'module',
15 | ecmaVersion: 2020,
16 | extraFileExtensions: ['.svelte']
17 | },
18 | env: {
19 | browser: true,
20 | es2017: true,
21 | node: true
22 | },
23 | overrides: [
24 | {
25 | files: ['*.svelte'],
26 | parser: 'svelte-eslint-parser',
27 | parserOptions: {
28 | parser: '@typescript-eslint/parser'
29 | }
30 | }
31 | ]
32 | };
33 |
--------------------------------------------------------------------------------
/console/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 | vite.config.js.timestamp-*
10 | vite.config.ts.timestamp-*
11 |
--------------------------------------------------------------------------------
/console/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 |
--------------------------------------------------------------------------------
/console/.idea/agent-ui.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/console/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/console/.idea/jsLibraryMappings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/console/.idea/jsLinters/eslint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/console/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/console/.idea/prettier.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/console/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/console/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict=true
2 | resolution-mode=highest
3 |
--------------------------------------------------------------------------------
/console/.prettierignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 |
10 | # Ignore files for PNPM, NPM and YARN
11 | pnpm-lock.yaml
12 | package-lock.json
13 | yarn.lock
14 |
--------------------------------------------------------------------------------
/console/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "useTabs": true,
3 | "trailingComma": "none",
4 | "tabWidth": 4,
5 | "printWidth": 100,
6 | "semi": true,
7 | "singleQuote": false,
8 | "jsxBracketSameLine": true,
9 | "plugins": ["prettier-plugin-organize-imports"],
10 | "overrides": [ {
11 | "files": "*.svelte",
12 | "options": {
13 | "svelteBracketNewLine": false,
14 | "svelteAllowShorthand": false,
15 | "svelteSortOrder" : "options-scripts-styles-markup",
16 | "plugins": [ "prettier-plugin-svelte" ]
17 | }
18 | } ],
19 | "pluginSearchDirs": [ "." ]
20 | }
--------------------------------------------------------------------------------
/console/.storybook/main.ts:
--------------------------------------------------------------------------------
1 | import type { StorybookConfig } from "@storybook/sveltekit";
2 |
3 | const config: StorybookConfig = {
4 | stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx|svelte)"],
5 | addons: [
6 | "@storybook/addon-svelte-csf",
7 | "@storybook/addon-links",
8 | "@storybook/addon-essentials",
9 | "@storybook/addon-interactions",
10 | {
11 | name: "@storybook/addon-styling",
12 | options: {}
13 | }
14 | ],
15 | framework: {
16 | name: "@storybook/sveltekit",
17 | options: {}
18 | },
19 | docs: {
20 | autodocs: "tag"
21 | }
22 | };
23 | export default config;
24 |
--------------------------------------------------------------------------------
/console/.storybook/preview.ts:
--------------------------------------------------------------------------------
1 | import type { Preview } from "@storybook/svelte";
2 |
3 | import { withThemeByClassName } from "@storybook/addon-styling";
4 |
5 | import "../src/app.css";
6 |
7 | const preview: Preview = {
8 | parameters: {
9 | actions: { argTypesRegex: "^on[A-Z].*" },
10 | controls: {
11 | matchers: {
12 | color: /(background|color)$/i,
13 | date: /Date$/
14 | }
15 | }
16 | },
17 |
18 | decorators: [
19 | // Adds theme switching support.
20 | // NOTE: requires setting "darkMode" to "class" in your tailwind config
21 | withThemeByClassName({
22 | themes: {
23 | light: "light",
24 | dark: "dark"
25 | },
26 | defaultTheme: "light"
27 | })
28 | ]
29 | };
30 |
31 | export default preview;
32 |
--------------------------------------------------------------------------------
/console/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:20-alpine3.17 as build-stage
2 |
3 | WORKDIR /app
4 |
5 | COPY package*.json .
6 |
7 | RUN npm ci
8 |
9 | COPY . .
10 |
11 | RUN npm run check
12 |
13 | RUN npm run build
14 |
15 | RUN npm prune --production
16 |
17 | FROM node:20-alpine3.17
18 |
19 | WORKDIR /app
20 |
21 | COPY --from=build-stage /app/build build/
22 | COPY --from=build-stage /app/node_modules node_modules/
23 | COPY package.json .
24 |
25 | ENV NODE_ENV=production
26 |
27 |
28 | CMD [ "sh", "-c", "node -r dotenv/config build" ]
29 |
--------------------------------------------------------------------------------
/console/Dockerfile.dev:
--------------------------------------------------------------------------------
1 | FROM node:20-alpine3.17
2 |
3 | WORKDIR /app
4 |
5 | VOLUME [ "/app" ]
6 |
7 | # IMPORTANT:
8 | # As svelte kit uses vite under the hood, which itself use esbuild, it is necessary to install the deps from inside
9 | # the container as esbuild is a native dependency and it needs to be compiled for the target platform.
10 |
11 | ENTRYPOINT [ "sh", "-c", "npm install && npm run dev -- --port 3000 --host" ]
12 |
--------------------------------------------------------------------------------
/console/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/console/src/app.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
--------------------------------------------------------------------------------
/console/src/app.d.ts:
--------------------------------------------------------------------------------
1 | // See https://kit.svelte.dev/docs/types#app
2 | // for information about these interfaces
3 | declare global {
4 | namespace App {
5 | // interface Error {}
6 | // interface Locals {}
7 | // interface PageData {}
8 | // interface Platform {}
9 | }
10 | }
11 |
12 | export {};
13 |
--------------------------------------------------------------------------------
/console/src/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | %sveltekit.head%
9 |
10 |
11 | %sveltekit.body%
12 |
13 |
14 |
--------------------------------------------------------------------------------
/console/src/index.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, it, expect } from 'vitest';
2 |
3 | describe('sum test', () => {
4 | it('adds 1 + 2 to equal 3', () => {
5 | expect(1 + 2).toBe(3);
6 | });
7 | });
8 |
--------------------------------------------------------------------------------
/console/src/lib/assets/img/gitlab-icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/console/src/lib/assets/img/google-icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/console/src/lib/assets/img/microsoft-icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/console/src/lib/components/auth/GithubIcon.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 | {#if $themeStore === "dark"}
8 |
9 | {:else}
10 |
11 | {/if}
12 |
--------------------------------------------------------------------------------
/console/src/lib/components/auth/GitlabIcon.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/console/src/lib/components/auth/GoogleIcon.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/console/src/lib/components/auth/MicrosoftIcon.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/console/src/lib/components/auth/types.ts:
--------------------------------------------------------------------------------
1 | export const AuthProviders = ["google", "github", "gitlab"] as const;
2 | export type AuthProvider = (typeof AuthProviders)[number];
3 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/alert/Alert.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/avatar/Avatar.stories.ts:
--------------------------------------------------------------------------------
1 | import type { Meta, StoryObj } from "@storybook/svelte";
2 |
3 | import Avatar from "./Avatar.svelte";
4 |
5 | // More on how to set up stories at: https://storybook.js.org/docs/svelte/writing-stories/introduction
6 | const meta = {
7 | title: "Common/Avatar",
8 | component: Avatar,
9 | tags: ["autodocs"]
10 | } satisfies Meta;
11 |
12 | export default meta;
13 | type Story = StoryObj;
14 |
15 | // More on writing stories with args: https://storybook.js.org/docs/svelte/writing-stories/args
16 | export const Basic: Story = {
17 | args: {
18 | alt: "Some user profile image",
19 | src: "https://media.licdn.com/dms/image/D4E03AQFXJiFpNFWE0A/profile-displayphoto-shrink_100_100/0/1680893451739?e=1699488000&v=beta&t=WiNliB67TjMHbaIycm8u55JDrX82xu9I20jw-b10u4A"
20 | }
21 | };
22 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/avatar/Avatar.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 | {#if image.src}
14 |

{
17 | image.src = null;
18 | }}
19 | alt={alt}
20 | class="rounded-full w-9" />
21 | {:else}
22 |
24 |
28 |
29 | {/if}
30 |
31 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/button/button.types.ts:
--------------------------------------------------------------------------------
1 | export const ButtonStatuses = ["disabled", "loading", "default"];
2 | export type ButtonStatus = (typeof ButtonStatuses)[number];
3 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/card/Card.stories.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/card/Card.svelte:
--------------------------------------------------------------------------------
1 |
16 |
17 | {}}
22 | class="{clickableClass} {disabledClass} w-full rounded-2xl border border-stroke-base dark:border-stroke-base-dark bg-background-tertiary dark:bg-background-tertiary-dark">
23 |
24 |
25 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/card/CardSkeleton.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
14 |
15 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/empty-state/EmptyState.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |

14 |
15 | {title}
16 | {description}
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/empty-state/NotResultState.svelte:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |

14 |
15 | {title}
16 | {description}
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/loading-frame/LoadingFrame.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
12 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/logo/AgentLabsLogo.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/markdown/markdown-image.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
12 |
13 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/markdown/markdown-link.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/markdown/markdown-list-item.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/markdown/markdown-list.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 | {#each token.items as item}
15 |
16 | {/each}
17 |
18 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/markdown/markdown-paragraph.svelte:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/markdown/markdown-renderer.svelte:
--------------------------------------------------------------------------------
1 |
13 |
14 |
26 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/multi-select/types.ts:
--------------------------------------------------------------------------------
1 | import type { ComponentType } from "svelte";
2 | import type { IconSource } from "svelte-hero-icons";
3 |
4 | export type MultiSelectItem = {
5 | id: string;
6 | label: string;
7 | value: string;
8 | heroIcon?: IconSource;
9 | customIcon?: ComponentType;
10 | disabled?: boolean;
11 | disabledLabel?: string;
12 | selected?: boolean;
13 | required?: boolean;
14 | };
15 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/navigation/nav-item/NavItem.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 | {}}
14 | on:click={() => goto(item.path)}
15 | class="{isActive ? 'bg-background-accent dark:bg-background-accent-dark' : ''}
16 | hover:bg-background-accent dark:hover:bg-background-accent-dark text-sm text-body-base dark:text-body-base-dark py-3 px-4 rounded-lg flex gap-2 items-center cursor-pointer">
17 | {#if item?.icon}
18 |
19 | {/if}
20 | {item.label}
21 |
22 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/navigation/nav-item/types.ts:
--------------------------------------------------------------------------------
1 | import type { IconSource } from "svelte-hero-icons";
2 |
3 | export type NavItemType = {
4 | path: string;
5 | label: string;
6 | icon?: IconSource;
7 | };
8 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/navigation/tab-nav/types.ts:
--------------------------------------------------------------------------------
1 | export type TabNavItem = {
2 | path: string;
3 | label: string;
4 | };
5 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/skeleton/MainTitleSkeleton.svelte:
--------------------------------------------------------------------------------
1 |
3 |
4 |
6 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/spacer/Spacer.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/table/ButtonCell.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/table/CopiableCell.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/table/NormalCell.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 | {cellValue}
8 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/table/types.ts:
--------------------------------------------------------------------------------
1 | import type { SvelteComponent } from "svelte";
2 |
3 | export type TableColumn = {
4 | name: string;
5 | key: K;
6 | format?: (rowValue: T) => string;
7 | customComponent?: typeof SvelteComponent<{ cellValue: any }>;
8 | };
9 |
10 | export type TableRow = T;
11 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/tabs/types.ts:
--------------------------------------------------------------------------------
1 | export type TabItem = {
2 | id: string;
3 | value: string;
4 | label: string;
5 | };
6 |
--------------------------------------------------------------------------------
/console/src/lib/components/common/top-cover/TopCover.svelte:
--------------------------------------------------------------------------------
1 |
3 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/console/src/lib/entities/agent/agent-connection.ts:
--------------------------------------------------------------------------------
1 | export interface AgentConnection {
2 | id: string;
3 | ip: string;
4 | createdAt: string;
5 | }
6 |
--------------------------------------------------------------------------------
/console/src/lib/entities/agent/agent.ts:
--------------------------------------------------------------------------------
1 | export interface Agent {
2 | id: string;
3 | name: string;
4 | createdAt: Date;
5 | updatedAt: Date;
6 | }
7 |
--------------------------------------------------------------------------------
/console/src/lib/entities/auth-method/auth-method-list-item.ts:
--------------------------------------------------------------------------------
1 | import type { SvelteComponent } from "svelte";
2 | import type { IconSource } from "svelte-hero-icons";
3 |
4 | export type AuthMethodListItem = {
5 | id: string;
6 | name: string;
7 | value: string;
8 | heroIcon: IconSource | null;
9 | componentIcon: typeof SvelteComponent | null;
10 | available: boolean;
11 | isEnabled: boolean;
12 | statusLabel: string;
13 | };
14 |
--------------------------------------------------------------------------------
/console/src/lib/entities/member/member.ts:
--------------------------------------------------------------------------------
1 | export type Member = {
2 | id: string;
3 | firstName: string | null;
4 | lastName: string | null;
5 | email: string | null;
6 | verifiedAt: Date | null;
7 | createdAt: Date;
8 | updatedAt: Date;
9 | };
10 |
--------------------------------------------------------------------------------
/console/src/lib/entities/project/project.ts:
--------------------------------------------------------------------------------
1 | export type Project = {
2 | id: string;
3 | name: string;
4 | organizationId: string;
5 | slug: string;
6 |
7 | createdAt: Date;
8 | updatedAt: Date;
9 | };
10 |
--------------------------------------------------------------------------------
/console/src/lib/entities/sdk-secret/sdk-secret.ts:
--------------------------------------------------------------------------------
1 | export type SdkSecret = {
2 | id: string;
3 | description: string | null;
4 | hash: string;
5 | preview: string;
6 | createdAt: Date;
7 | updatedAt: Date;
8 | projectId: string;
9 | };
10 |
11 | export type SanitizedSdkSecret = Omit;
12 |
--------------------------------------------------------------------------------
/console/src/lib/entities/user/user.ts:
--------------------------------------------------------------------------------
1 | export type User = {
2 | id: string;
3 | fullName: string;
4 | profilePictureUrl: string | null;
5 | verifiedAt: Date | null;
6 | email: string;
7 | createdAt: Date;
8 | };
9 |
--------------------------------------------------------------------------------
/console/src/lib/entities/user/userConfig.ts:
--------------------------------------------------------------------------------
1 | export type UserConfig = {
2 | id: string;
3 | fullName: string;
4 | verifiedAt: Date | null;
5 | email: string;
6 | createdAt: Date;
7 | organizationCount: number;
8 | defaultOrganizationId: string | null;
9 | defaultProjectId: string | null;
10 | projectCount: number;
11 | projectCreatedCount: number;
12 | onboarding: {
13 | hasAddedAuthMethod: boolean;
14 | hasUsedTheApplication: boolean;
15 | projectId: string | null;
16 | organizationId: string;
17 | };
18 | };
19 |
--------------------------------------------------------------------------------
/console/src/lib/index.ts:
--------------------------------------------------------------------------------
1 | // place files you want to import through the `$lib` alias in this folder.
2 |
--------------------------------------------------------------------------------
/console/src/lib/services/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/console/src/lib/services/.gitkeep
--------------------------------------------------------------------------------
/console/src/lib/services/oauth/codeVerifier.ts:
--------------------------------------------------------------------------------
1 | const CODE_VERIFIER_SESSION_KEY = "agentlabs/console/oauth/code-verifier";
2 |
3 | export const saveCodeVerifier = (codeVerifier: string): void => {
4 | sessionStorage.setItem(CODE_VERIFIER_SESSION_KEY, codeVerifier);
5 | };
6 |
7 | export const getCodeVerifier = (): string | null => {
8 | return sessionStorage.getItem(CODE_VERIFIER_SESSION_KEY);
9 | };
10 |
--------------------------------------------------------------------------------
/console/src/lib/services/oauth/randomState.ts:
--------------------------------------------------------------------------------
1 | export const randomState = (length = 40) => {
2 | const crypto = window.crypto;
3 | const validChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
4 | const array = new Uint8Array(length);
5 | crypto.getRandomValues(array);
6 | const values = new Array(length);
7 | array.forEach((v, i) => {
8 | values[i] = validChars.charCodeAt(v % validChars.length);
9 | });
10 | return String.fromCharCode.apply(null, values);
11 | };
12 |
--------------------------------------------------------------------------------
/console/src/lib/services/telemetry/types.ts:
--------------------------------------------------------------------------------
1 | export const PageCategories = ["console"] as const;
2 |
3 | export type PageCategory = (typeof PageCategories)[number];
4 |
--------------------------------------------------------------------------------
/console/src/lib/stores/agent.ts:
--------------------------------------------------------------------------------
1 | import { writable } from "svelte/store";
2 | import type { Agent } from "$lib/entities/agent/agent";
3 |
4 | export type AgentStore = {
5 | currentAgent: Agent | null;
6 | currentAgentId: string | null;
7 | };
8 |
9 | export const agentStore = writable({
10 | currentAgent: null,
11 | currentAgentId: null
12 | });
13 |
14 | export const setCurrentAgent = (agent: Agent | null) => {
15 | agentStore.update((store) => {
16 | return {
17 | ...store,
18 | currentAgent: agent,
19 | currentAgentId: agent?.id ?? null
20 | };
21 | });
22 | };
23 |
--------------------------------------------------------------------------------
/console/src/lib/stores/organization.ts:
--------------------------------------------------------------------------------
1 | import { writable } from "svelte/store";
2 |
3 | export const organizationStore = writable<{
4 | currentOrganizationId: string | null;
5 | }>({
6 | currentOrganizationId: null
7 | });
8 |
9 | export const setCurrentOrganizationId = (id: string | null) => {
10 | organizationStore.update((store) => {
11 | store.currentOrganizationId = id;
12 | return store;
13 | });
14 | };
15 |
--------------------------------------------------------------------------------
/console/src/lib/stores/theme.ts:
--------------------------------------------------------------------------------
1 | import { writable } from "svelte/store";
2 | import { createLocalStorage, persist } from "@macfja/svelte-persistent-store";
3 | import { genStoreKey } from "$lib/utils/genStoreKey";
4 |
5 | export type Theme = "light" | "dark";
6 |
7 | const THEME_STORE_KEY = genStoreKey("theme-store");
8 |
9 | export const themeStore = persist(writable("light"), createLocalStorage(), THEME_STORE_KEY);
10 |
--------------------------------------------------------------------------------
/console/src/lib/usecases/agents/createAgent.ts:
--------------------------------------------------------------------------------
1 | import type { Agent } from "$lib/entities/agent/agent";
2 | import { AgentsService } from "$lib/services/gen-api";
3 |
4 | export const createAgent = async (params: { projectId: string; name: string }): Promise => {
5 | const agent = await AgentsService.createAgent({
6 | requestBody: {
7 | projectId: params.projectId,
8 | name: params.name
9 | }
10 | });
11 |
12 | return {
13 | ...agent,
14 | createdAt: new Date(agent.createdAt),
15 | updatedAt: new Date(agent.updatedAt)
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/console/src/lib/usecases/agents/deleteAgent.ts:
--------------------------------------------------------------------------------
1 | import { AgentsService } from "$lib/services/gen-api";
2 |
3 | export const deleteAgent = async (agentId: string): Promise => {
4 | await AgentsService.deleteAgent({
5 | agentId
6 | });
7 | };
8 |
--------------------------------------------------------------------------------
/console/src/lib/usecases/agents/fetchAgentDetails.ts:
--------------------------------------------------------------------------------
1 | import type { Agent } from "$lib/entities/agent/agent";
2 | import { AgentsService } from "$lib/services/gen-api";
3 |
4 | const waitForDelay = (delay: number) => new Promise((resolve) => setTimeout(resolve, delay));
5 |
6 | export const fetchAgentDetails = async (agentId: string): Promise => {
7 | const item = await AgentsService.getById({
8 | agentId
9 | });
10 |
11 | await waitForDelay(500);
12 |
13 | return {
14 | id: item.id,
15 | name: item.name,
16 | createdAt: new Date(item.createdAt),
17 | updatedAt: new Date(item.updatedAt)
18 | };
19 | };
20 |
--------------------------------------------------------------------------------
/console/src/lib/usecases/agents/fetchAgents.ts:
--------------------------------------------------------------------------------
1 | import type { Agent } from "$lib/entities/agent/agent";
2 | import { AgentsService } from "$lib/services/gen-api";
3 |
4 | export const fetchAgents = async (projectId: string): Promise => {
5 | const result = await AgentsService.listForProject({
6 | projectId
7 | });
8 |
9 | return result.items.map((item) => ({
10 | id: item.id,
11 | name: item.name,
12 | createdAt: new Date(item.createdAt),
13 | updatedAt: new Date(item.updatedAt)
14 | }));
15 | };
16 |
--------------------------------------------------------------------------------
/console/src/lib/usecases/agents/renameAgent.ts:
--------------------------------------------------------------------------------
1 | import type { Agent } from "$lib/entities/agent/agent";
2 | import { AgentsService } from "$lib/services/gen-api";
3 | import { setCurrentAgent } from "$lib/stores/agent";
4 |
5 | export const renameAgent = async (params: { agentId: string; name: string }): Promise => {
6 | const result = await AgentsService.updateAgent({
7 | agentId: params.agentId,
8 | requestBody: {
9 | name: params.name
10 | }
11 | });
12 |
13 | const agent = {
14 | ...result,
15 | createdAt: new Date(result.createdAt),
16 | updatedAt: new Date(result.updatedAt)
17 | };
18 |
19 | setCurrentAgent(agent);
20 |
21 | return agent;
22 | };
23 |
--------------------------------------------------------------------------------
/console/src/lib/usecases/auth-methods/common.ts:
--------------------------------------------------------------------------------
1 | import GoogleIcon from "$lib/components/auth/GoogleIcon.svelte";
2 | import type { SvelteComponent } from "svelte";
3 | import type { IconSource } from "svelte-hero-icons";
4 | import { Envelope } from "svelte-hero-icons";
5 |
6 | export type AvailableAuthMethod = {
7 | name: string;
8 | providerId: string;
9 | heroIcon: IconSource | null;
10 | componentIcon: typeof SvelteComponent | null;
11 | type: "EMAIL" | "OAUTH2";
12 | };
13 |
14 | export const availableAuthMethods: AvailableAuthMethod[] = [
15 | {
16 | name: "Passwordless email",
17 | providerId: "PASSWORDLESS_EMAIL",
18 | heroIcon: Envelope,
19 | componentIcon: null,
20 | type: "EMAIL"
21 | },
22 | {
23 | name: "Google / Gmail",
24 | providerId: "GOOGLE",
25 | heroIcon: null,
26 | componentIcon: GoogleIcon,
27 | type: "OAUTH2"
28 | }
29 | ];
30 |
--------------------------------------------------------------------------------
/console/src/lib/usecases/auth-methods/upsert.ts:
--------------------------------------------------------------------------------
1 | import type { UpsertAuthMethodDto } from "$lib/services/gen-api";
2 | import { AuthMethodsService } from "$lib/services/gen-api";
3 |
4 | export const upsertAuthMethod = async (authMethod: UpsertAuthMethodDto) => {
5 | return AuthMethodsService.upsert({
6 | requestBody: {
7 | ...authMethod
8 | }
9 | });
10 | };
11 |
--------------------------------------------------------------------------------
/console/src/lib/usecases/common.config.ts:
--------------------------------------------------------------------------------
1 | import { OpenAPI } from "$lib/services/gen-api";
2 |
3 | // TODO: change that to the correct base path
4 | // Or add it directly in the SDK later.
5 | OpenAPI.BASE = "http://localhost:8080/console/lolilol";
6 |
--------------------------------------------------------------------------------
/console/src/lib/usecases/projects/create.ts:
--------------------------------------------------------------------------------
1 | import { ProjectsService } from "$lib/services/gen-api";
2 | import type { CreateProjectDto } from "$lib/services/gen-api";
3 | import dayjs from "dayjs";
4 | import type { Project } from "$lib/entities/project/project";
5 |
6 | export const createProject = async (project: CreateProjectDto): Promise => {
7 | const result = await ProjectsService.createProject({
8 | requestBody: project
9 | });
10 |
11 | return {
12 | id: result.id,
13 | name: result.name,
14 | organizationId: result.organizationId,
15 | slug: result.slug,
16 | createdAt: dayjs(result.createdAt).toDate(),
17 | updatedAt: dayjs(result.updatedAt).toDate()
18 | };
19 | };
20 |
--------------------------------------------------------------------------------
/console/src/lib/usecases/projects/fetchRealtimeBackendConnections.ts:
--------------------------------------------------------------------------------
1 | import { ProjectsService, type SerializedProjectBackendConnectionDto } from "$lib/services/gen-api"
2 |
3 | export const fetchRealtimeConnections = async (projectId: string): Promise => {
4 | const { items } = await ProjectsService.getRealtimeConnections({ projectId })
5 |
6 | return items
7 | }
8 |
--------------------------------------------------------------------------------
/console/src/lib/usecases/projects/retrieveProjectById.ts:
--------------------------------------------------------------------------------
1 | import type { Project } from "$lib/entities/project/project";
2 | import { ProjectsService } from "$lib/services/gen-api";
3 | import dayjs from "dayjs";
4 |
5 | export const retrieveProjectById = async (projectId: string): Promise => {
6 | await new Promise((resolve) => setTimeout(resolve, 500));
7 | const result = await ProjectsService.getById({
8 | projectId
9 | });
10 |
11 | return {
12 | createdAt: dayjs(result.createdAt).toDate(),
13 | id: result.id,
14 | name: result.name,
15 | organizationId: result.organizationId,
16 | slug: result.slug,
17 | updatedAt: dayjs(result.updatedAt).toDate()
18 | };
19 | };
20 |
--------------------------------------------------------------------------------
/console/src/lib/usecases/sdk-secrets/fetchSecrets.ts:
--------------------------------------------------------------------------------
1 | import type { ListSdkSecretDto } from "$lib/services/gen-api";
2 | import { SdkSecretsService } from "$lib/services/gen-api";
3 |
4 | export const fetchSecrets = async (projectId: string): Promise => {
5 | await new Promise((resolve) => setTimeout(resolve, 500));
6 | const secrets = await SdkSecretsService.listForProject({
7 | projectId
8 | });
9 |
10 | return secrets;
11 | };
12 |
--------------------------------------------------------------------------------
/console/src/lib/usecases/sdk-secrets/generateSecret.ts:
--------------------------------------------------------------------------------
1 | import type { CreatedSdkSecretDto } from "$lib/services/gen-api";
2 | import { SdkSecretsService } from "$lib/services/gen-api";
3 |
4 | export const generateSecret = async (projectId: string): Promise => {
5 | await new Promise((resolve) => setTimeout(resolve, 500));
6 | const secret = await SdkSecretsService.create({
7 | requestBody: {
8 | projectId
9 | }
10 | });
11 |
12 | return {
13 | ...secret
14 | };
15 | };
16 |
--------------------------------------------------------------------------------
/console/src/lib/usecases/sdk-secrets/revokeSecret.ts:
--------------------------------------------------------------------------------
1 | import { SdkSecretsService } from "$lib/services/gen-api";
2 |
3 | export const revokeSecret = async (secretId: string) => {
4 | await new Promise((resolve) => setTimeout(resolve, 500));
5 | const result = await SdkSecretsService.revokedById({
6 | secretId
7 | });
8 |
9 | return result;
10 | };
11 |
--------------------------------------------------------------------------------
/console/src/lib/usecases/users/register.ts:
--------------------------------------------------------------------------------
1 | import type { User } from "$lib/entities/user/user";
2 | import type { RegisterUserDto } from "$lib/services/gen-api";
3 | import { UsersService } from "$lib/services/gen-api";
4 | import dayjs from "dayjs";
5 |
6 | export const registerUser = async (user: RegisterUserDto): Promise => {
7 | const result = await UsersService.register({
8 | requestBody: {
9 | email: user.email,
10 | fullName: user.fullName,
11 | password: user.password
12 | }
13 | });
14 |
15 | return {
16 | createdAt: new Date(),
17 | id: result.id,
18 | email: result.email,
19 | fullName: result.fullName,
20 | profilePictureUrl: result.profilePictureUrl,
21 | verifiedAt: dayjs(result.verifiedAt).toDate()
22 | };
23 | };
24 |
--------------------------------------------------------------------------------
/console/src/lib/usecases/users/signInWithGoogle.ts:
--------------------------------------------------------------------------------
1 | import { env } from "$env/dynamic/public";
2 | import GoogleAuthProvider from "$lib/services/oauth/providers/google";
3 | import { signInWithRedirect } from "$lib/services/oauth/signInWithRedirect";
4 | import { validateEnv } from "$lib/utils/validateEnv";
5 |
6 | export const signInWithGoogle = async () => {
7 | const validatedEnv = validateEnv(env);
8 |
9 | if (!validatedEnv) {
10 | throw new Error("Environment validation error");
11 | }
12 |
13 | await signInWithRedirect(
14 | new GoogleAuthProvider({
15 | clientId: validatedEnv.PUBLIC_OAUTH_GOOGLE_CLIENT_ID,
16 | scopes: [
17 | "https://www.googleapis.com/auth/userinfo.email",
18 | "https://www.googleapis.com/auth/userinfo.profile"
19 | ]
20 | })
21 | );
22 | };
23 |
--------------------------------------------------------------------------------
/console/src/lib/utils/buildFrontendUrl.ts:
--------------------------------------------------------------------------------
1 | import { env } from "$env/dynamic/public";
2 | import { validateEnv } from "$lib/utils/validateEnv";
3 | const validatedEnv = validateEnv(env);
4 |
5 | if (!validatedEnv) {
6 | throw new Error("Invalid env");
7 | }
8 |
9 | const { PUBLIC_AI_AGENT_DOMAIN } = validatedEnv;
10 |
11 | export const buildFrontendUrl = (projectSlug: string) => {
12 | const protocol = window?.location?.protocol ?? "https:";
13 | return `${protocol}//${projectSlug}.${PUBLIC_AI_AGENT_DOMAIN}`;
14 | };
15 |
--------------------------------------------------------------------------------
/console/src/lib/utils/clickOutside.ts:
--------------------------------------------------------------------------------
1 | export const clickOutside = (node: Node, onEventFunction: () => void) => {
2 | const handleClick = (event: Event) => {
3 | const path = event.composedPath();
4 |
5 | if (!path.includes(node)) {
6 | onEventFunction();
7 | }
8 | };
9 |
10 | document.addEventListener("click", handleClick);
11 |
12 | return {
13 | destroy() {
14 | document.removeEventListener("click", handleClick);
15 | }
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/console/src/lib/utils/genStoreKey.ts:
--------------------------------------------------------------------------------
1 | export const genStoreKey = (storeName: string) => {
2 | return `agentlabs/client/${storeName}`;
3 | };
4 |
--------------------------------------------------------------------------------
/console/src/lib/utils/time.ts:
--------------------------------------------------------------------------------
1 | export const durationToHumanReadable = (lifetime: number): string => {
2 | const seconds = Math.floor(lifetime / 1000);
3 | const minutes = Math.floor(seconds / 60);
4 | const hours = Math.floor(minutes / 60);
5 |
6 | const secondsString = `${seconds % 60}s`;
7 | const minutesString = minutes > 0 ? `${minutes % 60}m ` : "";
8 | const hoursString = hours > 0 ? `${hours}h ` : "";
9 |
10 | return `${hoursString}${minutesString}${secondsString}`;
11 | };
12 |
--------------------------------------------------------------------------------
/console/src/lib/utils/toast.ts:
--------------------------------------------------------------------------------
1 | import { toast } from "@zerodevx/svelte-toast";
2 |
3 | export const toastError = (message: string) => {
4 | toast.push(message, {
5 | theme: {
6 | "--toastBackground": "#ef434b",
7 | "--toastProgressBackground": "#ff7875"
8 | }
9 | });
10 | };
11 |
12 | export const toastSuccess = (message: string) => {
13 | toast.push(message, {
14 | theme: {
15 | "--toastBackground": "#00C48C",
16 | "--toastProgressBackground": "#95de64"
17 | }
18 | });
19 | };
20 |
--------------------------------------------------------------------------------
/console/src/lib/utils/unique.ts:
--------------------------------------------------------------------------------
1 | export const unique = (arr: T[]): T[] => {
2 | const set = new Set(arr);
3 | return Array.from(set);
4 | };
5 |
--------------------------------------------------------------------------------
/console/src/lib/utils/validateEnv.ts:
--------------------------------------------------------------------------------
1 | import z from "zod";
2 |
3 | export const Environment = z.object({
4 | PUBLIC_AI_AGENT_DOMAIN: z.string().min(1),
5 | PUBLIC_OAUTH_GOOGLE_CLIENT_ID: z.string().min(1),
6 | PUBLIC_TELEMETRY_KEY: z.string().optional(),
7 | PUBLIC_DISCORD_URL: z.string().optional(),
8 | PUBLIC_INTERCOM_APP_ID: z.string().optional(),
9 | });
10 |
11 | export const validateEnv = (env: NodeJS.ProcessEnv) => {
12 | if (Object.keys(env).length === 0) {
13 | return null;
14 | }
15 |
16 | const parsed = Environment.safeParse(env);
17 |
18 | if (!parsed.success) {
19 | throw new Error(`Environment validation error: ${parsed.error}`);
20 | }
21 |
22 | return parsed.data;
23 | };
24 |
--------------------------------------------------------------------------------
/console/src/routes/+layout.svelte:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 | Home | AgentLabs
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/console/src/routes/+page.svelte:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/console/src/routes/login/+layout.svelte:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/console/src/routes/login/+page.server.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod";
2 | import type { Load } from "@sveltejs/kit";
3 |
4 | import { superValidate } from "sveltekit-superforms/server";
5 |
6 | const schema = z.object({
7 | email: z.string().email(),
8 | password: z.string().min(8)
9 | });
10 |
11 | export const load: Load = async (event) => {
12 | const form = await superValidate(schema);
13 | return {
14 | form
15 | };
16 | };
17 |
--------------------------------------------------------------------------------
/console/src/routes/logout/+page.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/console/src/routes/onboarding/+layout.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | Get started | AgentLabs
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/console/src/routes/onboarding/new/+layout.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
11 |
--------------------------------------------------------------------------------
/console/src/routes/onboarding/new/+page.server.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod";
2 | import type { Load } from "@sveltejs/kit";
3 |
4 | import { superValidate } from "sveltekit-superforms/server";
5 |
6 | const schema = z.object({
7 | name: z.string()
8 | });
9 |
10 | export const load: Load = async (event) => {
11 | const form = await superValidate(schema);
12 | return {
13 | form
14 | };
15 | };
16 |
--------------------------------------------------------------------------------
/console/src/routes/onboarding/project/[projectId]/+layout.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/console/src/routes/onboarding/project/[projectId]/ready/+layout.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
11 |
--------------------------------------------------------------------------------
/console/src/routes/project/+layout.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/console/src/routes/project/[projectId]/+layout.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 | Project | AgentLabs
11 |
12 |
13 |
14 |
23 |
24 |
--------------------------------------------------------------------------------
/console/src/routes/project/[projectId]/agent/[agentId]/+page.svelte:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/console/src/routes/project/[projectId]/agent/new/+page.server.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod";
2 | import type { Load } from "@sveltejs/kit";
3 |
4 | import { superValidate } from "sveltekit-superforms/server";
5 |
6 | const schema = z.object({
7 | name: z.string()
8 | });
9 |
10 | export const load: Load = async (event) => {
11 | const form = await superValidate(schema);
12 | return {
13 | form
14 | };
15 | };
16 |
--------------------------------------------------------------------------------
/console/src/routes/project/[projectId]/auth/+page.svelte:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/console/src/routes/project/[projectId]/backends/+layout.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/console/src/routes/project/[projectId]/secrets/+layout.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/console/src/routes/project/overview/+page.svelte:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/console/src/routes/register/+layout.svelte:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/console/src/routes/register/+page.server.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod";
2 | import type { Load } from "@sveltejs/kit";
3 |
4 | import { superValidate } from "sveltekit-superforms/server";
5 |
6 | const schema = z.object({
7 | email: z.string().email(),
8 | password: z.string().min(8),
9 | name: z.string().min(2)
10 | });
11 |
12 | export const load: Load = async (event) => {
13 | const form = await superValidate(schema);
14 | return {
15 | form
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/console/src/routes/types.ts:
--------------------------------------------------------------------------------
1 | export const SignInMethods = ["PASSWORDLESS_EMAIL", "GOOGLE"] as const;
2 | export type SignInMethod = (typeof SignInMethods)[number];
3 |
4 | export type MainLayoutContext = {
5 | lazy: {
6 | context: Promise<{
7 | tenantName: string;
8 | allowedSignInMethods: SignInMethod[];
9 | }>;
10 | };
11 | };
12 |
--------------------------------------------------------------------------------
/console/static/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/console/static/android-chrome-192x192.png
--------------------------------------------------------------------------------
/console/static/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/console/static/android-chrome-512x512.png
--------------------------------------------------------------------------------
/console/static/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/console/static/apple-touch-icon.png
--------------------------------------------------------------------------------
/console/static/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/console/static/favicon-16x16.png
--------------------------------------------------------------------------------
/console/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/console/static/favicon.ico
--------------------------------------------------------------------------------
/console/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/console/static/favicon.png
--------------------------------------------------------------------------------
/console/svelte.config.js:
--------------------------------------------------------------------------------
1 | import adapter from "@sveltejs/adapter-node";
2 | import { vitePreprocess } from "@sveltejs/kit/vite";
3 |
4 | /** @type {import('@sveltejs/kit').Config} */
5 | const config = {
6 | // Consult https://kit.svelte.dev/docs/integrations#preprocessors
7 | // for more information about preprocessors
8 | preprocess: vitePreprocess(),
9 | kit: {
10 | paths: {
11 | base: "/admin"
12 | },
13 | // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
14 | // If your environment is not supported or you settled on a specific environment, switch out the adapter.
15 | // See https://kit.svelte.dev/docs/adapters for more information about adapters.
16 | adapter: adapter()
17 | }
18 | };
19 |
20 | export default config;
21 |
--------------------------------------------------------------------------------
/console/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.svelte-kit/tsconfig.json",
3 | "compilerOptions": {
4 | "allowJs": true,
5 | "checkJs": true,
6 | "esModuleInterop": true,
7 | "forceConsistentCasingInFileNames": true,
8 | "resolveJsonModule": true,
9 | "skipLibCheck": true,
10 | "sourceMap": true,
11 | "strict": true
12 | }
13 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
14 | //
15 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
16 | // from the referenced tsconfig.json - TypeScript does not merge them in
17 | }
18 |
--------------------------------------------------------------------------------
/console/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { sveltekit } from "@sveltejs/kit/vite";
2 | import { defineConfig } from "vitest/config";
3 |
4 | export default defineConfig({
5 | plugins: [sveltekit()],
6 | test: {
7 | include: ["src/**/*.{test,spec}.{js,ts}"]
8 | },
9 | ssr: {
10 | noExternal: ["svelte-hero-icons"]
11 | }
12 | });
13 |
--------------------------------------------------------------------------------
/frontend/.dockerignore:
--------------------------------------------------------------------------------
1 | Dockerfile
2 | .dockerignore
3 | .git
4 | .gitignore
5 | .gitattributes
6 | README.md
7 | .npmrc
8 | .prettierrc
9 | .eslintrc.cjs
10 | .graphqlrc
11 | .editorconfig
12 | .svelte-kit
13 | .vscode
14 | node_modules
15 | build
16 | package
17 | **/.env
18 |
--------------------------------------------------------------------------------
/frontend/.eslintignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 |
10 | # Ignore files for PNPM, NPM and YARN
11 | pnpm-lock.yaml
12 | package-lock.json
13 | yarn.lock
14 |
--------------------------------------------------------------------------------
/frontend/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: [
4 | "eslint:recommended",
5 | "plugin:typescript-eslint/recommended",
6 | "plugin:svelte/recommended",
7 | "prettier",
8 | "plugin:storybook/recommended",
9 | "plugin:storybook/recommended"
10 | ],
11 | parser: '@typescript-eslint/parser',
12 | plugins: ['@typescript-eslint'],
13 | parserOptions: {
14 | sourceType: 'module',
15 | ecmaVersion: 2020,
16 | extraFileExtensions: ['.svelte']
17 | },
18 | env: {
19 | browser: true,
20 | es2017: true,
21 | node: true
22 | },
23 | overrides: [
24 | {
25 | files: ['*.svelte'],
26 | parser: 'svelte-eslint-parser',
27 | parserOptions: {
28 | parser: '@typescript-eslint/parser'
29 | }
30 | }
31 | ]
32 | };
33 |
--------------------------------------------------------------------------------
/frontend/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 | vite.config.js.timestamp-*
10 | vite.config.ts.timestamp-*
11 |
--------------------------------------------------------------------------------
/frontend/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 |
--------------------------------------------------------------------------------
/frontend/.idea/agent-ui.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/frontend/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/frontend/.idea/jsLibraryMappings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/frontend/.idea/jsLinters/eslint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/frontend/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/frontend/.idea/prettier.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/frontend/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/frontend/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict=true
2 | resolution-mode=highest
3 |
--------------------------------------------------------------------------------
/frontend/.prettierignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /build
4 | /.svelte-kit
5 | /package
6 | .env
7 | .env.*
8 | !.env.example
9 |
10 | # Ignore files for PNPM, NPM and YARN
11 | pnpm-lock.yaml
12 | package-lock.json
13 | yarn.lock
14 |
--------------------------------------------------------------------------------
/frontend/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "useTabs": true,
3 | "trailingComma": "none",
4 | "tabWidth": 4,
5 | "printWidth": 100,
6 | "semi": true,
7 | "singleQuote": false,
8 | "jsxBracketSameLine": true,
9 | "overrides": [ {
10 | "files": "*.svelte",
11 | "options": {
12 | "svelteBracketNewLine": false,
13 | "svelteAllowShorthand": false,
14 | "svelteSortOrder" : "options-scripts-styles-markup",
15 | "plugins": [ "prettier-plugin-svelte" ]
16 | }
17 | } ],
18 | "pluginSearchDirs": [ "." ],
19 | "plugins": ["prettier-plugin-organize-imports"]
20 | }
--------------------------------------------------------------------------------
/frontend/.storybook/main.ts:
--------------------------------------------------------------------------------
1 | import type { StorybookConfig } from "@storybook/sveltekit";
2 |
3 | const config: StorybookConfig = {
4 | stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx|svelte)"],
5 | addons: [
6 | "@storybook/addon-svelte-csf",
7 | "@storybook/addon-links",
8 | "@storybook/addon-essentials",
9 | "@storybook/addon-interactions",
10 | {
11 | name: "@storybook/addon-styling",
12 | options: {}
13 | }
14 | ],
15 | framework: {
16 | name: "@storybook/sveltekit",
17 | options: {}
18 | },
19 | docs: {
20 | autodocs: "tag"
21 | }
22 | };
23 | export default config;
24 |
--------------------------------------------------------------------------------
/frontend/.storybook/preview.ts:
--------------------------------------------------------------------------------
1 | import type { Preview } from "@storybook/svelte";
2 |
3 | import { withThemeByClassName } from "@storybook/addon-styling";
4 |
5 | import "../src/app.css";
6 |
7 | const preview: Preview = {
8 | parameters: {
9 | actions: { argTypesRegex: "^on[A-Z].*" },
10 | controls: {
11 | matchers: {
12 | color: /(background|color)$/i,
13 | date: /Date$/
14 | }
15 | }
16 | },
17 |
18 | decorators: [
19 | // Adds theme switching support.
20 | // NOTE: requires setting "darkMode" to "class" in your tailwind config
21 | withThemeByClassName({
22 | themes: {
23 | light: "light",
24 | dark: "dark"
25 | },
26 | defaultTheme: "light"
27 | })
28 | ]
29 | };
30 |
31 | export default preview;
32 |
--------------------------------------------------------------------------------
/frontend/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:20-alpine3.17 as build-stage
2 |
3 | WORKDIR /app
4 |
5 | COPY package*.json .
6 |
7 | RUN npm ci
8 |
9 | COPY . .
10 |
11 | RUN npm run check
12 |
13 | RUN npm run build
14 |
15 | RUN npm prune --production
16 |
17 | FROM node:20-alpine3.17
18 |
19 | WORKDIR /app
20 |
21 | COPY --from=build-stage /app/build build/
22 | COPY --from=build-stage /app/node_modules node_modules/
23 | COPY package.json .
24 |
25 | ENV NODE_ENV=production
26 |
27 |
28 | CMD [ "sh", "-c", "node -r dotenv/config build" ]
29 |
--------------------------------------------------------------------------------
/frontend/Dockerfile.dev:
--------------------------------------------------------------------------------
1 | FROM node:20-alpine3.17
2 |
3 | WORKDIR /app
4 |
5 | VOLUME [ "/app" ]
6 |
7 | # IMPORTANT:
8 | # As svelte kit uses vite under the hood, which itself use esbuild, it is necessary to install the deps from inside
9 | # the container as esbuild is a native dependency and it needs to be compiled for the target platform.
10 |
11 | ENTRYPOINT [ "sh", "-c", "npm install && npm run dev -- --port 3000 --host" ]
12 |
--------------------------------------------------------------------------------
/frontend/postcss.config.js:
--------------------------------------------------------------------------------
1 | export default {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/frontend/src/app.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
--------------------------------------------------------------------------------
/frontend/src/app.d.ts:
--------------------------------------------------------------------------------
1 | // See https://kit.svelte.dev/docs/types#app
2 | // for information about these interfaces
3 | declare global {
4 | namespace App {
5 | // interface Error {}
6 | // interface Locals {}
7 | // interface PageData {}
8 | // interface Platform {}
9 | }
10 | }
11 |
12 | export {};
13 |
--------------------------------------------------------------------------------
/frontend/src/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | %sveltekit.head%
9 |
10 |
11 | %sveltekit.body%
12 |
13 |
14 |
--------------------------------------------------------------------------------
/frontend/src/index.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, it, expect } from 'vitest';
2 |
3 | describe('sum test', () => {
4 | it('adds 1 + 2 to equal 3', () => {
5 | expect(1 + 2).toBe(3);
6 | });
7 | });
8 |
--------------------------------------------------------------------------------
/frontend/src/lib/assets/img/agent-icon.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/frontend/src/lib/assets/img/gitlab-icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/frontend/src/lib/assets/img/google-icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/frontend/src/lib/assets/img/microsoft-icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/auth/GithubIcon.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/auth/GitlabIcon.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/auth/GoogleIcon.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/auth/types.ts:
--------------------------------------------------------------------------------
1 | export const AuthProviders = [
2 | "PASSWORDLESS_EMAIL",
3 | "EMAIL_AND_PASSWORD",
4 | "SMS",
5 | "ANONYMOUS",
6 | "GOOGLE",
7 | "GITHUB",
8 | "GITLAB",
9 | "MICROSOFT"
10 | ] as const;
11 | export type AuthProvider = (typeof AuthProviders)[number];
12 |
13 | export const AuthProviderNameMap: Record = {
14 | GOOGLE: "Google",
15 | GITHUB: "GitHub",
16 | GITLAB: "GitLab",
17 | PASSWORDLESS_EMAIL: "Passwordless email",
18 | EMAIL_AND_PASSWORD: "Email and password",
19 | SMS: "SMS",
20 | ANONYMOUS: "Anonymous",
21 | MICROSOFT: "Microsoft"
22 | } as const;
23 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/chat/chat-message/SelectMessage/multi-select/types.ts:
--------------------------------------------------------------------------------
1 | import type { IconSource } from "svelte-hero-icons";
2 |
3 | export type MultiSelectChoice = {
4 | id: string;
5 | label: string;
6 | value: string;
7 | heroIcon?: IconSource;
8 | disabled?: boolean;
9 | disabledLabel?: string;
10 | selected?: boolean;
11 | required?: boolean;
12 | };
13 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/chat/chat-message/TypingLoader.svelte:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/chat/processing-status/ProcessingStatus.stories.ts:
--------------------------------------------------------------------------------
1 | import type { Meta, StoryObj } from "@storybook/svelte";
2 |
3 | import ProcessingStatus from "./ProcessingStatus.svelte";
4 |
5 | // More on how to set up stories at: https://storybook.js.org/docs/svelte/writing-stories/introduction
6 | const meta = {
7 | title: "Chat/ProcessingStatus",
8 | component: ProcessingStatus,
9 | tags: ["autodocs"]
10 | } satisfies Meta;
11 |
12 | export default meta;
13 | type Story = StoryObj;
14 |
15 | // More on writing stories with args: https://storybook.js.org/docs/svelte/writing-stories/args
16 | export const Default: Story = {
17 | args: {
18 | content: "Finding a way to proceed..."
19 | }
20 | };
21 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/chat/processing-status/ProcessingStatus.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | {content}
7 |
8 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/common/avatar/Avatar.stories.ts:
--------------------------------------------------------------------------------
1 | import type { Meta, StoryObj } from "@storybook/svelte";
2 |
3 | import Avatar from "./Avatar.svelte";
4 |
5 | // More on how to set up stories at: https://storybook.js.org/docs/svelte/writing-stories/introduction
6 | const meta = {
7 | title: "Common/Avatar",
8 | component: Avatar,
9 | tags: ["autodocs"]
10 | } satisfies Meta;
11 |
12 | export default meta;
13 | type Story = StoryObj;
14 |
15 | // More on writing stories with args: https://storybook.js.org/docs/svelte/writing-stories/args
16 | export const Basic: Story = {
17 | args: {
18 | alt: "Some user profile image",
19 | src: "https://media.licdn.com/dms/image/D4E03AQFXJiFpNFWE0A/profile-displayphoto-shrink_100_100/0/1680893451739?e=1699488000&v=beta&t=WiNliB67TjMHbaIycm8u55JDrX82xu9I20jw-b10u4A"
20 | }
21 | };
22 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/common/avatar/Avatar.svelte:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 | {#if image.src}
14 |

{
17 | image.src = null;
18 | }}
19 | alt={alt}
20 | class="rounded-full w-9" />
21 | {:else}
22 |
24 |
28 |
29 | {/if}
30 |
31 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/common/button/button.types.ts:
--------------------------------------------------------------------------------
1 | export const ButtonStatuses = ["disabled", "loading", "default"];
2 | export type ButtonStatus = (typeof ButtonStatuses)[number];
3 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/common/card/Card.stories.svelte:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/common/card/Card.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 | {}}
20 | class="{clickableClass} w-full rounded-2xl border border-stroke-base dark:border-stroke-base-dark bg-background-tertiary dark:bg-background-tertiary-dark">
21 |
22 |
23 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/common/card/CardBody.svelte:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/common/card/CardSkeleton.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
14 |
15 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/common/letter-avatar/LetterAvatar.svelte:
--------------------------------------------------------------------------------
1 |
3 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/common/loading-frame/LoadingFrame.svelte:
--------------------------------------------------------------------------------
1 |
14 |
15 |
21 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/common/logo/AgentLabsLogo.svelte:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/common/logo/PoweredBy.svelte:
--------------------------------------------------------------------------------
1 |
3 |
4 | Powered by AgentLabs.dev
7 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/common/navigation/nav-item/NavItem.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 | {}}
14 | on:click={() => goto(item.path)}
15 | class="{isActive ? 'bg-background-accent dark:bg-background-accent-dark' : ''}
16 | hover:bg-background-accent dark:hover:bg-background-accent-dark text-sm text-body-base dark:text-body-base-dark py-3 px-4 rounded-lg flex gap-2 items-center cursor-pointer">
17 | {#if item?.icon}
18 |
19 | {/if}
20 | {item.label}
21 |
22 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/common/navigation/nav-item/types.ts:
--------------------------------------------------------------------------------
1 | import type { IconSource } from "svelte-hero-icons";
2 |
3 | export type NavItemType = {
4 | path: string;
5 | label: string;
6 | icon?: IconSource;
7 | };
8 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/common/navigation/tab-nav/types.ts:
--------------------------------------------------------------------------------
1 | export type TabNavItem = {
2 | path: string;
3 | label: string;
4 | };
5 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/common/spacer/Spacer.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/markdown/markdown-image.svelte:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
12 |
13 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/markdown/markdown-link.svelte:
--------------------------------------------------------------------------------
1 |
8 |
9 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/markdown/markdown-list-item.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/markdown/markdown-list.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 | {#each token.items as item}
15 |
16 | {/each}
17 |
18 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/markdown/markdown-paragraph.svelte:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/markdown/markdown-renderer.svelte:
--------------------------------------------------------------------------------
1 |
13 |
14 |
26 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/sidebar/Sidebar.svelte:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/frontend/src/lib/components/sidebar/header/SidebarHeader.svelte:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/frontend/src/lib/context/AgentContext.svelte:
--------------------------------------------------------------------------------
1 |
21 |
22 | {#if loading}
23 |
24 | {:else}
25 |
26 | {/if}
27 |
--------------------------------------------------------------------------------
/frontend/src/lib/context/RealtimeContext.svelte:
--------------------------------------------------------------------------------
1 |
27 |
28 | {#if isLoading}
29 |
30 | {:else}
31 |
32 | {/if}
33 |
--------------------------------------------------------------------------------
/frontend/src/lib/entities/agent/agent.ts:
--------------------------------------------------------------------------------
1 | export interface Agent {
2 | id: string;
3 | name: string;
4 | createdAt: string;
5 | updatedAt: string;
6 | }
7 |
--------------------------------------------------------------------------------
/frontend/src/lib/entities/conversation/conversation.ts:
--------------------------------------------------------------------------------
1 | import type { ConversationMessage } from "../message/message";
2 |
3 | export interface Conversation {
4 | id: string;
5 | createdAt: string;
6 | updatedAt: string;
7 |
8 | projectId: string;
9 | memberId: string;
10 | }
11 |
12 | export interface ConversationWithMessages extends Conversation {
13 | messages: ConversationMessage[];
14 | }
15 |
--------------------------------------------------------------------------------
/frontend/src/lib/entities/member/member.ts:
--------------------------------------------------------------------------------
1 | export type Member = {
2 | id: string;
3 | fullName: string | null;
4 | firstName: string | null;
5 | lastName: string | null;
6 | profilePictureUrl: string | null;
7 | isAnonymous: boolean;
8 | verifiedAt: Date | null;
9 | email: string | null;
10 | createdAt: Date;
11 | updatedAt: Date;
12 | };
13 |
--------------------------------------------------------------------------------
/frontend/src/lib/entities/message/message.ts:
--------------------------------------------------------------------------------
1 | export type Message = {
2 | id: string;
3 | text: string;
4 | createdAt: Date;
5 | senderFullName: string;
6 | senderId: string;
7 | from: "user" | "agent";
8 | };
9 |
10 | export const AgentMessageSources = [
11 | 'USER',
12 | 'AGENT',
13 | 'SYSTEM'
14 | ]
15 |
16 | export type AgentMessageSource = typeof AgentMessageSources[number]
17 |
18 | export interface MessageAttachmentWrapper {
19 | attachment: MessageAttachment;
20 | }
21 |
22 | export interface MessageAttachment {
23 | id: string;
24 | createdAt: string;
25 | updatedAt: string;
26 | name: string;
27 | mimeType: string;
28 | sizeBytes: number;
29 | }
30 |
31 | export interface ConversationMessage {
32 | id: string;
33 | createdAt: string;
34 | updateAt: string;
35 |
36 | source: AgentMessageSource;
37 | text: string;
38 |
39 | conversationId: string;
40 |
41 | attachments: MessageAttachmentWrapper[];
42 | }
43 |
--------------------------------------------------------------------------------
/frontend/src/lib/entities/project/public-project-config.ts:
--------------------------------------------------------------------------------
1 | export interface PublicProjectConfig {
2 | id: string;
3 | slug: string;
4 | name: string;
5 | }
6 |
--------------------------------------------------------------------------------
/frontend/src/lib/index.ts:
--------------------------------------------------------------------------------
1 | // place files you want to import through the `$lib` alias in this folder.
2 |
--------------------------------------------------------------------------------
/frontend/src/lib/routes/routes.ts:
--------------------------------------------------------------------------------
1 | const basePath = "";
2 |
3 | export const homeRoute = {
4 | path: () => `${basePath}/chat`
5 | };
6 |
7 | export const agentChatRoute = {
8 | path: () => `${basePath}/chat`
9 | };
10 |
11 | export const chatConversationRoute = {
12 | path: (conversationId: string) => `${basePath}/chat/c/${conversationId}`
13 | };
14 |
15 | export const logoutRoute = {
16 | path: () => `${basePath}/logout`
17 | };
18 |
19 | export const verifyPasswordlessEmailRoute = {
20 | path: (email: string) => `${basePath}/register/verify?email=${email}`
21 | };
22 |
23 | export const projectNotFoundRoute = {
24 | path: () => `${basePath}/project-not-found`
25 | };
26 |
--------------------------------------------------------------------------------
/frontend/src/lib/services/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/frontend/src/lib/services/.gitkeep
--------------------------------------------------------------------------------
/frontend/src/lib/services/oauth/codeVerifier.ts:
--------------------------------------------------------------------------------
1 | const CODE_VERIFIER_SESSION_KEY = "agentlabs/console/oauth/code-verifier";
2 |
3 | export const saveCodeVerifier = (codeVerifier: string): void => {
4 | sessionStorage.setItem(CODE_VERIFIER_SESSION_KEY, codeVerifier);
5 | };
6 |
7 | export const getCodeVerifier = (): string | null => {
8 | return sessionStorage.getItem(CODE_VERIFIER_SESSION_KEY);
9 | };
10 |
--------------------------------------------------------------------------------
/frontend/src/lib/services/oauth/randomState.ts:
--------------------------------------------------------------------------------
1 | export const randomState = (length = 40) => {
2 | const crypto = window.crypto;
3 | const validChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
4 | const array = new Uint8Array(length);
5 | crypto.getRandomValues(array);
6 | const values = new Array(length);
7 | array.forEach((v, i) => {
8 | values[i] = validChars.charCodeAt(v % validChars.length);
9 | });
10 | return String.fromCharCode.apply(null, values);
11 | };
12 |
--------------------------------------------------------------------------------
/frontend/src/lib/store/chat/chat.ts:
--------------------------------------------------------------------------------
1 | import { writable } from "svelte/store";
2 |
3 | function createChat() {
4 | const { subscribe, set, update } = writable(0);
5 |
6 | return {
7 | subscribe,
8 | interrupt: () => {
9 | alert("Agent has been interrupted!");
10 | },
11 | continue: () => {
12 | alert("Human triggered continue.");
13 | },
14 | activateContinuous: () => {
15 | alert("Continuous mode activated");
16 | }
17 | };
18 | }
19 |
20 | export const chat = createChat();
21 |
--------------------------------------------------------------------------------
/frontend/src/lib/stores/agent.ts:
--------------------------------------------------------------------------------
1 | import { get, writable } from "svelte/store";
2 | import type { Agent } from "$lib/entities/agent/agent";
3 |
4 | export type AgentStore = {
5 | list: Agent[];
6 | };
7 |
8 | export const agentStore = writable({
9 | list: [],
10 | });
11 |
12 | export const setSelectedAgent = (agent: Agent) => {
13 | agentStore.update((store) => {
14 | return {
15 | ...store,
16 | selectedAgent: agent
17 | };
18 | });
19 | };
20 |
21 | export const setAvailableAgents = (agents: Agent[]) => {
22 | agentStore.update((store) => {
23 | return {
24 | ...store,
25 | list: agents
26 | };
27 | });
28 | };
29 |
30 | export const getAgentById = (id: string) => {
31 | return get(agentStore).list.find((agent) => agent.id === id);
32 | }
33 |
--------------------------------------------------------------------------------
/frontend/src/lib/stores/left-nav.ts:
--------------------------------------------------------------------------------
1 | import { writable } from "svelte/store";
2 |
3 | export type LeftNavStore = {
4 | isOpened: boolean;
5 | toggle: () => void;
6 | close: () => void;
7 | };
8 |
9 | export const leftNavStore = writable({
10 | isOpened: true,
11 | close: () => {
12 | leftNavStore.update((theme) => {
13 | return {
14 | ...theme,
15 | isOpened: false
16 | };
17 | });
18 | },
19 | toggle: () => {
20 | leftNavStore.update((theme) => {
21 | return {
22 | ...theme,
23 | isOpened: !theme.isOpened
24 | };
25 | });
26 | }
27 | });
28 |
--------------------------------------------------------------------------------
/frontend/src/lib/stores/main-context.ts:
--------------------------------------------------------------------------------
1 | import type { PublicProjectConfigDto } from "$lib/services/gen-api";
2 | import { get, writable } from "svelte/store";
3 |
4 | export type MainContextStore = {
5 | publicProjectConfig: PublicProjectConfigDto | null;
6 | };
7 |
8 | export const mainContextStore = writable({
9 | publicProjectConfig: null
10 | });
11 |
12 | export const setPublicProjectConfig = (value: PublicProjectConfigDto) => {
13 | mainContextStore.update((store) => {
14 | store.publicProjectConfig = value;
15 | return store;
16 | });
17 | };
18 |
19 | export const getMainContextStore = () => {
20 | return get(mainContextStore);
21 | };
22 |
23 |
--------------------------------------------------------------------------------
/frontend/src/lib/stores/theme.ts:
--------------------------------------------------------------------------------
1 | import { genStoreKey } from "$lib/utils/genStoreKey";
2 | import { createLocalStorage, persist } from "@macfja/svelte-persistent-store";
3 | import { writable } from "svelte/store";
4 |
5 | export type Theme = "light" | "dark";
6 |
7 | const THEME_STORE_KEY = genStoreKey("theme-store");
8 |
9 | export const themeStore = persist(writable("dark"), createLocalStorage(), THEME_STORE_KEY);
10 |
--------------------------------------------------------------------------------
/frontend/src/lib/usecases/agents/fetch-agents.ts:
--------------------------------------------------------------------------------
1 | import type { Agent } from "$lib/entities/agent/agent";
2 | import { AgentsService } from "$lib/services/gen-api";
3 | import { setAvailableAgents } from "$lib/stores/agent";
4 |
5 | export const fetchAgents = async (projectId: string): Promise => {
6 | const { items: agents } = await AgentsService.listForProject({ projectId });
7 |
8 | setAvailableAgents(agents);
9 |
10 | return agents;
11 | };
12 |
--------------------------------------------------------------------------------
/frontend/src/lib/usecases/chat/fetch-messages.ts:
--------------------------------------------------------------------------------
1 | import { ChatMessagesService } from "$lib/services/gen-api"
2 | import { loadMessages } from "$lib/stores/chat"
3 |
4 | export const fetchMessages = async (conversationId: string) => {
5 | const messages = await ChatMessagesService.listByConversationId({ conversationId })
6 |
7 | loadMessages(messages)
8 |
9 | return messages
10 | }
11 |
--------------------------------------------------------------------------------
/frontend/src/lib/usecases/conversations/fetch-conversations.ts:
--------------------------------------------------------------------------------
1 | import type { Conversation } from "$lib/entities/conversation/conversation";
2 | import { ConversationsService } from "$lib/services/gen-api";
3 | import { setConversationList } from "$lib/stores/conversation";
4 |
5 | export const fetchConversations = async (projectId: string): Promise => {
6 | const conversations = await ConversationsService.getAllConversations({
7 | projectId
8 | });
9 |
10 | setConversationList(conversations);
11 |
12 | return conversations;
13 | };
14 |
--------------------------------------------------------------------------------
/frontend/src/lib/usecases/members/requestPasswordlessEmail.ts:
--------------------------------------------------------------------------------
1 | import type { RegisterResponseDto } from "$lib/services/gen-api";
2 | import { MembersService } from "$lib/services/gen-api";
3 |
4 | export const requestPasswordlessEmail = async (params: {
5 | projectId: string;
6 | email: string;
7 | }): Promise => {
8 | const { projectId, email } = params;
9 |
10 | const result = await MembersService.requestPasswordlessEmail({
11 | projectId,
12 | requestBody: {
13 | email
14 | }
15 | });
16 |
17 | return result;
18 | };
19 |
--------------------------------------------------------------------------------
/frontend/src/lib/usecases/members/verifyMemberOrLogout.ts:
--------------------------------------------------------------------------------
1 | import { goto } from "$app/navigation";
2 | import { logoutRoute } from "$lib/routes/routes";
3 | import { MembersService } from "$lib/services/gen-api";
4 |
5 | export const verifyMemberOrLogout = async () => {
6 | try {
7 | const member = await MembersService.whoami();
8 | } catch (e: any) {
9 | if (e.status === 401) {
10 | await goto(logoutRoute.path());
11 | } else {
12 | console.error(e);
13 | }
14 | }
15 | };
16 |
--------------------------------------------------------------------------------
/frontend/src/lib/usecases/project/retrievePublicConfig.ts:
--------------------------------------------------------------------------------
1 | import { ProjectsService } from "$lib/services/gen-api";
2 | import { setPublicProjectConfig } from "$lib/stores/main-context";
3 |
4 | export const retrievePublicConfig = async (hostname: string) => {
5 | const config = await ProjectsService.getPublicConfig({ hostname });
6 |
7 | setPublicProjectConfig(config);
8 |
9 | return config;
10 | };
11 |
--------------------------------------------------------------------------------
/frontend/src/lib/utils/clickOutside.ts:
--------------------------------------------------------------------------------
1 | export const clickOutside = (node: Node, onEventFunction: () => void) => {
2 | const handleClick = (event: Event) => {
3 | const path = event.composedPath();
4 |
5 | if (!path.includes(node)) {
6 | onEventFunction();
7 | }
8 | };
9 |
10 | document.addEventListener("click", handleClick);
11 |
12 | return {
13 | destroy() {
14 | document.removeEventListener("click", handleClick);
15 | }
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/frontend/src/lib/utils/genStoreKey.ts:
--------------------------------------------------------------------------------
1 | export const genStoreKey = (storeName: string) => {
2 | return `agentlabs/client/${storeName}`;
3 | };
4 |
--------------------------------------------------------------------------------
/frontend/src/lib/utils/toast.ts:
--------------------------------------------------------------------------------
1 | import { toast } from "@zerodevx/svelte-toast";
2 |
3 | export const toastError = (message: string) => {
4 | toast.push(message, {
5 | theme: {
6 | "--toastBackground": "#ef434b",
7 | "--toastProgressBackground": "#ff7875"
8 | }
9 | });
10 | };
11 |
12 | export const toastSuccess = (message: string) => {
13 | toast.push(message, {
14 | theme: {
15 | "--toastBackground": "#00C48C",
16 | "--toastProgressBackground": "#95de64"
17 | }
18 | });
19 | };
20 |
--------------------------------------------------------------------------------
/frontend/src/lib/utils/unique.ts:
--------------------------------------------------------------------------------
1 | export const unique = (arr: T[]): T[] => {
2 | const set = new Set(arr);
3 | return Array.from(set);
4 | };
5 |
--------------------------------------------------------------------------------
/frontend/src/lib/utils/validateEnv.ts:
--------------------------------------------------------------------------------
1 | import z from "zod";
2 |
3 | export const Environment = z.object({
4 | PUBLIC_APP_HOST: z.string().min(1)
5 | });
6 |
7 | export const validateEnv = (env: NodeJS.ProcessEnv) => {
8 | if (Object.keys(env).length === 0) {
9 | return null;
10 | }
11 |
12 | const parsed = Environment.safeParse(env);
13 |
14 | if (!parsed.success) {
15 | throw new Error(`Environment validation error: ${parsed.error}`);
16 | }
17 |
18 | return parsed.data;
19 | };
20 |
--------------------------------------------------------------------------------
/frontend/src/routes/+page.svelte:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/frontend/src/routes/chat/+page.svelte:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/frontend/src/routes/chat/c/[conversationId]/+page.svelte:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/frontend/src/routes/logout/+page.svelte:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/frontend/src/routes/types.ts:
--------------------------------------------------------------------------------
1 | export const SignInMethods = ["PASSWORDLESS_EMAIL", "GOOGLE"] as const;
2 | export type SignInMethod = (typeof SignInMethods)[number];
3 |
4 | export type MainLayoutContext = {
5 | mainLayoutLazy: {
6 | isLoaded: Promise;
7 | };
8 | };
9 |
--------------------------------------------------------------------------------
/frontend/src/services/agents.types.ts:
--------------------------------------------------------------------------------
1 | export interface AgentInfo {
2 | id: string
3 | logoUrl: string | null;
4 | name: string;
5 | }
6 |
--------------------------------------------------------------------------------
/frontend/static/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/frontend/static/android-chrome-192x192.png
--------------------------------------------------------------------------------
/frontend/static/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/frontend/static/android-chrome-512x512.png
--------------------------------------------------------------------------------
/frontend/static/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/frontend/static/apple-touch-icon.png
--------------------------------------------------------------------------------
/frontend/static/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/frontend/static/favicon-16x16.png
--------------------------------------------------------------------------------
/frontend/static/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/frontend/static/favicon-32x32.png
--------------------------------------------------------------------------------
/frontend/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/frontend/static/favicon.ico
--------------------------------------------------------------------------------
/frontend/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/frontend/static/favicon.png
--------------------------------------------------------------------------------
/frontend/svelte.config.js:
--------------------------------------------------------------------------------
1 | import adapter from "@sveltejs/adapter-node";
2 | import { vitePreprocess } from "@sveltejs/kit/vite";
3 |
4 | /** @type {import('@sveltejs/kit').Config} */
5 | const config = {
6 | // Consult https://kit.svelte.dev/docs/integrations#preprocessors
7 | // for more information about preprocessors
8 | preprocess: vitePreprocess(),
9 |
10 | kit: {
11 | // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
12 | // If your environment is not supported or you settled on a specific environment, switch out the adapter.
13 | // See https://kit.svelte.dev/docs/adapters for more information about adapters.
14 | adapter: adapter()
15 | }
16 | };
17 |
18 | export default config;
19 |
--------------------------------------------------------------------------------
/frontend/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.svelte-kit/tsconfig.json",
3 | "compilerOptions": {
4 | "allowJs": true,
5 | "checkJs": true,
6 | "esModuleInterop": true,
7 | "forceConsistentCasingInFileNames": true,
8 | "resolveJsonModule": true,
9 | "skipLibCheck": true,
10 | "sourceMap": true,
11 | "strict": true
12 | }
13 | // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
14 | //
15 | // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
16 | // from the referenced tsconfig.json - TypeScript does not merge them in
17 | }
18 |
--------------------------------------------------------------------------------
/frontend/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { sveltekit } from "@sveltejs/kit/vite";
2 | import { defineConfig } from "vitest/config";
3 |
4 | export default defineConfig({
5 | plugins: [sveltekit()],
6 | test: {
7 | include: ["src/**/*.{test,spec}.{js,ts}"]
8 | },
9 | ssr: {
10 | noExternal: ["svelte-hero-icons", "marked"]
11 | },
12 | server: {},
13 |
14 | });
15 |
--------------------------------------------------------------------------------
/scripts/frontend-clients/.gitignore:
--------------------------------------------------------------------------------
1 | src
2 |
--------------------------------------------------------------------------------
/scripts/frontend-clients/build_for_console.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | set -e
4 |
5 | echo "🚀 Generating typescript client for console..."
6 |
7 | npx --yes openapi-typescript-codegen \
8 | --input ../../server/openapi.yaml \
9 | --output ./src \
10 | --useOptions \
11 | --useUnionTypes
12 |
13 | cp client.ts src/
14 |
15 | OPENAPI_BASE=${OPENAPI_BASE:-http://localhost:3001}
16 |
17 | echo 'Setting environment variables for OpenAPI_BASE:' ${OPENAPI_BASE}
18 | echo "OpenAPI.BASE = '${OPENAPI_BASE}';" >> src/client.ts
19 |
20 | echo 'export { getToken } from "./client";' >> src/index.ts
21 |
22 | rm -rf ../../console/src/lib/services/gen-api
23 | # important: gen-api folder must be in .gitignore since we don't want to commit it.
24 | cp -R ./src ../../console/src/lib/services/gen-api
25 |
26 | echo -e "✅ Done!\n"
27 |
--------------------------------------------------------------------------------
/scripts/frontend-clients/build_for_frontend.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | set -e
4 |
5 | echo "🚀 Generating typescript client for console..."
6 |
7 | npx --yes openapi-typescript-codegen \
8 | --input ../../server/openapi.yaml \
9 | --output ./src \
10 | --useOptions \
11 | --useUnionTypes
12 |
13 | cp client.ts src/
14 |
15 | OPENAPI_BASE=${OPENAPI_BASE:-http://localhost:3001}
16 |
17 | echo 'Setting environment variables for OpenAPI_BASE:' ${OPENAPI_BASE}
18 | echo "OpenAPI.BASE = '${OPENAPI_BASE}';" >> src/client.ts
19 |
20 | echo 'export { getToken } from "./client";' >> src/index.ts
21 |
22 | rm -rf ../../frontend/src/lib/services/gen-api
23 | # important: gen-api folder must be in .gitignore since we don't want to commit it.
24 | cp -R ./src ../../frontend/src/lib/services/gen-api
25 |
26 | echo -e "✅ Done!\n"
27 |
--------------------------------------------------------------------------------
/scripts/frontend-clients/client.ts:
--------------------------------------------------------------------------------
1 | import { OpenAPI } from "./index";
2 | import { getAccessTokenPromise } from "$lib/stores/auth";
3 |
4 | /* We can overwrite the default configuration by exporting a getToken function.
5 | * This function will be called before each request to get a token.
6 | * See: https://github.com/ferdikoomen/openapi-typescript-codegen/blob/master/docs/authorization.md
7 | */
8 | export const getToken = async () => {
9 | return await getAccessTokenPromise();
10 | };
11 |
12 | OpenAPI.TOKEN = getToken;
13 |
--------------------------------------------------------------------------------
/sdks/node-sdk/.dockerignore:
--------------------------------------------------------------------------------
1 | dist
2 | node_modules
3 |
--------------------------------------------------------------------------------
/sdks/node-sdk/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 | require('@rushstack/eslint-patch/modern-module-resolution');
3 |
4 | module.exports = {
5 | root: true,
6 | extends: [
7 | 'plugin:vue/vue3-essential',
8 | 'eslint:recommended',
9 | '@vue/eslint-config-typescript',
10 | '@vue/eslint-config-prettier',
11 | ],
12 | parserOptions: {
13 | ecmaVersion: 'latest',
14 | },
15 | };
16 |
--------------------------------------------------------------------------------
/sdks/node-sdk/.gitignore:
--------------------------------------------------------------------------------
1 | dist
2 | node_modules
3 | .idea
4 | *tgz
5 |
--------------------------------------------------------------------------------
/sdks/node-sdk/.npmrc:
--------------------------------------------------------------------------------
1 | //registry.npmjs.org/:_authToken=${NPM_TOKEN}
2 |
--------------------------------------------------------------------------------
/sdks/node-sdk/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "semi": true,
4 | "arrowParens": "always",
5 | "tabWidth": 4,
6 | "useTabs": false,
7 | "bracketSpacing": true
8 | }
--------------------------------------------------------------------------------
/sdks/node-sdk/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:20-alpine3.17 as build
2 |
3 | WORKDIR /app
4 |
5 | COPY . .
6 |
7 | COPY .npmrc /root/.npmrc
8 |
9 | COPY scripts/docker-entrypoint.sh /entrypoint.sh
10 |
11 | CMD [ "sh", "/entrypoint.sh" ]
12 |
--------------------------------------------------------------------------------
/sdks/node-sdk/scripts/build.js:
--------------------------------------------------------------------------------
1 | const esbuild = require('esbuild');
2 | const packageJson = require('../package.json');
3 | const { join } = require('path');
4 |
5 | console.time('done in');
6 | console.log('Building package... 👨🍳');
7 |
8 | esbuild.buildSync({
9 | entryPoints: [join(__dirname, '..', 'src', 'index.ts')],
10 | outfile: join(__dirname, '..', 'dist', 'index.js'),
11 | bundle: true,
12 | target: ['esnext'],
13 | platform: 'node',
14 | minify: false,
15 | external: [
16 | ...Object.keys(packageJson.dependencies ?? []),
17 | ...Object.keys(packageJson.peerDependencies ?? []),
18 | ],
19 | });
20 |
21 | console.timeEnd('done in');
22 |
--------------------------------------------------------------------------------
/sdks/node-sdk/scripts/docker-entrypoint.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 |
3 | set -e
4 |
5 | validate_env() {
6 | if [ -z "$NPM_TOKEN" ]; then
7 | echo "NPM_TOKEN is not set, exiting"
8 | exit 1
9 | fi
10 | }
11 |
12 | prepare_config() {
13 | sed -i "s/\"version\": \".*\"/\"version\": \"$VERSION\"/g" package.json
14 | echo "Configured package.json version to $VERSION"
15 | }
16 |
17 | validate_env
18 |
19 | if [ -z "$VERSION" ]; then
20 | echo "VERSION is not set, skipping package.json configuration"
21 | exit 1
22 | else
23 | prepare_config
24 | fi
25 |
26 | npm ci
27 | npm run build
28 |
29 | npm publish --access public
30 |
--------------------------------------------------------------------------------
/sdks/node-sdk/src/const.ts:
--------------------------------------------------------------------------------
1 | export const DEFAULT_INITIAL_MESSAGE_LOADING_DELAY_MS = 1500;
2 | export const DEFAULT_MESSAGE_TYPING_INTERVAL_MS = 60;
3 |
4 | export const DEFAULT_STREAM_TOKEN_SIZE = 3;
5 |
--------------------------------------------------------------------------------
/sdks/node-sdk/src/constants.ts:
--------------------------------------------------------------------------------
1 | import { MessageFormat } from "./types";
2 |
3 | export const localMessageFormatToRemote: Record = {
4 | PlainText: 'PLAIN_TEXT',
5 | Markdown: 'MARKDOWN',
6 | }
7 |
--------------------------------------------------------------------------------
/sdks/node-sdk/src/incoming-chat-message.ts:
--------------------------------------------------------------------------------
1 | import { MessageAttachment } from './message-attachment';
2 | import { Member, RawChatMessage } from './types';
3 | import { HttpApi } from './http';
4 |
5 | export class IncomingChatMessage {
6 | public readonly text: string;
7 | public readonly conversationId: string;
8 | public readonly messageId: string;
9 | public readonly memberId: string;
10 | public readonly member: Member;
11 | public readonly attachments: MessageAttachment[];
12 |
13 | constructor(http: HttpApi, message: RawChatMessage) {
14 | this.text = message.text;
15 | this.conversationId = message.conversationId;
16 | this.messageId = message.messageId;
17 | this.memberId = message.member.id;
18 | this.member = message.member;
19 | this.attachments = (message.attachments ?? []).map((a) => new MessageAttachment(http, a));
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/sdks/node-sdk/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './agent';
2 | export * from './project';
3 | export * from './types';
4 | export * from './attachment'
5 |
--------------------------------------------------------------------------------
/sdks/node-sdk/src/utils/chunk.ts:
--------------------------------------------------------------------------------
1 | export const chunk = (text: string, size: number) => {
2 | const length = text == null ? 0 : text.length;
3 | if (!length || size < 1) {
4 | return [];
5 | }
6 | let index = 0;
7 | let resIndex = 0;
8 | const result = new Array(Math.ceil(length / size));
9 |
10 | while (index < length) {
11 | result[resIndex++] = text.slice(index, (index += size));
12 | }
13 | return result;
14 | };
15 |
--------------------------------------------------------------------------------
/sdks/python-sdk/.gitignore:
--------------------------------------------------------------------------------
1 | dist
2 | __pycache__
3 |
--------------------------------------------------------------------------------
/sdks/python-sdk/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.12.0-alpine3.18
2 |
3 | RUN apk add --no-cache \
4 | curl \
5 | poetry
6 |
7 | ENV PATH="${PATH}:/root/.local/bin"
8 |
9 | COPY . .
10 |
11 | COPY ./scripts/docker-entrypoint.sh /entrypoint.sh
12 |
13 | ENTRYPOINT ["sh", "/entrypoint.sh"]
14 |
--------------------------------------------------------------------------------
/sdks/python-sdk/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/sdks/python-sdk/README.md
--------------------------------------------------------------------------------
/sdks/python-sdk/agentlabs/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/sdks/python-sdk/agentlabs/__init__.py
--------------------------------------------------------------------------------
/sdks/python-sdk/agentlabs/_internals/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/sdks/python-sdk/agentlabs/_internals/__init__.py
--------------------------------------------------------------------------------
/sdks/python-sdk/agentlabs/_internals/const.py:
--------------------------------------------------------------------------------
1 | DEFAULT_INITIAL_MESSAGE_LOADING_DELAY_MS = 1500
2 | DEFAULT_MESSAGE_TYPING_INTERVAL_MS = 60
3 | DEFAULT_STREAM_TOKEN_SIZE = 3
4 |
--------------------------------------------------------------------------------
/sdks/python-sdk/agentlabs/_internals/logger.py:
--------------------------------------------------------------------------------
1 | from datetime import datetime
2 |
3 | class Logger:
4 | def __init__(self, name: str) -> None:
5 | self.name = name
6 |
7 | def _format_log(self, level: str, message: str) -> str:
8 | return f"[{self.name}] {datetime.now().strftime('%m/%d/%Y, %H:%M:%S')} {level} {message}"
9 |
10 | def _log(self, level: str, message: str) -> None:
11 | print(self._format_log(level, message))
12 |
13 | def info(self, message: str) -> None:
14 | self._log("INFO", message)
15 |
16 | def warn(self, message: str) -> None:
17 | self._log("WARN", message)
18 |
19 | def error(self, message: str) -> None:
20 | self._log("ERROR", message)
21 |
22 | def debug(self, message: str) -> None:
23 | self._log("DEBUG", message)
24 |
--------------------------------------------------------------------------------
/sdks/python-sdk/agentlabs/_internals/utils.py:
--------------------------------------------------------------------------------
1 | def chunk_str(input_string, chunk_size):
2 | return [input_string[i:i + chunk_size] for i in range(0, len(input_string), chunk_size)]
3 |
--------------------------------------------------------------------------------
/sdks/python-sdk/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "agentlabs-sdk"
3 | version = "0.0.0"
4 | description = "AgentLabs SDK for Python"
5 | authors = ["Aurélien Brabant "]
6 | readme = "README.md"
7 | packages = [
8 | { include = "agentlabs" }
9 | ]
10 |
11 | [tool.poetry.dependencies]
12 | python = ">=3.9"
13 | websocket-client = "^1.6.3"
14 | python-socketio = "^5.9.0"
15 | requests = "^2.31.0"
16 |
17 | [build-system]
18 | requires = ["poetry-core"]
19 | build-backend = "poetry.core.masonry.api"
20 |
--------------------------------------------------------------------------------
/sdks/python-sdk/scripts/docker-entrypoint.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 |
3 | set -e
4 |
5 | validate_env() {
6 | if [ -z "$PYPI_TOKEN" ]; then
7 | echo "PYPI_TOKEN env var is not set, exiting"
8 | exit 1
9 | fi
10 | }
11 |
12 | prepare_config() {
13 | sed -i "s/^version = .*$/version = \"$VERSION\"/" pyproject.toml
14 | echo "Wrote version to pyproject.toml ($VERSION)"
15 | }
16 |
17 | validate_env
18 |
19 | if [ -z "$VERSION" ]; then
20 | echo "VERSION env var is not set, will use pyproject.toml version unmodified."
21 | else
22 | prepare_config
23 | fi
24 |
25 | poetry config pypi-token.pypi "$PYPI_TOKEN"
26 |
27 | poetry publish --build \
28 | --no-interaction \
29 | --build
30 |
--------------------------------------------------------------------------------
/sdks/python-sdk/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/sdks/python-sdk/tests/__init__.py
--------------------------------------------------------------------------------
/server/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .git
3 | dist
4 | Dockerfile
5 | .dockerignore
6 | test
7 | README.md
8 |
--------------------------------------------------------------------------------
/server/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser',
3 | parserOptions: {
4 | project: 'tsconfig.json',
5 | tsconfigRootDir: __dirname,
6 | sourceType: 'module',
7 | },
8 | plugins: ['@typescript-eslint/eslint-plugin'],
9 | extends: [
10 | 'plugin:@typescript-eslint/recommended',
11 | 'plugin:prettier/recommended',
12 | ],
13 | root: true,
14 | env: {
15 | node: true,
16 | jest: true,
17 | },
18 | ignorePatterns: ['.eslintrc.js'],
19 | rules: {
20 | '@typescript-eslint/interface-name-prefix': 'off',
21 | '@typescript-eslint/explicit-function-return-type': 'off',
22 | '@typescript-eslint/explicit-module-boundary-types': 'off',
23 | '@typescript-eslint/no-explicit-any': 'off',
24 | },
25 | };
26 |
--------------------------------------------------------------------------------
/server/.gitignore:
--------------------------------------------------------------------------------
1 | # compiled output
2 | /dist
3 | /node_modules
4 | /attachments
5 |
6 | # Logs
7 | logs
8 | *.log
9 | npm-debug.log*
10 | pnpm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 | lerna-debug.log*
14 |
15 | # OS
16 | .DS_Store
17 |
18 | # Tests
19 | /coverage
20 | /.nyc_output
21 |
22 | # IDEs and editors
23 | /.idea
24 | .project
25 | .classpath
26 | .c9/
27 | *.launch
28 | .settings/
29 | *.sublime-workspace
30 |
31 | # IDE - VSCode
32 | .vscode/*
33 | !.vscode/settings.json
34 | !.vscode/tasks.json
35 | !.vscode/launch.json
36 | !.vscode/extensions.json
37 |
--------------------------------------------------------------------------------
/server/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "all"
4 | }
--------------------------------------------------------------------------------
/server/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:20-alpine3.17 as build
2 |
3 | WORKDIR /app
4 |
5 | COPY package.json package-lock.json ./
6 |
7 | RUN npm ci
8 |
9 | COPY . .
10 |
11 | RUN npx prisma generate
12 |
13 | RUN npm run build
14 |
15 | RUN npm prune --production
16 |
17 | FROM node:20-alpine3.17 as release
18 |
19 | WORKDIR /app
20 |
21 | COPY --from=build /app/dist ./dist
22 | COPY --from=build /app/node_modules ./node_modules
23 | COPY --from=build /app/package.json ./package.json
24 | COPY --from=build /app/prisma ./prisma
25 |
26 | COPY --from=build /app/scripts/docker-entrypoint.sh docker-entrypoint.sh
27 |
28 | ENTRYPOINT [ "sh", "docker-entrypoint.sh" ]
29 |
--------------------------------------------------------------------------------
/server/Dockerfile.dev:
--------------------------------------------------------------------------------
1 | FROM node:20-alpine3.17 as dev
2 |
3 | WORKDIR /app
4 |
5 | VOLUME [ "/app" ]
6 |
7 | COPY ./scripts/docker-entrypoint.dev.sh /docker-entrypoint.dev.sh
8 |
9 | ENTRYPOINT [ "sh", "/docker-entrypoint.dev.sh" ]
10 |
--------------------------------------------------------------------------------
/server/README.md:
--------------------------------------------------------------------------------
1 | # server
2 |
3 | A server that for now manages everything.
4 |
5 | ## Development
6 |
7 | ### Migrations
8 |
9 | **Important**: if required to work with migrations manually, you must do so inside the docker container where proper environment variables are set. Otherwise you'll run into issues to connect to the database.
10 |
11 | As long as the project is in its POC state we want to continuously allow ourselves to edit the initial migration file and not create many of them.
12 | We will start proper versioning once the first public release airs.
13 |
14 | To regenerate the initial migration file, run the following command.
15 | (If destructive schema operations were introduced, prisma will ask to wipe the schema and you will thus loose data)
16 |
17 | ```
18 | npm run poc:regenerate-migrations
19 | ```
20 |
--------------------------------------------------------------------------------
/server/nest-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/nest-cli",
3 | "collection": "@nestjs/schematics",
4 | "sourceRoot": "src",
5 | "compilerOptions": {
6 | "assets": [
7 | { "include": "**/*.hbs", "watchAssets": true }
8 | ],
9 | "deleteOutDir": true,
10 | "plugins": [
11 | {
12 | "name": "@nestjs/swagger",
13 | "options": {
14 | "classValidatorShim": true,
15 | "introspectComments": false
16 | }
17 | }
18 | ]
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/server/openapitools.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json",
3 | "spaces": 2,
4 | "generator-cli": {
5 | "version": "7.0.0"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/server/print-oas.Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:20-alpine3.17 as build
2 |
3 | WORKDIR /app
4 |
5 | COPY package.json package-lock.json ./
6 |
7 | RUN npm ci
8 |
9 | COPY . .
10 |
11 | RUN npx prisma generate
12 |
13 | RUN npm run build
14 |
15 | RUN npm prune --production
16 |
17 | FROM node:20-alpine3.17 as release
18 |
19 | WORKDIR /app
20 |
21 | COPY --from=build /app/dist ./dist
22 | COPY --from=build /app/node_modules ./node_modules
23 | COPY --from=build /app/package.json ./package.json
24 | COPY --from=build /app/prisma ./prisma
25 |
26 | # we do use the special print-oas-docker-entrypoint.sh script here
27 | COPY --from=build /app/scripts/print-oas-docker-entrypoint.sh docker-entrypoint.sh
28 |
29 | ENTRYPOINT [ "sh", "docker-entrypoint.sh" ]
30 |
--------------------------------------------------------------------------------
/server/prisma/migrations/20231020133514_anonymous_users/migration.sql:
--------------------------------------------------------------------------------
1 | -- AlterTable
2 | ALTER TABLE "Member" ADD COLUMN "isAnonymous" BOOLEAN NOT NULL DEFAULT false,
3 | ALTER COLUMN "email" DROP NOT NULL;
4 |
--------------------------------------------------------------------------------
/server/prisma/migrations/20231023224256_add_size_bytes_and_project_id_fields_to_attachment/migration.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Warnings:
3 |
4 | - Added the required column `projectId` to the `Attachment` table without a default value. This is not possible if the table is not empty.
5 | - Added the required column `sizeBytes` to the `Attachment` table without a default value. This is not possible if the table is not empty.
6 |
7 | */
8 | -- AlterTable
9 | ALTER TABLE "Attachment" ADD COLUMN "projectId" TEXT NOT NULL,
10 | ADD COLUMN "sizeBytes" INTEGER NOT NULL;
11 |
12 | -- AddForeignKey
13 | ALTER TABLE "Attachment" ADD CONSTRAINT "Attachment_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
14 |
--------------------------------------------------------------------------------
/server/prisma/migrations/20231026115736_add_type_and_metadata_fields_to_chat_message/migration.sql:
--------------------------------------------------------------------------------
1 | -- AlterTable
2 | ALTER TABLE "ChatMessage" ADD COLUMN "metadata" JSONB NOT NULL DEFAULT '{}',
3 | ADD COLUMN "type" TEXT NOT NULL DEFAULT 'TEXT';
4 |
--------------------------------------------------------------------------------
/server/prisma/migrations/migration_lock.toml:
--------------------------------------------------------------------------------
1 | # Please do not edit this file manually
2 | # It should be added in your version-control system (i.e. Git)
3 | provider = "postgresql"
--------------------------------------------------------------------------------
/server/scripts/docker-entrypoint.dev.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 |
3 | set -e
4 |
5 | npm install
6 |
7 | npx prisma generate
8 | npx prisma migrate deploy
9 |
10 | npm run start:dev
11 |
--------------------------------------------------------------------------------
/server/scripts/docker-entrypoint.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 |
3 | set -e
4 |
5 | npx prisma migrate deploy
6 |
7 | node dist/main.js $@
8 |
--------------------------------------------------------------------------------
/server/scripts/print-oas-docker-entrypoint.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 |
3 | set -e
4 |
5 | SKIP_ENV_VALIDATION=true DRY_RUN=true node dist/main.js $@ > /dev/null
6 |
7 | cat ./openapi.yaml
8 |
--------------------------------------------------------------------------------
/server/src/agents/agents.constants.ts:
--------------------------------------------------------------------------------
1 | export const acceptedLogoMimeTypes = [
2 | 'image/jpeg',
3 | 'image/jpg',
4 | 'image/png',
5 | 'image/webp',
6 | ];
7 |
--------------------------------------------------------------------------------
/server/src/agents/agents.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { AgentsController } from './agents.controller';
3 | import { AgentsService } from './agents.service';
4 |
5 | describe('AgentsController', () => {
6 | let controller: AgentsController;
7 |
8 | beforeEach(async () => {
9 | const module: TestingModule = await Test.createTestingModule({
10 | controllers: [AgentsController],
11 | providers: [AgentsService],
12 | }).compile();
13 |
14 | controller = module.get(AgentsController);
15 | });
16 |
17 | it('should be defined', () => {
18 | expect(controller).toBeDefined();
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/server/src/agents/agents.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { ProjectBackendConnectionManagerModule } from 'src/project-backend-connection-manager/project-backend-connection-manager.module';
3 | import { AttachmentsModule } from 'src/attachments/attachments.module';
4 | import { ProjectsModule } from 'src/projects/projects.module';
5 | import { TelemetryModule } from '../telemetry/telemetry.module';
6 | import { AgentsController } from './agents.controller';
7 | import { AgentsService } from './agents.service';
8 |
9 | @Module({
10 | imports: [
11 | ProjectsModule,
12 | AttachmentsModule,
13 | TelemetryModule,
14 | ProjectBackendConnectionManagerModule,
15 | ],
16 | controllers: [AgentsController],
17 | providers: [AgentsService],
18 | exports: [AgentsService],
19 | })
20 | export class AgentsModule {}
21 |
--------------------------------------------------------------------------------
/server/src/agents/agents.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { AgentsService } from './agents.service';
3 |
4 | describe('AgentsService', () => {
5 | let service: AgentsService;
6 |
7 | beforeEach(async () => {
8 | const module: TestingModule = await Test.createTestingModule({
9 | providers: [AgentsService],
10 | }).compile();
11 |
12 | service = module.get(AgentsService);
13 | });
14 |
15 | it('should be defined', () => {
16 | expect(service).toBeDefined();
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/server/src/agents/dtos/agent-connection.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsString } from 'class-validator';
2 |
3 | export class AgentConnectionDto {
4 | @IsString()
5 | ip: string;
6 |
7 | @IsString()
8 | sid: string;
9 |
10 | @IsString()
11 | createdAt: string;
12 | }
13 |
--------------------------------------------------------------------------------
/server/src/agents/dtos/create.agent.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsString } from 'class-validator';
2 |
3 | export class CreateAgentDto {
4 | @IsString()
5 | name: string;
6 |
7 | @IsString()
8 | projectId: string;
9 | }
10 |
--------------------------------------------------------------------------------
/server/src/agents/dtos/created.agent.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsDate, IsString } from 'class-validator';
2 |
3 | export class CreatedAgentDto {
4 | @IsString()
5 | id: string;
6 |
7 | @IsString()
8 | name: string;
9 |
10 | @IsString()
11 | projectId: string;
12 |
13 | @IsString()
14 | creatorId: string;
15 |
16 | @IsDate()
17 | createdAt: Date;
18 |
19 | @IsDate()
20 | updatedAt: Date;
21 | }
22 |
--------------------------------------------------------------------------------
/server/src/agents/dtos/deleted.agent.response.dto.ts:
--------------------------------------------------------------------------------
1 | export class DeletedAgentResponseDto {
2 | success: boolean;
3 | }
4 |
--------------------------------------------------------------------------------
/server/src/agents/dtos/did-agent-ever-connect.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsBoolean } from 'class-validator';
2 |
3 | export class DidAgentEverConnectResponse {
4 | @IsBoolean()
5 | didEverConnect: boolean;
6 | }
7 |
--------------------------------------------------------------------------------
/server/src/agents/dtos/get.agent.response.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsDate, IsString } from 'class-validator';
2 |
3 | export class GetAgentResponseDto {
4 | @IsString()
5 | id: string;
6 |
7 | @IsString()
8 | name: string;
9 |
10 | @IsString()
11 | projectId: string;
12 |
13 | @IsString()
14 | creatorId: string;
15 |
16 | @IsDate()
17 | createdAt: Date;
18 |
19 | @IsDate()
20 | updatedAt: Date;
21 | }
22 |
--------------------------------------------------------------------------------
/server/src/agents/dtos/list-agent-connections.response.dto.ts:
--------------------------------------------------------------------------------
1 | import { Type } from 'class-transformer';
2 | import { ValidateNested } from 'class-validator';
3 | import { AgentConnectionDto } from './agent-connection.dto';
4 |
5 | export class ListAgentConnectionsDto {
6 | @ValidateNested()
7 | @Type(() => AgentConnectionDto)
8 | items: AgentConnectionDto[];
9 | }
10 |
--------------------------------------------------------------------------------
/server/src/agents/dtos/list.agents.response.dto.ts:
--------------------------------------------------------------------------------
1 | import { Type } from 'class-transformer';
2 | import {
3 | IsArray,
4 | IsDate,
5 | IsNumber,
6 | IsString,
7 | ValidateNested,
8 | } from 'class-validator';
9 | import { ListResponse } from '../../common/list.response';
10 |
11 | class ListAgentItem {
12 | @IsString()
13 | id: string;
14 |
15 | @IsString()
16 | name: string;
17 |
18 | @IsString()
19 | projectId: string;
20 |
21 | @IsString()
22 | creatorId: string;
23 |
24 | @IsDate()
25 | createdAt: Date;
26 |
27 | @IsDate()
28 | updatedAt: Date;
29 | }
30 |
31 | export class ListAgentsResponseDto implements ListResponse {
32 | @IsArray()
33 | @ValidateNested({ each: true })
34 | @Type(() => ListAgentItem)
35 | items: ListAgentItem[];
36 |
37 | @IsNumber()
38 | total: number;
39 | }
40 |
--------------------------------------------------------------------------------
/server/src/agents/dtos/update.agent.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsString } from 'class-validator';
2 |
3 | export class UpdateAgentDto {
4 | @IsString()
5 | name: string;
6 | }
7 |
--------------------------------------------------------------------------------
/server/src/agents/dtos/updated.agent.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsDate, IsString } from 'class-validator';
2 |
3 | export class UpdatedAgentDto {
4 | @IsString()
5 | id: string;
6 |
7 | @IsString()
8 | name: string;
9 |
10 | @IsString()
11 | projectId: string;
12 |
13 | @IsString()
14 | creatorId: string;
15 |
16 | @IsDate()
17 | createdAt: Date;
18 |
19 | @IsDate()
20 | updatedAt: Date;
21 | }
22 |
--------------------------------------------------------------------------------
/server/src/app.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { AppController } from './app.controller';
3 | import { AppService } from './app.service';
4 |
5 | describe('AppController', () => {
6 | let appController: AppController;
7 |
8 | beforeEach(async () => {
9 | const app: TestingModule = await Test.createTestingModule({
10 | controllers: [AppController],
11 | providers: [AppService],
12 | }).compile();
13 |
14 | appController = app.get(AppController);
15 | });
16 |
17 | describe('root', () => {
18 | it('should return "Hello World!"', () => {
19 | expect(appController.getHello()).toBe('Hello World!');
20 | });
21 | });
22 | });
23 |
--------------------------------------------------------------------------------
/server/src/app.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller, Get } from '@nestjs/common';
2 | import { AppService } from './app.service';
3 |
4 | @Controller()
5 | export class AppController {
6 | constructor(private readonly appService: AppService) {}
7 |
8 | @Get()
9 | getHello(): string {
10 | return this.appService.getHello();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/server/src/app.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 |
3 | @Injectable()
4 | export class AppService {
5 | getHello(): string {
6 | return 'Hello World!';
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/server/src/attachments/attachment-storage/attachment-storage.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common';
2 |
3 | export interface AttachmentMetadata {
4 | attachmentId: string;
5 | filename: string;
6 | mimeType: string;
7 | checksumSha256: string;
8 | extension?: string;
9 | }
10 |
11 | // An attachment has to be retrievable by its sole ID, without any other
12 | // kind of metadata. The upload implementation should account for this.
13 | @Injectable()
14 | export abstract class AttachmentStorageService {
15 | abstract upload(data: Buffer, metadata: AttachmentMetadata): Promise;
16 |
17 | abstract download(attachmentId: string): Promise;
18 |
19 | abstract delete(attachmentId: string): Promise;
20 | }
21 |
--------------------------------------------------------------------------------
/server/src/attachments/attachments.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { AttachmentsController } from './attachments.controller';
3 |
4 | describe('AttachmentsController', () => {
5 | let controller: AttachmentsController;
6 |
7 | beforeEach(async () => {
8 | const module: TestingModule = await Test.createTestingModule({
9 | controllers: [AttachmentsController],
10 | }).compile();
11 |
12 | controller = module.get(AttachmentsController);
13 | });
14 |
15 | it('should be defined', () => {
16 | expect(controller).toBeDefined();
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/server/src/attachments/attachments.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { AttachmentStorageService } from './attachment-storage/attachment-storage.service';
3 | import { LocalAttachmentStorageService } from './attachment-storage/local-attachment-storage/local-attachment-storage.service';
4 | import { AttachmentsService } from './attachments.service';
5 | import { AttachmentsController } from './attachments.controller';
6 |
7 | @Module({
8 | imports: [],
9 | providers: [
10 | AttachmentsService,
11 | {
12 | provide: AttachmentStorageService,
13 | useClass: LocalAttachmentStorageService,
14 | },
15 | ],
16 | exports: [AttachmentsService, AttachmentStorageService],
17 | controllers: [AttachmentsController],
18 | })
19 | export class AttachmentsModule {}
20 |
--------------------------------------------------------------------------------
/server/src/attachments/attachments.types.ts:
--------------------------------------------------------------------------------
1 | export interface CreateAttachmentPayload {
2 | data: Buffer;
3 | mimeType: string;
4 | filename: string;
5 | size: number;
6 | projectId: string;
7 | isPublic?: boolean;
8 | }
9 |
--------------------------------------------------------------------------------
/server/src/auth-methods/auth-methods.config.ts:
--------------------------------------------------------------------------------
1 | import { Inject } from '@nestjs/common';
2 | import { registerAs } from '@nestjs/config';
3 | import { validateEnv } from 'src/config/validate-env';
4 |
5 | export interface AuthMethodsConfig {
6 | authMethodSecretEncryptionKey: string;
7 | authMethodSecretEncryptionAlgorithm: string;
8 | }
9 |
10 | export const authMethodsConfig = registerAs(
11 | 'AuthMethodsConfig',
12 | (): AuthMethodsConfig => {
13 | const env = validateEnv(process.env);
14 |
15 | return {
16 | authMethodSecretEncryptionKey: env.AES_ENCRYPTION_KEY,
17 | authMethodSecretEncryptionAlgorithm: 'aes-256-cbc',
18 | };
19 | },
20 | );
21 |
22 | export const InjectAuthMethodsConfig = () => Inject(authMethodsConfig.KEY);
23 |
--------------------------------------------------------------------------------
/server/src/auth-methods/auth-methods.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { AuthMethodsController } from './auth-methods.controller';
3 | import { AuthMethodsService } from './auth-methods.service';
4 |
5 | describe('AuthMethodsController', () => {
6 | let controller: AuthMethodsController;
7 |
8 | beforeEach(async () => {
9 | const module: TestingModule = await Test.createTestingModule({
10 | controllers: [AuthMethodsController],
11 | providers: [AuthMethodsService],
12 | }).compile();
13 |
14 | controller = module.get(AuthMethodsController);
15 | });
16 |
17 | it('should be defined', () => {
18 | expect(controller).toBeDefined();
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/server/src/auth-methods/auth-methods.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { TelemetryModule } from '../telemetry/telemetry.module';
3 | import { AuthMethodsController } from './auth-methods.controller';
4 | import { AuthMethodsService } from './auth-methods.service';
5 |
6 | @Module({
7 | controllers: [AuthMethodsController],
8 | providers: [AuthMethodsService],
9 | exports: [AuthMethodsService],
10 | imports: [TelemetryModule],
11 | })
12 | export class AuthMethodsModule {}
13 |
--------------------------------------------------------------------------------
/server/src/auth-methods/auth-methods.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { AuthMethodsService } from './auth-methods.service';
3 |
4 | describe('AuthMethodsService', () => {
5 | let service: AuthMethodsService;
6 |
7 | beforeEach(async () => {
8 | const module: TestingModule = await Test.createTestingModule({
9 | providers: [AuthMethodsService],
10 | }).compile();
11 |
12 | service = module.get(AuthMethodsService);
13 | });
14 |
15 | it('should be defined', () => {
16 | expect(service).toBeDefined();
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/server/src/auth-methods/dtos/create.auth-method.dto.ts:
--------------------------------------------------------------------------------
1 | import { AuthProvider } from '@prisma/client';
2 | import { Type } from 'class-transformer';
3 | import {
4 | IsArray,
5 | IsBoolean,
6 | IsIn,
7 | IsOptional,
8 | IsString,
9 | ValidateNested,
10 | } from 'class-validator';
11 |
12 | const AuthProviders = Object.values(AuthProvider);
13 |
14 | export class CreateAuthMethodDto {
15 | @IsIn(AuthProviders)
16 | provider: AuthProvider;
17 |
18 | @IsString()
19 | projectId: string;
20 |
21 | @IsBoolean()
22 | isEnabled: boolean;
23 |
24 | @IsOptional()
25 | @IsString()
26 | clientId: string;
27 |
28 | @IsOptional()
29 | @IsString()
30 | clientSecret: string;
31 |
32 | @IsArray()
33 | @ValidateNested({ each: true })
34 | @Type(() => String)
35 | @IsOptional()
36 | scopes: string[];
37 | }
38 |
--------------------------------------------------------------------------------
/server/src/auth-methods/dtos/created.auth-method.dto.ts:
--------------------------------------------------------------------------------
1 | import { AuthMethodItemDto } from './auth-method.item.dto';
2 |
3 | export class CreatedAuthMethodDto extends AuthMethodItemDto {}
4 |
--------------------------------------------------------------------------------
/server/src/auth-methods/dtos/created.demo.auth-method.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsBoolean } from 'class-validator';
2 |
3 | export class CreatedDemoAuthMethodsDto {
4 | @IsBoolean()
5 | success: boolean;
6 | }
7 |
--------------------------------------------------------------------------------
/server/src/auth-methods/dtos/list.auth-method.response.dto.ts:
--------------------------------------------------------------------------------
1 | import { Type } from 'class-transformer';
2 | import { IsArray, IsNumber, ValidateNested } from 'class-validator';
3 | import { ListResponse } from '../../common/list.response';
4 | import { AuthMethodItemDto } from './auth-method.item.dto';
5 |
6 | class ListAuthMethodItem extends AuthMethodItemDto {}
7 |
8 | export class ListAuthMethodResponseDto
9 | implements ListResponse
10 | {
11 | @IsArray()
12 | @ValidateNested({ each: true })
13 | @Type(() => ListAuthMethodItem)
14 | items: ListAuthMethodItem[];
15 |
16 | @IsNumber()
17 | total: number;
18 | }
19 |
--------------------------------------------------------------------------------
/server/src/auth-methods/dtos/upsert.auth-method.dto.ts:
--------------------------------------------------------------------------------
1 | import { AuthMethodType, AuthProvider } from '@prisma/client';
2 | import { Type } from 'class-transformer';
3 | import {
4 | IsArray,
5 | IsBoolean,
6 | IsIn,
7 | IsOptional,
8 | IsString,
9 | ValidateNested,
10 | } from 'class-validator';
11 |
12 | const AuthMethodTypes = Object.values(AuthMethodType);
13 | const AuthProviders = Object.values(AuthProvider);
14 |
15 | export class UpsertAuthMethodDto {
16 | @IsIn(AuthProviders)
17 | provider: AuthProvider;
18 |
19 | @IsString()
20 | projectId: string;
21 |
22 | @IsBoolean()
23 | isEnabled: boolean;
24 |
25 | @IsString()
26 | clientId: string;
27 |
28 | @IsString()
29 | clientSecret: string;
30 |
31 | @IsArray()
32 | @ValidateNested({ each: true })
33 | @Type(() => String)
34 | @IsOptional()
35 | scopes: string[];
36 | }
37 |
--------------------------------------------------------------------------------
/server/src/auth-methods/dtos/upserted.auth-method.dto.ts:
--------------------------------------------------------------------------------
1 | import { AuthMethodItemDto } from './auth-method.item.dto';
2 |
3 | export class UpsertedAuthMethodDto extends AuthMethodItemDto {}
4 |
--------------------------------------------------------------------------------
/server/src/chat-messages/chat-messages.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { AttachmentsModule } from 'src/attachments/attachments.module';
3 | import { ConversationsModule } from 'src/conversations/conversations.module';
4 | import { ChatMessagesController } from './chat-messages.controller';
5 | import { ChatMessagesService } from './chat-messages.service';
6 |
7 | @Module({
8 | imports: [ConversationsModule, AttachmentsModule],
9 | providers: [ChatMessagesService],
10 | exports: [ChatMessagesService],
11 | controllers: [ChatMessagesController],
12 | })
13 | export class ChatMessagesModule {}
14 |
--------------------------------------------------------------------------------
/server/src/chat-messages/chat-messages.types.ts:
--------------------------------------------------------------------------------
1 | import { ChatMessageSource, MessageFormat } from 'prisma/prisma-client';
2 |
3 | export interface BaseChatMessagePayload {
4 | text: string;
5 | conversationId: string;
6 | format: MessageFormat;
7 | metadata?: any;
8 | type: MessageType;
9 | source: ChatMessageSource;
10 | agentId?: string;
11 | }
12 |
13 | export type CreateUserChatMessagePayload = BaseChatMessagePayload;
14 |
15 | export type CreateSystemChatMessagePayload = BaseChatMessagePayload;
16 |
17 | export const MessageTypes = ['TEXT', 'ECHART'] as const;
18 |
19 | export type MessageType = (typeof MessageTypes)[number];
20 |
21 | export interface EchartMetadata {
22 | chartType: string;
23 | }
24 |
--------------------------------------------------------------------------------
/server/src/common/list.response.ts:
--------------------------------------------------------------------------------
1 | export interface ListResponse {
2 | items: T[];
3 | total: number;
4 | }
5 |
--------------------------------------------------------------------------------
/server/src/common/mime.ts:
--------------------------------------------------------------------------------
1 | export const mimeTypeToExtension: Record = {
2 | 'image/jpeg': 'jpg',
3 | 'image/png': 'png',
4 | 'image/jpg': 'jpg',
5 | 'image/webp': 'webp',
6 | 'application/pdf': 'pdf',
7 | 'application/json': 'json',
8 | };
9 |
--------------------------------------------------------------------------------
/server/src/common/ms-time.ts:
--------------------------------------------------------------------------------
1 | export const seconds = (n: number) => n * 1000;
2 | export const minutes = (n: number) => seconds(n) * 60;
3 | export const hours = (n: number) => minutes(n) * 60;
4 | export const days = (n: number) => hours(n) * 24;
5 | export const weeks = (n: number) => days(n) * 7;
6 | export const months = (n: number) => days(n) * 30;
7 | export const years = (n: number) => days(n) * 365;
8 |
--------------------------------------------------------------------------------
/server/src/common/paginated.query.dto.ts:
--------------------------------------------------------------------------------
1 | import { Transform } from 'class-transformer';
2 | import { IsNumber, Max, Min } from 'class-validator';
3 |
4 | export class PaginatedQueryDto {
5 | @IsNumber()
6 | @Min(1)
7 | @Transform(({ value }) => Number.parseInt(value, 10))
8 | page: number;
9 |
10 | @IsNumber()
11 | @Min(1)
12 | @Max(1000)
13 | @Transform(({ value }) => Number.parseInt(value, 10))
14 | limit: number;
15 | }
16 |
--------------------------------------------------------------------------------
/server/src/common/paginated.response.ts:
--------------------------------------------------------------------------------
1 | export interface PaginatedResponse {
2 | items: T[];
3 | resultCount: number;
4 | totalCount: number;
5 | hasMore: boolean;
6 | }
7 |
--------------------------------------------------------------------------------
/server/src/common/result.ts:
--------------------------------------------------------------------------------
1 | export type Result = { ok: true; value: T } | { ok: false; error: E };
2 | export type PResult = Promise>;
3 |
4 | export const ok = (value: T): Result => ({ ok: true, value });
5 | export const err = (error: E): Result => ({ ok: false, error });
6 |
--------------------------------------------------------------------------------
/server/src/conversations/conversations.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { ConversationsController } from './conversations.controller';
3 | import { ConversationsService } from './conversations.service';
4 |
5 | @Module({
6 | providers: [ConversationsService],
7 | controllers: [ConversationsController],
8 | exports: [ConversationsService],
9 | })
10 | export class ConversationsModule {}
11 |
--------------------------------------------------------------------------------
/server/src/conversations/conversations.types.ts:
--------------------------------------------------------------------------------
1 | export interface CreateConversationPayload {
2 | id: string;
3 | projectId: string;
4 | memberId: string;
5 | }
6 |
7 | export interface FindAllConversationsPayload {
8 | projectId: string;
9 | memberId: string;
10 | }
11 |
--------------------------------------------------------------------------------
/server/src/conversations/dto/get-all-conversations.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsString } from 'class-validator';
2 |
3 | export class GetAllConversationsDto {
4 | @IsString()
5 | readonly projectId: string;
6 | }
--------------------------------------------------------------------------------
/server/src/frontend-connection-manager/frontend-connection-manager.constants.ts:
--------------------------------------------------------------------------------
1 | export const frontend_namespace = 'frontend';
2 |
--------------------------------------------------------------------------------
/server/src/frontend-connection-manager/frontend-connection-manager.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { FrontendConnectionManagerService } from './frontend-connection-manager.service';
3 |
4 | @Module({
5 | imports: [],
6 | providers: [FrontendConnectionManagerService],
7 | exports: [FrontendConnectionManagerService],
8 | })
9 | export class FrontendConnectionManagerModule {}
10 |
--------------------------------------------------------------------------------
/server/src/frontend-connection-manager/frontend-connection-manager.types.ts:
--------------------------------------------------------------------------------
1 | import { Socket } from 'socket.io';
2 |
3 | export interface FrontendConnection {
4 | socket: Socket;
5 | projectId: string;
6 | createdAt: Date;
7 | key: string;
8 | memberId: string;
9 | host: string;
10 | }
11 |
12 | export interface RegisterFrontendConnectionPayload {
13 | projectId: string;
14 | socket: Socket;
15 | memberId: string;
16 | host: string;
17 | }
18 |
19 | export interface ComputeFrontendConnectionKeyPayload {
20 | projectId: string;
21 | memberId: string;
22 | }
23 |
--------------------------------------------------------------------------------
/server/src/frontend-connection/dto/frontend-chat-message.dto.ts:
--------------------------------------------------------------------------------
1 | import { Type } from 'class-transformer';
2 | import { IsOptional, IsString, ValidateNested } from 'class-validator';
3 | import { BaseRealtimeMessageDto } from 'src/common/base-realtime-message.dto';
4 |
5 | class AttachmentDto {
6 | @IsString()
7 | id: string;
8 | }
9 |
10 | class FrontendChatMessageDtoData {
11 | @IsString()
12 | text: string;
13 |
14 | @IsOptional()
15 | @IsString()
16 | conversationId: string;
17 |
18 | @ValidateNested({ each: true })
19 | @Type(() => AttachmentDto)
20 | attachments: AttachmentDto[];
21 | }
22 |
23 | export class FrontendChatMessageDto extends BaseRealtimeMessageDto {
24 | @ValidateNested()
25 | @Type(() => FrontendChatMessageDtoData)
26 | data: FrontendChatMessageDtoData;
27 | }
28 |
--------------------------------------------------------------------------------
/server/src/iam/iam.decorators.ts:
--------------------------------------------------------------------------------
1 | import { SetMetadata } from '@nestjs/common';
2 | import { AuthMethod } from './iam.types';
3 |
4 | export const REQUIRE_AUTH_METHOD_METADATA_KEY = 'require-auth';
5 |
6 | export const RequireAuthMethod = (...method: AuthMethod[]) =>
7 | SetMetadata(REQUIRE_AUTH_METHOD_METADATA_KEY, method);
8 |
--------------------------------------------------------------------------------
/server/src/iam/server-sdk-auth/server-sdk-auth.types.ts:
--------------------------------------------------------------------------------
1 | export interface SdkUser {
2 | projectId: string;
3 | }
4 |
--------------------------------------------------------------------------------
/server/src/mailer/mailer.config.ts:
--------------------------------------------------------------------------------
1 | import { Inject } from '@nestjs/common';
2 | import { registerAs } from '@nestjs/config';
3 | import { validateEnv } from 'src/config/validate-env';
4 |
5 | export interface MailerConfig {
6 | host: string;
7 | port: number;
8 | user: string;
9 | password: string;
10 | senderAddress: string;
11 | senderName: string;
12 | }
13 |
14 | export const mailerConfig = registerAs(
15 | 'MailerConfig',
16 | (): MailerConfig => {
17 | const env = validateEnv(process.env);
18 |
19 | return {
20 | host: env.SMTP_HOST,
21 | port: env.SMTP_PORT,
22 | user: env.SMTP_USERNAME,
23 | password: env.SMTP_PASSWORD,
24 | senderAddress: env.EMAIL_SENDER_ADDRESS,
25 | senderName: env.EMAIL_SENDER_NAME,
26 | };
27 | },
28 | );
29 |
30 | export const InjectMailerConfig = () => Inject(mailerConfig.KEY);
31 |
--------------------------------------------------------------------------------
/server/src/mailer/mailer.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { MailerService } from './mailer.service';
3 |
4 | @Module({
5 | providers: [MailerService],
6 | exports: [MailerService],
7 | })
8 | export class MailerModule {}
9 |
--------------------------------------------------------------------------------
/server/src/mailer/mailer.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { MailerService } from './mailer.service';
3 |
4 | describe('MailerService', () => {
5 | let service: MailerService;
6 |
7 | beforeEach(async () => {
8 | const module: TestingModule = await Test.createTestingModule({
9 | providers: [MailerService],
10 | }).compile();
11 |
12 | service = module.get(MailerService);
13 | });
14 |
15 | it('should be defined', () => {
16 | expect(service).toBeDefined();
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/server/src/members/dtos/list.members.response.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsDate, IsString } from 'class-validator';
2 | import { PaginatedResponse } from '../../common/paginated.response';
3 |
4 | export class MemberItem {
5 | @IsString()
6 | id: string;
7 |
8 | @IsString()
9 | email: string | null;
10 |
11 | @IsString()
12 | firstName: string | null;
13 |
14 | @IsString()
15 | lastName: string | null;
16 |
17 | @IsDate()
18 | createdAt: Date;
19 |
20 | @IsDate()
21 | updatedAt: Date;
22 |
23 | @IsDate()
24 | verifiedAt: Date | null;
25 | }
26 |
27 | export class ListMembersResponseDto implements PaginatedResponse {
28 | items: MemberItem[];
29 | resultCount: number;
30 | totalCount: number;
31 | hasMore: boolean;
32 | }
33 |
--------------------------------------------------------------------------------
/server/src/members/dtos/login.member.response.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsString } from 'class-validator';
2 | import { SanitizedMemberDto } from './sanitized.member.dto';
3 |
4 | export class LoginMemberResponseDto {
5 | @IsString()
6 | accessToken: string;
7 |
8 | member: SanitizedMemberDto;
9 | }
10 |
--------------------------------------------------------------------------------
/server/src/members/dtos/member.whoami.result.dto.ts:
--------------------------------------------------------------------------------
1 | import { SanitizedMemberDto } from './sanitized.member.dto';
2 |
3 | export class MemberWhoAmIResultDto extends SanitizedMemberDto {}
4 |
--------------------------------------------------------------------------------
/server/src/members/dtos/oauth.authorize.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsString } from 'class-validator';
2 |
3 | export class oauthAuthorizeDto {
4 | @IsString()
5 | code: string;
6 |
7 | @IsString()
8 | state: string;
9 |
10 | @IsString()
11 | redirectUri: string;
12 |
13 | @IsString()
14 | projectId: string;
15 | }
16 |
--------------------------------------------------------------------------------
/server/src/members/dtos/register.response.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsDate, IsString } from 'class-validator';
2 |
3 | export class RegisterResponseDto {
4 | @IsString()
5 | email: string | null;
6 |
7 | @IsDate()
8 | createdAt: Date;
9 |
10 | @IsDate()
11 | updatedAt: Date;
12 | }
13 |
--------------------------------------------------------------------------------
/server/src/members/dtos/request.passwordless-email.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsString } from 'class-validator';
2 |
3 | export class RequestPasswordlessEmailDto {
4 | @IsString()
5 | email: string;
6 | }
7 |
--------------------------------------------------------------------------------
/server/src/members/dtos/sanitized.member.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsDate, IsString } from 'class-validator';
2 |
3 | export class SanitizedMemberDto {
4 | @IsString()
5 | id: string;
6 |
7 | @IsString()
8 | email: string | null;
9 |
10 | @IsString()
11 | fullName: string | null;
12 |
13 | @IsString()
14 | firstName: string | null;
15 |
16 | @IsString()
17 | lastName: string | null;
18 |
19 | @IsString()
20 | profilePictureUrl: string | null;
21 |
22 | @IsDate()
23 | verifiedAt: Date | null;
24 |
25 | @IsDate()
26 | createdAt: Date;
27 |
28 | @IsDate()
29 | updatedAt: Date;
30 | }
31 |
--------------------------------------------------------------------------------
/server/src/members/dtos/verify-passwordless-email.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsEmail, IsString } from 'class-validator';
2 |
3 | export class VerifyPasswordlessEmailDto {
4 | @IsEmail()
5 | email: string;
6 |
7 | @IsString()
8 | code: string;
9 | }
10 |
--------------------------------------------------------------------------------
/server/src/members/members.config.ts:
--------------------------------------------------------------------------------
1 | import { Inject } from '@nestjs/common';
2 | import { registerAs } from '@nestjs/config';
3 | import { validateEnv } from 'src/config/validate-env';
4 |
5 | export interface MembersConfig {
6 | accessTokenSecret: string;
7 | accessTokenExpirationTime: string;
8 | authCodeExpirationDelayInMinutes: number;
9 | }
10 |
11 | export const membersConfig = registerAs(
12 | 'MembersConfig',
13 | (): MembersConfig => {
14 | const env = validateEnv(process.env);
15 |
16 | return {
17 | accessTokenSecret: env.MEMBERS_ACCESS_TOKEN_SECRET,
18 | accessTokenExpirationTime: '24h',
19 | authCodeExpirationDelayInMinutes:
20 | env.MEMBERS_AUTH_CODE_EXPIRATION_DELAY_IN_MINUTES,
21 | };
22 | },
23 | );
24 |
25 | export const InjectMembersConfig = () => Inject(membersConfig.KEY);
26 |
--------------------------------------------------------------------------------
/server/src/members/members.controller.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { MembersController } from './members.controller';
3 | import { MembersService } from './members.service';
4 |
5 | describe('MembersController', () => {
6 | let controller: MembersController;
7 |
8 | beforeEach(async () => {
9 | const module: TestingModule = await Test.createTestingModule({
10 | controllers: [MembersController],
11 | providers: [MembersService],
12 | }).compile();
13 |
14 | controller = module.get(MembersController);
15 | });
16 |
17 | it('should be defined', () => {
18 | expect(controller).toBeDefined();
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/server/src/members/members.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { AuthMethodsModule } from '../auth-methods/auth-methods.module';
3 | import { MailerModule } from '../mailer/mailer.module';
4 | import { OauthProvidersModule } from '../oauth-providers/oauth-providers.module';
5 | import { MembersController } from './members.controller';
6 | import { MembersService } from './members.service';
7 |
8 | @Module({
9 | imports: [MailerModule, OauthProvidersModule, AuthMethodsModule],
10 | controllers: [MembersController],
11 | providers: [MembersService],
12 | exports: [MembersService],
13 | })
14 | export class MembersModule {}
15 |
--------------------------------------------------------------------------------
/server/src/members/members.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { MembersService } from './members.service';
3 |
4 | describe('MembersService', () => {
5 | let service: MembersService;
6 |
7 | beforeEach(async () => {
8 | const module: TestingModule = await Test.createTestingModule({
9 | providers: [MembersService],
10 | }).compile();
11 |
12 | service = module.get(MembersService);
13 | });
14 |
15 | it('should be defined', () => {
16 | expect(service).toBeDefined();
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/server/src/members/members.types.ts:
--------------------------------------------------------------------------------
1 | import { JWTPayload } from 'jose';
2 |
3 | export type AccessTokenPayload = {
4 | sub: string;
5 | email: string | null;
6 | firstName: string | null;
7 | lastName: string | null;
8 | projectId: string;
9 | };
10 |
11 | export const isAccessTokenPayload = (
12 | payload: JWTPayload,
13 | ): payload is AccessTokenPayload => {
14 | return typeof payload.sub === 'string';
15 | };
16 |
--------------------------------------------------------------------------------
/server/src/oauth-providers/google/google.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { GoogleService } from './google.service';
3 |
4 | describe('GoogleService', () => {
5 | let service: GoogleService;
6 |
7 | beforeEach(async () => {
8 | const module: TestingModule = await Test.createTestingModule({
9 | providers: [GoogleService],
10 | }).compile();
11 |
12 | service = module.get(GoogleService);
13 | });
14 |
15 | it('should be defined', () => {
16 | expect(service).toBeDefined();
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/server/src/oauth-providers/oauth-providers.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { GoogleService } from './google/google.service';
3 |
4 | @Module({
5 | providers: [GoogleService],
6 | exports: [GoogleService],
7 | })
8 | export class OauthProvidersModule {}
9 |
--------------------------------------------------------------------------------
/server/src/openapi-tools/index.ts:
--------------------------------------------------------------------------------
1 | export * from './openapi-tools.module';
2 | export * from './openapi.service';
3 | export * from './openapi-nest.factory';
4 | export * from './openapi-file-generator/openapi-file-generator.service';
5 |
--------------------------------------------------------------------------------
/server/src/openapi-tools/openapi-file-generator/openapi-file-generator.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { OpenApiFileGeneratorService } from './openapi-file-generator.service';
3 |
4 | describe('OpenApiFileGeneratorService', () => {
5 | let service: OpenApiFileGeneratorService;
6 |
7 | beforeEach(async () => {
8 | const module: TestingModule = await Test.createTestingModule({
9 | providers: [OpenApiFileGeneratorService],
10 | }).compile();
11 |
12 | service = module.get(
13 | OpenApiFileGeneratorService,
14 | );
15 | });
16 |
17 | it('should be defined', () => {
18 | expect(service).toBeDefined();
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/server/src/openapi-tools/openapi-tools.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { OpenApiFileGeneratorService } from './openapi-file-generator/openapi-file-generator.service';
3 | import { OpenApiService } from './openapi.service';
4 |
5 | @Module({
6 | providers: [OpenApiService, OpenApiFileGeneratorService],
7 | exports: [OpenApiService],
8 | })
9 | export class OpenApiToolsModule {}
10 |
--------------------------------------------------------------------------------
/server/src/prisma/prisma.module.ts:
--------------------------------------------------------------------------------
1 | import { Global, Module } from '@nestjs/common';
2 | import { PrismaService } from './prisma.service';
3 |
4 | @Global()
5 | @Module({
6 | providers: [PrismaService],
7 | exports: [PrismaService],
8 | })
9 | export class PrismaModule {}
10 |
--------------------------------------------------------------------------------
/server/src/prisma/prisma.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, OnModuleInit } from '@nestjs/common';
2 | import { PrismaClient } from '@prisma/client';
3 |
4 | @Injectable()
5 | export class PrismaService extends PrismaClient implements OnModuleInit {
6 | async onModuleInit() {
7 | await this.$connect();
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/server/src/project-backend-connection-manager/dto/register-agent-connection.dto.ts:
--------------------------------------------------------------------------------
1 | export class RegisterAgentConnectionDto {
2 | projectId: string;
3 | agentId: string;
4 | }
5 |
--------------------------------------------------------------------------------
/server/src/project-backend-connection-manager/dto/serialized-project-backend-connection.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsString } from 'class-validator';
2 |
3 | export class SerializedProjectBackendConnectionDto {
4 | @IsString()
5 | id: string;
6 |
7 | @IsString()
8 | createdAt: string;
9 |
10 | @IsString()
11 | projectId: string;
12 |
13 | @IsString()
14 | ipAddress: string;
15 | }
16 |
--------------------------------------------------------------------------------
/server/src/project-backend-connection-manager/project-backend-connection-manager.constants.ts:
--------------------------------------------------------------------------------
1 | export const AGENT_SOCKETIO_NAMESPACE = 'agent';
2 |
--------------------------------------------------------------------------------
/server/src/project-backend-connection-manager/project-backend-connection-manager.controller.ts:
--------------------------------------------------------------------------------
1 | import { Controller } from '@nestjs/common';
2 |
3 | @Controller('agent-connection-manager')
4 | export class ProjectBackendConnectionManagerController {
5 | constructor() {}
6 | }
7 |
--------------------------------------------------------------------------------
/server/src/project-backend-connection-manager/project-backend-connection-manager.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { FrontendConnectionManagerModule } from 'src/frontend-connection-manager/frontend-connection-manager.module';
3 | import { ProjectBackendConnectionManagerController } from './project-backend-connection-manager.controller';
4 | import { ProjectBackendConnectionManagerService } from './project-backend-connection-manager.service';
5 |
6 | @Module({
7 | imports: [FrontendConnectionManagerModule],
8 | providers: [ProjectBackendConnectionManagerService],
9 | exports: [ProjectBackendConnectionManagerService],
10 | controllers: [ProjectBackendConnectionManagerController],
11 | })
12 | export class ProjectBackendConnectionManagerModule {}
13 |
--------------------------------------------------------------------------------
/server/src/project-backend-connection-manager/project-backend-connection-manager.types.ts:
--------------------------------------------------------------------------------
1 | import { Socket } from 'socket.io';
2 |
3 | export interface AgentConnection {
4 | socket: Socket;
5 | projectId: string;
6 | key: string;
7 | createdAt: Date;
8 | ip: string;
9 | }
10 |
11 | export interface RegisterAgentConnectionPayload {
12 | socket: Socket;
13 | projectId: string;
14 | ip: string;
15 | }
16 |
--------------------------------------------------------------------------------
/server/src/project-backend-connection/dto/stream-chat-message-token.dto.ts:
--------------------------------------------------------------------------------
1 | import { MessageFormat } from '@prisma/client';
2 | import { Type } from 'class-transformer';
3 | import { IsEnum, IsString, ValidateNested } from 'class-validator';
4 | import { BaseRealtimeMessageDto } from 'src/common/base-realtime-message.dto';
5 |
6 | class StreamChatMessageTokenDtoData {
7 | @IsString()
8 | text: string;
9 |
10 | @IsString()
11 | conversationId: string;
12 |
13 | @IsString()
14 | messageId: string;
15 |
16 | @IsEnum(MessageFormat)
17 | format: MessageFormat;
18 |
19 | @IsString()
20 | agentId: string;
21 | }
22 |
23 | export class StreamChatMessageTokenDto extends BaseRealtimeMessageDto {
24 | @ValidateNested()
25 | @Type(() => StreamChatMessageTokenDtoData)
26 | data: StreamChatMessageTokenDtoData;
27 | }
28 |
--------------------------------------------------------------------------------
/server/src/projects/dtos/create.project.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsString } from 'class-validator';
2 |
3 | export class CreateProjectDto {
4 | @IsString()
5 | name: string;
6 |
7 | @IsString()
8 | slug: string;
9 |
10 | @IsString()
11 | organizationId: string;
12 | }
13 |
--------------------------------------------------------------------------------
/server/src/projects/dtos/created.project.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsDate, IsString } from 'class-validator';
2 |
3 | export class CreatedProjectDto {
4 | @IsString()
5 | id: string;
6 |
7 | @IsString()
8 | name: string;
9 |
10 | @IsString()
11 | slug: string;
12 |
13 | @IsString()
14 | organizationId: string;
15 |
16 | @IsString()
17 | creatorId: string;
18 |
19 | @IsDate()
20 | createdAt: Date;
21 |
22 | @IsDate()
23 | updatedAt: Date;
24 | }
25 |
--------------------------------------------------------------------------------
/server/src/projects/dtos/get-realtime-connections.response.dto.ts:
--------------------------------------------------------------------------------
1 | import { Type } from 'class-transformer';
2 | import { ValidateNested } from 'class-validator';
3 | import { SerializedProjectBackendConnectionDto } from '../../project-backend-connection-manager/dto/serialized-project-backend-connection.dto';
4 |
5 | export class GetRealtimeConnectionsResponseDto {
6 | @ValidateNested({ each: true })
7 | @Type(() => SerializedProjectBackendConnectionDto)
8 | items: SerializedProjectBackendConnectionDto[];
9 | }
10 |
--------------------------------------------------------------------------------
/server/src/projects/dtos/get.public.config.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsString } from 'class-validator';
2 |
3 | export class GetPublicConfigDto {
4 | @IsString()
5 | hostname: string;
6 | }
7 |
--------------------------------------------------------------------------------
/server/src/projects/dtos/list.projects.result.dto.ts:
--------------------------------------------------------------------------------
1 | import { Type } from 'class-transformer';
2 | import {
3 | IsArray,
4 | IsDate,
5 | IsNumber,
6 | IsString,
7 | ValidateNested,
8 | } from 'class-validator';
9 | import { ListResponse } from '../../common/list.response';
10 |
11 | export class ListProjectItemDto {
12 | @IsString()
13 | id: string;
14 |
15 | @IsString()
16 | name: string;
17 |
18 | @IsString()
19 | slug: string;
20 |
21 | @IsString()
22 | organizationId: string;
23 |
24 | @IsString()
25 | creatorId: string;
26 |
27 | @IsDate()
28 | createdAt: Date;
29 |
30 | @IsDate()
31 | updatedAt: Date;
32 | }
33 |
34 | export class ListProjectsResultDto implements ListResponse {
35 | @IsArray()
36 | @ValidateNested({ each: true })
37 | @Type(() => ListProjectItemDto)
38 | items: ListProjectItemDto[];
39 |
40 | @IsNumber()
41 | total: number;
42 | }
43 |
--------------------------------------------------------------------------------
/server/src/projects/dtos/project.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsDate, IsString } from 'class-validator';
2 |
3 | export class ProjectDto {
4 | @IsString()
5 | id: string;
6 |
7 | @IsString()
8 | name: string;
9 |
10 | @IsString()
11 | slug: string;
12 |
13 | @IsString()
14 | organizationId: string;
15 |
16 | @IsString()
17 | creatorId: string;
18 |
19 | @IsDate()
20 | createdAt: Date;
21 |
22 | @IsDate()
23 | updatedAt: Date;
24 | }
25 |
--------------------------------------------------------------------------------
/server/src/projects/dtos/project.exists.response.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsBoolean } from 'class-validator';
2 |
3 | export class ProjectExistsResponseDto {
4 | @IsBoolean()
5 | exists: boolean;
6 | }
7 |
--------------------------------------------------------------------------------
/server/src/projects/projects.config.ts:
--------------------------------------------------------------------------------
1 | import { Inject } from '@nestjs/common';
2 | import { registerAs } from '@nestjs/config';
3 | import { validateEnv } from 'src/config/validate-env';
4 |
5 | // eslint-disable-next-line @typescript-eslint/no-empty-interface
6 | export interface ProjectsConfig {}
7 |
8 | export const projectsConfig = registerAs(
9 | 'ProjectsConfig',
10 | (): ProjectsConfig => {
11 | const env = validateEnv(process.env);
12 |
13 | console.log('env', env);
14 |
15 | return {};
16 | },
17 | );
18 |
19 | export const InjectProjectsConfig = () => Inject(projectsConfig.KEY);
20 |
--------------------------------------------------------------------------------
/server/src/projects/projects.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { ProjectBackendConnectionManagerModule } from 'src/project-backend-connection-manager/project-backend-connection-manager.module';
3 | import { TelemetryModule } from '../telemetry/telemetry.module';
4 | import { ProjectsController } from './projects.controller';
5 | import { ProjectsService } from './projects.service';
6 |
7 | @Module({
8 | controllers: [ProjectsController],
9 | providers: [ProjectsService],
10 | exports: [ProjectsService],
11 | imports: [TelemetryModule, ProjectBackendConnectionManagerModule],
12 | })
13 | export class ProjectsModule {}
14 |
--------------------------------------------------------------------------------
/server/src/projects/projects.types.ts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/server/src/projects/projects.types.ts
--------------------------------------------------------------------------------
/server/src/sdk-secrets/dtos/create.sdk-secret.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsOptional, IsString } from 'class-validator';
2 |
3 | export class CreateSdkSecretDto {
4 | @IsString()
5 | @IsOptional()
6 | description?: string;
7 |
8 | @IsString()
9 | projectId: string;
10 | }
11 |
--------------------------------------------------------------------------------
/server/src/sdk-secrets/dtos/created.sdk-secret.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsString } from 'class-validator';
2 | import { SanitizedSdkSecretDto } from './sanitized.sdk-secret.dto';
3 |
4 | export class CreatedSdkSecretDto extends SanitizedSdkSecretDto {
5 | @IsString()
6 | clearValue: string;
7 | }
8 |
--------------------------------------------------------------------------------
/server/src/sdk-secrets/dtos/list.sdk-secret.dto.ts:
--------------------------------------------------------------------------------
1 | import { PaginatedResponse } from '../../common/paginated.response';
2 | import { SanitizedSdkSecretDto } from './sanitized.sdk-secret.dto';
3 | export class ListSdkSecretDto
4 | implements PaginatedResponse
5 | {
6 | items: SanitizedSdkSecretDto[];
7 | resultCount: number;
8 | hasMore: boolean;
9 | totalCount: number;
10 | }
11 |
--------------------------------------------------------------------------------
/server/src/sdk-secrets/dtos/revoke.sdk-secret.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsBoolean } from 'class-validator';
2 |
3 | export class RevokeSdkSecretDto {
4 | @IsBoolean()
5 | isRevoked: boolean;
6 | }
7 |
--------------------------------------------------------------------------------
/server/src/sdk-secrets/dtos/sanitized.sdk-secret.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsDate, IsString } from 'class-validator';
2 |
3 | export class SanitizedSdkSecretDto {
4 | @IsString()
5 | id: string;
6 |
7 | @IsString()
8 | description: string | null;
9 |
10 | @IsString()
11 | projectId: string;
12 |
13 | @IsString()
14 | preview: string;
15 |
16 | @IsDate()
17 | createdAt: Date;
18 |
19 | @IsDate()
20 | updatedAt: Date;
21 | }
22 |
--------------------------------------------------------------------------------
/server/src/sdk-secrets/sdk-secrets.errors.ts:
--------------------------------------------------------------------------------
1 | export const VerifyIfIsProjectUserErrors = [
2 | 'ProjectNotFound',
3 | 'NotAProjectUser',
4 | ] as const;
5 |
6 | export type VerifyIfIsProjectUserError =
7 | (typeof VerifyIfIsProjectUserErrors)[number];
8 |
--------------------------------------------------------------------------------
/server/src/sdk-secrets/sdk-secrets.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { TelemetryModule } from '../telemetry/telemetry.module';
3 | import { SdkSecretsController } from './sdk-secrets.controller';
4 | import { SdkSecretsService } from './sdk-secrets.service';
5 |
6 | @Module({
7 | imports: [TelemetryModule],
8 | controllers: [SdkSecretsController],
9 | providers: [SdkSecretsService],
10 | exports: [SdkSecretsService],
11 | })
12 | export class SdkSecretsModule {}
13 |
--------------------------------------------------------------------------------
/server/src/telemetry/telemetry.config.ts:
--------------------------------------------------------------------------------
1 | import { Inject } from '@nestjs/common';
2 | import { registerAs } from '@nestjs/config';
3 | import { validateEnv } from 'src/config/validate-env';
4 |
5 | export interface TelemetryConfig {
6 | telemetryKey?: string;
7 | }
8 |
9 | export const telemetryConfig = registerAs(
10 | 'TelemetryConfig',
11 | (): TelemetryConfig => {
12 | const env = validateEnv(process.env);
13 |
14 | return {
15 | telemetryKey: env.SECRET_TELEMETRY_KEY,
16 | };
17 | },
18 | );
19 |
20 | export const InjectTelemetryConfig = () => Inject(telemetryConfig.KEY);
21 |
--------------------------------------------------------------------------------
/server/src/telemetry/telemetry.module.ts:
--------------------------------------------------------------------------------
1 | import { Global, Module } from '@nestjs/common';
2 | import { TelemetryService } from './telemetry.service';
3 |
4 | @Global()
5 | @Module({
6 | providers: [TelemetryService],
7 | exports: [TelemetryService],
8 | })
9 | export class TelemetryModule {}
10 |
--------------------------------------------------------------------------------
/server/src/telemetry/telemetry.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { TelemetryService } from './telemetry.service';
3 |
4 | describe('TelemetryService', () => {
5 | let service: TelemetryService;
6 |
7 | beforeEach(async () => {
8 | const module: TestingModule = await Test.createTestingModule({
9 | providers: [TelemetryService],
10 | }).compile();
11 |
12 | service = module.get(TelemetryService);
13 | });
14 |
15 | it('should be defined', () => {
16 | expect(service).toBeDefined();
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/server/src/telemetry/telemetry.types.ts:
--------------------------------------------------------------------------------
1 | export const TelemetryEvents = [
2 | 'User Logged In',
3 | 'User Created',
4 | 'Project Created',
5 | 'AuthMethod Configured',
6 | 'Demo AuthMethod Configured',
7 | 'Agent Created',
8 | 'Agent Updated',
9 | 'Agent Deleted',
10 | 'SDK Secret Created',
11 | 'Project Backend Connected',
12 | 'Message Sent',
13 | ] as const;
14 | export type TelemetryEvent = (typeof TelemetryEvents)[number];
15 |
--------------------------------------------------------------------------------
/server/src/users/dtos/login.response.dto.ts:
--------------------------------------------------------------------------------
1 | import { SanitizedUserResponseDto } from './sanitized.user.response.dto';
2 |
3 | export class LoginResponseDto {
4 | accessToken: string;
5 | user: SanitizedUserResponseDto;
6 | }
7 |
--------------------------------------------------------------------------------
/server/src/users/dtos/login.user.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsEmail, IsString, MinLength } from 'class-validator';
2 |
3 | export class LoginUserDto {
4 | @IsEmail()
5 | email: string;
6 |
7 | @IsString()
8 | @MinLength(6)
9 | password: string;
10 | }
11 |
--------------------------------------------------------------------------------
/server/src/users/dtos/login.user.response.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsString } from 'class-validator';
2 | import { SanitizedUserResponseDto } from './sanitized.user.response.dto';
3 |
4 | export class LoginUserResponseDto {
5 | @IsString()
6 | accessToken: string;
7 |
8 | user: SanitizedUserResponseDto;
9 | }
10 |
--------------------------------------------------------------------------------
/server/src/users/dtos/oauth.authorize.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsString } from 'class-validator';
2 |
3 | export class oauthUserAuthorizeDto {
4 | @IsString()
5 | code: string;
6 |
7 | @IsString()
8 | state: string;
9 |
10 | @IsString()
11 | redirectUri: string;
12 | }
13 |
--------------------------------------------------------------------------------
/server/src/users/dtos/oauthlogin.user.response.dto.ts:
--------------------------------------------------------------------------------
1 | import { LoginResponseDto } from './login.response.dto';
2 |
3 | export class OAuthLoginUserResponseDto extends LoginResponseDto {
4 | created: boolean;
5 | }
6 |
--------------------------------------------------------------------------------
/server/src/users/dtos/register.user.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsEmail, IsString, MinLength } from 'class-validator';
2 |
3 | export class RegisterUserDto {
4 | @IsEmail()
5 | email: string;
6 |
7 | @IsString()
8 | @MinLength(6)
9 | password: string;
10 |
11 | @IsString()
12 | @MinLength(2)
13 | fullName: string;
14 | }
15 |
--------------------------------------------------------------------------------
/server/src/users/dtos/sanitized.user.response.dto.ts:
--------------------------------------------------------------------------------
1 | import { IsDate, IsEmail, IsString } from 'class-validator';
2 |
3 | export class SanitizedUserResponseDto {
4 | @IsString()
5 | id: string;
6 |
7 | @IsEmail()
8 | email: string;
9 |
10 | @IsString()
11 | fullName: string;
12 |
13 | @IsString()
14 | profilePictureUrl: string | null;
15 |
16 | @IsDate()
17 | verifiedAt: Date | null;
18 | }
19 |
--------------------------------------------------------------------------------
/server/src/users/dtos/user.created.response.dto.ts:
--------------------------------------------------------------------------------
1 | import { SanitizedUserResponseDto } from './sanitized.user.response.dto';
2 |
3 | export class UserCreatedResponseDto extends SanitizedUserResponseDto {}
4 |
--------------------------------------------------------------------------------
/server/src/users/templates/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agentlabs-dev/agentlabs/39eb66fe15d039ffb9ba4e7a4415b97e8ed7c53a/server/src/users/templates/.gitkeep
--------------------------------------------------------------------------------
/server/src/users/users.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { MailerModule } from '../mailer/mailer.module';
3 | import { OauthProvidersModule } from '../oauth-providers/oauth-providers.module';
4 | import { TelemetryModule } from '../telemetry/telemetry.module';
5 | import { UsersController } from './users.controller';
6 | import { UsersService } from './users.service';
7 |
8 | @Module({
9 | providers: [UsersService],
10 | exports: [UsersService],
11 | controllers: [UsersController],
12 | imports: [MailerModule, OauthProvidersModule, TelemetryModule],
13 | })
14 | export class UsersModule {}
15 |
--------------------------------------------------------------------------------
/server/src/users/users.service.errors.ts:
--------------------------------------------------------------------------------
1 | export const RegisterUserErrors = ['UserAlreadyExists'] as const;
2 | export type RegisterUserError = (typeof RegisterUserErrors)[number];
3 |
4 | export const LoginUserErrors = [
5 | 'UserNotFound',
6 | 'InvalidPassword',
7 | 'UserDoesNotHavePasswordHashConfig',
8 | 'UserDoesNotHavePassword',
9 | ] as const;
10 | export type LoginUserError = (typeof LoginUserErrors)[number];
11 |
12 | export const WhoAmIErrors = ['UserNotFound'] as const;
13 | export type WhoAmIError = (typeof WhoAmIErrors)[number];
14 |
15 | export const OAuthLoginErrors = [
16 | 'InvalidRedirectUri',
17 | 'InvalidState',
18 | 'InvalidCode',
19 | 'MissingClientSecret',
20 | 'MissingClientId',
21 | 'UnsupportedOAuthProvider',
22 | 'TokenRequestFailed',
23 | 'ImpossibleToGetUserInfo',
24 | ] as const;
25 |
26 | export type OAuthLoginError = (typeof OAuthLoginErrors)[number];
27 |
--------------------------------------------------------------------------------
/server/src/users/users.types.ts:
--------------------------------------------------------------------------------
1 | import { PasswordHashConfig } from '@prisma/client';
2 | import { JWTPayload } from 'jose';
3 |
4 | export type CreatePasswordHashConfig =
5 | | PasswordHashConfig
6 | | Omit;
7 |
8 | export type AccessTokenPayload = {
9 | sub: string;
10 | };
11 |
12 | export const isAccessTokenPayload = (
13 | payload: JWTPayload,
14 | ): payload is AccessTokenPayload => {
15 | return typeof payload.sub === 'string';
16 | };
17 |
--------------------------------------------------------------------------------
/server/test/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { INestApplication } from '@nestjs/common';
3 | import * as request from 'supertest';
4 | import { AppModule } from './../src/app.module';
5 |
6 | describe('AppController (e2e)', () => {
7 | let app: INestApplication;
8 |
9 | beforeEach(async () => {
10 | const moduleFixture: TestingModule = await Test.createTestingModule({
11 | imports: [AppModule],
12 | }).compile();
13 |
14 | app = moduleFixture.createNestApplication();
15 | await app.init();
16 | });
17 |
18 | it('/ (GET)', () => {
19 | return request(app.getHttpServer())
20 | .get('/')
21 | .expect(200)
22 | .expect('Hello World!');
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/server/test/jest-e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "moduleFileExtensions": ["js", "json", "ts"],
3 | "rootDir": ".",
4 | "testEnvironment": "node",
5 | "testRegex": ".e2e-spec.ts$",
6 | "transform": {
7 | "^.+\\.(t|j)s$": "ts-jest"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/server/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
4 | }
5 |
--------------------------------------------------------------------------------
/server/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "removeComments": true,
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "allowSyntheticDefaultImports": true,
9 | "target": "ES2021",
10 | "sourceMap": true,
11 | "outDir": "./dist",
12 | "baseUrl": "./",
13 | "incremental": true,
14 | "skipLibCheck": true,
15 | "strictNullChecks": true,
16 | "noImplicitAny": true,
17 | "strictBindCallApply": false,
18 | "forceConsistentCasingInFileNames": true,
19 | "noFallthroughCasesInSwitch": false,
20 | }
21 | }
22 |
--------------------------------------------------------------------------------