Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
181cf3f
Add prototype agents launcher
matthewlouisbrockman Jun 17, 2026
1746cfa
Make terminal launch command editable
matthewlouisbrockman Jun 17, 2026
c3f4da6
Clean up agent naming
matthewlouisbrockman Jun 17, 2026
96116bb
Merge remote-tracking branch 'origin/main' into feat/prototype-agents
matthewlouisbrockman Jun 17, 2026
164b1ba
Remove alternate agent names
matthewlouisbrockman Jun 17, 2026
1720fce
Stabilize sandbox terminal launch target
matthewlouisbrockman Jun 17, 2026
b3d28e0
Add agents page layout config
matthewlouisbrockman Jun 17, 2026
8e469c1
refactor: migrate feature flags to LaunchDarkly
ben-fornefeld Jun 18, 2026
0e26b79
chore: remove PostHog build vars from app env schema
ben-fornefeld Jun 18, 2026
49437d5
chore: keep PostHog build vars in env schema
ben-fornefeld Jun 18, 2026
f9197d8
fix: cache failed LaunchDarkly initialization
ben-fornefeld Jun 18, 2026
6ae9ccd
Merge remote-tracking branch 'origin/pr-434' into feat/prototype-agents
matthewlouisbrockman Jun 18, 2026
dcf6d2d
Gate agents page behind feature flag
matthewlouisbrockman Jun 18, 2026
b284782
Use underscored agents feature flag key
matthewlouisbrockman Jun 18, 2026
1c387c8
Merge main into prototype agents
matthewlouisbrockman Jun 18, 2026
a8a81dd
Disable prefetch for agent start links
matthewlouisbrockman Jun 18, 2026
af1f19f
Merge remote-tracking branch 'origin/main' into feat/prototype-agents
matthewlouisbrockman Jun 18, 2026
88533f0
Merge remote-tracking branch 'origin/main' into feat/prototype-agents
matthewlouisbrockman Jun 18, 2026
225fd43
Use sandbox template identity for terminal launch
matthewlouisbrockman Jun 19, 2026
119c72d
Use sandbox template for terminal sandbox links
matthewlouisbrockman Jun 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ NEXT_PUBLIC_E2B_DOMAIN=e2b.dev
# (Required if NEXT_PUBLIC_INCLUDE_REPORT_ISSUE=1)
# PLAIN_API_KEY=

### LaunchDarkly feature flags
### Use the SDK key for the LaunchDarkly environment selected below.
# LAUNCHDARKLY_SDK_KEY=
# FEATURE_FLAG_ENVIRONMENT=staging

### OTEL Configuration
# OTEL_SERVICE_NAME=
# OTEL_EXPORTER_OTLP_ENDPOINT=
Expand All @@ -74,7 +79,7 @@ NEXT_PUBLIC_E2B_DOMAIN=e2b.dev
### OPTIONAL CLIENT ENVIRONMENT VARIABLES
### =================================

### PostHog analytics and feature flag project key
### PostHog analytics project key
# NEXT_PUBLIC_POSTHOG_KEY=

### PostHog source map upload (build-time only, used by @posthog/nextjs-config).
Expand Down
32 changes: 24 additions & 8 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@
},
"dependencies": {
"@hookform/resolvers": "^5.2.2",
"@launchdarkly/node-server-sdk": "^9.11.2",
"@launchdarkly/openfeature-node-server": "^1.2.0",
"@next/env": "^16.2.7",
"@openfeature/server-sdk": "^1.22.0",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/auto-instrumentations-node": "^0.77.0",
"@opentelemetry/exporter-logs-otlp-http": "^0.203.0",
Expand Down Expand Up @@ -117,7 +120,6 @@
"pathe": "^2.0.3",
"pino": "^9.7.0",
"posthog-js": "^1.268.1",
"posthog-node": "^5.38.0",
"react": "19.2.4",
"react-day-picker": "^9.9.0",
"react-dom": "19.2.4",
Expand Down
14 changes: 14 additions & 0 deletions scripts/check-app-env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,19 @@ const schema = appEnvSchema
path: ['PLAIN_API_KEY'],
}
)
.refine(
(data) => {
if (data.LAUNCHDARKLY_SDK_KEY) {
return !!data.FEATURE_FLAG_ENVIRONMENT
}

return true
},
{
message:
'LAUNCHDARKLY_SDK_KEY is set, but FEATURE_FLAG_ENVIRONMENT is missing',
path: ['FEATURE_FLAG_ENVIRONMENT'],
}
)

validateEnv(schema)
64 changes: 64 additions & 0 deletions src/app/dashboard/[teamSlug]/agents/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import type { Metadata } from 'next'
import { notFound, redirect } from 'next/navigation'
import { AUTH_URLS } from '@/configs/urls'
import { featureFlags } from '@/core/modules/feature-flags/feature-flags.server'
import { getAuthContext } from '@/core/server/auth'
import { getTeamIdFromSlug } from '@/core/server/functions/team/get-team-id-from-slug'
import { AgentsList } from '@/features/dashboard/agents/agents-list'
import { AGENT_TEMPLATES } from '@/features/dashboard/agents/config'
import { Page } from '@/features/dashboard/layouts/page'

export const metadata: Metadata = {
title: 'Agents - E2B',
}

type AgentsPageProps = {
params: Promise<{
teamSlug: string
}>
}

export default async function AgentsPage({ params }: AgentsPageProps) {
const [{ teamSlug }, authContext] = await Promise.all([
params,
getAuthContext(),
])

if (!authContext) {
redirect(AUTH_URLS.SIGN_IN)
}

const teamId = await getTeamIdFromSlug(teamSlug, authContext.accessToken)

if (!teamId.ok || !teamId.data) {
notFound()
}

const agentsEnabled = await featureFlags.isEnabled('agentsEnabled', {
user: {
id: authContext.user.id,
email: authContext.user.email ?? undefined,
},
team: {
id: teamId.data,
slug: teamSlug,
},
})

if (!agentsEnabled) {
notFound()
}

return (
<Page className="flex flex-col gap-4">
<div className="flex flex-col gap-1">
<h2 className="prose-title text-fg">Agents</h2>
<p className="prose-body text-fg-tertiary max-w-2xl">
Start a coding-agent sandbox and open it in the dashboard terminal.
</p>
</div>

<AgentsList agents={AGENT_TEMPLATES} />
</Page>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,18 @@ interface SandboxTerminalPageProps {
params: Promise<{
teamSlug: string
}>
searchParams: Promise<{
command?: string
template?: string
}>
}

export default async function SandboxTerminalPage({
params,
searchParams,
}: SandboxTerminalPageProps) {
const [{ teamSlug }, authContext] = await Promise.all([
params,
getAuthContext(),
])
const [{ teamSlug }, { command = '', template }, authContext] =
await Promise.all([params, searchParams, getAuthContext()])

if (!authContext) {
redirect(AUTH_URLS.SIGN_IN)
Expand All @@ -33,10 +36,12 @@ export default async function SandboxTerminalPage({

return (
<SandboxTerminalView
command={command}
sandboxManagementAuth={createSandboxManagementAuth(
authContext,
teamId.data
)}
template={template}
Comment thread
matthewlouisbrockman marked this conversation as resolved.
Outdated
/>
)
}
Loading
Loading