Compare commits
1 commit
5fe330f9fb
...
d5734bc3d7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5734bc3d7 |
5 changed files with 26 additions and 144 deletions
26
.agents/mcp_config.json
Normal file
26
.agents/mcp_config.json
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"mcpServers": {
|
||||
"supabase": {
|
||||
"type": "http",
|
||||
"serverUrl": "https://mcp.supabase.com/mcp?project_ref=qynbahcxyenxreplmyam",
|
||||
"headers": {
|
||||
"Authorization": "Bearer sbp_2f51ed33e9a5bb75664b888bd8667823593ab3b0"
|
||||
}
|
||||
},
|
||||
"next-devtools": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "next-devtools-mcp@latest"]
|
||||
},
|
||||
"n8n-mcp": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "n8n-mcp"]
|
||||
},
|
||||
"vercel": {
|
||||
"type": "http",
|
||||
"serverUrl": "https://mcp.vercel.com",
|
||||
"headers": {
|
||||
"Authorization": "Bearer vcp_0iOjcKWnaTMxaMAzpXw7RI0FcPs1wwrpkwoHrbBHDu4KukjqFN37fhdr"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -40,6 +40,3 @@ yarn-error.log*
|
|||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
|
||||
# agents config
|
||||
.agents/
|
||||
|
|
|
|||
|
|
@ -1,39 +0,0 @@
|
|||
import "./load-env";
|
||||
import { createServerSupabaseClient } from "@/lib/supabase";
|
||||
|
||||
async function main() {
|
||||
const supabase = createServerSupabaseClient();
|
||||
const { data: interviews, error } = await supabase
|
||||
.from("interviews")
|
||||
.select("*, candidates(name, contact_info), jobs(title, requirements)");
|
||||
|
||||
if (error) {
|
||||
console.error("Error fetching interviews:", error.message);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("Found interviews:", interviews?.length);
|
||||
for (const i of interviews || []) {
|
||||
const candidateId = i.candidate_id;
|
||||
const jobId = i.job_id;
|
||||
|
||||
// Fetch latest score
|
||||
const { data: scores } = await supabase
|
||||
.from("scores")
|
||||
.select("*")
|
||||
.eq("candidate_id", candidateId)
|
||||
.eq("job_id", jobId)
|
||||
.order("created_at", { ascending: false })
|
||||
.limit(1);
|
||||
|
||||
const score = scores?.[0];
|
||||
console.log(`Interview ID: ${i.id}`);
|
||||
console.log(` Candidate: ${i.candidates?.name}`);
|
||||
console.log(` Job: ${i.jobs?.title}`);
|
||||
console.log(` AI Score: ${score ? score.ai_score : "No Score"}`);
|
||||
console.log(` AI Classification: ${score ? score.evaluation.classification : "No Score"}`);
|
||||
console.log("---------------------------------------");
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
import "./load-env";
|
||||
import { createServerSupabaseClient } from "@/lib/supabase";
|
||||
|
||||
const skillsMatch = (candSkill: string, jobSkill: string): boolean => {
|
||||
const c = candSkill.toLowerCase().trim();
|
||||
const j = jobSkill.toLowerCase().trim();
|
||||
if (c === j) return true;
|
||||
if (c.includes(j) || j.includes(c)) return true;
|
||||
|
||||
const cWords = c.split(/[\s,./()&+-]+/).filter(w => w.length > 2);
|
||||
const jWords = j.split(/[\s,./()&+-]+/).filter(w => w.length > 2);
|
||||
|
||||
const stopWords = ['and', 'for', 'with', 'the', 'management', 'administration', 'development', 'developer', 'engineer', 'system', 'systems', 'integration', 'operations', 'knowledge', 'experience', 'expert', 'proficiency', 'proficient'];
|
||||
|
||||
const sharedWords = cWords.filter(w => jWords.includes(w) && !stopWords.includes(w));
|
||||
return sharedWords.length > 0;
|
||||
};
|
||||
|
||||
async function main() {
|
||||
const supabase = createServerSupabaseClient();
|
||||
|
||||
// 1. Fetch all interviews
|
||||
const { data: interviews, error: interviewsError } = await supabase
|
||||
.from("interviews")
|
||||
.select("*, candidates(*), jobs(*)");
|
||||
|
||||
if (interviewsError) {
|
||||
console.error("Error fetching interviews:", interviewsError.message);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Analyzing ${interviews?.length} interviews...`);
|
||||
|
||||
for (const i of interviews || []) {
|
||||
const candidate = i.candidates;
|
||||
const job = i.jobs;
|
||||
if (!candidate || !job) continue;
|
||||
|
||||
// Check skills overlap
|
||||
const jobSkills: string[] = job.requirements?.skills || [];
|
||||
const candidateSkills: string[] = candidate.contact_info?.skills || [];
|
||||
const matchedSkills = jobSkills.filter((js) =>
|
||||
candidateSkills.some((cs) => skillsMatch(cs, js))
|
||||
);
|
||||
|
||||
const overlapCount = matchedSkills.length;
|
||||
const totalRequired = jobSkills.length;
|
||||
const matchPct = totalRequired > 0 ? Math.round((overlapCount / totalRequired) * 100) : 0;
|
||||
const isPotentialMatch = matchPct >= 75;
|
||||
|
||||
// Fetch score
|
||||
const { data: scores } = await supabase
|
||||
.from("scores")
|
||||
.select("*")
|
||||
.eq("candidate_id", candidate.id)
|
||||
.eq("job_id", job.id)
|
||||
.order("created_at", { ascending: false })
|
||||
.limit(1);
|
||||
|
||||
const score = scores?.[0];
|
||||
const isUnqualified = score?.evaluation?.classification === "Unqualified";
|
||||
|
||||
if (!isPotentialMatch || isUnqualified) {
|
||||
console.log(`Deleting interview ID ${i.id}:`);
|
||||
console.log(` Candidate: ${candidate.name}`);
|
||||
console.log(` Job: ${job.title}`);
|
||||
console.log(` Reason: ${!isPotentialMatch ? `Skill mismatch (${matchPct}% overlap)` : 'Deemed Unqualified by AI'}`);
|
||||
|
||||
const { error: deleteError } = await supabase
|
||||
.from("interviews")
|
||||
.delete()
|
||||
.eq("id", i.id);
|
||||
|
||||
if (deleteError) {
|
||||
console.error(` Failed to delete: ${deleteError.message}`);
|
||||
} else {
|
||||
console.log(" Successfully deleted.");
|
||||
}
|
||||
} else {
|
||||
console.log(`Keeping interview ID ${i.id} for ${candidate.name} - ${job.title}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
|
||||
const envPath = path.resolve(process.cwd(), ".env");
|
||||
if (fs.existsSync(envPath)) {
|
||||
const envContent = fs.readFileSync(envPath, "utf8");
|
||||
for (const line of envContent.split("\n")) {
|
||||
const match = line.match(/^\s*([\w.-]+)\s*=\s*(.*)\s*$/);
|
||||
if (match) {
|
||||
const key = match[1];
|
||||
let value = match[2].trim();
|
||||
if (value.startsWith('"') && value.endsWith('"')) value = value.slice(1, -1);
|
||||
else if (value.startsWith("'") && value.endsWith("'")) value = value.slice(1, -1);
|
||||
process.env[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue