Skip to content

Commit 479b756

Browse files
Your Namecursoragent
andcommitted
Expand admin observability with drill-downs, geo clarity, and LLM tracking.
Clickable dashboard panels, admin-gated detail APIs, full country names with SA highlight, and server-side token logging on all LLM routes for open-beta monitoring without exposing PII. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 0429d72 commit 479b756

32 files changed

Lines changed: 1383 additions & 67 deletions

File tree

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { ok, handleError, enforceRateLimit } from "../../../_utils";
2+
import { parseDaysParam, requireAdmin } from "@/lib/analytics/admin-api";
3+
import { buildAuditInsight } from "@/lib/analytics/drilldown";
4+
5+
export const runtime = "nodejs";
6+
export const dynamic = "force-dynamic";
7+
8+
/** Admin drill-down: per-user or global audit trail (no raw PII). */
9+
export async function GET(req: Request) {
10+
try {
11+
const limited = await enforceRateLimit(req, "default");
12+
if (limited) return limited;
13+
14+
const { user, error } = await requireAdmin();
15+
if (error) return error;
16+
17+
const url = new URL(req.url);
18+
const days = parseDaysParam(req.url);
19+
const userId = url.searchParams.get("userId") || undefined;
20+
const payload = await buildAuditInsight(days, userId);
21+
return ok({ ...payload, admin: { email: user!.email } });
22+
} catch (e) {
23+
return handleError(e);
24+
}
25+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { ok, handleError, enforceRateLimit } from "../../../_utils";
2+
import { parseDaysParam, requireAdmin } from "@/lib/analytics/admin-api";
3+
import { buildGeoInsight } from "@/lib/analytics/drilldown";
4+
5+
export const runtime = "nodejs";
6+
export const dynamic = "force-dynamic";
7+
8+
/** Admin drill-down: geographic traffic with full country names and SA highlight. */
9+
export async function GET(req: Request) {
10+
try {
11+
const limited = await enforceRateLimit(req, "default");
12+
if (limited) return limited;
13+
14+
const { user, error } = await requireAdmin();
15+
if (error) return error;
16+
17+
const days = parseDaysParam(req.url);
18+
const payload = await buildGeoInsight(days);
19+
return ok({ ...payload, admin: { email: user!.email } });
20+
} catch (e) {
21+
return handleError(e);
22+
}
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { ok, handleError, enforceRateLimit } from "../../../_utils";
2+
import { parseDaysParam, requireAdmin } from "@/lib/analytics/admin-api";
3+
import { buildLLMInsight } from "@/lib/analytics/drilldown";
4+
5+
export const runtime = "nodejs";
6+
export const dynamic = "force-dynamic";
7+
8+
/** Admin drill-down: LLM call and token usage statistics. */
9+
export async function GET(req: Request) {
10+
try {
11+
const limited = await enforceRateLimit(req, "default");
12+
if (limited) return limited;
13+
14+
const { user, error } = await requireAdmin();
15+
if (error) return error;
16+
17+
const days = parseDaysParam(req.url);
18+
const payload = await buildLLMInsight(days);
19+
return ok({ ...payload, admin: { email: user!.email } });
20+
} catch (e) {
21+
return handleError(e);
22+
}
23+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { ok, handleError, enforceRateLimit } from "../../../_utils";
2+
import { parseDaysParam, requireAdmin } from "@/lib/analytics/admin-api";
3+
import { buildPageInsight } from "@/lib/analytics/drilldown";
4+
5+
export const runtime = "nodejs";
6+
export const dynamic = "force-dynamic";
7+
8+
/** Admin drill-down: page view breakdown (all pages or single path). */
9+
export async function GET(req: Request) {
10+
try {
11+
const limited = await enforceRateLimit(req, "default");
12+
if (limited) return limited;
13+
14+
const { user, error } = await requireAdmin();
15+
if (error) return error;
16+
17+
const url = new URL(req.url);
18+
const days = parseDaysParam(req.url);
19+
const path = url.searchParams.get("path") || undefined;
20+
const payload = await buildPageInsight(days, path);
21+
return ok({ ...payload, admin: { email: user!.email } });
22+
} catch (e) {
23+
return handleError(e);
24+
}
25+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { ok, handleError, enforceRateLimit } from "../../../_utils";
2+
import { parseDaysParam, requireAdmin } from "@/lib/analytics/admin-api";
3+
import { buildUsersInsight } from "@/lib/analytics/drilldown";
4+
5+
export const runtime = "nodejs";
6+
export const dynamic = "force-dynamic";
7+
8+
/** Admin drill-down: registered users with masked emails and activity stats. */
9+
export async function GET(req: Request) {
10+
try {
11+
const limited = await enforceRateLimit(req, "default");
12+
if (limited) return limited;
13+
14+
const { user, error } = await requireAdmin();
15+
if (error) return error;
16+
17+
const days = parseDaysParam(req.url);
18+
const payload = await buildUsersInsight(days);
19+
return ok({ ...payload, admin: { email: user!.email } });
20+
} catch (e) {
21+
return handleError(e);
22+
}
23+
}

app/api/llm/complete-checklist-item/route.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { bad, handleError, ok, safeJson, enforceRateLimit } from "../../_utils";
22
import { GLOBAL_SYSTEM } from "@/lib/prompts";
3-
import { callLLM, extractJSON, isLLMConfigured } from "@/lib/llm";
3+
import { callLLM, llmTracking, extractJSON, isLLMConfigured } from "@/lib/llm";
44
import type { ResearchTypeAnswersV2 } from "@/lib/types";
55
import { buildContextBundle, bundleToPromptBlock } from "@/lib/agents/contextBundle";
66

@@ -65,6 +65,7 @@ Return ONLY this JSON:
6565
maxTokens: 900,
6666
temperature: 0.15,
6767
jsonOnly: true,
68+
tracking: llmTracking(req, "/api/llm/complete-checklist-item"),
6869
});
6970
const parsed = extractJSON<{
7071
canDraft: boolean;

app/api/llm/cover-letter/route.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { bad, handleError, ok, safeJson, enforceRateLimit } from "../../_utils";
22
import { GLOBAL_SYSTEM } from "@/lib/prompts";
3-
import { callLLM, isLLMConfigured } from "@/lib/llm";
3+
import { callLLM, llmTracking, isLLMConfigured } from "@/lib/llm";
44
import { buildContextBundle, bundleToPromptBlock } from "@/lib/agents/contextBundle";
55
import type { ProjectState } from "@/lib/types";
66

@@ -69,6 +69,7 @@ Return ONLY this JSON:
6969
prompt,
7070
jsonOnly: true,
7171
maxTokens: 1500,
72+
tracking: llmTracking(req, "/api/llm/cover-letter"),
7273
});
7374
let parsed: { letter?: string; warnings?: string[] };
7475
try {

app/api/llm/enhance/route.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { bad, handleError, ok, safeJson, enforceRateLimit } from "../../_utils";
22
import { GLOBAL_SYSTEM } from "@/lib/prompts";
3-
import { callLLM, isLLMConfigured } from "@/lib/llm";
3+
import { callLLM, llmTracking, isLLMConfigured } from "@/lib/llm";
44
import type { ResearchTypeAnswersV2 } from "@/lib/types";
55
import { buildContextBundle, bundleToPromptBlock } from "@/lib/agents/contextBundle";
66

@@ -54,6 +54,7 @@ Return ONLY this JSON:
5454
maxTokens: 400,
5555
temperature: 0.2,
5656
jsonOnly: true,
57+
tracking: llmTracking(req, "/api/llm/enhance"),
5758
});
5859

5960
// Try to parse the JSON; on failure, return the raw text as value.

app/api/llm/final-report/route.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { bad, handleError, ok, safeJson, enforceRateLimit } from "../../_utils";
2-
import { callLLM, extractJSON, isLLMConfigured } from "@/lib/llm";
2+
import { callLLM, llmTracking, extractJSON, isLLMConfigured } from "@/lib/llm";
33
import { GLOBAL_SYSTEM, finalReportPrompt } from "@/lib/prompts";
44
import type { ProjectState } from "@/lib/types";
55
import { buildContextBundle, bundleToPromptBlock } from "@/lib/agents/contextBundle";
@@ -113,6 +113,7 @@ export async function POST(req: Request) {
113113
maxTokens: 4000,
114114
temperature: 0.1,
115115
jsonOnly: true,
116+
tracking: llmTracking(req, "/api/llm/final-report"),
116117
});
117118
let report = extractJSON<Record<string, unknown>>(text1);
118119

@@ -130,6 +131,7 @@ export async function POST(req: Request) {
130131
maxTokens: 4000,
131132
temperature: 0.05,
132133
jsonOnly: true,
134+
tracking: llmTracking(req, "/api/llm/final-report"),
133135
});
134136
report = extractJSON<Record<string, unknown>>(text2);
135137
} catch {

app/api/llm/generate-section/route.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { bad, handleError, ok, safeJson, enforceRateLimit } from "../../_utils";
22
import { GLOBAL_SYSTEM, REFINE_SECTION_SCHEMA } from "@/lib/prompts";
3-
import { callLLM, extractJSON, isLLMConfigured } from "@/lib/llm";
3+
import { callLLM, llmTracking, extractJSON, isLLMConfigured } from "@/lib/llm";
44
import type { LLMRefineResponse, ResearchTypeAnswersV2 } from "@/lib/types";
55
import { designById } from "@/lib/registry/designs";
66
import { guidelineById } from "@/lib/guidelines";
@@ -108,6 +108,7 @@ Return ONLY the JSON object.`;
108108
maxTokens: 4000,
109109
temperature: 0.25,
110110
jsonOnly: true,
111+
tracking: llmTracking(req, "/api/llm/generate-section"),
111112
});
112113
const parsed = extractJSON<LLMRefineResponse>(text);
113114
return ok(parsed);

0 commit comments

Comments
 (0)