|
|
|
|
@@ -2,6 +2,25 @@ import { Hono } from "hono";
|
|
|
|
|
import { requireUser, type AuthContext } from "../auth/clerk.js";
|
|
|
|
|
import { listServiceCapabilities } from "../workflows/service-capabilities.js";
|
|
|
|
|
import { interviewService, resumeService, roleplayService, type JsonObject } from "../services/product-service-clients.js";
|
|
|
|
|
import { db } from "../db/client.js";
|
|
|
|
|
import { events } from "../db/schema.js";
|
|
|
|
|
|
|
|
|
|
const DEFAULT_QSCORE = {
|
|
|
|
|
q_score: 76,
|
|
|
|
|
profession: "Student",
|
|
|
|
|
quotients: {
|
|
|
|
|
SQ: 76,
|
|
|
|
|
XQ: 74,
|
|
|
|
|
CQm: 78,
|
|
|
|
|
VQ: 72,
|
|
|
|
|
DQ: 75,
|
|
|
|
|
GQ: 80,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
async function recordServiceEvent(userId: string, type: string, payload: Record<string, unknown>) {
|
|
|
|
|
await db.insert(events).values({ userId, actorId: "service-gateway", type, payload });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function serviceRoutes() {
|
|
|
|
|
const app = new Hono<AuthContext>();
|
|
|
|
|
@@ -17,7 +36,18 @@ export function serviceRoutes() {
|
|
|
|
|
return c.json({ error: "unknown_service" }, 404);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
app.post("/interview/configure", async (c) => c.json(await interviewService.configure(await c.req.json<JsonObject>())));
|
|
|
|
|
app.get("/interview/page-state", async (c) => c.json(await interviewService.pageState(c.get("userId"))));
|
|
|
|
|
app.post("/interview/configure", async (c) => {
|
|
|
|
|
const body = await c.req.json<JsonObject>();
|
|
|
|
|
const payload = {
|
|
|
|
|
...body,
|
|
|
|
|
user_id: String(body.user_id ?? c.get("userId")),
|
|
|
|
|
org_id: String(body.org_id ?? "growqr"),
|
|
|
|
|
} satisfies JsonObject;
|
|
|
|
|
const result = await interviewService.configure(payload);
|
|
|
|
|
await recordServiceEvent(c.get("userId"), "interview.configured", { request: payload, result });
|
|
|
|
|
return c.json(result);
|
|
|
|
|
});
|
|
|
|
|
app.post("/interview/preview", async (c) => c.json(await interviewService.preview(await c.req.json<JsonObject>())));
|
|
|
|
|
app.post("/interview/questions", async (c) => c.json(await interviewService.editQuestions(await c.req.json())));
|
|
|
|
|
app.post("/interview/approve", async (c) => {
|
|
|
|
|
@@ -28,13 +58,30 @@ export function serviceRoutes() {
|
|
|
|
|
app.get("/interview/assignments", async (c) => c.json(await interviewService.listAssignments(c.req.query("email") ?? "", c.req.query("status") ?? "pending", Number(c.req.query("limit") ?? 20))));
|
|
|
|
|
app.post("/interview/assignments/unassign", async (c) => c.json(await interviewService.unassign(await c.req.json())));
|
|
|
|
|
app.post("/interview/results:bulk", async (c) => c.json(await interviewService.resultsBulk(await c.req.json<JsonObject>())));
|
|
|
|
|
app.get("/interview/review/:sessionId", async (c) => c.json(await interviewService.review(c.req.param("sessionId"))));
|
|
|
|
|
app.get("/interview/review/:sessionId", async (c) => {
|
|
|
|
|
const sessionId = c.req.param("sessionId");
|
|
|
|
|
const result = await interviewService.review(sessionId);
|
|
|
|
|
await recordServiceEvent(c.get("userId"), "interview.review_checked", { sessionId, result });
|
|
|
|
|
return c.json(result);
|
|
|
|
|
});
|
|
|
|
|
app.get("/interview/leaderboard", async (c) => c.json(await interviewService.leaderboard()));
|
|
|
|
|
app.get("/interview/artifacts/:sessionId/:artifactType", async (c) => c.json(await interviewService.artifact(c.req.param("sessionId"), c.req.param("artifactType"))));
|
|
|
|
|
app.post("/interview/sessions/:sessionId/video/upload-url", async (c) => c.json(await interviewService.createVideoUploadUrl(c.req.param("sessionId"), await c.req.json<JsonObject>())));
|
|
|
|
|
app.post("/interview/sessions/:sessionId/video/uploaded", async (c) => c.json(await interviewService.markVideoUploaded(c.req.param("sessionId"), await c.req.json<JsonObject>())));
|
|
|
|
|
|
|
|
|
|
app.post("/roleplay/configure", async (c) => c.json(await roleplayService.configure(await c.req.json<JsonObject>())));
|
|
|
|
|
app.get("/roleplay/page-state", async (c) => c.json(await roleplayService.pageState(c.get("userId"))));
|
|
|
|
|
app.post("/roleplay/configure", async (c) => {
|
|
|
|
|
const body = await c.req.json<JsonObject>();
|
|
|
|
|
const payload = {
|
|
|
|
|
...body,
|
|
|
|
|
user_id: String(body.user_id ?? c.get("userId")),
|
|
|
|
|
org_id: String(body.org_id ?? "growqr"),
|
|
|
|
|
qscore: (body.qscore as JsonObject | undefined) ?? DEFAULT_QSCORE,
|
|
|
|
|
} satisfies JsonObject;
|
|
|
|
|
const result = await roleplayService.configure(payload);
|
|
|
|
|
await recordServiceEvent(c.get("userId"), "roleplay.configured", { request: payload, result });
|
|
|
|
|
return c.json(result);
|
|
|
|
|
});
|
|
|
|
|
app.post("/roleplay/preview", async (c) => c.json(await roleplayService.preview(await c.req.json<JsonObject>())));
|
|
|
|
|
app.post("/roleplay/questions", async (c) => c.json(await roleplayService.editQuestions(await c.req.json())));
|
|
|
|
|
app.post("/roleplay/approve", async (c) => {
|
|
|
|
|
@@ -45,7 +92,12 @@ export function serviceRoutes() {
|
|
|
|
|
app.get("/roleplay/assignments", async (c) => c.json(await roleplayService.listAssignments(c.req.query("email") ?? "", c.req.query("status") ?? "pending", Number(c.req.query("limit") ?? 20))));
|
|
|
|
|
app.post("/roleplay/assignments/unassign", async (c) => c.json(await roleplayService.unassign(await c.req.json())));
|
|
|
|
|
app.post("/roleplay/results:bulk", async (c) => c.json(await roleplayService.resultsBulk(await c.req.json<JsonObject>())));
|
|
|
|
|
app.get("/roleplay/review/:sessionId", async (c) => c.json(await roleplayService.review(c.req.param("sessionId"))));
|
|
|
|
|
app.get("/roleplay/review/:sessionId", async (c) => {
|
|
|
|
|
const sessionId = c.req.param("sessionId");
|
|
|
|
|
const result = await roleplayService.review(sessionId);
|
|
|
|
|
await recordServiceEvent(c.get("userId"), "roleplay.review_checked", { sessionId, result });
|
|
|
|
|
return c.json(result);
|
|
|
|
|
});
|
|
|
|
|
app.get("/roleplay/leaderboard", async (c) => c.json(await roleplayService.leaderboard()));
|
|
|
|
|
app.get("/roleplay/artifacts/:sessionId/:artifactType", async (c) => c.json(await roleplayService.artifact(c.req.param("sessionId"), c.req.param("artifactType"))));
|
|
|
|
|
app.post("/roleplay/sessions/:sessionId/video/upload-url", async (c) => c.json(await roleplayService.createVideoUploadUrl(c.req.param("sessionId"), await c.req.json<JsonObject>())));
|
|
|
|
|
@@ -61,7 +113,13 @@ export function serviceRoutes() {
|
|
|
|
|
app.post("/resume/resumes", async (c) => c.json(await resumeService.createResume(await c.req.json<JsonObject>())));
|
|
|
|
|
app.get("/resume/resumes/:resumeId", async (c) => c.json(await resumeService.getResume(c.req.param("resumeId"))));
|
|
|
|
|
app.put("/resume/resumes/:resumeId", async (c) => c.json(await resumeService.updateResume(c.req.param("resumeId"), await c.req.json<JsonObject>())));
|
|
|
|
|
app.post("/resume/resumes/:resumeId/analyze", async (c) => c.json(await resumeService.analyzeResume(c.req.param("resumeId"), await c.req.json<JsonObject>().catch(() => ({})))));
|
|
|
|
|
app.post("/resume/resumes/:resumeId/analyze", async (c) => {
|
|
|
|
|
const resumeId = c.req.param("resumeId");
|
|
|
|
|
const payload = await c.req.json<JsonObject>().catch(() => ({}));
|
|
|
|
|
const result = await resumeService.analyzeResume(resumeId, payload);
|
|
|
|
|
await recordServiceEvent(c.get("userId"), "resume.analysis_completed", { resumeId, request: payload, result });
|
|
|
|
|
return c.json(result);
|
|
|
|
|
});
|
|
|
|
|
app.get("/resume/resumes/:resumeId/suggestions", async (c) => c.json(await resumeService.suggestions(c.req.param("resumeId"))));
|
|
|
|
|
app.post("/resume/ai/copilot", async (c) => c.json(await resumeService.copilot(await c.req.json<JsonObject>())));
|
|
|
|
|
app.post("/resume/ai/optimize-summary", async (c) => c.json(await resumeService.optimizeSummary(await c.req.json<JsonObject>())));
|
|
|
|
|
|