"use client";
import { useState, useEffect } from "react";
import { Card, Button, Badge, Input } from "@/shared/components";
/**
* Shared MITM infrastructure card — manages SSL cert + server start/stop.
* DNS per-tool is handled separately in MitmToolCard.
*/
export default function MitmServerCard({ apiKeys, cloudEnabled, onStatusChange }) {
const [status, setStatus] = useState(null);
const [loading, setLoading] = useState(false);
const [showPasswordModal, setShowPasswordModal] = useState(false);
const [sudoPassword, setSudoPassword] = useState("");
const [selectedApiKey, setSelectedApiKey] = useState("");
const [pendingAction, setPendingAction] = useState(null);
const [modalError, setModalError] = useState(null);
const isWindows = typeof navigator !== "undefined" && navigator.userAgent?.includes("Windows");
const isAdmin = status?.isAdmin !== false;
useEffect(() => {
if (apiKeys?.length > 0 && !selectedApiKey) {
setSelectedApiKey(apiKeys[0].key);
}
}, [apiKeys, selectedApiKey]);
useEffect(() => {
fetchStatus();
}, []);
const fetchStatus = async () => {
try {
const res = await fetch("/api/cli-tools/antigravity-mitm");
if (res.ok) {
const data = await res.json();
setStatus(data);
onStatusChange?.(data);
}
} catch {
setStatus({ running: false, certExists: false, dnsStatus: {} });
}
};
const handleAction = (action) => {
if (isWindows || status?.hasCachedPassword) {
doAction(action, "");
} else {
setPendingAction(action);
setShowPasswordModal(true);
setModalError(null);
}
};
const doAction = async (action, password) => {
setLoading(true);
try {
if (action === "trust-cert") {
await fetch("/api/cli-tools/antigravity-mitm", {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ action: "trust-cert", sudoPassword: password }),
});
} else if (action === "start") {
const keyToUse = selectedApiKey?.trim()
|| (apiKeys?.length > 0 ? apiKeys[0].key : null)
|| (!cloudEnabled ? "sk_9router" : null);
await fetch("/api/cli-tools/antigravity-mitm", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ apiKey: keyToUse, sudoPassword: password }),
});
} else {
await fetch("/api/cli-tools/antigravity-mitm", {
method: "DELETE",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ sudoPassword: password }),
});
}
setShowPasswordModal(false);
setSudoPassword("");
await fetchStatus();
} catch { /* ignore */ } finally {
setLoading(false);
setPendingAction(null);
}
};
const handleConfirmPassword = () => {
if (!sudoPassword.trim()) {
setModalError("Sudo password is required");
return;
}
doAction(pendingAction, sudoPassword);
};
const isRunning = status?.running;
return (
<>
Purpose: Use Antigravity IDE & GitHub Copilot → with ANY provider/model from 9Router
How it works: Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot
Enable DNS per tool below to activate interception
Required for SSL certificate and server startup