diff --git a/.gitignore b/.gitignore index ba0b02e8..6f2518da 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,6 @@ logs/ .DS_Store Thumbs.db .pnpm-store + +# opensrc - source code for packages +opensrc/ diff --git a/AGENTS.md b/AGENTS.md index 51e82079..b215e26a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -272,3 +272,26 @@ If you need to log information for debugging purposes: **Remember: When in doubt, use a static string. No exceptions.** + + + +## Source Code Reference + +Source code for dependencies is available in `opensrc/` for deeper understanding of implementation details. + +See `opensrc/sources.json` for the list of available packages and their versions. + +Use this source code when you need to understand how a package works internally, not just its types/interface. + +### Fetching Additional Source Code + +To fetch source code for a package or repository you need to understand, run: + +```bash +npx opensrc # npm package (e.g., npx opensrc zod) +npx opensrc pypi: # Python package (e.g., npx opensrc pypi:requests) +npx opensrc crates: # Rust crate (e.g., npx opensrc crates:serde) +npx opensrc / # GitHub repo (e.g., npx opensrc vercel/ai) +``` + + \ No newline at end of file diff --git a/app/[owner]/[repo]/page.tsx b/app/[owner]/[repo]/page.tsx index 96d3bbaf..6ddfae36 100644 --- a/app/[owner]/[repo]/page.tsx +++ b/app/[owner]/[repo]/page.tsx @@ -17,6 +17,7 @@ export default async function OwnerRepoPage({ params }: OwnerRepoPageProps) { const cookieStore = await cookies() const installDependencies = cookieStore.get('install-dependencies')?.value === 'true' const keepAlive = cookieStore.get('keep-alive')?.value === 'true' + const enableBrowser = cookieStore.get('enable-browser')?.value === 'true' const session = await getServerSession() @@ -33,6 +34,7 @@ export default async function OwnerRepoPage({ params }: OwnerRepoPageProps) { initialInstallDependencies={installDependencies} initialMaxDuration={maxDuration} initialKeepAlive={keepAlive} + initialEnableBrowser={enableBrowser} maxSandboxDuration={maxSandboxDuration} user={session?.user ?? null} initialStars={stars} diff --git a/app/api/tasks/route.ts b/app/api/tasks/route.ts index 45e82d89..2473fef3 100644 --- a/app/api/tasks/route.ts +++ b/app/api/tasks/route.ts @@ -231,6 +231,7 @@ export async function POST(request: NextRequest) { validatedData.selectedModel, validatedData.installDependencies || false, validatedData.keepAlive || false, + validatedData.enableBrowser || false, userApiKeys, userGithubToken, githubUser, @@ -257,6 +258,7 @@ async function processTaskWithTimeout( selectedModel?: string, installDependencies: boolean = false, keepAlive: boolean = false, + enableBrowser: boolean = false, apiKeys?: { OPENAI_API_KEY?: string GEMINI_API_KEY?: string @@ -301,6 +303,7 @@ async function processTaskWithTimeout( selectedModel, installDependencies, keepAlive, + enableBrowser, apiKeys, githubToken, githubUser, @@ -369,6 +372,7 @@ async function processTask( selectedModel?: string, installDependencies: boolean = false, keepAlive: boolean = false, + enableBrowser: boolean = false, apiKeys?: { OPENAI_API_KEY?: string GEMINI_API_KEY?: string @@ -458,6 +462,7 @@ async function processTask( selectedModel, installDependencies, keepAlive, + enableBrowser, preDeterminedBranchName: aiBranchName || undefined, onProgress: async (progress: number, message: string) => { // Use real-time logger for progress updates diff --git a/app/new/[owner]/[repo]/page.tsx b/app/new/[owner]/[repo]/page.tsx index ce3b1daf..94f85ed1 100644 --- a/app/new/[owner]/[repo]/page.tsx +++ b/app/new/[owner]/[repo]/page.tsx @@ -17,6 +17,7 @@ export default async function NewRepoPage({ params }: NewRepoPageProps) { const cookieStore = await cookies() const installDependencies = cookieStore.get('install-dependencies')?.value === 'true' const keepAlive = cookieStore.get('keep-alive')?.value === 'true' + const enableBrowser = cookieStore.get('enable-browser')?.value === 'true' const session = await getServerSession() @@ -33,6 +34,7 @@ export default async function NewRepoPage({ params }: NewRepoPageProps) { initialInstallDependencies={installDependencies} initialMaxDuration={maxDuration} initialKeepAlive={keepAlive} + initialEnableBrowser={enableBrowser} maxSandboxDuration={maxSandboxDuration} user={session?.user ?? null} initialStars={stars} diff --git a/app/page.tsx b/app/page.tsx index 137899a3..13a27da9 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -10,6 +10,7 @@ export default async function Home() { const selectedRepo = cookieStore.get('selected-repo')?.value || '' const installDependencies = cookieStore.get('install-dependencies')?.value === 'true' const keepAlive = cookieStore.get('keep-alive')?.value === 'true' + const enableBrowser = cookieStore.get('enable-browser')?.value === 'true' const session = await getServerSession() @@ -26,6 +27,7 @@ export default async function Home() { initialInstallDependencies={installDependencies} initialMaxDuration={maxDuration} initialKeepAlive={keepAlive} + initialEnableBrowser={enableBrowser} maxSandboxDuration={maxSandboxDuration} user={session?.user ?? null} initialStars={stars} diff --git a/components/app-layout.tsx b/components/app-layout.tsx index 991c27d9..7782f8a0 100644 --- a/components/app-layout.tsx +++ b/components/app-layout.tsx @@ -227,6 +227,7 @@ export function AppLayout({ children, initialSidebarWidth, initialSidebarOpen, i installDependencies: taskData.installDependencies, maxDuration: taskData.maxDuration, keepAlive: false, + enableBrowser: false, status: 'pending', progress: 0, logs: [], diff --git a/components/home-page-content.tsx b/components/home-page-content.tsx index 72843b26..07f87cc9 100644 --- a/components/home-page-content.tsx +++ b/components/home-page-content.tsx @@ -24,6 +24,7 @@ interface HomePageContentProps { initialInstallDependencies?: boolean initialMaxDuration?: number initialKeepAlive?: boolean + initialEnableBrowser?: boolean maxSandboxDuration?: number user?: Session['user'] | null initialStars?: number @@ -35,6 +36,7 @@ export function HomePageContent({ initialInstallDependencies = false, initialMaxDuration = 300, initialKeepAlive = false, + initialEnableBrowser = false, maxSandboxDuration = 300, user = null, initialStars = 1200, @@ -130,6 +132,7 @@ export function HomePageContent({ installDependencies: boolean maxDuration: number keepAlive: boolean + enableBrowser: boolean }) => { // Check if user is authenticated if (!user) { @@ -183,6 +186,7 @@ export function HomePageContent({ installDependencies: data.installDependencies, maxDuration: data.maxDuration, keepAlive: data.keepAlive, + enableBrowser: data.enableBrowser, } }) @@ -256,6 +260,7 @@ export function HomePageContent({ installDependencies: data.installDependencies, maxDuration: data.maxDuration, keepAlive: data.keepAlive, + enableBrowser: data.enableBrowser, } }) @@ -366,6 +371,7 @@ export function HomePageContent({ initialInstallDependencies={initialInstallDependencies} initialMaxDuration={initialMaxDuration} initialKeepAlive={initialKeepAlive} + initialEnableBrowser={initialEnableBrowser} maxSandboxDuration={maxSandboxDuration} /> diff --git a/components/home-page-header.tsx b/components/home-page-header.tsx index 2f547343..b6529d80 100644 --- a/components/home-page-header.tsx +++ b/components/home-page-header.tsx @@ -158,7 +158,7 @@ export function HomePageHeader({ prompt: 'Work on this repository', repoUrl: repoUrl, selectedAgent: localStorage.getItem('last-selected-agent') || 'claude', - selectedModel: localStorage.getItem('last-selected-model-claude') || 'claude-sonnet-4-5-20250929', + selectedModel: localStorage.getItem('last-selected-model-claude') || 'claude-sonnet-4-5', installDependencies: true, maxDuration: 300, keepAlive: false, diff --git a/components/repo-issues.tsx b/components/repo-issues.tsx index 75b1dfff..39559185 100644 --- a/components/repo-issues.tsx +++ b/components/repo-issues.tsx @@ -39,10 +39,9 @@ const CODING_AGENTS = [ const AGENT_MODELS = { claude: [ - { value: 'claude-sonnet-4-5-20250929', label: 'Sonnet 4.5' }, - { value: 'claude-haiku-4-5-20251001', label: 'Haiku 4.5' }, - { value: 'claude-opus-4-1-20250805', label: 'Opus 4.1' }, - { value: 'claude-sonnet-4-20250514', label: 'Sonnet 4' }, + { value: 'claude-sonnet-4-5', label: 'Sonnet 4.5' }, + { value: 'claude-opus-4-5', label: 'Opus 4.5' }, + { value: 'claude-haiku-4-5', label: 'Haiku 4.5' }, ], codex: [ { value: 'openai/gpt-5.1', label: 'GPT-5.1' }, @@ -81,14 +80,14 @@ const AGENT_MODELS = { { value: 'gpt-5-mini', label: 'GPT-5 mini' }, { value: 'gpt-5-nano', label: 'GPT-5 nano' }, { value: 'gpt-4.1', label: 'GPT-4.1' }, - { value: 'claude-sonnet-4-5-20250929', label: 'Sonnet 4.5' }, - { value: 'claude-sonnet-4-20250514', label: 'Sonnet 4' }, - { value: 'claude-opus-4-1-20250805', label: 'Opus 4.1' }, + { value: 'claude-sonnet-4-5', label: 'Sonnet 4.5' }, + { value: 'claude-opus-4-5', label: 'Opus 4.5' }, + { value: 'claude-haiku-4-5', label: 'Haiku 4.5' }, ], } as const const DEFAULT_MODELS = { - claude: 'claude-sonnet-4-5-20250929', + claude: 'claude-sonnet-4-5', codex: 'openai/gpt-5.1', copilot: 'claude-sonnet-4.5', cursor: 'auto', diff --git a/components/repo-pull-requests.tsx b/components/repo-pull-requests.tsx index b8868199..a751ae6c 100644 --- a/components/repo-pull-requests.tsx +++ b/components/repo-pull-requests.tsx @@ -47,10 +47,9 @@ const CODING_AGENTS = [ const AGENT_MODELS = { claude: [ - { value: 'claude-sonnet-4-5-20250929', label: 'Sonnet 4.5' }, - { value: 'claude-haiku-4-5-20251001', label: 'Haiku 4.5' }, - { value: 'claude-opus-4-1-20250805', label: 'Opus 4.1' }, - { value: 'claude-sonnet-4-20250514', label: 'Sonnet 4' }, + { value: 'claude-sonnet-4-5', label: 'Sonnet 4.5' }, + { value: 'claude-opus-4-5', label: 'Opus 4.5' }, + { value: 'claude-haiku-4-5', label: 'Haiku 4.5' }, ], codex: [ { value: 'openai/gpt-5.1', label: 'GPT-5.1' }, @@ -89,14 +88,14 @@ const AGENT_MODELS = { { value: 'gpt-5-mini', label: 'GPT-5 mini' }, { value: 'gpt-5-nano', label: 'GPT-5 nano' }, { value: 'gpt-4.1', label: 'GPT-4.1' }, - { value: 'claude-sonnet-4-5-20250929', label: 'Sonnet 4.5' }, - { value: 'claude-sonnet-4-20250514', label: 'Sonnet 4' }, - { value: 'claude-opus-4-1-20250805', label: 'Opus 4.1' }, + { value: 'claude-sonnet-4-5', label: 'Sonnet 4.5' }, + { value: 'claude-opus-4-5', label: 'Opus 4.5' }, + { value: 'claude-haiku-4-5', label: 'Haiku 4.5' }, ], } as const const DEFAULT_MODELS = { - claude: 'claude-sonnet-4-5-20250929', + claude: 'claude-sonnet-4-5', codex: 'openai/gpt-5.1', copilot: 'claude-sonnet-4.5', cursor: 'auto', diff --git a/components/revert-commit-dialog.tsx b/components/revert-commit-dialog.tsx index 32285e95..702cf528 100644 --- a/components/revert-commit-dialog.tsx +++ b/components/revert-commit-dialog.tsx @@ -61,10 +61,9 @@ const CODING_AGENTS = [ const AGENT_MODELS = { claude: [ - { value: 'claude-sonnet-4-5-20250929', label: 'Sonnet 4.5' }, - { value: 'claude-haiku-4-5-20251001', label: 'Haiku 4.5' }, - { value: 'claude-opus-4-1-20250805', label: 'Opus 4.1' }, - { value: 'claude-sonnet-4-20250514', label: 'Sonnet 4' }, + { value: 'claude-sonnet-4-5', label: 'Sonnet 4.5' }, + { value: 'claude-opus-4-5', label: 'Opus 4.5' }, + { value: 'claude-haiku-4-5', label: 'Haiku 4.5' }, ], codex: [ { value: 'openai/gpt-5', label: 'GPT-5' }, @@ -99,14 +98,14 @@ const AGENT_MODELS = { { value: 'gpt-5-mini', label: 'GPT-5 Mini' }, { value: 'gpt-5-nano', label: 'GPT-5 Nano' }, { value: 'gpt-4.1', label: 'GPT-4.1' }, - { value: 'claude-sonnet-4-5-20250929', label: 'Sonnet 4.5' }, - { value: 'claude-sonnet-4-20250514', label: 'Sonnet 4' }, - { value: 'claude-opus-4-1-20250805', label: 'Opus 4.1' }, + { value: 'claude-sonnet-4-5', label: 'Sonnet 4.5' }, + { value: 'claude-opus-4-5', label: 'Opus 4.5' }, + { value: 'claude-haiku-4-5', label: 'Haiku 4.5' }, ], } as const const DEFAULT_MODELS = { - claude: 'claude-sonnet-4-5-20250929', + claude: 'claude-sonnet-4-5', codex: 'openai/gpt-5.1', copilot: 'claude-sonnet-4.5', cursor: 'auto', diff --git a/components/task-chat.tsx b/components/task-chat.tsx index 0e405a04..bff2042a 100644 --- a/components/task-chat.tsx +++ b/components/task-chat.tsx @@ -1144,7 +1144,7 @@ export function TaskChat({ taskId, task }: TaskChatProps) { ) })} - {/* Show "Awaiting response..." or "Awaiting response..." if task is processing and latest message is from user without response */} + {/* Show sandbox setup progress or "Awaiting response..." if task is processing and latest message is from user without response */} {(task.status === 'processing' || task.status === 'pending') && displayMessages.length > 0 && (() => { @@ -1154,13 +1154,59 @@ export function TaskChat({ taskId, task }: TaskChatProps) { // Check if this is the first user message (sandbox initialization) const userMessages = displayMessages.filter((m) => m.role === 'user') const isFirstMessage = userMessages.length === 1 - const placeholderText = isFirstMessage ? 'Awaiting response...' : 'Awaiting response...' + // Get the latest logs to show progress (filter out server logs) + const setupLogs = (task.logs || []).filter((log) => !log.message.startsWith('[SERVER]')).slice(-8) // Show last 8 logs + + // If first message and we have logs, show sandbox setup progress + if (isFirstMessage && setupLogs.length > 0) { + return ( +
+
+
+
+ + Setting up sandbox... +
+
+ {setupLogs.map((log, idx) => { + const isLatest = idx === setupLogs.length - 1 + return ( +
+ {log.message} +
+ ) + })} +
+
+ {formatDuration(lastMessage.createdAt)} +
+
+
+
+ ) + } + + // Otherwise show simple awaiting response return (
-
{placeholderText}
+
+ + Awaiting response... +
{formatDuration(lastMessage.createdAt)}
diff --git a/components/task-details.tsx b/components/task-details.tsx index 5b1b2c4f..246a0066 100644 --- a/components/task-details.tsx +++ b/components/task-details.tsx @@ -110,10 +110,9 @@ const CODING_AGENTS = [ const AGENT_MODELS = { claude: [ - { value: 'claude-sonnet-4-5-20250929', label: 'Sonnet 4.5' }, - { value: 'claude-haiku-4-5-20251001', label: 'Haiku 4.5' }, - { value: 'claude-opus-4-1-20250805', label: 'Opus 4.1' }, - { value: 'claude-sonnet-4-20250514', label: 'Sonnet 4' }, + { value: 'claude-sonnet-4-5', label: 'Sonnet 4.5' }, + { value: 'claude-opus-4-5', label: 'Opus 4.5' }, + { value: 'claude-haiku-4-5', label: 'Haiku 4.5' }, ], codex: [ { value: 'openai/gpt-5.1', label: 'GPT-5.1' }, @@ -152,14 +151,14 @@ const AGENT_MODELS = { { value: 'gpt-5-mini', label: 'GPT-5 Mini' }, { value: 'gpt-5-nano', label: 'GPT-5 Nano' }, { value: 'gpt-4.1', label: 'GPT-4.1' }, - { value: 'claude-sonnet-4-5-20250929', label: 'Sonnet 4.5' }, - { value: 'claude-sonnet-4-20250514', label: 'Sonnet 4' }, - { value: 'claude-opus-4-1-20250805', label: 'Opus 4.1' }, + { value: 'claude-sonnet-4-5', label: 'Sonnet 4.5' }, + { value: 'claude-opus-4-5', label: 'Opus 4.5' }, + { value: 'claude-haiku-4-5', label: 'Haiku 4.5' }, ], } as const const DEFAULT_MODELS = { - claude: 'claude-sonnet-4-5-20250929', + claude: 'claude-sonnet-4-5', codex: 'openai/gpt-5.1', copilot: 'claude-sonnet-4.5', cursor: 'auto', @@ -186,6 +185,7 @@ export function TaskDetails({ task, maxSandboxDuration = 300 }: TaskDetailsProps const [tryAgainInstallDeps, setTryAgainInstallDeps] = useState(task.installDependencies || false) const [tryAgainMaxDuration, setTryAgainMaxDuration] = useState(task.maxDuration || maxSandboxDuration) const [tryAgainKeepAlive, setTryAgainKeepAlive] = useState(task.keepAlive || false) + const [tryAgainEnableBrowser, setTryAgainEnableBrowser] = useState(task.enableBrowser || false) const [deploymentUrl, setDeploymentUrl] = useState(task.previewUrl || null) const [loadingDeployment, setLoadingDeployment] = useState(false) const [showPRDialog, setShowPRDialog] = useState(false) @@ -680,10 +680,9 @@ export function TaskDetails({ task, maxSandboxDuration = 300 }: TaskDetailsProps // Model mappings for all agents const AGENT_MODELS: Record> = { claude: [ - { value: 'claude-sonnet-4-5-20250929', label: 'Sonnet 4.5' }, - { value: 'claude-haiku-4-5-20251001', label: 'Haiku 4.5' }, - { value: 'claude-opus-4-1-20250805', label: 'Opus 4.1' }, - { value: 'claude-sonnet-4-20250514', label: 'Sonnet 4' }, + { value: 'claude-sonnet-4-5', label: 'Sonnet 4.5' }, + { value: 'claude-opus-4-5', label: 'Opus 4.5' }, + { value: 'claude-haiku-4-5', label: 'Haiku 4.5' }, ], codex: [ { value: 'openai/gpt-5', label: 'GPT-5' }, @@ -718,9 +717,9 @@ export function TaskDetails({ task, maxSandboxDuration = 300 }: TaskDetailsProps { value: 'gpt-5-mini', label: 'GPT-5 mini' }, { value: 'gpt-5-nano', label: 'GPT-5 nano' }, { value: 'gpt-4.1', label: 'GPT-4.1' }, - { value: 'claude-sonnet-4-5-20250929', label: 'Sonnet 4.5' }, - { value: 'claude-sonnet-4-20250514', label: 'Sonnet 4' }, - { value: 'claude-opus-4-1-20250805', label: 'Opus 4.1' }, + { value: 'claude-sonnet-4-5', label: 'Sonnet 4.5' }, + { value: 'claude-opus-4-5', label: 'Opus 4.5' }, + { value: 'claude-haiku-4-5', label: 'Haiku 4.5' }, ], } @@ -1209,6 +1208,7 @@ export function TaskDetails({ task, maxSandboxDuration = 300 }: TaskDetailsProps installDependencies: tryAgainInstallDeps, maxDuration: tryAgainMaxDuration, keepAlive: tryAgainKeepAlive, + enableBrowser: tryAgainEnableBrowser, }), }) @@ -1928,8 +1928,23 @@ export function TaskDetails({ task, maxSandboxDuration = 300 }: TaskDetailsProps + {task.sandboxUrl && ( + <> + window.open(task.sandboxUrl!, '_blank')}> + Open in New Tab + + { + navigator.clipboard.writeText(task.sandboxUrl!) + }} + > + Copy URL + + + )} {task.keepAlive && ( <> + {task.sandboxUrl && } {sandboxHealth === 'stopped' || !task.sandboxUrl ? ( {isStartingSandbox ? ( @@ -1956,16 +1971,19 @@ export function TaskDetails({ task, maxSandboxDuration = 300 }: TaskDetailsProps )} {sandboxHealth === 'running' && ( - - {isRestartingDevServer ? ( - <> - - Restarting... - - ) : ( - 'Restart Dev Server' - )} - + <> + {(task.sandboxUrl || task.keepAlive) && } + + {isRestartingDevServer ? ( + <> + + Restarting... + + ) : ( + 'Restart Dev Server' + )} + + )} @@ -2160,8 +2178,23 @@ export function TaskDetails({ task, maxSandboxDuration = 300 }: TaskDetailsProps + {task.sandboxUrl && ( + <> + window.open(task.sandboxUrl!, '_blank')}> + Open in New Tab + + { + navigator.clipboard.writeText(task.sandboxUrl!) + }} + > + Copy URL + + + )} {task.keepAlive && ( <> + {task.sandboxUrl && } {task.sandboxUrl ? ( {isStoppingSandbox ? ( @@ -2187,19 +2220,21 @@ export function TaskDetails({ task, maxSandboxDuration = 300 }: TaskDetailsProps )} )} - - {isRestartingDevServer ? ( - <> - - Restarting... - - ) : ( - 'Restart Dev Server' - )} - + {task.sandboxUrl && ( + <> + {task.keepAlive && } + + {isRestartingDevServer ? ( + <> + + Restarting... + + ) : ( + 'Restart Dev Server' + )} + + + )}
@@ -2498,6 +2533,20 @@ export function TaskDetails({ task, maxSandboxDuration = 300 }: TaskDetailsProps Keep Alive ({maxSandboxDuration} minutes max)
+ +
+ setTryAgainEnableBrowser(!!checked)} + /> + +
diff --git a/components/task-form.tsx b/components/task-form.tsx index 4567f987..375f9e95 100644 --- a/components/task-form.tsx +++ b/components/task-form.tsx @@ -15,9 +15,9 @@ import { DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip' -import { Loader2, ArrowUp, Settings, X, Cable, Users } from 'lucide-react' +import { Loader2, ArrowUp, Settings, X, Cable, Users, Globe } from 'lucide-react' import { Claude, Codex, Copilot, Cursor, Gemini, OpenCode } from '@/components/logos' -import { setInstallDependencies, setMaxDuration, setKeepAlive } from '@/lib/utils/cookies' +import { setInstallDependencies, setMaxDuration, setKeepAlive, setEnableBrowser } from '@/lib/utils/cookies' import { useConnectors } from '@/components/connectors-provider' import { ConnectorDialog } from '@/components/connectors/manage-connectors' import { toast } from 'sonner' @@ -46,6 +46,7 @@ interface TaskFormProps { installDependencies: boolean maxDuration: number keepAlive: boolean + enableBrowser: boolean }) => void isSubmitting: boolean selectedOwner: string @@ -53,6 +54,7 @@ interface TaskFormProps { initialInstallDependencies?: boolean initialMaxDuration?: number initialKeepAlive?: boolean + initialEnableBrowser?: boolean maxSandboxDuration?: number } @@ -70,11 +72,9 @@ const CODING_AGENTS = [ // Model options for each agent const AGENT_MODELS = { claude: [ - { value: 'claude-sonnet-4-5-20250929', label: 'Sonnet 4.5' }, - { value: 'claude-opus-4-5-20250201', label: 'Opus 4.5' }, - { value: 'claude-haiku-4-5-20251001', label: 'Haiku 4.5' }, - { value: 'claude-opus-4-1-20250805', label: 'Opus 4.1' }, - { value: 'claude-sonnet-4-20250514', label: 'Sonnet 4' }, + { value: 'claude-sonnet-4-5', label: 'Sonnet 4.5' }, + { value: 'claude-opus-4-5', label: 'Opus 4.5' }, + { value: 'claude-haiku-4-5', label: 'Haiku 4.5' }, ], codex: [ { value: 'openai/gpt-5.1', label: 'GPT-5.1' }, @@ -114,15 +114,15 @@ const AGENT_MODELS = { { value: 'gpt-5-mini', label: 'GPT-5 mini' }, { value: 'gpt-5-nano', label: 'GPT-5 nano' }, { value: 'gpt-4.1', label: 'GPT-4.1' }, - { value: 'claude-sonnet-4-5-20250929', label: 'Sonnet 4.5' }, - { value: 'claude-sonnet-4-20250514', label: 'Sonnet 4' }, - { value: 'claude-opus-4-1-20250805', label: 'Opus 4.1' }, + { value: 'claude-sonnet-4-5', label: 'Sonnet 4.5' }, + { value: 'claude-opus-4-5', label: 'Opus 4.5' }, + { value: 'claude-haiku-4-5', label: 'Haiku 4.5' }, ], } as const // Default models for each agent const DEFAULT_MODELS = { - claude: 'claude-sonnet-4-5-20250929', + claude: 'claude-sonnet-4-5', codex: 'openai/gpt-5.1', copilot: 'claude-sonnet-4.5', cursor: 'auto', @@ -164,6 +164,7 @@ export function TaskForm({ initialInstallDependencies = false, initialMaxDuration = 300, initialKeepAlive = false, + initialEnableBrowser = false, maxSandboxDuration = 300, }: TaskFormProps) { const [prompt, setPrompt] = useAtom(taskPromptAtom) @@ -178,6 +179,7 @@ export function TaskForm({ const [installDependencies, setInstallDependenciesState] = useState(initialInstallDependencies) const [maxDuration, setMaxDurationState] = useState(initialMaxDuration) const [keepAlive, setKeepAliveState] = useState(initialKeepAlive) + const [enableBrowser, setEnableBrowserState] = useState(initialEnableBrowser) const [showMcpServersDialog, setShowMcpServersDialog] = useState(false) // Connectors state @@ -202,6 +204,11 @@ export function TaskForm({ setKeepAlive(value) } + const updateEnableBrowser = (value: boolean) => { + setEnableBrowserState(value) + setEnableBrowser(value) + } + // Handle keyboard events in textarea const handleTextareaKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { @@ -339,6 +346,7 @@ export function TaskForm({ installDependencies, maxDuration, keepAlive, + enableBrowser, }) return } @@ -383,6 +391,7 @@ export function TaskForm({ installDependencies, maxDuration, keepAlive, + enableBrowser, }) } @@ -605,6 +614,26 @@ export function TaskForm({ {/* Buttons */}
+ + + + + +

Agent Browser

+
+
+