diff --git a/src/renderer/src/components/onboarding/AgentFeatureSetupStep.test.tsx b/src/renderer/src/components/onboarding/AgentFeatureSetupStep.test.tsx index 8a11419d6..93a4033b2 100644 --- a/src/renderer/src/components/onboarding/AgentFeatureSetupStep.test.tsx +++ b/src/renderer/src/components/onboarding/AgentFeatureSetupStep.test.tsx @@ -14,13 +14,15 @@ describe('AgentFeatureSetupStep', () => { onFeatureSetupChange={vi.fn()} featureSetupCommand={null} featureSetupCommandSelection={null} + setupBusyLabel={null} + onStartFeatureSetup={vi.fn()} /> ) - expect(html).toContain('Set up agent features') expect(html).toContain('Agent Browser Use') expect(html).toContain('Computer Use') expect(html).toContain('Agent Orchestration') + expect(html).toContain('Enable capabilities') expect(html).toContain('role="checkbox"') }) }) diff --git a/src/renderer/src/components/onboarding/AgentFeatureSetupStep.tsx b/src/renderer/src/components/onboarding/AgentFeatureSetupStep.tsx index e6f4a3e50..f1afa6e9b 100644 --- a/src/renderer/src/components/onboarding/AgentFeatureSetupStep.tsx +++ b/src/renderer/src/components/onboarding/AgentFeatureSetupStep.tsx @@ -1,23 +1,49 @@ +import { Loader2 } from 'lucide-react' +import { Button } from '@/components/ui/button' import { FeatureSetupChecklist } from './FeatureSetupChecklist' import { FeatureSetupInlineTerminal } from './FeatureSetupInlineTerminal' -import type { OnboardingFeatureSetupSelection } from './onboarding-feature-setup' +import { + hasSelectedOnboardingFeatureSetup, + type OnboardingFeatureSetupSelection +} from './onboarding-feature-setup' type AgentFeatureSetupStepProps = { featureSetup: OnboardingFeatureSetupSelection onFeatureSetupChange: (value: OnboardingFeatureSetupSelection) => void featureSetupCommand: string | null featureSetupCommandSelection: OnboardingFeatureSetupSelection | null + setupBusyLabel: string | null + onStartFeatureSetup: () => void } export function AgentFeatureSetupStep({ featureSetup, onFeatureSetupChange, featureSetupCommand, - featureSetupCommandSelection + featureSetupCommandSelection, + setupBusyLabel, + onStartFeatureSetup }: AgentFeatureSetupStepProps): React.JSX.Element { + const hasSelectedFeatures = hasSelectedOnboardingFeatureSetup(featureSetup) + const showSetupAction = !featureSetupCommand + return ( <> + {showSetupAction ? ( +
+ +
+ ) : null} {featureSetupCommand ? ( { - let canceled = false - const refreshCliNotice = async (): Promise => { - try { - const status = await window.api.cli.getInstallStatus() - if (!canceled) { - setShowCliNotice(!isOrcaCliAvailableOnPath(status)) - } - } catch { - if (!canceled) { - setShowCliNotice(true) - } - } - } - - void refreshCliNotice() - window.addEventListener('focus', refreshCliNotice) - return () => { - canceled = true - window.removeEventListener('focus', refreshCliNotice) - } - }, []) - return ( -
-
-

Set up agent features

-

- Pick the capabilities you want ready after onboarding. Selected features run setup on the - next click and show a terminal here with the skill command ready for review. -

- {showCliNotice ? ( -

- {AGENT_SKILL_CLI_PREREQUISITE_NOTICE} -

- ) : null} -
- +
{FEATURE_SETUP_ROWS.map((row) => { const selected = value[row.id] diff --git a/src/renderer/src/components/onboarding/FeatureSetupInlineTerminal.tsx b/src/renderer/src/components/onboarding/FeatureSetupInlineTerminal.tsx index be5db1acd..b438964b1 100644 --- a/src/renderer/src/components/onboarding/FeatureSetupInlineTerminal.tsx +++ b/src/renderer/src/components/onboarding/FeatureSetupInlineTerminal.tsx @@ -58,6 +58,9 @@ export function FeatureSetupInlineTerminal({ title="Skill setup" ariaLabel="Skill setup command" description="Press Enter to run the command and confirm npx if asked. You can also set this up later in Settings." + terminalHeightPx={180} + terminalTopMarginPx={16} + autoScrollIntoView={false} onOpened={trackTerminalOpened} onInteracted={trackTerminalInteraction} /> diff --git a/src/renderer/src/components/onboarding/OnboardingFlow.test.tsx b/src/renderer/src/components/onboarding/OnboardingFlow.test.tsx index f8dc0bf3a..6eacc14fb 100644 --- a/src/renderer/src/components/onboarding/OnboardingFlow.test.tsx +++ b/src/renderer/src/components/onboarding/OnboardingFlow.test.tsx @@ -30,11 +30,12 @@ describe('OnboardingFlow', () => { /> ) - expect(html).toContain('Interested in Orca's advanced features?') - expect(html).toContain('Take a short tour before getting started.') - expect(html).toContain('Learn how Orca can help you') - expect(html).toContain('Hand off a feature to an orchestrator agent.') - expect(html).toContain('Grab an element from your running app and send it to an agent.') + expect(html).toContain('Explore Orca') + expect(html).toContain('Preview the core workflow.') + expect(html).toContain('Run agents in isolated worktrees.') + expect(html).toContain('Orchestrate agents to finish larger tasks.') + expect(html).toContain('Start tasks from GitHub or Linear.') + expect(html).toContain('Send webpage elements to agents from the Orca browser.') expect(html).not.toContain('Write and preview Markdown.') expect(html).toContain('items-start') expect(html).toContain('text-left') @@ -42,4 +43,23 @@ describe('OnboardingFlow', () => { expect(html).toContain('Skip to project setup') expect(html).not.toContain('Skip the tour') }) + + it('keeps agent setup actions out of the footer', () => { + const html = renderToStaticMarkup( + + ) + + expect(html).toContain('Set up Orca for agents') + expect(html).toContain('Turn on advanced Orca capabilities for agents.') + expect(html).toContain('Enable capabilities') + expect(html).toContain('Continue') + expect(html).toContain('Skip to project setup') + expect(html).not.toContain('>Skip') + }) }) diff --git a/src/renderer/src/components/onboarding/OnboardingFlow.tsx b/src/renderer/src/components/onboarding/OnboardingFlow.tsx index 8ce35e7bc..b04a533df 100644 --- a/src/renderer/src/components/onboarding/OnboardingFlow.tsx +++ b/src/renderer/src/components/onboarding/OnboardingFlow.tsx @@ -31,15 +31,15 @@ const stepCopy = { }, agentSetup: { title: 'Set up Orca for agents', - subtitle: 'Choose the capabilities Orca should enable on this computer.' + subtitle: 'Turn on advanced Orca capabilities for agents.' }, integrations: { title: 'Connect your task sources', subtitle: 'Connect GitHub or Linear to:' }, tour: { - title: "Interested in Orca's advanced features?", - subtitle: 'Take a short tour before getting started.' + title: 'Explore Orca', + subtitle: '' }, repo: { title: 'Point Orca at some code', @@ -72,18 +72,15 @@ export default function OnboardingFlow({ const continueShortcutModifierLabel = getScreenSubmitModifierLabel() const { currentStep, stepIndex, busyLabel } = flow const copy = stepCopy[currentStep.id] - const shouldShowSetupAction = - currentStep.id === 'agentSetup' && - flow.hasSelectedFeatureSetup && - !flow.featureSetupTerminalCommand - const primaryActionLabel = busyLabel ?? (shouldShowSetupAction ? 'Set up' : 'Continue') const isTourStep = currentStep.id === 'tour' const tourStarted = flow.tourStarted const isInlineTourRunning = isTourStep && tourStarted const shouldShowFooter = !isInlineTourRunning const shouldShowSkipToProjectSetup = currentStep.id !== 'repo' const shouldShowStepHeading = !isInlineTourRunning - const footerPrimaryLabel = primaryActionLabel + const shouldShowFooterBusy = Boolean(busyLabel) && currentStep.id !== 'agentSetup' + const footerPrimaryLabel = + currentStep.id === 'agentSetup' ? 'Continue' : (busyLabel ?? 'Continue') const { next: flowNext, openFolder: flowOpenFolder, @@ -138,10 +135,7 @@ export default function OnboardingFlow({ return (
@@ -233,7 +225,12 @@ export default function OnboardingFlow({ {copy.title} {copy.subtitle ? ( -

+

{copy.subtitle}

) : null} @@ -242,8 +239,15 @@ export default function OnboardingFlow({
{currentStep.id === 'agent' && ( @@ -271,6 +275,8 @@ export default function OnboardingFlow({ onFeatureSetupChange={flow.setFeatureSetupSelection} featureSetupCommand={flow.featureSetupTerminalCommand} featureSetupCommandSelection={flow.featureSetupTerminalSelection} + setupBusyLabel={currentStep.id === 'agentSetup' ? busyLabel : null} + onStartFeatureSetup={() => void flow.startFeatureSetup()} /> )} {currentStep.id === 'integrations' && } @@ -305,7 +311,7 @@ export default function OnboardingFlow({
{shouldShowFooter && ( -
+
{shouldShowSkipToProjectSetup ? ( - )} {(currentStep.id !== 'repo' || flow.hasExistingProject) && ( - ~ 60 seconds +
~ 60 seconds
-

- This tour can be seen anytime under Help > Explore Orca. + Available later under Help > Explore Orca.

) diff --git a/src/renderer/src/components/onboarding/use-onboarding-flow-persistence.ts b/src/renderer/src/components/onboarding/use-onboarding-flow-persistence.ts index 327508923..e5ee4e975 100644 --- a/src/renderer/src/components/onboarding/use-onboarding-flow-persistence.ts +++ b/src/renderer/src/components/onboarding/use-onboarding-flow-persistence.ts @@ -128,6 +128,10 @@ export type PersistCurrentStepResult = { featureSetupResult?: OnboardingFeatureSetupResult } +type PersistCurrentStepOptions = { + runFeatureSetup?: boolean +} + export function usePersistCurrentStep({ currentStepId, selectedAgent, @@ -139,97 +143,104 @@ export function usePersistCurrentStep({ onOnboardingChange, setError }: PersistCurrentStepDeps) { - return useCallback(async (): Promise => { - if (!settings) { - return { ok: false } - } - try { - if (currentStepId === 'agent') { - const defaultTuiAgent = selectedAgentOrBlank(selectedAgent) - await updateSettings({ defaultTuiAgent }) - const choseAgent = defaultTuiAgent !== 'blank' - const wasAlreadyChosen = onboardingChecklist.choseAgent - onOnboardingChange( - await persistStep(1, { - checklist: { ...onboardingChecklist, choseAgent } - }) - ) - if (choseAgent && !wasAlreadyChosen) { - track('activation_checklist_item_completed', { - item: 'choseAgent', - time_since_completed_ms: 0 - }) - } - return { ok: true } + return useCallback( + async (options: PersistCurrentStepOptions = {}): Promise => { + if (!settings) { + return { ok: false } } - if (currentStepId === 'theme') { - await updateSettings({ theme }) - onOnboardingChange(await persistStep(2)) - return { ok: true } - } - if (currentStepId === 'notifications') { - await updateSettings({ - notifications: { - ...settings.notifications, - enabled: true, - agentTaskComplete: true, - terminalBell: true - } - }) - onOnboardingChange(await persistStep(3)) - return { ok: true } - } - if (currentStepId === 'agentSetup') { - const setupResult = await runOnboardingFeatureSetup(featureSetupSelection) - const featureSetupResult: OnboardingFeatureSetupResult = setupResult - track('onboarding_feature_setup_run', { - ...onboardingFeatureSetupRunTelemetry(featureSetupSelection, setupResult) - }) - if (hasSelectedOnboardingFeatureSetup(featureSetupSelection)) { - const firstWarning = setupResult.warnings[0] - if (firstWarning) { - toast.warning('Some feature setup needs attention', { - description: firstWarning.message + try { + if (currentStepId === 'agent') { + const defaultTuiAgent = selectedAgentOrBlank(selectedAgent) + await updateSettings({ defaultTuiAgent }) + const choseAgent = defaultTuiAgent !== 'blank' + const wasAlreadyChosen = onboardingChecklist.choseAgent + onOnboardingChange( + await persistStep(1, { + checklist: { ...onboardingChecklist, choseAgent } + }) + ) + if (choseAgent && !wasAlreadyChosen) { + track('activation_checklist_item_completed', { + item: 'choseAgent', + time_since_completed_ms: 0 }) } - if (setupResult.skillCommandsCopied) { - toast.success('Feature setup ready', { - description: 'Skill command copied and inserted below for review.' - }) - } - if (setupResult.computerUsePermissionsOpened) { - toast.message('Opened Computer Use permissions') - } + return { ok: true } } - onOnboardingChange(await persistStep(4)) - return { ok: true, featureSetupResult } + if (currentStepId === 'theme') { + await updateSettings({ theme }) + onOnboardingChange(await persistStep(2)) + return { ok: true } + } + if (currentStepId === 'notifications') { + await updateSettings({ + notifications: { + ...settings.notifications, + enabled: true, + agentTaskComplete: true, + terminalBell: true + } + }) + onOnboardingChange(await persistStep(3)) + return { ok: true } + } + if (currentStepId === 'agentSetup') { + if (!options.runFeatureSetup) { + onOnboardingChange(await persistStep(4)) + return { ok: true } + } + const setupResult = await runOnboardingFeatureSetup(featureSetupSelection) + const featureSetupResult: OnboardingFeatureSetupResult = setupResult + track('onboarding_feature_setup_run', { + ...onboardingFeatureSetupRunTelemetry(featureSetupSelection, setupResult) + }) + if (hasSelectedOnboardingFeatureSetup(featureSetupSelection)) { + const firstWarning = setupResult.warnings[0] + if (firstWarning) { + toast.warning('Some feature setup needs attention', { + description: firstWarning.message + }) + } + if (setupResult.skillCommandsCopied) { + toast.success('Feature setup ready', { + description: 'Skill command copied and inserted below for review.' + }) + } + if (setupResult.computerUsePermissionsOpened) { + toast.message('Opened Computer Use permissions') + } + } + onOnboardingChange(await persistStep(4)) + return { ok: true, featureSetupResult } + } + if (currentStepId === 'integrations') { + // Why: GitHub and Linear connections persist through their own + // store slices when the user actually wires them up. The step itself + // is a no-op for settings/onboarding state beyond marking it + // completed. + onOnboardingChange(await persistStep(5)) + return { ok: true } + } + if (currentStepId === 'tour') { + onOnboardingChange(await persistStep(6)) + return { ok: true } + } + return { ok: false } + } catch (err) { + setError(err instanceof Error ? err.message : String(err)) + return { ok: false } } - if (currentStepId === 'integrations') { - // Why: GitHub and Linear connections persist through their own - // store slices when the user actually wires them up. The step itself - // is a no-op for settings/onboarding state beyond marking it - // completed. - onOnboardingChange(await persistStep(5)) - return { ok: true } - } - if (currentStepId === 'tour') { - onOnboardingChange(await persistStep(6)) - return { ok: true } - } - return { ok: false } - } catch (err) { - setError(err instanceof Error ? err.message : String(err)) - return { ok: false } - } - }, [ - currentStepId, - featureSetupSelection, - onboardingChecklist, - onOnboardingChange, - selectedAgent, - settings, - theme, - updateSettings, - setError - ]) + }, + [ + currentStepId, + featureSetupSelection, + onboardingChecklist, + onOnboardingChange, + selectedAgent, + settings, + theme, + updateSettings, + setError + ] + ) } diff --git a/src/renderer/src/components/onboarding/use-onboarding-flow.ts b/src/renderer/src/components/onboarding/use-onboarding-flow.ts index 0306d16e4..07b28efd8 100644 --- a/src/renderer/src/components/onboarding/use-onboarding-flow.ts +++ b/src/renderer/src/components/onboarding/use-onboarding-flow.ts @@ -466,6 +466,36 @@ export function useOnboardingFlow( // step. A ref flips synchronously so re-entries bail immediately. const nextInFlightRef = useRef(false) const featureSetupStepCompletedTrackedRef = useRef(false) + const trackCurrentStepCompleted = useCallback( + (advancedVia: 'button' | 'keyboard'): void => { + if (currentStep.id === 'agentSetup') { + if (featureSetupStepCompletedTrackedRef.current) { + return + } + // Why: feature setup can keep the user on this already-persisted + // step to review a terminal command; later checklist edits must + // not double-count the same step completion. + featureSetupStepCompletedTrackedRef.current = true + } + const durationMs = consumeStepDurationMs() + track('onboarding_step_completed', { + step: currentStep.stepNumber, + value_kind: currentStep.valueKind, + duration_ms: durationMs, + advanced_via: advancedVia + }) + if (currentStep.id === 'integrations') { + trackTaskSourcesSnapshot('continue', durationMs, advancedVia) + } + }, + [ + consumeStepDurationMs, + currentStep.id, + currentStep.stepNumber, + currentStep.valueKind, + trackTaskSourcesSnapshot + ] + ) const next = useCallback( async (advancedVia: 'button' | 'keyboard' = 'button') => { if (nextInFlightRef.current || busyLabel || currentStep.id === 'repo') { @@ -476,64 +506,69 @@ export function useOnboardingFlow( return } nextInFlightRef.current = true - if (currentStep.id === 'agentSetup' && hasSelectedFeatureSetup) { - setBusyLabel('Setting up features…') - } try { - const trackCurrentStepCompleted = (): void => { - if (currentStep.id === 'agentSetup') { - if (featureSetupStepCompletedTrackedRef.current) { - return - } - // Why: feature setup can keep the user on this already-persisted - // step to review a terminal command; later checklist edits must - // not double-count the same step completion. - featureSetupStepCompletedTrackedRef.current = true - } - const durationMs = consumeStepDurationMs() - track('onboarding_step_completed', { - step: currentStep.stepNumber, - value_kind: currentStep.valueKind, - duration_ms: durationMs, - advanced_via: advancedVia - }) - if (currentStep.id === 'integrations') { - trackTaskSourcesSnapshot('continue', durationMs, advancedVia) - } - } const result = await persistCurrentStep() const nextCommand = result.featureSetupResult?.skillInstallCommand ?? null if (currentStep.id === 'agentSetup' && nextCommand) { - trackCurrentStepCompleted() + trackCurrentStepCompleted(advancedVia) setFeatureSetupTerminalSelection(featureSetupSelection) setFeatureSetupTerminalCommand(nextCommand) return } if (result.ok) { - trackCurrentStepCompleted() + trackCurrentStepCompleted(advancedVia) setStepIndex((idx) => Math.min(idx + 1, STEPS.length - 1)) } } finally { - if (currentStep.id === 'agentSetup') { - setBusyLabel(null) - } nextInFlightRef.current = false } }, [ busyLabel, - consumeStepDurationMs, currentStep.id, - currentStep.stepNumber, - currentStep.valueKind, featureSetupSelection, featureSetupTerminalCommand, - hasSelectedFeatureSetup, persistCurrentStep, - trackTaskSourcesSnapshot + trackCurrentStepCompleted ] ) + const startFeatureSetup = useCallback(async () => { + if ( + nextInFlightRef.current || + busyLabel || + currentStep.id !== 'agentSetup' || + featureSetupTerminalCommand || + !hasSelectedFeatureSetup + ) { + return + } + nextInFlightRef.current = true + setBusyLabel('Setting up features…') + try { + const result = await persistCurrentStep({ runFeatureSetup: true }) + const nextCommand = result.featureSetupResult?.skillInstallCommand ?? null + if (result.ok) { + trackCurrentStepCompleted('button') + } + if (nextCommand) { + setFeatureSetupTerminalSelection(featureSetupSelection) + setFeatureSetupTerminalCommand(nextCommand) + } + } finally { + setBusyLabel(null) + nextInFlightRef.current = false + } + }, [ + busyLabel, + currentStep.id, + featureSetupSelection, + featureSetupTerminalCommand, + hasSelectedFeatureSetup, + persistCurrentStep, + trackCurrentStepCompleted + ]) + const openFolder = useCallback( async (kind: 'git' | 'folder' = 'git') => { // Why: re-entry guard — rapid Cmd+Enter must not launch duplicate pickers. @@ -945,6 +980,7 @@ export function useOnboardingFlow( detectedSet, isDetectingAgents, next, + startFeatureSetup, skipAgentSetup, skipToRepo, startTour, diff --git a/src/renderer/src/components/terminal-quick-commands/terminal-agent-quick-command-presets.test.ts b/src/renderer/src/components/terminal-quick-commands/terminal-agent-quick-command-presets.test.ts index ca59de7e8..09e2a3cdc 100644 --- a/src/renderer/src/components/terminal-quick-commands/terminal-agent-quick-command-presets.test.ts +++ b/src/renderer/src/components/terminal-quick-commands/terminal-agent-quick-command-presets.test.ts @@ -14,7 +14,8 @@ describe('terminal agent quick command presets', () => { gemini: "gemini --prompt-interactive 'your prompt here'", antigravity: "agy --prompt-interactive 'your prompt here'", cursor: "cursor-agent 'your prompt here'", - droid: "droid 'your prompt here'" + droid: "droid 'your prompt here'", + omp: "omp 'your prompt here'" } const promptStartingCommands = Object.keys(TUI_AGENT_CONFIG) diff --git a/src/shared/agents-orchestration-steps.ts b/src/shared/agents-orchestration-steps.ts index c43fbc438..d787874b2 100644 --- a/src/shared/agents-orchestration-steps.ts +++ b/src/shared/agents-orchestration-steps.ts @@ -21,15 +21,13 @@ export const AGENTS_STEPS: readonly AgentsStep[] = [ id: 'statuses', name: 'Visibility', subtitle: 'Agent Visibility', - description: - 'Track every running agent across your workspaces, including who is working, waiting, or needs you.' + description: 'Know which agents are working, waiting, live, or blocked.' }, { id: 'orchestration', name: 'Orchestration', subtitle: 'Orchestration', - description: - 'Enable agents to manage and coordinate Orca workspaces so larger tasks can move to completion.' + description: 'Enable agents to manage and coordinate Orca workspaces to execute larger tasks.' }, { id: 'usage', diff --git a/src/shared/feature-wall-workflows.ts b/src/shared/feature-wall-workflows.ts index 87c11b3c1..79791dff5 100644 --- a/src/shared/feature-wall-workflows.ts +++ b/src/shared/feature-wall-workflows.ts @@ -27,7 +27,7 @@ export const FEATURE_WALL_WORKFLOWS: readonly FeatureWallWorkflow[] = [ id: 'workspaces', title: 'Workspaces', meta: 'Isolated work · Context kept together', - lede: 'Workspaces let you quickly split tasks into isolated environments, so multiple agents can work side by side without interfering with each other. Each workspace has its own branch, terminal, and agent state, keeping parallel work organized.', + lede: 'Orca splits each task into an isolated workspace so agents can run in parallel.', primaryTileId: 'tile-01', relatedTileIds: ['tile-10'], docsUrl: 'https://www.onorca.dev/docs/model/worktrees' @@ -36,7 +36,7 @@ export const FEATURE_WALL_WORKFLOWS: readonly FeatureWallWorkflow[] = [ id: 'tasks', title: 'Tasks', meta: 'GitHub · Linear', - lede: "See your GitHub and Linear tasks in one place, and start a workspace for each when you're ready to build.", + lede: 'Start work directly from GitHub or Linear.', primaryTileId: 'tile-03', relatedTileIds: [], docsUrl: 'https://www.onorca.dev/docs/review/linear' diff --git a/src/shared/review-steps.ts b/src/shared/review-steps.ts index 0dacaa615..38181eb6e 100644 --- a/src/shared/review-steps.ts +++ b/src/shared/review-steps.ts @@ -16,21 +16,19 @@ export const REVIEW_STEPS: readonly ReviewStep[] = [ id: 'notes', name: 'Notes', subtitle: 'Notes & diffs', - description: - 'Review diffs, leave notes on exact changed lines, and send focused feedback back to an agent.' + description: 'Send focused review notes to an agent.' }, { id: 'pr-view', name: 'PR checks', subtitle: 'PR checks & comments', - description: 'See PR details, CI, comments, conflicts, and merge readiness from the Checks tab.' + description: 'See PR status in the Checks tab.' }, { id: 'ship', name: 'Ship with AI', subtitle: 'Ship with AI', - description: - "Use Orca's built-in AI flow to draft commit messages and pull requests from the diff, with everything editable before submission." + description: 'Let AI prepare commit and PR drafts for you.' } ] as const diff --git a/src/shared/workbench-steps.ts b/src/shared/workbench-steps.ts index fa4deb719..42e3928e1 100644 --- a/src/shared/workbench-steps.ts +++ b/src/shared/workbench-steps.ts @@ -19,22 +19,20 @@ export const WORKBENCH_STEPS: readonly WorkbenchStep[] = [ id: 'terminal', name: 'Terminal', subtitle: 'Terminal', - description: - 'Bring your terminal setup into Orca, then split panes to keep servers, tests, logs, and agents running side by side.' + description: 'Keep your agents, tests, and dev logs visible at once.' }, { id: 'editor', name: 'Editor', subtitle: 'Editor', - description: - 'A rich Notion-style markdown editor with slash commands, inline blocks, and autosave.' + description: 'Use our Notion-style markdown editor to write notes without leaving Orca.' }, { id: 'browser', name: 'Browser', subtitle: 'Browser', description: - "Run your app in Orca's browser, send selected UI elements to agents, and let agents navigate, click, and verify pages." + "Run your app in Orca's browser, send selected UI elements to agents, and let your agents interact with your webpage." } ] as const