Start default agent for onboarding folders

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
brennanb2025
2026-05-17 21:21:49 -07:00
co-authored by Orca
parent 956a6a2b03
commit 6dca348325
3 changed files with 86 additions and 2 deletions
@@ -0,0 +1,39 @@
import { describe, expect, it } from 'vitest'
import { getDefaultSettings } from '../../../../shared/constants'
import { buildOnboardingFolderAgentStartup } from './onboarding-folder-agent-startup'
describe('buildOnboardingFolderAgentStartup', () => {
it('queues the persisted default agent with onboarding telemetry', () => {
const startup = buildOnboardingFolderAgentStartup({
...getDefaultSettings('/tmp/orca-workspaces'),
defaultTuiAgent: 'codex'
})
expect(startup).toEqual({
command: 'codex',
telemetry: {
agent_kind: 'codex',
launch_source: 'onboarding',
request_kind: 'new'
}
})
})
it('respects the blank terminal preference', () => {
const startup = buildOnboardingFolderAgentStartup({
...getDefaultSettings('/tmp/orca-workspaces'),
defaultTuiAgent: 'blank'
})
expect(startup).toBeUndefined()
})
it('does not infer an agent from auto mode', () => {
const startup = buildOnboardingFolderAgentStartup({
...getDefaultSettings('/tmp/orca-workspaces'),
defaultTuiAgent: null
})
expect(startup).toBeUndefined()
})
})
@@ -0,0 +1,41 @@
import { buildAgentStartupPlan } from '@/lib/tui-agent-startup'
import { CLIENT_PLATFORM } from '@/lib/new-workspace'
import { tuiAgentToAgentKind } from '@/lib/telemetry'
import type { AgentStartedTelemetry } from '@/lib/worktree-activation'
import type { GlobalSettings } from '../../../../shared/types'
export type OnboardingFolderAgentStartup = {
command: string
env?: Record<string, string>
telemetry: AgentStartedTelemetry
}
export function buildOnboardingFolderAgentStartup(
settings: GlobalSettings | null
): OnboardingFolderAgentStartup | undefined {
const agent = settings?.defaultTuiAgent
if (!settings || !agent || agent === 'blank') {
return undefined
}
const startupPlan = buildAgentStartupPlan({
agent,
prompt: '',
cmdOverrides: settings.agentCmdOverrides ?? {},
platform: CLIENT_PLATFORM,
allowEmptyPromptLaunch: true
})
if (!startupPlan) {
return undefined
}
return {
command: startupPlan.launchCommand,
...(startupPlan.env ? { env: startupPlan.env } : {}),
telemetry: {
agent_kind: tuiAgentToAgentKind(agent),
launch_source: 'onboarding',
request_kind: 'new'
}
}
}
@@ -20,6 +20,7 @@ import {
import { STEPS, type StepNumber } from './use-onboarding-flow-types'
import { persistStep, useCloseWith, usePersistCurrentStep } from './use-onboarding-flow-persistence'
import { callRuntimeRpc, getActiveRuntimeTarget } from '@/runtime/runtime-rpc-client'
import { buildOnboardingFolderAgentStartup } from './onboarding-folder-agent-startup'
export { STEPS } from './use-onboarding-flow-types'
export type { StepId, StepNumber } from './use-onboarding-flow-types'
@@ -268,7 +269,10 @@ export function useOnboardingFlow(
await fetchWorktrees(repoId)
const worktree = useAppStore.getState().worktreesByRepo[repoId]?.[0]
if (worktree) {
activateAndRevealWorktree(worktree.id)
// Why: onboarding asks for a default agent immediately before this step.
// Non-git folders skip the composer, so seed their first terminal here.
const startup = isGit ? undefined : buildOnboardingFolderAgentStartup(settings)
activateAndRevealWorktree(worktree.id, startup ? { startup } : undefined)
}
// Why: next() short-circuits step 4, so emit step_completed here once the
// repo is successfully added to keep the funnel consistent. Gate on
@@ -299,7 +303,7 @@ export function useOnboardingFlow(
})
}
},
[closeWith, consumeStepDurationMs, fetchRepos, fetchWorktrees, openModal]
[closeWith, consumeStepDurationMs, fetchRepos, fetchWorktrees, openModal, settings]
)
const persistCurrentStep = usePersistCurrentStep({