import { useSendToAgentChat } from "@agent-native/core/client/agent-chat"; import { appApiPath, agentNativePath, } from "@agent-native/core/client/api-path"; import { PromptComposer } from "@agent-native/core/client/composer"; import { callAction, useActionMutation, useActionQuery, } from "@agent-native/core/client/hooks"; import { oauthRedirectUri } from "@agent-native/core/client/host"; import { useT } from "@agent-native/core/client/i18n"; import { IconCheck, IconChevronDown, IconChevronUp, IconExternalLink, IconLoader2, IconCircle, IconAlertCircle, IconUpload, IconPencil, IconTrash, IconSearch, IconPlus, IconKey, IconCopy, IconDotsVertical, IconBrandGithub, IconBrandGoogle, IconPlugConnected, } from "@tabler/icons-react"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { useEffect, useState } from "react"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { Skeleton } from "@/components/ui/skeleton"; import { getIdToken } from "@/lib/auth"; import { getOptionalCredentialKeys, getSharedConnectionStatus, getGoogleDriveConnection, isSourceReady, isSourceLocallyConfigured, credentialRowsFromStatus, type DataSourceStatusResponse, type EnvKeyStatus, type SharedConnectionStatus, } from "@/lib/data-source-status"; import { dataSources, categoryLabels, categoryOrder, type DataSource, type WalkthroughStep, } from "@/lib/data-sources"; interface AnalyticsPublicKeyRow { id: string; name: string; publicKeyPrefix: string; createdAt: string; lastUsedAt: string | null; revokedAt: string | null; orgId: string | null; } interface GitHubOAuthStatus { configured: boolean; connected: boolean; valid?: boolean; viewer?: { login: string; name?: string | null; email?: string | null; avatarUrl?: string | null; htmlUrl?: string | null; }; error?: string; } const firstPartyAnalyticsEndpoint = (import.meta.env as Record) .VITE_AGENT_NATIVE_ANALYTICS_ENDPOINT || "https://analytics.agent-native.com/track"; async function saveEnvVars( vars: Array<{ key: string; value: string }>, ): Promise { await callAction("update-data-source-credentials", { vars }); } async function testConnection( source: string, ): Promise<{ ok: boolean; error?: string }> { const token = await getIdToken(); const res = await fetch(appApiPath("/api/test-connection"), { method: "POST", headers: { "Content-Type": "application/json", ...(token && { Authorization: `Bearer ${token}` }), }, body: JSON.stringify({ source }), }); return res.json(); } async function fetchGitHubOAuthStatus(): Promise { const res = await fetch( agentNativePath("/_agent-native/oauth/github/status"), ); if (!res.ok) { const data = await res.json().catch(() => ({})); throw new Error(data.error || "Failed to load GitHub status"); } return res.json(); } function StepItem({ step, index, isComplete, isActive, isSaved, inputValues, onInputChange, }: { step: WalkthroughStep; index: number; isComplete: boolean; isActive: boolean; isSaved: boolean; inputValues: Record; onInputChange: (key: string, value: string) => void; }) { const t = useT(); const handleFileUpload = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file || !step.inputKey) return; const reader = new FileReader(); reader.onload = () => { if (typeof reader.result === "string") { onInputChange(step.inputKey!, reader.result); } }; reader.readAsText(file); // Reset so the same file can be re-selected e.target.value = ""; }; return (
{isComplete ? : index + 1}

{step.title}

{step.description}

{step.url && ( {step.linkText || t("dataSources.open")}{" "} )} {step.inputKey && (
{step.inputAcceptFile && ( )}
{step.inputType === "textarea" ? (