import { Button, Chip, cn, Form, Input, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, Select, SelectedItemProps, SelectedItems, SelectItem, Textarea, useDisclosure } from '@heroui/react' import { loggerService } from '@logger' import type { Selection } from '@react-types/shared' import { getModelLogo } from '@renderer/config/models' import { useAgent } from '@renderer/hooks/agents/useAgent' import { useApiModels } from '@renderer/hooks/agents/useModels' import { useSessions } from '@renderer/hooks/agents/useSessions' import { useUpdateSession } from '@renderer/hooks/agents/useUpdateSession' import { AgentEntity, AgentSessionEntity, BaseSessionForm, CreateSessionForm, Tool, UpdateSessionForm } from '@renderer/types' import { ChangeEvent, FormEvent, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { ErrorBoundary } from '../../ErrorBoundary' import { BaseOption, ModelOption, Option } from './shared' const logger = loggerService.withContext('SessionAgentPopup') type Option = ModelOption type AgentWithTools = AgentEntity & { tools?: Tool[] } type SessionWithTools = AgentSessionEntity & { tools?: Tool[] } const buildSessionForm = (existing?: SessionWithTools, agent?: AgentWithTools): BaseSessionForm => ({ name: existing?.name ?? agent?.name ?? 'Claude Code', description: existing?.description ?? agent?.description, instructions: existing?.instructions ?? agent?.instructions, model: existing?.model ?? agent?.model ?? '', accessible_paths: existing?.accessible_paths ? [...existing.accessible_paths] : agent?.accessible_paths ? [...agent.accessible_paths] : [], allowed_tools: existing?.allowed_tools ? [...existing.allowed_tools] : agent?.allowed_tools ? [...agent.allowed_tools] : [] }) interface BaseProps { agentId: string session?: SessionWithTools onSessionCreated?: (session: AgentSessionEntity) => void } interface TriggerProps extends BaseProps { trigger: { content: ReactNode; className?: string } isOpen?: never onClose?: never } interface StateProps extends BaseProps { trigger?: never isOpen: boolean onClose: () => void } type Props = TriggerProps | StateProps /** * Modal component for creating or editing a Session. * * Either trigger or isOpen and onClose is given. * @param agentId - The ID of agent which the session is related. * @param session - Optional session entity for editing mode. * @param trigger - Optional trigger element that opens the modal. It MUST propagate the click event to trigger the modal. * @param isOpen - Optional controlled modal open state. From useDisclosure. * @param onClose - Optional callback when modal closes. From useDisclosure. * @returns Modal component for agent creation/editing */ export const SessionModal: React.FC = ({ agentId, session, trigger, isOpen: _isOpen, onClose: _onClose, onSessionCreated }) => { const { isOpen, onClose, onOpen } = useDisclosure({ isOpen: _isOpen, onClose: _onClose }) const { t } = useTranslation() const loadingRef = useRef(false) // const { setTimeoutTimer } = useTimer() const { createSession } = useSessions(agentId) const updateSession = useUpdateSession(agentId) // Only support claude code for now const { models } = useApiModels({ providerType: 'anthropic' }) const { agent } = useAgent(agentId) const isEditing = (session?: AgentSessionEntity) => session !== undefined const [form, setForm] = useState(() => buildSessionForm(session, agent ?? undefined)) useEffect(() => { if (isOpen) { setForm(buildSessionForm(session, agent ?? undefined)) } }, [session, agent, isOpen]) const availableTools = useMemo(() => session?.tools ?? agent?.tools ?? [], [agent?.tools, session?.tools]) const selectedToolKeys = useMemo(() => new Set(form.allowed_tools ?? []), [form.allowed_tools]) useEffect(() => { if (!availableTools.length) { return } setForm((prev) => { const allowed = prev.allowed_tools ?? [] const validTools = allowed.filter((id) => availableTools.some((tool) => tool.id === id)) if (validTools.length === allowed.length) { return prev } return { ...prev, allowed_tools: validTools } }) }, [availableTools]) const Item = useCallback(({ item }: { item: SelectedItemProps }) =>