import { copyTextToClipboard } from "@/lib/clipboard"; import { useEffect, useId, useRef, useState } from "react"; import { useQuery } from "@tanstack/react-query"; import { GITHUB_REVIEW_EVENTS, type GitHubChatConfiguration, type GitHubReviewPolicy, type GitHubAllowedPerson, } from "@paperclipai/shared"; import { accessApi } from "@/api/access"; import { chatEndpointsApi } from "@/api/chatEndpoints"; import { githubChatApi } from "@/api/githubChat"; import { useOptionalCompany } from "@/context/CompanyContext"; import { Button } from "@/components/ui/button"; import { AtSign, Check, Copy, HelpCircle, MoreHorizontal, Plus, } from "lucide-react"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Checkbox } from "@/components/ui/checkbox"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { GitHubSettingsDisclosure } from "./GitHubSettingsDisclosure"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { MarkdownEditor } from "@/components/MarkdownEditor"; import { Label } from "@/components/ui/label"; import { ToggleSwitch } from "@/components/ui/toggle-switch"; import { Link } from "@/lib/router"; import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; export const githubSelectClass = "w-full rounded-md border border-input bg-background px-3 py-2 text-sm"; const eventLabels = { opened: "New pull request", synchronize: "Updated commits", reopened: "Reopened", ready_for_review: "Ready for review", mention: "Mention", comment: "Follow-up comment", }; function GitHubHelp({ label, children, }: { label: string; children: React.ReactNode; }) { const [open, setOpen] = useState(false); return ( {children} ); } export function GitHubToggle({ label, description, help, checked, onChange, ariaLabel, disabled, }: { label: string; description?: string; help?: string; checked: boolean; onChange: (checked: boolean) => void; ariaLabel?: string; disabled?: boolean; }) { return (

{label}

{help && {help}}
{description && (

{description}

)}
); } /** Keep separators while typing; the saved policy still contains normalized lists. */ function GitHubListInput({ id, values, separator = "\n", onChange, }: { id: string; values: string[]; separator?: "\n" | ","; onChange: (values: string[]) => void; }) { const joiner = separator === "," ? ", " : "\n"; const [text, setText] = useState(values.join(joiner)); const parse = (value: string) => value .split(separator) .map((item) => item.trim()) .filter(Boolean); useEffect(() => { setText((current) => JSON.stringify(parse(current)) === JSON.stringify(values) ? current : values.join(joiner), ); }, [values, separator]); const props = { id, value: text, onChange: ( event: React.ChangeEvent, ) => { setText(event.target.value); onChange(parse(event.target.value)); }, }; return separator === "\n" ?