@agenticmail/enterprise 0.5.533 ā 0.5.535
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-tools-DPFLLLPX.js +14677 -0
- package/dist/agent-tools-LGYJAAQC.js +14677 -0
- package/dist/agent-tools-QKPZR7G7.js +14677 -0
- package/dist/chunk-3BDIHYJC.js +5703 -0
- package/dist/chunk-444JTF2W.js +2309 -0
- package/dist/chunk-7QK66JEZ.js +5703 -0
- package/dist/chunk-AQC7U6S5.js +1728 -0
- package/dist/chunk-AZ6J36XT.js +2309 -0
- package/dist/chunk-BEGUEOCV.js +6049 -0
- package/dist/chunk-CGKHMXPI.js +1728 -0
- package/dist/chunk-COW5UCDA.js +2309 -0
- package/dist/chunk-ELB4CQC7.js +1687 -0
- package/dist/chunk-MKEIIEBO.js +1728 -0
- package/dist/chunk-OHK3W7NS.js +1687 -0
- package/dist/chunk-QZZZYL2Q.js +5703 -0
- package/dist/chunk-R5VQMEP6.js +6057 -0
- package/dist/chunk-SKU664KR.js +6074 -0
- package/dist/chunk-SS3VLEHR.js +7951 -0
- package/dist/chunk-WIGW5DJ5.js +7951 -0
- package/dist/chunk-XDUUWZOB.js +1687 -0
- package/dist/chunk-YDUBYJQR.js +7951 -0
- package/dist/cli-agent-BEEZSY3N.js +2882 -0
- package/dist/cli-agent-RQHYDDF5.js +2882 -0
- package/dist/cli-agent-ZPDDD2DP.js +2882 -0
- package/dist/cli-serve-AOTSNL3X.js +322 -0
- package/dist/cli-serve-GKF73PPW.js +322 -0
- package/dist/cli-serve-QO2H2UJZ.js +322 -0
- package/dist/cli.js +3 -3
- package/dist/index.js +6 -6
- package/dist/polymarket-3CPMIB2W.js +17 -0
- package/dist/polymarket-IKYXY4EF.js +17 -0
- package/dist/polymarket-NISQEHN6.js +17 -0
- package/dist/polymarket-runtime-PS2WY4HM.js +108 -0
- package/dist/polymarket-runtime-QEVWVBSL.js +108 -0
- package/dist/polymarket-runtime-QN5ICQNC.js +108 -0
- package/dist/polymarket-watcher-FZNJC5GF.js +23 -0
- package/dist/polymarket-watcher-I46HUKZ4.js +23 -0
- package/dist/polymarket-watcher-Y2OZD5W7.js +23 -0
- package/dist/runtime-D242TS34.js +50 -0
- package/dist/runtime-HA4USL4X.js +50 -0
- package/dist/runtime-IKTJLO7L.js +50 -0
- package/dist/server-5RD74WZK.js +36 -0
- package/dist/server-RXMHX4JW.js +36 -0
- package/dist/server-UYEMOR7X.js +36 -0
- package/dist/setup-3ZVF7S24.js +20 -0
- package/dist/setup-6QBAONHF.js +20 -0
- package/dist/setup-PDTOPLVS.js +20 -0
- package/logs/cloudflared-error.log +60 -0
- package/package.json +1 -1
- package/indeed-apply.cjs +0 -82
- package/indeed-bot.cjs +0 -296
package/indeed-bot.cjs
DELETED
|
@@ -1,296 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Indeed Job Application Bot ā Headed Chrome
|
|
3
|
-
* Searches multiple queries, filters out accounting firms, clicks Easy Apply.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const { chromium } = require('playwright');
|
|
7
|
-
const path = require('path');
|
|
8
|
-
const fs = require('fs');
|
|
9
|
-
|
|
10
|
-
const PROFILE_DIR = path.join(process.env.HOME, '.agenticmail', 'browser-profile-indeed');
|
|
11
|
-
const LOG_FILE = '/tmp/indeed-applied.json';
|
|
12
|
-
|
|
13
|
-
const BLOCKED_COMPANIES = [
|
|
14
|
-
'deloitte', 'kpmg', 'pwc', 'pricewaterhousecoopers', 'ernst & young', 'ey ',
|
|
15
|
-
'grant thornton', 'bdo', 'rsm', 'crowe', 'baker tilly', 'cbiz', 'marcum',
|
|
16
|
-
'moss adams', 'cla', 'cliftonlarsonallen', 'plante moran', 'cherry bekaert',
|
|
17
|
-
'forvis', 'mazars', 'withum', 'armanino', 'eide bailly', 'h&r block',
|
|
18
|
-
'jackson hewitt', 'liberty tax',
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
function isBlockedCompany(company) {
|
|
22
|
-
const lc = company.toLowerCase();
|
|
23
|
-
return BLOCKED_COMPANIES.some(b => lc.includes(b));
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const SEARCH_QUERIES = [
|
|
27
|
-
'AI Engineer', 'Data Scientist', 'Machine Learning Engineer',
|
|
28
|
-
'Financial Analyst', 'Procurement Analyst', 'Data Analyst',
|
|
29
|
-
'Business Analyst', 'Compliance Analyst', 'Tax Analyst',
|
|
30
|
-
'Full Stack Developer', 'Software Engineer',
|
|
31
|
-
];
|
|
32
|
-
|
|
33
|
-
const LOCATION = 'Charlotte, NC';
|
|
34
|
-
const applied = [];
|
|
35
|
-
|
|
36
|
-
async function delay(ms) { return new Promise(r => setTimeout(r, ms)); }
|
|
37
|
-
|
|
38
|
-
async function screenshot(page, name) {
|
|
39
|
-
try { await page.screenshot({ path: `/tmp/indeed-${name}.png` }); } catch {}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async function searchJobs(page, query) {
|
|
43
|
-
console.log(`\nš Searching: "${query}" in "${LOCATION}"...`);
|
|
44
|
-
await page.goto(
|
|
45
|
-
`https://www.indeed.com/jobs?q=${encodeURIComponent(query)}&l=${encodeURIComponent(LOCATION)}&radius=50&fromage=14`,
|
|
46
|
-
{ waitUntil: 'domcontentloaded', timeout: 30000 }
|
|
47
|
-
);
|
|
48
|
-
await delay(3000);
|
|
49
|
-
|
|
50
|
-
const jobs = await page.evaluate(() => {
|
|
51
|
-
const cards = document.querySelectorAll('.job_seen_beacon, [data-jk]');
|
|
52
|
-
return Array.from(cards).map(card => {
|
|
53
|
-
const titleEl = card.querySelector('h2 a, .jobTitle a');
|
|
54
|
-
const companyEl = card.querySelector('[data-testid="company-name"], .companyName');
|
|
55
|
-
const locationEl = card.querySelector('[data-testid="text-location"], .companyLocation');
|
|
56
|
-
return {
|
|
57
|
-
title: titleEl?.textContent?.trim() || '',
|
|
58
|
-
company: companyEl?.textContent?.trim() || '',
|
|
59
|
-
location: locationEl?.textContent?.trim() || '',
|
|
60
|
-
href: titleEl?.href || '',
|
|
61
|
-
jk: card.getAttribute('data-jk') || '',
|
|
62
|
-
};
|
|
63
|
-
}).filter(j => j.title && j.href);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
console.log(` Found ${jobs.length} listings`);
|
|
67
|
-
return jobs;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async function tryApply(page, job, ctx) {
|
|
71
|
-
const company = job.company;
|
|
72
|
-
if (isBlockedCompany(company)) {
|
|
73
|
-
console.log(` ā SKIP (accounting firm): ${company}`);
|
|
74
|
-
return false;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Check if already applied
|
|
78
|
-
if (applied.some(a => a.title === job.title && a.company === job.company)) {
|
|
79
|
-
console.log(` ā Already applied: ${job.title}`);
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
console.log(`\nš Opening: ${job.title} @ ${company}`);
|
|
84
|
-
|
|
85
|
-
// Open job in new tab
|
|
86
|
-
const jobPage = await ctx.newPage();
|
|
87
|
-
try {
|
|
88
|
-
await jobPage.goto(job.href, { waitUntil: 'domcontentloaded', timeout: 20000 });
|
|
89
|
-
await delay(2000);
|
|
90
|
-
|
|
91
|
-
// Look for Apply button
|
|
92
|
-
const applyBtn = await jobPage.$('button#indeedApplyButton') ||
|
|
93
|
-
await jobPage.$('button[id*="indeedApply"]') ||
|
|
94
|
-
await jobPage.$('.indeed-apply-button') ||
|
|
95
|
-
await jobPage.$('button:has-text("Apply now")') ||
|
|
96
|
-
await jobPage.$('a:has-text("Apply now")') ||
|
|
97
|
-
await jobPage.$('button:has-text("Apply on company site")') ||
|
|
98
|
-
await jobPage.$('a:has-text("Apply on company site")');
|
|
99
|
-
|
|
100
|
-
if (!applyBtn) {
|
|
101
|
-
console.log(` ā No apply button found`);
|
|
102
|
-
await screenshot(jobPage, `no-apply-${job.jk || 'unknown'}`);
|
|
103
|
-
await jobPage.close();
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const btnText = await applyBtn.textContent();
|
|
108
|
-
console.log(` š Button: "${btnText.trim()}"`);
|
|
109
|
-
|
|
110
|
-
// If "Apply on company site" ā opens external link
|
|
111
|
-
if (btnText.toLowerCase().includes('company site')) {
|
|
112
|
-
console.log(` ā External application ā clicking to open`);
|
|
113
|
-
await applyBtn.click();
|
|
114
|
-
await delay(3000);
|
|
115
|
-
|
|
116
|
-
// Check if new tab opened
|
|
117
|
-
const pages = ctx.pages();
|
|
118
|
-
const newPage = pages[pages.length - 1];
|
|
119
|
-
if (newPage !== jobPage) {
|
|
120
|
-
const url = newPage.url();
|
|
121
|
-
console.log(` š External URL: ${url}`);
|
|
122
|
-
|
|
123
|
-
// Check for email verification requirement
|
|
124
|
-
const pageContent = await newPage.content();
|
|
125
|
-
if (pageContent.includes('verify your email') || pageContent.includes('email verification') || pageContent.includes('confirm your email')) {
|
|
126
|
-
console.log(` ā Requires email verification ā skipping`);
|
|
127
|
-
await newPage.close();
|
|
128
|
-
await jobPage.close();
|
|
129
|
-
return false;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
await screenshot(newPage, `external-${job.jk || Date.now()}`);
|
|
133
|
-
applied.push({ ...job, status: 'external_opened', url, time: new Date().toISOString() });
|
|
134
|
-
// Don't close external page ā leave for manual review if needed
|
|
135
|
-
}
|
|
136
|
-
await jobPage.close();
|
|
137
|
-
return true;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Indeed Easy Apply
|
|
141
|
-
console.log(` ā
Indeed Easy Apply ā clicking...`);
|
|
142
|
-
await applyBtn.click();
|
|
143
|
-
await delay(3000);
|
|
144
|
-
|
|
145
|
-
// Handle the apply modal/flow
|
|
146
|
-
const allPages = ctx.pages();
|
|
147
|
-
const applyPage = allPages[allPages.length - 1];
|
|
148
|
-
|
|
149
|
-
// Check for email verification
|
|
150
|
-
const applyContent = await applyPage.content();
|
|
151
|
-
if (applyContent.includes('verify your email') || applyContent.includes('email verification')) {
|
|
152
|
-
console.log(` ā Requires email verification ā skipping`);
|
|
153
|
-
await applyPage.close();
|
|
154
|
-
if (applyPage !== jobPage) await jobPage.close();
|
|
155
|
-
return false;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Take screenshot of the application form
|
|
159
|
-
await screenshot(applyPage, `apply-${job.jk || Date.now()}`);
|
|
160
|
-
|
|
161
|
-
// Try to navigate through the apply flow
|
|
162
|
-
let step = 0;
|
|
163
|
-
while (step < 10) {
|
|
164
|
-
step++;
|
|
165
|
-
await delay(2000);
|
|
166
|
-
|
|
167
|
-
// Check if we see "Application submitted" or similar
|
|
168
|
-
const text = await applyPage.evaluate(() => document.body?.innerText || '').catch(() => '');
|
|
169
|
-
if (text.includes('Application submitted') || text.includes('application has been submitted') || text.includes('successfully applied')) {
|
|
170
|
-
console.log(` š APPLICATION SUBMITTED!`);
|
|
171
|
-
applied.push({ ...job, status: 'submitted', time: new Date().toISOString() });
|
|
172
|
-
await screenshot(applyPage, `submitted-${job.jk || Date.now()}`);
|
|
173
|
-
break;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// Look for Continue / Next / Submit / Apply button
|
|
177
|
-
const continueBtn = await applyPage.$('button:has-text("Continue")') ||
|
|
178
|
-
await applyPage.$('button:has-text("Next")') ||
|
|
179
|
-
await applyPage.$('button:has-text("Submit your application")') ||
|
|
180
|
-
await applyPage.$('button:has-text("Apply")') ||
|
|
181
|
-
await applyPage.$('button:has-text("Review")') ||
|
|
182
|
-
await applyPage.$('button[type="submit"]');
|
|
183
|
-
|
|
184
|
-
if (continueBtn) {
|
|
185
|
-
const cText = await continueBtn.textContent().catch(() => '');
|
|
186
|
-
console.log(` ā Step ${step}: clicking "${cText.trim()}"...`);
|
|
187
|
-
|
|
188
|
-
// If there's a resume upload ā check if already attached
|
|
189
|
-
const resumeInput = await applyPage.$('input[type="file"]');
|
|
190
|
-
if (resumeInput) {
|
|
191
|
-
console.log(` š Resume upload detected ā using master resume`);
|
|
192
|
-
const resumePath = path.join(process.env.HOME, '.openclaw/workspace/job-search/master-tech-resume.docx');
|
|
193
|
-
if (fs.existsSync(resumePath)) {
|
|
194
|
-
await resumeInput.setInputFiles(resumePath);
|
|
195
|
-
await delay(1000);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// Fill in any required fields that are empty
|
|
200
|
-
const requiredInputs = await applyPage.$$('input[required]:not([type="file"]):not([type="hidden"])');
|
|
201
|
-
for (const inp of requiredInputs) {
|
|
202
|
-
const val = await inp.inputValue().catch(() => '');
|
|
203
|
-
const name = await inp.getAttribute('name') || await inp.getAttribute('id') || '';
|
|
204
|
-
const placeholder = await inp.getAttribute('placeholder') || '';
|
|
205
|
-
if (!val) {
|
|
206
|
-
// Try to fill based on field name
|
|
207
|
-
const field = (name + ' ' + placeholder).toLowerCase();
|
|
208
|
-
if (field.includes('phone')) await inp.fill('3362763915');
|
|
209
|
-
else if (field.includes('email')) await inp.fill('fola@agenticmail.io');
|
|
210
|
-
else if (field.includes('city') || field.includes('location')) await inp.fill('Charlotte, NC');
|
|
211
|
-
else if (field.includes('name') && field.includes('first')) await inp.fill('Ope');
|
|
212
|
-
else if (field.includes('name') && field.includes('last')) await inp.fill('Olatunji');
|
|
213
|
-
else if (field.includes('linkedin')) await inp.fill('linkedin.com/in/opeolatunji');
|
|
214
|
-
else if (field.includes('salary') || field.includes('compensation')) await inp.fill('90000');
|
|
215
|
-
else if (field.includes('years') || field.includes('experience')) await inp.fill('5');
|
|
216
|
-
else {
|
|
217
|
-
console.log(` ā Unknown required field: ${name || placeholder}`);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
await continueBtn.click();
|
|
223
|
-
await delay(2000);
|
|
224
|
-
await screenshot(applyPage, `step${step}-${job.jk || Date.now()}`);
|
|
225
|
-
} else {
|
|
226
|
-
console.log(` ā No continue button at step ${step}`);
|
|
227
|
-
await screenshot(applyPage, `stuck-${job.jk || Date.now()}`);
|
|
228
|
-
applied.push({ ...job, status: 'stuck_at_step_' + step, time: new Date().toISOString() });
|
|
229
|
-
break;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
if (applyPage !== jobPage) {
|
|
234
|
-
try { await applyPage.close(); } catch {}
|
|
235
|
-
}
|
|
236
|
-
try { await jobPage.close(); } catch {}
|
|
237
|
-
return true;
|
|
238
|
-
} catch (err) {
|
|
239
|
-
console.log(` ā Error: ${err.message}`);
|
|
240
|
-
try { await jobPage.close(); } catch {}
|
|
241
|
-
return false;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
async function main() {
|
|
246
|
-
console.log('š Indeed Job Application Bot');
|
|
247
|
-
console.log(`š Location: ${LOCATION}`);
|
|
248
|
-
console.log(`š Queries: ${SEARCH_QUERIES.length}`);
|
|
249
|
-
console.log('---\n');
|
|
250
|
-
|
|
251
|
-
const ctx = await chromium.launchPersistentContext(PROFILE_DIR, {
|
|
252
|
-
headless: false,
|
|
253
|
-
channel: 'chrome',
|
|
254
|
-
args: ['--no-first-run', '--disable-blink-features=AutomationControlled'],
|
|
255
|
-
viewport: { width: 1400, height: 900 },
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
const page = ctx.pages()[0] || await ctx.newPage();
|
|
259
|
-
|
|
260
|
-
// First verify we're logged in
|
|
261
|
-
await page.goto('https://www.indeed.com', { waitUntil: 'domcontentloaded', timeout: 20000 });
|
|
262
|
-
await delay(2000);
|
|
263
|
-
await screenshot(page, 'home');
|
|
264
|
-
|
|
265
|
-
for (const query of SEARCH_QUERIES) {
|
|
266
|
-
try {
|
|
267
|
-
const jobs = await searchJobs(page, query);
|
|
268
|
-
|
|
269
|
-
for (const job of jobs) {
|
|
270
|
-
try {
|
|
271
|
-
await tryApply(page, job, ctx);
|
|
272
|
-
await delay(2000); // Rate limit
|
|
273
|
-
} catch (err) {
|
|
274
|
-
console.log(` ā Error with ${job.title}: ${err.message}`);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
// Save progress after each query
|
|
279
|
-
fs.writeFileSync(LOG_FILE, JSON.stringify(applied, null, 2));
|
|
280
|
-
console.log(`\nš¾ Progress saved: ${applied.length} jobs processed`);
|
|
281
|
-
} catch (err) {
|
|
282
|
-
console.log(`ā Search error for "${query}": ${err.message}`);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
console.log(`\n=== DONE ===`);
|
|
287
|
-
console.log(`Processed: ${applied.length} jobs`);
|
|
288
|
-
console.log(`Log: ${LOG_FILE}`);
|
|
289
|
-
|
|
290
|
-
fs.writeFileSync(LOG_FILE, JSON.stringify(applied, null, 2));
|
|
291
|
-
|
|
292
|
-
// Keep browser open
|
|
293
|
-
await new Promise(() => {});
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
main().catch(e => { console.error('FATAL:', e.message); process.exit(1); });
|