"use client";
import { useState } from "react";
import { IconCode } from "@tabler/icons-react";
import { Card, CardContent, CardHeader, CardTitle } from "@kandev/ui/card";
import { Button } from "@kandev/ui/button";
import { Input } from "@kandev/ui/input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@kandev/ui/select";
import { SettingsSection } from "@/components/settings/settings-section";
import { useAppStore, useAppStoreApi } from "@/components/state-provider";
import { useShellSettings } from "@/hooks/domains/settings/use-shell-settings";
import { updateUserSettings } from "@/lib/api";
import { useRequest } from "@/lib/http/use-request";
const AUTO_SHELL = "auto";
const CUSTOM_SHELL = "custom";
type ShellOption = { value: string; label: string };
function resolveShellSelection(preferredShell: string, shellOptions: ShellOption[]) {
if (!preferredShell) {
return { selection: AUTO_SHELL, customShell: "" };
}
if (shellOptions.some((option) => option.value === preferredShell)) {
return { selection: preferredShell, customShell: "" };
}
return { selection: CUSTOM_SHELL, customShell: preferredShell };
}
type ShellSelectProps = {
shellSelection: string;
onSelectionChange: (value: string) => void;
customShell: string;
onCustomShellChange: (value: string) => void;
shellLoaded: boolean;
shellOptions: ShellOption[];
};
function ShellSelect({
shellSelection,
onSelectionChange,
customShell,
onCustomShellChange,
shellLoaded,
shellOptions,
}: ShellSelectProps) {
return (
<>
{shellSelection === CUSTOM_SHELL && (
)}
>
);
}
export function ShellSettingsCard() {
const setUserSettings = useAppStore((state) => state.setUserSettings);
const storeApi = useAppStoreApi();
const shellSettings = useShellSettings();
const initialShellValue = shellSettings.preferredShell ?? "";
const initialShellOptions = shellSettings.shellOptions ?? [];
const initialSelection = resolveShellSelection(initialShellValue, initialShellOptions);
const [preferredShell, setPreferredShell] = useState(initialShellValue);
const [baselineShell, setBaselineShell] = useState(initialShellValue);
const [shellSelection, setShellSelection] = useState(initialSelection.selection);
const [customShell, setCustomShell] = useState(initialSelection.customShell);
const [shellLoaded] = useState(shellSettings.loaded);
const [shellOptions] = useState(initialShellOptions);
const saveShellRequest = useRequest(async () => {
const trimmed = preferredShell.trim();
const currentSettings = storeApi.getState().userSettings;
await updateUserSettings({
workspace_id: currentSettings.workspaceId ?? "",
repository_ids: currentSettings.repositoryIds,
preferred_shell: trimmed,
});
setBaselineShell(trimmed);
setUserSettings({
...currentSettings,
preferredShell: trimmed || null,
loaded: true,
});
});
// Store data is SSR-hydrated for settings. Local state is initialized once.
const shellDirty = preferredShell.trim() !== baselineShell.trim();
return (
}
title="Shell"
description="Pick the default shell for task sessions"
>
Preferred Shell
{
setShellSelection(value);
if (value === AUTO_SHELL) {
setPreferredShell("");
setCustomShell("");
return;
}
if (value === CUSTOM_SHELL) {
setPreferredShell(customShell);
return;
}
setPreferredShell(value);
setCustomShell("");
}}
customShell={customShell}
onCustomShellChange={(value) => {
setCustomShell(value);
setPreferredShell(value);
}}
shellLoaded={shellLoaded}
shellOptions={shellOptions}
/>
New task sessions will use this shell. Existing sessions keep their current shell.
);
}