"use client"; import { memo, useCallback, useState } from "react"; import Link from "next/link"; import type { AgentProfileOption } from "@/lib/state/slices"; import type { WorkflowSnapshotData } from "@/lib/state/slices/kanban/types"; import { WorkflowSelectorRow } from "@/components/workflow-selector-row"; import { AgentLogo } from "@/components/agent-logo"; import type { DialogFormState } from "@/components/task-create-dialog-types"; import type { useKeyboardShortcutHandler } from "@/hooks/use-keyboard-shortcut"; import { TaskFormInputs } from "@/components/task-create-dialog-selectors"; import { FreshBranchToggle, computeBranchPlaceholder, } from "@/components/task-create-dialog-fresh-branch"; import type { JiraTicket } from "@/lib/types/jira"; import type { LinearIssue } from "@/lib/types/linear"; type SelectorOption = { value: string; label: string; renderLabel: () => React.ReactNode; }; type CreateEditSelectorsProps = { isTaskStarted: boolean; hasRepositorySelection: boolean; branchOptions: SelectorOption[]; branch: string; onBranchChange: (value: string) => void; branchesLoading: boolean; onRefreshBranches?: () => void; branchesFetchedAt?: string; branchesFetchError?: string; localBranchesLoading: boolean; agentProfiles: AgentProfileOption[]; agentProfilesLoading: boolean; agentProfileOptions: SelectorOption[]; agentProfileId: string; onAgentProfileChange: (value: string) => void; isCreatingSession: boolean; executorProfileOptions: Array<{ value: string; label: string; renderLabel?: () => React.ReactNode; }>; executorProfileId: string; onExecutorProfileChange: (value: string) => void; executorsLoading: boolean; BranchSelectorComponent: React.ComponentType<{ options: SelectorOption[]; value: string; onValueChange: (value: string) => void; disabled: boolean; placeholder: string; searchPlaceholder: string; emptyMessage: string; onRefresh?: () => void; refreshing?: boolean; fetchedAt?: string; fetchError?: string; loading?: boolean; }>; AgentSelectorComponent: React.ComponentType<{ options: SelectorOption[]; value: string; onValueChange: (value: string) => void; disabled: boolean; placeholder: string; triggerClassName?: string; }>; ExecutorProfileSelectorComponent: React.ComponentType<{ options: Array<{ value: string; label: string; renderLabel?: () => React.ReactNode }>; value: string; onValueChange: (value: string) => void; disabled: boolean; placeholder: string; triggerClassName?: string; }>; isLocalExecutor: boolean; useGitHubUrl: boolean; workflowAgentLocked: boolean; freshBranchEnabled: boolean; onToggleFreshBranch: (enabled: boolean) => void; currentLocalBranch: string; branchLocked?: boolean; }; type AgentColumnProps = Pick< CreateEditSelectorsProps, | "agentProfiles" | "agentProfilesLoading" | "agentProfileOptions" | "agentProfileId" | "onAgentProfileChange" | "isCreatingSession" | "AgentSelectorComponent" | "workflowAgentLocked" >; function AgentColumn({ agentProfiles, agentProfilesLoading, agentProfileOptions, agentProfileId, onAgentProfileChange, isCreatingSession, AgentSelectorComponent, workflowAgentLocked, }: AgentColumnProps) { if (agentProfiles.length === 0 && !agentProfilesLoading) { return (
Agent set by workflow
)} > ); } function computeBranchDisabled(args: { branchLocked?: boolean; lockedToCurrentBranch: boolean; hasRepositorySelection: boolean; branchesLoading: boolean; localBranchesLoading: boolean; optionCount: number; }): boolean { if (args.branchLocked) return true; if (args.lockedToCurrentBranch) return true; if (!args.hasRepositorySelection) return true; if (args.branchesLoading || args.localBranchesLoading) return true; return args.optionCount === 0; } export const CreateEditSelectors = memo(function CreateEditSelectors( props: CreateEditSelectorsProps, ) { if (props.isTaskStarted) return null; const { hasRepositorySelection, branchOptions, branch, onBranchChange, branchesLoading, onRefreshBranches, branchesFetchedAt, branchesFetchError, localBranchesLoading, executorProfileOptions, executorProfileId, onExecutorProfileChange, executorsLoading, isLocalExecutor, useGitHubUrl, freshBranchEnabled, onToggleFreshBranch, currentLocalBranch, BranchSelectorComponent, ExecutorProfileSelectorComponent, branchLocked, } = props; const isLocalWithoutGitHubUrl = isLocalExecutor && !useGitHubUrl; // When `branchLocked` is true the caller pinned a specific branch (e.g. // Improve Kandev) — suppress the local-executor "current branch" shortcut and // the FreshBranchToggle so users can't drift away from the pinned value. const lockedToCurrentBranch = !branchLocked && isLocalWithoutGitHubUrl && !freshBranchEnabled; const branchPlaceholder = computeBranchPlaceholder({ lockedToCurrentBranch, currentLocalBranch, hasRepositorySelection, loading: branchesLoading || localBranchesLoading, optionCount: branchOptions.length, }); const branchDisabled = computeBranchDisabled({ branchLocked, lockedToCurrentBranch, hasRepositorySelection, branchesLoading, localBranchesLoading, optionCount: branchOptions.length, }); // When the local executor locks to the current branch, ignore any branch // value the user picked under a different executor — the placeholder // should reflect the actual checked-out branch instead. const branchValue = lockedToCurrentBranch ? "" : branch; return (Prompt ignored — passthrough mode active
)} > ); }