"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 [message, setMessage] = useState(null);
const [pendingAction, setPendingAction] = useState(null); // "start" | "stop"
const isWindows = typeof navigator !== "undefined" && navigator.userAgent?.includes("Windows");
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);
setMessage(null);
}
};
const doAction = async (action, password) => {
setLoading(true);
setMessage(null);
try {
if (action === "start") {
const keyToUse = selectedApiKey?.trim()
|| (apiKeys?.length > 0 ? apiKeys[0].key : null)
|| (!cloudEnabled ? "sk_9router" : null);
const res = await fetch("/api/cli-tools/antigravity-mitm", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ apiKey: keyToUse, sudoPassword: password }),
});
const data = await res.json();
if (res.ok) {
setMessage({ type: "success", text: "Server started" });
} else {
setMessage({ type: "error", text: data.error || "Failed to start server" });
}
} else {
const res = await fetch("/api/cli-tools/antigravity-mitm", {
method: "DELETE",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ sudoPassword: password }),
});
const data = await res.json();
if (res.ok) {
setMessage({ type: "success", text: "Server stopped — all DNS cleared" });
} else {
setMessage({ type: "error", text: data.error || "Failed to stop server" });
}
}
setShowPasswordModal(false);
setSudoPassword("");
await fetchStatus();
} catch (error) {
setMessage({ type: "error", text: error.message });
} finally {
setLoading(false);
setPendingAction(null);
}
};
const handleConfirmPassword = () => {
if (!sudoPassword.trim()) {
setMessage({ type: "error", text: "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