const { useCallback, useEffect, useMemo, useRef, useState } = React;
const ORIGIN_BASE = window.location.origin.replace(/\/+$/, "");
const SAVED_BASE = (localStorage.getItem("sneaksolve_api_base") || "").trim();
const DEFAULT_BASE = (SAVED_BASE || ORIGIN_BASE).replace(/\/+$/, "");
function normalizeBase(value) {
return String(value || "").trim().replace(/\/+$/, "");
}
function formatTime(isoValue) {
if (!isoValue) return "-";
const date = new Date(isoValue);
if (Number.isNaN(date.getTime())) return String(isoValue);
return date.toLocaleString();
}
function classForProblemStatus(status) {
if (status === "\ud574\uacb0") return "bg-emerald-50 text-emerald-700 border-emerald-200";
if (status === "\ud574\uacb0\uc911") return "bg-amber-50 text-amber-700 border-amber-200";
return "bg-slate-50 text-slate-700 border-slate-200";
}
function classForPodStatus(status) {
if (status === "IDLE") return "bg-emerald-50 text-emerald-700 border-emerald-200";
if (status === "BUSY") return "bg-blue-50 text-blue-700 border-blue-200";
if (status === "AUTH_REQUIRED") return "bg-amber-50 text-amber-700 border-amber-200";
return "bg-slate-100 text-slate-700 border-slate-200";
}
function statusPill(label, extraClass = "") {
return `inline-flex items-center rounded-full border px-2.5 py-1 text-xs font-medium ${extraClass} ${label}`;
}
function useCurrentBaseState() {
const [apiBase, setApiBase] = useState(DEFAULT_BASE);
const base = useMemo(() => normalizeBase(apiBase) || ORIGIN_BASE, [apiBase]);
return { apiBase, setApiBase, base };
}
function App() {
const { apiBase, setApiBase, base } = useCurrentBaseState();
const [contestInput, setContestInput] = useState("");
const [contestId, setContestId] = useState(null);
const [contests, setContests] = useState([]);
const [contestStatus, setContestStatus] = useState(null);
const [pods, setPods] = useState([]);
const [selectedProblemId, setSelectedProblemId] = useState(null);
const [problemDetail, setProblemDetail] = useState(null);
const [lastError, setLastError] = useState("");
const [loading, setLoading] = useState({
contests: false,
contestStatus: false,
pods: false,
detail: false,
authAction: "",
});
const [authDialog, setAuthDialog] = useState({
open: false,
podId: "",
code: "",
verificationUri: "",
expiresAt: "",
podError: "",
popup: null,
});
const eventSourceRef = useRef(null);
const requestJson = useCallback(async (requestBase, path, init = {}) => {
const response = await fetch(`${requestBase}${path}`, {
...init,
headers: {
"Content-Type": "application/json",
...(init.headers || {}),
},
});
if (!response.ok) {
const text = await response.text();
throw new Error(text || `HTTP ${response.status}`);
}
return response.json();
}, []);
const api = useCallback(
async (path, init = {}) => {
try {
return await requestJson(base, path, init);
} catch (error) {
if (base !== ORIGIN_BASE) {
console.warn("[SneakSolve] fallback to origin base", {
from: base,
to: ORIGIN_BASE,
path,
error: String(error),
});
setApiBase(ORIGIN_BASE);
localStorage.setItem("sneaksolve_api_base", ORIGIN_BASE);
return requestJson(ORIGIN_BASE, path, init);
}
throw error;
}
},
[base, requestJson, setApiBase]
);
const loadPods = useCallback(
async ({ silent = false } = {}) => {
if (!silent) setLoading((prev) => ({ ...prev, pods: true }));
try {
const payload = await api("/v1/pods");
const list = Array.isArray(payload) ? payload : [];
setPods(list);
return list;
} catch (error) {
setLastError(String(error));
console.error(error);
return [];
} finally {
if (!silent) setLoading((prev) => ({ ...prev, pods: false }));
}
},
[api]
);
const loadContests = useCallback(async () => {
setLoading((prev) => ({ ...prev, contests: true }));
try {
const payload = await api("/v1/contests");
const list = Array.isArray(payload) ? payload : [];
setContests(list);
return list;
} catch (error) {
setLastError(String(error));
console.error(error);
return [];
} finally {
setLoading((prev) => ({ ...prev, contests: false }));
}
}, [api]);
const loadContestStatus = useCallback(
async (nextContestId) => {
if (!nextContestId) return null;
setLoading((prev) => ({ ...prev, contestStatus: true }));
try {
const payload = await api(`/v1/contests/${nextContestId}/status`);
setContestStatus(payload);
return payload;
} catch (error) {
setLastError(String(error));
console.error(error);
return null;
} finally {
setLoading((prev) => ({ ...prev, contestStatus: false }));
}
},
[api]
);
const loadProblemDetail = useCallback(
async (problemId, { silent = false } = {}) => {
if (!problemId) return;
if (!silent) setLoading((prev) => ({ ...prev, detail: true }));
try {
const payload = await api(`/v1/problems/${problemId}/solution`);
setProblemDetail(payload);
} catch (error) {
setLastError(String(error));
console.error(error);
} finally {
if (!silent) setLoading((prev) => ({ ...prev, detail: false }));
}
},
[api]
);
const closeAuthDialog = useCallback(() => {
setAuthDialog((prev) => {
if (prev.popup && !prev.popup.closed) {
prev.popup.close();
}
return {
open: false,
podId: "",
code: "",
verificationUri: "",
expiresAt: "",
podError: "",
popup: null,
};
});
}, []);
const startAuth = useCallback(
async (podId) => {
setLoading((prev) => ({ ...prev, authAction: podId }));
setLastError("");
try {
const payload = await api(`/v1/pods/${podId}/auth/start`, {
method: "POST",
body: JSON.stringify({ provider: "codex" }),
});
setAuthDialog({
open: true,
podId: payload.id,
code: payload.auth_code || "",
verificationUri: payload.auth_verification_uri || "",
expiresAt: payload.auth_expires_at || "",
podError: payload.last_error || "",
popup: null,
});
await loadPods({ silent: true });
} catch (error) {
setLastError(String(error));
console.error(error);
} finally {
setLoading((prev) => ({ ...prev, authAction: "" }));
}
},
[api, loadPods]
);
const authOff = useCallback(
async (podId) => {
setLoading((prev) => ({ ...prev, authAction: podId }));
try {
await api(`/v1/pods/${podId}/auth`, {
method: "PATCH",
body: JSON.stringify({ authenticated: false }),
});
if (authDialog.open && authDialog.podId === podId) closeAuthDialog();
await loadPods();
} catch (error) {
setLastError(String(error));
console.error(error);
} finally {
setLoading((prev) => ({ ...prev, authAction: "" }));
}
},
[api, authDialog.open, authDialog.podId, closeAuthDialog, loadPods]
);
const clearAuthCode = useCallback(
async (podId) => {
setLoading((prev) => ({ ...prev, authAction: podId }));
try {
await api(`/v1/pods/${podId}/auth/challenge`, { method: "DELETE" });
await loadPods();
} catch (error) {
setLastError(String(error));
console.error(error);
} finally {
setLoading((prev) => ({ ...prev, authAction: "" }));
}
},
[api, loadPods]
);
const markAuthComplete = useCallback(
async (podId) => {
setLoading((prev) => ({ ...prev, authAction: podId }));
try {
await api(`/v1/pods/${podId}/auth/complete`, {
method: "POST",
body: JSON.stringify({ authenticated: true }),
});
await loadPods();
} catch (error) {
setLastError(String(error));
console.error(error);
} finally {
setLoading((prev) => ({ ...prev, authAction: "" }));
}
},
[api, loadPods]
);
useEffect(() => {
const run = async () => {
await loadPods();
const fetchedContests = await loadContests();
const params = new URLSearchParams(window.location.search);
const fromUrl = Number(params.get("contestId") || "");
const initialContestId =
Number.isFinite(fromUrl) && fromUrl > 0
? fromUrl
: fetchedContests.length > 0
? fetchedContests[0].contestId
: null;
if (initialContestId) {
setContestId(initialContestId);
setContestInput(String(initialContestId));
await loadContestStatus(initialContestId);
}
};
run().catch((error) => {
setLastError(String(error));
console.error(error);
});
}, [loadContestStatus, loadContests, loadPods]);
useEffect(() => {
if (!contestId) return;
if (eventSourceRef.current) {
eventSourceRef.current.close();
}
const source = new EventSource(`${base}/v1/contests/${contestId}/stream`);
source.onmessage = async () => {
await Promise.all([
loadContestStatus(contestId),
loadPods({ silent: true }),
selectedProblemId ? loadProblemDetail(selectedProblemId, { silent: true }) : Promise.resolve(),
]);
};
source.onerror = (error) => {
console.warn("[SneakSolve] stream error", error);
};
eventSourceRef.current = source;
return () => {
source.close();
if (eventSourceRef.current === source) {
eventSourceRef.current = null;
}
};
}, [base, contestId, loadContestStatus, loadPods, loadProblemDetail, selectedProblemId]);
useEffect(() => {
if (!authDialog.open || !authDialog.podId) return undefined;
const interval = setInterval(async () => {
const list = await loadPods({ silent: true });
const pod = list.find((item) => item.id === authDialog.podId);
if (!pod) return;
if (pod.auth_state) {
closeAuthDialog();
return;
}
setAuthDialog((prev) => ({
...prev,
code: pod.auth_code || "",
verificationUri: pod.auth_verification_uri || "",
expiresAt: pod.auth_expires_at || "",
podError: pod.last_error || "",
}));
}, 2000);
return () => clearInterval(interval);
}, [authDialog.open, authDialog.podId, closeAuthDialog, loadPods]);
useEffect(() => {
if (!authDialog.open || !authDialog.podId || !authDialog.verificationUri) return;
if (authDialog.popup && !authDialog.popup.closed) return;
const popup = window.open(
authDialog.verificationUri,
`sneaksolve-auth-${authDialog.podId}`,
"width=560,height=760,noopener"
);
setAuthDialog((prev) => ({
...prev,
popup: popup || null,
}));
}, [authDialog.open, authDialog.podId, authDialog.verificationUri, authDialog.popup]);
const podCounts = useMemo(() => {
const counts = { IDLE: 0, BUSY: 0, AUTH_REQUIRED: 0, OFFLINE: 0 };
for (const pod of pods) {
counts[pod.status] = (counts[pod.status] || 0) + 1;
}
return counts;
}, [pods]);
const onContestLoadClick = async () => {
const value = Number(contestInput || "");
if (!Number.isFinite(value) || value <= 0) return;
setContestId(value);
setSelectedProblemId(null);
setProblemDetail(null);
await loadContestStatus(value);
};
const openProblem = async (problem) => {
setSelectedProblemId(problem.bojProblemId);
await loadProblemDetail(problem.bojProblemId);
};
const copyAuthCode = async () => {
if (!authDialog.code) return;
try {
await navigator.clipboard.writeText(authDialog.code);
} catch (error) {
console.warn("[SneakSolve] clipboard copy failed", error);
}
};
return (
SneakSolve
Notion-style control room for contest solving and pod authentication.
{lastError ? (
{lastError}
) : null}
Pod Auth
{Object.entries(podCounts).map(([status, count]) => (
{status}: {count}
))}
{pods.map((pod) => (
auth={String(pod.auth_state)} | current={pod.current_job_id || "-"}
{pod.auth_state ? (
account={pod.auth_account_email || "-"}
) : null}
{pod.auth_code ? (
code: {pod.auth_code}
{pod.auth_code_expired ? " (expired)" : ""}
provider: {pod.auth_provider || "-"}
expires: {formatTime(pod.auth_expires_at)}
) : (
No auth code issued
)}
))}
Contest Overview
{contestStatus ? `Contest ${contestStatus.contestId}` : "No contest selected"}
{contests.slice(0, 8).map((contest) => (
))}
{loading.contests ? (
loading contests...
) : null}
{(contestStatus?.problems || []).map((problem) => (
))}
{!loading.contestStatus && (contestStatus?.problems || []).length === 0 ? (
No problems loaded yet. Run Tampermonkey sync first.
) : null}
Problem Detail
{!problemDetail ? (
Select a problem card to view detail.
) : (
#{problemDetail.bojProblemId} · {problemDetail.status}
Core Summary
{problemDetail.coreSummary || "No summary yet."}
Detailed Explanation
{problemDetail.detailedExplanation || "No explanation yet."}
)}
{authDialog.open ? (
Pod Auth In Progress
pod: {authDialog.podId}
Device Code
{authDialog.code || "-"}
expires: {formatTime(authDialog.expiresAt)}
{authDialog.verificationUri ? (
Open verification page
) : null}
Waiting for pod-side challenge and verification. Dialog closes automatically when
auth_state becomes true.
{authDialog.podError ? (
{authDialog.podError}
) : null}
) : null}
);
}
ReactDOM.createRoot(document.getElementById("root")).render();