Allow agent creation outside git repos

This commit is contained in:
Mohamed Boudra
2025-12-23 23:11:48 +07:00
parent 38c1f52035
commit 993eed0628
@@ -1524,6 +1524,9 @@ function AgentFlowModal({
? daemonAvailabilityError ?? ? daemonAvailabilityError ??
"Repository details will load automatically once the selected host is back online." "Repository details will load automatically once the selected host is back online."
: null; : null;
const isNonGitDirectory =
repoRequestStatus === "error" &&
/not in a git repository/i.test(repoRequestError?.message ?? "");
const repoInfoStatus: "idle" | "loading" | "ready" | "error" = !shouldInspectRepo const repoInfoStatus: "idle" | "loading" | "ready" | "error" = !shouldInspectRepo
? "idle" ? "idle"
: repoAvailabilityError : repoAvailabilityError
@@ -1531,11 +1534,16 @@ function AgentFlowModal({
: repoRequestStatus === "loading" : repoRequestStatus === "loading"
? "loading" ? "loading"
: repoRequestStatus === "error" : repoRequestStatus === "error"
? "error" ? isNonGitDirectory
? "idle"
: "error"
: repoRequestStatus === "success" : repoRequestStatus === "success"
? "ready" ? "ready"
: "idle"; : "idle";
const repoInfoError = repoAvailabilityError ?? repoRequestError?.message ?? null; const repoInfoError = repoAvailabilityError ?? (isNonGitDirectory ? null : repoRequestError?.message ?? null);
const gitHelperText = isNonGitDirectory
? "No git repository detected. Git options are disabled for this directory."
: null;
useEffect(() => { useEffect(() => {
if (!shouldInspectRepo) { if (!shouldInspectRepo) {
@@ -1575,6 +1583,35 @@ function AgentFlowModal({
}); });
}, [repoInfo]); }, [repoInfo]);
useEffect(() => {
if (!isNonGitDirectory) {
return;
}
if (
createNewBranch ||
createWorktree ||
baseBranch.trim().length > 0 ||
branchName.trim().length > 0 ||
worktreeSlug.trim().length > 0
) {
setCreateNewBranch(false);
setCreateWorktree(false);
setBaseBranch("");
setBranchName("");
setWorktreeSlug("");
setBranchNameEdited(false);
setWorktreeSlugEdited(false);
shouldSyncBaseBranchRef.current = true;
}
}, [
baseBranch,
branchName,
createNewBranch,
createWorktree,
isNonGitDirectory,
worktreeSlug,
]);
const handleCreate = useCallback(async () => { const handleCreate = useCallback(async () => {
const trimmedPath = workingDir.trim(); const trimmedPath = workingDir.trim();
if (!trimmedPath) { if (!trimmedPath) {
@@ -1638,7 +1675,7 @@ function AgentFlowModal({
createWorktree || createWorktree ||
(trimmedBaseBranch.length > 0 && trimmedBaseBranch !== currentBranch); (trimmedBaseBranch.length > 0 && trimmedBaseBranch !== currentBranch);
const gitOptions = shouldIncludeBase const gitOptions = shouldIncludeBase && !isNonGitDirectory
? { ? {
...(trimmedBaseBranch ? { baseBranch: trimmedBaseBranch } : {}), ...(trimmedBaseBranch ? { baseBranch: trimmedBaseBranch } : {}),
...(createNewBranch ...(createNewBranch
@@ -1904,6 +1941,9 @@ function AgentFlowModal({
) : null; ) : null;
const gitBlockingError = useMemo(() => { const gitBlockingError = useMemo(() => {
if (isNonGitDirectory) {
return null;
}
const trimmedBase = baseBranch.trim(); const trimmedBase = baseBranch.trim();
const currentBranch = repoInfo?.currentBranch ?? ""; const currentBranch = repoInfo?.currentBranch ?? "";
const isCustomBase = const isCustomBase =
@@ -1950,6 +1990,7 @@ function AgentFlowModal({
branchName, branchName,
createNewBranch, createNewBranch,
createWorktree, createWorktree,
isNonGitDirectory,
repoInfo, repoInfo,
validateWorktreeName, validateWorktreeName,
worktreeSlug, worktreeSlug,
@@ -2189,6 +2230,8 @@ function AgentFlowModal({
branches={repoInfo?.branches ?? []} branches={repoInfo?.branches ?? []}
status={repoInfoStatus} status={repoInfoStatus}
repoError={repoInfoError} repoError={repoInfoError}
helperText={gitHelperText}
isGitDisabled={Boolean(gitHelperText)}
warning={ warning={
!createWorktree && repoInfo?.isDirty !createWorktree && repoInfo?.isDirty
? "Working directory has uncommitted changes" ? "Working directory has uncommitted changes"
@@ -3075,6 +3118,7 @@ interface GitOptionsSectionProps {
branches: Array<{ name: string; isCurrent: boolean }>; branches: Array<{ name: string; isCurrent: boolean }>;
status: "idle" | "loading" | "ready" | "error"; status: "idle" | "loading" | "ready" | "error";
repoError: string | null; repoError: string | null;
helperText?: string | null;
warning: string | null; warning: string | null;
createNewBranch: boolean; createNewBranch: boolean;
onToggleCreateNewBranch: (value: boolean) => void; onToggleCreateNewBranch: (value: boolean) => void;
@@ -3085,6 +3129,7 @@ interface GitOptionsSectionProps {
worktreeSlug: string; worktreeSlug: string;
onWorktreeSlugChange: (value: string) => void; onWorktreeSlugChange: (value: string) => void;
gitValidationError: string | null; gitValidationError: string | null;
isGitDisabled?: boolean;
isBaseDropdownOpen: boolean; isBaseDropdownOpen: boolean;
onToggleBaseDropdown: () => void; onToggleBaseDropdown: () => void;
onCloseDropdown: () => void; onCloseDropdown: () => void;
@@ -3096,6 +3141,7 @@ function GitOptionsSection({
branches, branches,
status, status,
repoError, repoError,
helperText,
warning, warning,
createNewBranch, createNewBranch,
onToggleCreateNewBranch, onToggleCreateNewBranch,
@@ -3106,6 +3152,7 @@ function GitOptionsSection({
worktreeSlug, worktreeSlug,
onWorktreeSlugChange, onWorktreeSlugChange,
gitValidationError, gitValidationError,
isGitDisabled,
isBaseDropdownOpen, isBaseDropdownOpen,
onToggleBaseDropdown, onToggleBaseDropdown,
onCloseDropdown, onCloseDropdown,
@@ -3122,6 +3169,7 @@ function GitOptionsSection({
const currentBranchLabel = const currentBranchLabel =
branches.find((branch) => branch.isCurrent)?.name ?? ""; branches.find((branch) => branch.isCurrent)?.name ?? "";
const baseInputRef = useRef<TextInput | null>(null); const baseInputRef = useRef<TextInput | null>(null);
const gitInputsDisabled = Boolean(isGitDisabled) || status === "loading";
useEffect(() => { useEffect(() => {
if (isBaseDropdownOpen) { if (isBaseDropdownOpen) {
@@ -3143,13 +3191,14 @@ function GitOptionsSection({
value={baseBranch} value={baseBranch}
placeholder={currentBranchLabel || "main"} placeholder={currentBranchLabel || "main"}
onPress={onToggleBaseDropdown} onPress={onToggleBaseDropdown}
disabled={status === "loading"} disabled={gitInputsDisabled}
errorMessage={repoError} errorMessage={repoError}
warningMessage={!gitValidationError ? warning : null} warningMessage={!gitValidationError && !isGitDisabled ? warning : null}
helperText={ helperText={
status === "loading" helperText ??
(status === "loading"
? "Inspecting repository…" ? "Inspecting repository…"
: "Search existing branches, then tap to select." : "Search existing branches, then tap to select.")
} }
/> />
<DropdownSheet <DropdownSheet
@@ -3215,6 +3264,7 @@ function GitOptionsSection({
description="Create a feature branch before launching the agent" description="Create a feature branch before launching the agent"
value={createNewBranch} value={createNewBranch}
onToggle={onToggleCreateNewBranch} onToggle={onToggleCreateNewBranch}
disabled={isGitDisabled}
/> />
{createNewBranch ? ( {createNewBranch ? (
<TextInput <TextInput
@@ -3233,6 +3283,7 @@ function GitOptionsSection({
description="Use an isolated directory so your current branch stays untouched" description="Use an isolated directory so your current branch stays untouched"
value={createWorktree} value={createWorktree}
onToggle={onToggleCreateWorktree} onToggle={onToggleCreateWorktree}
disabled={isGitDisabled}
/> />
{createWorktree ? ( {createWorktree ? (
<TextInput <TextInput