feat: meter AI usage
This commit is contained in:
@@ -14,7 +14,7 @@ import ReplayIcon from "@mui/icons-material/Replay";
|
||||
import { getApiErrorMessage } from "../api";
|
||||
import { useToast } from "../toast";
|
||||
import Markdown from "./Markdown";
|
||||
import { AI_MODULES, AiInteraction, COVER_LETTER_MODES, aiWorkspaceApi } from "../aiWorkspace";
|
||||
import { AI_MODULES, AiInteraction, AiUsage, COVER_LETTER_MODES, aiWorkspaceApi } from "../aiWorkspace";
|
||||
|
||||
// Phase 5 — the central AI Workspace for one job application. Every result is a suggestion the user
|
||||
// reviews and copies; nothing is applied automatically.
|
||||
@@ -24,6 +24,7 @@ export default function AiWorkspacePanel({ jobId }: { jobId: number }) {
|
||||
const [mode, setMode] = useState("professional");
|
||||
const [extra, setExtra] = useState("");
|
||||
const [provider, setProvider] = useState("");
|
||||
const [usage, setUsage] = useState<AiUsage | null>(null);
|
||||
const [busy, setBusy] = useState(false);
|
||||
const [current, setCurrent] = useState<AiInteraction | null>(null);
|
||||
const [history, setHistory] = useState<AiInteraction[]>([]);
|
||||
@@ -44,6 +45,7 @@ export default function AiWorkspacePanel({ jobId }: { jobId: number }) {
|
||||
|
||||
useEffect(() => {
|
||||
aiWorkspaceApi.modules(jobId).then((r) => setProvider(r.provider)).catch(() => undefined);
|
||||
aiWorkspaceApi.usage().then(setUsage).catch(() => undefined);
|
||||
loadHistory();
|
||||
}, [jobId, loadHistory]);
|
||||
|
||||
@@ -54,6 +56,7 @@ export default function AiWorkspacePanel({ jobId }: { jobId: number }) {
|
||||
const res = await aiWorkspaceApi.generate(jobId, { module, mode: module === "cover-letter" ? mode : undefined, extraContext: extra || undefined });
|
||||
setCurrent(res);
|
||||
setHistory((h) => [res, ...h]);
|
||||
aiWorkspaceApi.usage().then(setUsage).catch(() => undefined);
|
||||
} catch (err) {
|
||||
toast(getApiErrorMessage(err, "AI generation failed."), "error");
|
||||
} finally {
|
||||
@@ -85,6 +88,7 @@ export default function AiWorkspacePanel({ jobId }: { jobId: number }) {
|
||||
<Alert severity="info" sx={{ py: 0.5 }}>
|
||||
AI suggestions never change your profile, CVs, or this application. Review, then copy what you want to keep.
|
||||
{provider && <> Provider: <strong>{provider}</strong>.</>}
|
||||
{usage && <> This month: <strong>{usage.currentMonth.calls}</strong> runs · approximately <strong>{usage.currentMonth.estimatedTokens.toLocaleString()}</strong> tokens.</>}
|
||||
</Alert>
|
||||
|
||||
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 1 }}>
|
||||
|
||||
Reference in New Issue
Block a user