* feat(settings): add rxresume mode and v5 api key settings * feat(server): add mode-aware rxresume adapter with auto v5-first selection * refactor(server): route settings profile and pdf generation through rxresume adapter * feat(api): support rxresume v4/v5 in onboarding and settings routes with ok/meta responses * feat(client): add rxresume mode selector and v5 api key setup flow * docs: document rxresume auto mode with v5-first self-hosted setup * test: verify dual-mode rxresume support and ci parity checks * comments * services folder * correct types for v5 * tests and docs fix * Fix RxResume auto fallback and route API consistency * warning for both being set * simpler response * onboarding component improvements, v5 check still not working * fix list resume endpoint... * fix api endpoints to latest v5 docs * don't show the entire project field on v5 * remove auto entirely * formatting * ci green * v5 has a different resume schema * remove redundant check * remove requirement that only one must be specified * consolidate sections * base resume can be v4 or v5 * saving now works * status indicator * actually render some pills * reason for failure * fix apikey verification * dedupe isValidatingMode * reefactoor * simplification? * refactor? * ci passing * remove auto from docs * tailoring is schema dependent * skills object tighter * remove redundant text * fix lint * mode
207 lines
5.5 KiB
TypeScript
207 lines
5.5 KiB
TypeScript
import type {
|
|
ApplicationTask,
|
|
AppSettings,
|
|
Job,
|
|
PipelineRun,
|
|
ResumeProjectCatalogItem,
|
|
StageEvent,
|
|
} from "../types";
|
|
|
|
export const createJob = (overrides: Partial<Job> = {}): Job => ({
|
|
id: "job-1",
|
|
source: "linkedin",
|
|
sourceJobId: null,
|
|
jobUrlDirect: null,
|
|
datePosted: null,
|
|
title: "Backend Engineer",
|
|
employer: "Acme Labs",
|
|
employerUrl: null,
|
|
jobUrl: "https://example.com/job-1",
|
|
applicationLink: "https://example.com/apply",
|
|
disciplines: null,
|
|
deadline: null,
|
|
salary: null,
|
|
location: "California",
|
|
degreeRequired: null,
|
|
starting: null,
|
|
jobDescription: "Job description content",
|
|
status: "ready",
|
|
outcome: null,
|
|
closedAt: null,
|
|
suitabilityScore: 90,
|
|
suitabilityReason: "Strong fit",
|
|
tailoredSummary: null,
|
|
tailoredHeadline: null,
|
|
tailoredSkills: null,
|
|
selectedProjectIds: null,
|
|
pdfPath: null,
|
|
tracerLinksEnabled: false,
|
|
sponsorMatchScore: null,
|
|
sponsorMatchNames: null,
|
|
jobType: null,
|
|
salarySource: null,
|
|
salaryInterval: null,
|
|
salaryMinAmount: null,
|
|
salaryMaxAmount: null,
|
|
salaryCurrency: null,
|
|
isRemote: null,
|
|
jobLevel: null,
|
|
jobFunction: null,
|
|
listingType: null,
|
|
emails: null,
|
|
companyIndustry: null,
|
|
companyLogo: null,
|
|
companyUrlDirect: null,
|
|
companyAddresses: null,
|
|
companyNumEmployees: null,
|
|
companyRevenue: null,
|
|
companyDescription: null,
|
|
skills: null,
|
|
experienceRange: null,
|
|
companyRating: null,
|
|
companyReviewsCount: null,
|
|
vacancyCount: null,
|
|
workFromHomeType: null,
|
|
discoveredAt: "2025-01-01T00:00:00Z",
|
|
processedAt: null,
|
|
appliedAt: null,
|
|
createdAt: "2025-01-01T00:00:00Z",
|
|
updatedAt: "2025-01-01T00:00:00Z",
|
|
...overrides,
|
|
});
|
|
|
|
export const createStageEvent = (
|
|
overrides: Partial<StageEvent> = {},
|
|
): StageEvent => ({
|
|
id: "event-1",
|
|
applicationId: "job-1",
|
|
title: "Moved to applied",
|
|
groupId: null,
|
|
fromStage: null,
|
|
toStage: "applied",
|
|
occurredAt: Date.now(),
|
|
metadata: null,
|
|
outcome: null,
|
|
...overrides,
|
|
});
|
|
|
|
export const createApplicationTask = (
|
|
overrides: Partial<ApplicationTask> = {},
|
|
): ApplicationTask => ({
|
|
id: "task-1",
|
|
applicationId: "job-1",
|
|
type: "todo",
|
|
title: "Follow up",
|
|
dueDate: null,
|
|
isCompleted: false,
|
|
notes: null,
|
|
...overrides,
|
|
});
|
|
|
|
export const createPipelineRun = (
|
|
overrides: Partial<PipelineRun> = {},
|
|
): PipelineRun => ({
|
|
id: "run-1",
|
|
startedAt: "2025-01-01T00:00:00Z",
|
|
completedAt: null,
|
|
status: "running",
|
|
jobsDiscovered: 0,
|
|
jobsProcessed: 0,
|
|
errorMessage: null,
|
|
...overrides,
|
|
});
|
|
|
|
export const createResumeProjectCatalogItem = (
|
|
overrides: Partial<ResumeProjectCatalogItem> = {},
|
|
): ResumeProjectCatalogItem => ({
|
|
id: "p1",
|
|
name: "Project 1",
|
|
description: "Description 1",
|
|
date: "2024",
|
|
isVisibleInBase: true,
|
|
...overrides,
|
|
});
|
|
|
|
export const createAppSettings = (
|
|
overrides: Partial<AppSettings> = {},
|
|
): AppSettings => ({
|
|
model: { value: "gpt-4o", default: "gpt-4o", override: null },
|
|
modelScorer: { value: "gpt-4o", override: null },
|
|
modelTailoring: { value: "gpt-4o", override: null },
|
|
modelProjectSelection: { value: "gpt-4o", override: null },
|
|
llmProvider: { value: "openai", default: "openai", override: null },
|
|
llmBaseUrl: {
|
|
value: "https://api.openai.com/v1",
|
|
default: "https://api.openai.com/v1",
|
|
override: null,
|
|
},
|
|
pipelineWebhookUrl: { value: "", default: "", override: null },
|
|
jobCompleteWebhookUrl: { value: "", default: "", override: null },
|
|
profileProjects: [],
|
|
resumeProjects: {
|
|
value: { maxProjects: 3, lockedProjectIds: [], aiSelectableProjectIds: [] },
|
|
default: {
|
|
maxProjects: 3,
|
|
lockedProjectIds: [],
|
|
aiSelectableProjectIds: [],
|
|
},
|
|
override: null,
|
|
},
|
|
rxresumeBaseResumeId: null,
|
|
rxresumeBaseResumeIdV4: null,
|
|
rxresumeBaseResumeIdV5: null,
|
|
ukvisajobsMaxJobs: { value: 50, default: 50, override: null },
|
|
adzunaMaxJobsPerTerm: { value: 50, default: 50, override: null },
|
|
gradcrackerMaxJobsPerTerm: { value: 50, default: 50, override: null },
|
|
searchTerms: {
|
|
value: ["Software Engineer"],
|
|
default: ["Software Engineer"],
|
|
override: null,
|
|
},
|
|
blockedCompanyKeywords: {
|
|
value: [],
|
|
default: [],
|
|
override: null,
|
|
},
|
|
searchCities: {
|
|
value: "United Kingdom",
|
|
default: "United Kingdom",
|
|
override: null,
|
|
},
|
|
jobspyResultsWanted: { value: 20, default: 20, override: null },
|
|
jobspyCountryIndeed: {
|
|
value: "united kingdom",
|
|
default: "united kingdom",
|
|
override: null,
|
|
},
|
|
showSponsorInfo: { value: true, default: true, override: null },
|
|
chatStyleTone: {
|
|
value: "professional",
|
|
default: "professional",
|
|
override: null,
|
|
},
|
|
chatStyleFormality: { value: "medium", default: "medium", override: null },
|
|
chatStyleConstraints: { value: "", default: "", override: null },
|
|
chatStyleDoNotUse: { value: "", default: "", override: null },
|
|
llmApiKeyHint: null,
|
|
rxresumeApiKeyHint: null,
|
|
rxresumeEmail: null,
|
|
rxresumePasswordHint: null,
|
|
basicAuthUser: null,
|
|
basicAuthPasswordHint: null,
|
|
ukvisajobsEmail: null,
|
|
ukvisajobsPasswordHint: null,
|
|
adzunaAppId: null,
|
|
adzunaAppKeyHint: null,
|
|
webhookSecretHint: null,
|
|
basicAuthActive: false,
|
|
backupEnabled: { value: false, default: false, override: null },
|
|
backupHour: { value: 3, default: 3, override: null },
|
|
backupMaxCount: { value: 7, default: 7, override: null },
|
|
penalizeMissingSalary: { value: false, default: false, override: null },
|
|
missingSalaryPenalty: { value: 10, default: 10, override: null },
|
|
autoSkipScoreThreshold: { value: null, default: null, override: null },
|
|
rxresumeMode: { value: "v5", default: "v5", override: null },
|
|
...overrides,
|
|
});
|