Add CV extraction review surfaces

This commit is contained in:
2026-03-28 23:51:03 +01:00
parent 107c181506
commit 2392b135c2
7 changed files with 390 additions and 34 deletions
+40
View File
@@ -4,6 +4,23 @@ export type ParsedCvSection = {
wordCount: number;
};
export type StructuredCvFieldMetadata = {
confidence?: number;
method?: string;
sourceSnippet?: string;
sourcePage?: number;
sourceBlockId?: string;
reviewState?: string;
lastUpdatedAtUtc?: string;
};
export type StructuredCvMetadata = {
profileVersion?: number;
appliedExtractionRunId?: number;
updatedAtUtc?: string;
fields: Record<string, StructuredCvFieldMetadata>;
};
export type StructuredCvContact = {
fullName?: string;
headline?: string;
@@ -47,6 +64,7 @@ export type StructuredCvOtherSection = {
export type StructuredCvProfile = {
version: string;
metadata: StructuredCvMetadata;
contact: StructuredCvContact;
summary: string[];
jobs: StructuredCvJob[];
@@ -72,6 +90,7 @@ export function joinLines(values: string[]) {
export function emptyStructuredCv(): StructuredCvProfile {
return {
version: "1",
metadata: { fields: {} },
contact: {},
summary: [],
jobs: [],
@@ -135,6 +154,7 @@ function buildLegacyStructuredCv(sections: ParsedCvSection[]): StructuredCvProfi
return {
...emptyStructuredCv(),
metadata: { fields: {} },
contact,
summary,
skills,
@@ -153,6 +173,22 @@ export function normalizeStructuredCv(value: unknown): StructuredCvProfile {
const sections = normalizeParsedSections(source.sections);
const normalized: StructuredCvProfile = {
version: normalizeString(source.version) ?? "1",
metadata: {
profileVersion: Number.isFinite(Number(source.metadata?.profileVersion)) ? Number(source.metadata.profileVersion) : undefined,
appliedExtractionRunId: Number.isFinite(Number(source.metadata?.appliedExtractionRunId)) ? Number(source.metadata.appliedExtractionRunId) : undefined,
updatedAtUtc: normalizeString(source.metadata?.updatedAtUtc),
fields: source.metadata?.fields && typeof source.metadata.fields === "object"
? Object.fromEntries(Object.entries(source.metadata.fields as Record<string, any>).map(([key, value]) => [key, {
confidence: Number.isFinite(Number(value?.confidence)) ? Number(value.confidence) : undefined,
method: normalizeString(value?.method),
sourceSnippet: normalizeString(value?.sourceSnippet),
sourcePage: Number.isFinite(Number(value?.sourcePage)) ? Number(value.sourcePage) : undefined,
sourceBlockId: normalizeString(value?.sourceBlockId),
reviewState: normalizeString(value?.reviewState),
lastUpdatedAtUtc: normalizeString(value?.lastUpdatedAtUtc),
}]))
: {},
},
contact: {
fullName: normalizeString(source.contact?.fullName),
headline: normalizeString(source.contact?.headline),
@@ -221,3 +257,7 @@ export function parseStructuredCvJson(value?: string): StructuredCvProfile {
return emptyStructuredCv();
}
}
export function getStructuredCvFieldMetadata(profile: StructuredCvProfile, key: string): StructuredCvFieldMetadata | undefined {
return profile.metadata?.fields?.[key];
}