Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,6 @@ logs/
.DS_Store
Thumbs.db
.pnpm-store

# opensrc - source code for packages
opensrc/
23 changes: 23 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,3 +272,26 @@ If you need to log information for debugging purposes:

**Remember: When in doubt, use a static string. No exceptions.**


<!-- opensrc:start -->

## 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 <package> # npm package (e.g., npx opensrc zod)
npx opensrc pypi:<package> # Python package (e.g., npx opensrc pypi:requests)
npx opensrc crates:<package> # Rust crate (e.g., npx opensrc crates:serde)
npx opensrc <owner>/<repo> # GitHub repo (e.g., npx opensrc vercel/ai)
```

<!-- opensrc:end -->
2 changes: 2 additions & 0 deletions app/[owner]/[repo]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand All @@ -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}
Expand Down
5 changes: 5 additions & 0 deletions app/api/tasks/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ export async function POST(request: NextRequest) {
validatedData.selectedModel,
validatedData.installDependencies || false,
validatedData.keepAlive || false,
validatedData.enableBrowser || false,
userApiKeys,
userGithubToken,
githubUser,
Expand All @@ -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
Expand Down Expand Up @@ -301,6 +303,7 @@ async function processTaskWithTimeout(
selectedModel,
installDependencies,
keepAlive,
enableBrowser,
apiKeys,
githubToken,
githubUser,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions app/new/[owner]/[repo]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand All @@ -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}
Expand Down
2 changes: 2 additions & 0 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand All @@ -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}
Expand Down
1 change: 1 addition & 0 deletions components/app-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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: [],
Expand Down
6 changes: 6 additions & 0 deletions components/home-page-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ interface HomePageContentProps {
initialInstallDependencies?: boolean
initialMaxDuration?: number
initialKeepAlive?: boolean
initialEnableBrowser?: boolean
maxSandboxDuration?: number
user?: Session['user'] | null
initialStars?: number
Expand All @@ -35,6 +36,7 @@ export function HomePageContent({
initialInstallDependencies = false,
initialMaxDuration = 300,
initialKeepAlive = false,
initialEnableBrowser = false,
maxSandboxDuration = 300,
user = null,
initialStars = 1200,
Expand Down Expand Up @@ -130,6 +132,7 @@ export function HomePageContent({
installDependencies: boolean
maxDuration: number
keepAlive: boolean
enableBrowser: boolean
}) => {
// Check if user is authenticated
if (!user) {
Expand Down Expand Up @@ -183,6 +186,7 @@ export function HomePageContent({
installDependencies: data.installDependencies,
maxDuration: data.maxDuration,
keepAlive: data.keepAlive,
enableBrowser: data.enableBrowser,
}
})

Expand Down Expand Up @@ -256,6 +260,7 @@ export function HomePageContent({
installDependencies: data.installDependencies,
maxDuration: data.maxDuration,
keepAlive: data.keepAlive,
enableBrowser: data.enableBrowser,
}
})

Expand Down Expand Up @@ -366,6 +371,7 @@ export function HomePageContent({
initialInstallDependencies={initialInstallDependencies}
initialMaxDuration={initialMaxDuration}
initialKeepAlive={initialKeepAlive}
initialEnableBrowser={initialEnableBrowser}
maxSandboxDuration={maxSandboxDuration}
/>
</div>
Expand Down
2 changes: 1 addition & 1 deletion components/home-page-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
15 changes: 7 additions & 8 deletions components/repo-issues.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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' },
Expand Down Expand Up @@ -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',
Expand Down
15 changes: 7 additions & 8 deletions components/repo-pull-requests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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' },
Expand Down Expand Up @@ -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',
Expand Down
15 changes: 7 additions & 8 deletions components/revert-commit-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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' },
Expand Down Expand Up @@ -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',
Expand Down
52 changes: 49 additions & 3 deletions components/task-chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 &&
(() => {
Expand All @@ -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 (
<div className="mt-4">
<div className="text-xs px-2">
<div className="space-y-1">
<div className="text-muted-foreground font-medium mb-2 flex items-center gap-2">
<Loader2 className="h-3 w-3 animate-spin" />
Setting up sandbox...
</div>
<div className="space-y-0.5 pl-5">
{setupLogs.map((log, idx) => {
const isLatest = idx === setupLogs.length - 1
return (
<div
key={idx}
className={`truncate ${
isLatest
? 'text-foreground'
: log.type === 'error'
? 'text-red-500/60'
: log.type === 'success'
? 'text-green-500/60'
: 'text-muted-foreground/60'
}`}
>
{log.message}
</div>
)
})}
</div>
<div className="text-right font-mono text-muted-foreground/50 mt-2">
{formatDuration(lastMessage.createdAt)}
</div>
</div>
</div>
</div>
)
}

// Otherwise show simple awaiting response
return (
<div className="mt-4">
<div className="text-xs text-muted-foreground px-2">
<div className="opacity-50">
<div className="italic">{placeholderText}</div>
<div className="italic flex items-center gap-2">
<Loader2 className="h-3 w-3 animate-spin" />
Awaiting response...
</div>
<div className="text-right font-mono opacity-70 mt-1">
{formatDuration(lastMessage.createdAt)}
</div>
Expand Down
Loading
Loading