"use client";
import { useState, useCallback } from "react";
import {
IconCheck,
IconX,
IconRefresh,
IconKey,
IconTrash,
IconEye,
IconEyeOff,
} from "@tabler/icons-react";
import { Badge } from "@kandev/ui/badge";
import { Button } from "@kandev/ui/button";
import { Input } from "@kandev/ui/input";
import { Spinner } from "@kandev/ui/spinner";
import { useGitHubStatus } from "@/hooks/domains/github/use-github-status";
import { useToast } from "@/components/toast-provider";
import { configureGitHubToken, clearGitHubToken } from "@/lib/api/domains/github-api";
import type { AuthDiagnostics } from "@/lib/types/github";
function DiagnosticsOutput({ diagnostics }: { diagnostics: AuthDiagnostics }) {
return (
{diagnostics.command}
exit code: {diagnostics.exit_code}
{diagnostics.exit_code !== 0 && (
A non-zero exit code means the command failed. Review the output below for details.
)}
{diagnostics.output.trim()}
);
}
function TokenConfigForm({ onSuccess }: { onSuccess: () => void }) {
const [token, setToken] = useState("");
const [showToken, setShowToken] = useState(false);
const [saving, setSaving] = useState(false);
const { toast } = useToast();
const handleSubmit = useCallback(
async (e: React.FormEvent) => {
e.preventDefault();
if (!token.trim()) return;
setSaving(true);
try {
await configureGitHubToken(token.trim());
toast({ description: "GitHub token configured successfully", variant: "success" });
setToken("");
onSuccess();
} catch (err) {
const message = err instanceof Error ? err.message : "Failed to configure token";
toast({ description: message, variant: "error" });
} finally {
setSaving(false);
}
},
[token, toast, onSuccess],
);
return (
);
}
export function GitHubStatusCard() {
const { status, loaded, loading, refresh } = useGitHubStatus();
const { toast } = useToast();
const [clearing, setClearing] = useState(false);
const handleClearToken = useCallback(async () => {
setClearing(true);
try {
await clearGitHubToken();
toast({ description: "GitHub token removed", variant: "success" });
refresh();
} catch {
toast({ description: "Failed to clear token", variant: "error" });
} finally {
setClearing(false);
}
}, [toast, refresh]);
if (loading || !loaded) {
return (
Checking GitHub connection...
);
}
if (!status || !status.authenticated) {
return (
Not connected to GitHub
{/* Token configuration form */}
{/* Alternative methods */}
Other authentication methods:
-
Environment variable — set{" "}
GITHUB_TOKEN when starting Kandev
-
GitHub CLI — run{" "}
gh auth login
{status?.diagnostics &&
}
);
}
return (
Connected as {status.username}
{status.auth_method === "gh_cli" ? "gh CLI" : "PAT"}
{status.token_configured && (
)}
{status.token_configured && (
Token stored in secrets. This token is used by remote agents for GitHub operations.
)}
);
}