mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-08-23 23:02:17 +10:00
fix(ai): provide current date to resume analysis (#3353)
This commit is contained in:
@@ -47,6 +47,7 @@ Do not include markdown, comments, or additional keys.
|
|||||||
4. Never invent candidate achievements or facts.
|
4. Never invent candidate achievements or facts.
|
||||||
5. If data is missing, call it out explicitly in rationale/suggestions.
|
5. If data is missing, call it out explicitly in rationale/suggestions.
|
||||||
6. Keep scorecard dimensions practical and common for resume review.
|
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
|
## Suggestions Requirements
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { UIMessage } from "ai";
|
import type { UIMessage } from "ai";
|
||||||
|
import type { ResumeData } from "@reactive-resume/schema/resume/data";
|
||||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||||
import { convertToModelMessages, modelMessageSchema } from "ai";
|
import { convertToModelMessages, modelMessageSchema } from "ai";
|
||||||
|
|
||||||
@@ -10,6 +11,7 @@ vi.mock("@reactive-resume/env/server", () => ({ env: envMock }));
|
|||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
vi.unstubAllGlobals();
|
vi.unstubAllGlobals();
|
||||||
|
vi.useRealTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
function stubOpenAICompatibleResponse(response?: { content?: string; finishReason?: string }) {
|
function stubOpenAICompatibleResponse(response?: { content?: string; finishReason?: string }) {
|
||||||
@@ -67,7 +69,7 @@ function stubRejectedFetch(error: unknown) {
|
|||||||
return fetchMock;
|
return fetchMock;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { testConnection } = await import("./service");
|
const { analyzeResume, testConnection } = await import("./service");
|
||||||
|
|
||||||
describe("AI provider connection test", () => {
|
describe("AI provider connection test", () => {
|
||||||
it("names the rejected key instead of reporting a transport failure", async () => {
|
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", () => {
|
describe("AI chat service", () => {
|
||||||
it("tests OpenAI-compatible providers without requiring structured output", async () => {
|
it("tests OpenAI-compatible providers without requiring structured output", async () => {
|
||||||
const openAiCompatible = stubOpenAICompatibleResponse();
|
const openAiCompatible = stubOpenAICompatibleResponse();
|
||||||
|
|||||||
@@ -509,8 +509,9 @@ type AnalyzeResumeInput = z.infer<typeof aiCredentialsSchema> & {
|
|||||||
resumeData: ResumeData;
|
resumeData: ResumeData;
|
||||||
};
|
};
|
||||||
|
|
||||||
function buildAnalyzeResumeSystemPrompt(resumeData: ResumeData): string {
|
function buildAnalyzeResumeSystemPrompt(resumeData: ResumeData, now = new Date()): string {
|
||||||
return `${analyzeResumeSystemPromptTemplate}\n\n## Resume Data\n\n${JSON.stringify(resumeData, null, 2)}`;
|
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. */
|
/** Sends resume data to the AI provider and returns a structured analysis, parsing raw JSON from the response text. */
|
||||||
|
|||||||
Reference in New Issue
Block a user