-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathagent.js
More file actions
149 lines (125 loc) · 6.62 KB
/
Copy pathagent.js
File metadata and controls
149 lines (125 loc) · 6.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
const { InferenceClient } = require("@huggingface/inference");
const { google } = require('googleapis');
const nodemailer = require('nodemailer');
require('dotenv').config();
const EXPERIENCE = [
{
company: "Unikul Solutions Pvt Ltd.",
role: "Software Developer",
date: "Aug 2024 - Present",
description: "Assisted in developing web-based modules using Python and RESTful APIs. Backend-database integration for analytics dashboards. Built API endpoints. Git version control, CI/CD pipelines. Managed a team and mentored juniors. Implemented Python automation scripts."
},
{
company: "Nexus Info",
role: "AI/ML Intern",
date: "Jun 2024 - Jul 2024",
description: "Data cleaning, feature engineering, and model training using Python and Scikit-learn. Developed chatbots using Python, Flask, and Ollama API. JSON structured data storage."
}
];
const MY_SKILLS = "Python, REST APIs, FastAPI,Javascript,React.js, Node.js, Flask, Scikit-learn, JSON, Git, CI/CD, Automation.";
const hf = new InferenceClient(process.env.HF_TOKEN);
// --- 1. YOUR RESUME DICTIONARY & SOCIAL LINKS ---
const RESUMES = {
"dev_mnc": "https://drive.google.com/file/d/1V3MdkM4PdDPqHYHoZ5X0-RgJ6RgLQit1/view?usp=sharing",
"dev_startup": "https://drive.google.com/file/d/1XHDyoRFuhMcOdQx8Pc_79VxXtdPDYsRw/view?usp=sharing",
"analyst_mnc": "https://drive.google.com/file/d/17MewuAi1JNWoi2kwRCEMFj_tUjzvpX5k/view?usp=sharing",
"analyst_startup": "https://drive.google.com/file/d/1JO-hzswARdQ2sJ2Q1ApY-fbmhg1giKQh/view?usp=sharing"
};
const SOCIALS = `
Best Regards,
Kanak Megha
Portfolio: https://kanak-megha-portfolio.vercel.app/
GitHub: https://github.com/kanakmegha
LinkedIn: https://linkedin.com/in/kanakmegha
`;
// --- 2. SETUP ---
// --- 2. AUTH SETUP ---
const auth = new google.auth.OAuth2(process.env.GOOGLE_CLIENT_ID, process.env.GOOGLE_CLIENT_SECRET, "https://developers.google.com/oauthplayground");
auth.setCredentials({ refresh_token: process.env.GOOGLE_REFRESH_TOKEN });
const sheets = google.sheets({ version: 'v4', auth });
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
type: 'OAuth2',
user: process.env.EMAIL_USER,
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
refreshToken: process.env.GOOGLE_REFRESH_TOKEN,
},
});
const experienceContext = EXPERIENCE.map(e => `${e.role} at ${e.company}: ${e.description}`).join("\n");
async function runAgent() {
try {
console.log("📊 Fetching all data from Sheet1...");
// READ FROM SHEET1
const response = await sheets.spreadsheets.values.get({
spreadsheetId: process.env.SHEET_ID,
range: 'Sheet1!A2:G',
});
const rows = response.data.values;
if (!rows || rows.length === 0) return console.log("No data found.");
for (let i = 0; i < rows.length; i++) {
const rowIndex = i + 2;
const [companyRaw, roleRaw, exp, location, email, status] = rows[i] || [];
// Skip logic: Checks Column F (index 5) in the data we just fetched
if (status?.toLowerCase() === 'sent' || !email || !email.includes('@')) continue;
const company = companyRaw || "your company";
const role = roleRaw || "Software Developer";
try {
console.log(`\n📧 [Row ${rowIndex}] Processing: ${company}`);
// --- 3. AI RESEARCH ---
let category = "dev_mnc";
const research = await hf.chatCompletion({
model: "meta-llama/Llama-3.2-1B-Instruct",
messages: [{ role: "user", content: `Categorize: Company=${company}, Role=${role}. Reply ONLY with one: dev_mnc, dev_startup, analyst_mnc, or analyst_startup.` }],
max_tokens: 10
});
const aiResult = research.choices[0].message.content.trim().toLowerCase();
if (RESUMES[aiResult]) category = aiResult;
// --- 4. STRICT TRUTH GENERATION ---
const emailResponse = await hf.chatCompletion({
model: "meta-llama/Llama-3.2-1B-Instruct",
messages: [
{
role: "system",
content: `You are Kanak Megha. STRICT KNOWLEDGE: ${experienceContext} and ${MY_SKILLS}. FORBIDDEN: R, Apache, Hadoop, SQL, Spark, "5 years". RULES: 2 paragraphs only. Start directly with the text. No headers/greetings.`
},
{ role: "user", content: `Write a cover letter body for ${role} at ${company}.` }
],
max_tokens: 250
});
let aiBody = emailResponse.choices[0].message.content.trim();
const forbiddenPrefixes = ["subject", "dear", "sincerely", "regards", "best", "thanks", "application"];
aiBody = aiBody.split('\n')
.filter(line => !forbiddenPrefixes.some(pref => line.toLowerCase().startsWith(pref)))
.join('\n').trim();
const finalEmail = `Dear Hiring Manager,\n\n${aiBody}\n\nI have included my resume link below for your review:\n${RESUMES[category]}\n\n${SOCIALS.trim()}`;
// --- 5. SEND ---
await transporter.sendMail({
from: process.env.EMAIL_USER,
to: email,
subject: `Application: ${role} at ${company} - Kanak Megha`,
text: finalEmail,
});
// --- 6. WRITE BACK TO SHEET1 (Syncing indices) ---
// F is index 5 (status), G is index 6 (category)
await sheets.spreadsheets.values.update({
spreadsheetId: process.env.SHEET_ID,
range: `Sheet1!F${rowIndex}:G${rowIndex}`,
valueInputOption: 'USER_ENTERED',
resource: { values: [['Sent', category]] },
});
console.log(`✅ Success: Sent ${category} to ${company}`);
// Throttle to avoid Quota Exceeded (6 seconds)
await new Promise(r => setTimeout(r, 6000));
} catch (innerError) {
console.error(`⚠️ Failed row ${rowIndex}:`, innerError.message);
if (innerError.message.includes("quota")) return;
}
}
console.log("\n🏁 All rows processed!");
} catch (error) {
console.error("❌ CRITICAL ERROR:", error.message);
}
}
runAgent();