import { useAtomValue } from "@effect/atom-react"; import { useNavigate } from "@tanstack/react-router"; import { useRef } from "react"; import type { ProviderInstanceId, SourceControlWritingStyleMode } from "@t3tools/contracts"; import { DEFAULT_UNIFIED_SETTINGS } from "@t3tools/contracts/settings"; import { createModelSelection } from "@t3tools/shared/model"; import { resolveSourceControlWriterModelSelection } from "@t3tools/shared/serverSettings"; import { usePrimarySettings, useUpdatePrimarySettings } from "../../hooks/useSettings"; import { applyProviderInstanceSettings, deriveProviderInstanceEntries, sortProviderInstanceEntries, } from "../../providerInstances"; import { getCustomModelOptionsByInstance, resolveAppModelSelectionState, } from "../../modelSelection"; import { primaryServerProvidersAtom } from "../../state/server"; import { usePrimaryEnvironmentId } from "../../state/environments"; import { ProviderModelPicker } from "../chat/ProviderModelPicker"; import { Select, SelectItem, SelectPopup, SelectTrigger, SelectValue } from "../ui/select"; import { Switch } from "../ui/switch"; import { Textarea } from "../ui/textarea"; import { SETTINGS_PICKER_TRIGGER_CLASSNAME, SettingResetButton, SettingsRow, SettingsSection, } from "./settingsLayout"; import { searchableSetting } from "./settingsSearch"; const MODE_OPTIONS: Record = { repo_conventions: { label: "Repository conventions", description: "In each project, matches recent change descriptions and change request titles.", }, conventional_commits: { label: "Conventional Commits", description: "Use Conventional Commit prefixes and keep change request text concise.", }, custom: { label: "Custom instructions", description: "Use your instructions for change descriptions and change requests in every project.", }, }; export function SourceControlWritingSettingsSection() { const settings = usePrimarySettings(); const updateSettings = useUpdatePrimarySettings(); const navigate = useNavigate(); const environmentId = usePrimaryEnvironmentId(); const serverProviders = useAtomValue(primaryServerProvidersAtom); const customInstructionsRef = useRef(null); const style = settings.sourceControlWritingStyle; const defaults = DEFAULT_UNIFIED_SETTINGS.sourceControlWritingStyle; const isSourceControlWritingStyleDirty = style.mode !== defaults.mode || style.customInstructions !== defaults.customInstructions; const textGenerationProviders = serverProviders.filter( (provider) => provider.supportsTextGeneration !== false, ); const defaultModelSelection = resolveAppModelSelectionState(settings, textGenerationProviders); const usesDedicatedModel = settings.sourceControlWriterModelSelection !== null; const activeSelection = resolveAppModelSelectionState( { ...settings, textGenerationModelSelection: resolveSourceControlWriterModelSelection( settings, textGenerationProviders, ), }, textGenerationProviders, ); const instanceEntries = sortProviderInstanceEntries( applyProviderInstanceSettings(deriveProviderInstanceEntries(textGenerationProviders), settings), ); const canEnableDedicatedModel = instanceEntries.some( (entry) => entry.instanceId === defaultModelSelection.instanceId && entry.enabled && entry.isAvailable, ); const modelOptionsByInstance = getCustomModelOptionsByInstance( settings, textGenerationProviders, activeSelection.instanceId, activeSelection.model, ); return ( updateSettings({ sourceControlWritingStyle: { mode: defaults.mode, customInstructions: defaults.customInstructions, }, }) } /> ) : null } control={ } > {style.mode === "custom" ? (