fix(ai): provide current date to resume analysis (#3353)

This commit is contained in:
Emanuele Tonello
2026-08-19 05:48:31 +02:00
committed by GitHub
parent 4d53a6d1de
commit 8acde4c1ac
3 changed files with 27 additions and 3 deletions
@@ -47,6 +47,7 @@ Do not include markdown, comments, or additional keys.
4. Never invent candidate achievements or facts.
5. If data is missing, call it out explicitly in rationale/suggestions.
6. Keep scorecard dimensions practical and common for resume review.
7. Use the current date from the analysis context for chronology checks. Do not flag a date on or before that date as future-dated.
## Suggestions Requirements
+23 -1
View File
@@ -1,4 +1,5 @@
import type { UIMessage } from "ai";
import type { ResumeData } from "@reactive-resume/schema/resume/data";
import { afterEach, describe, expect, it, vi } from "vitest";
import { convertToModelMessages, modelMessageSchema } from "ai";
@@ -10,6 +11,7 @@ vi.mock("@reactive-resume/env/server", () => ({ env: envMock }));
afterEach(() => {
vi.unstubAllGlobals();
vi.useRealTimers();
});
function stubOpenAICompatibleResponse(response?: { content?: string; finishReason?: string }) {
@@ -67,7 +69,7 @@ function stubRejectedFetch(error: unknown) {
return fetchMock;
}
const { testConnection } = await import("./service");
const { analyzeResume, testConnection } = await import("./service");
describe("AI provider connection test", () => {
it("names the rejected key instead of reporting a transport failure", async () => {
@@ -168,6 +170,26 @@ describe("AI provider connection test", () => {
});
});
describe("AI resume analysis", () => {
it("gives the model the actual current date for chronology checks", async () => {
vi.useFakeTimers();
vi.setSystemTime(new Date("2026-08-18T12:00:00Z"));
const response = stubOpenAICompatibleResponse({
content: JSON.stringify({
overallScore: 80,
scorecard: [{ dimension: "Clarity", score: 80, rationale: "Clear." }],
suggestions: [],
strengths: ["Clear experience."],
}),
});
await analyzeResume({ ...testInput(), resumeData: {} as ResumeData });
expect(JSON.stringify(response.getRequestBody())).toContain("Current date: 2026-08-18");
});
});
describe("AI chat service", () => {
it("tests OpenAI-compatible providers without requiring structured output", async () => {
const openAiCompatible = stubOpenAICompatibleResponse();
+3 -2
View File
@@ -509,8 +509,9 @@ type AnalyzeResumeInput = z.infer<typeof aiCredentialsSchema> & {
resumeData: ResumeData;
};
function buildAnalyzeResumeSystemPrompt(resumeData: ResumeData): string {
return `${analyzeResumeSystemPromptTemplate}\n\n## Resume Data\n\n${JSON.stringify(resumeData, null, 2)}`;
function buildAnalyzeResumeSystemPrompt(resumeData: ResumeData, now = new Date()): string {
const currentDate = now.toISOString().slice(0, 10);
return `${analyzeResumeSystemPromptTemplate}\n\n## Analysis Context\n\nCurrent date: ${currentDate} (UTC). Treat dates on or before this date as not future-dated. Flag a date as future-dated only when it is after the current date.\n\n## Resume Data\n\n${JSON.stringify(resumeData, null, 2)}`;
}
/** Sends resume data to the AI provider and returns a structured analysis, parsing raw JSON from the response text. */