resuml 3.0.0 → 3.2.0
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/DOCS.md +77 -18
- package/README.md +5 -0
- package/bin/resuml +3 -2
- package/data/jobs/companies.json +76 -0
- package/dist/ats/index.d.ts +7 -0
- package/dist/ats/index.js +8 -0
- package/dist/ats/index.js.map +1 -0
- package/dist/chunk-C2JG5KF4.js +2088 -0
- package/dist/chunk-C2JG5KF4.js.map +1 -0
- package/dist/chunk-G4AN2EMI.js +461 -0
- package/dist/chunk-G4AN2EMI.js.map +1 -0
- package/dist/chunk-QBCXFLW6.js +686 -0
- package/dist/chunk-QBCXFLW6.js.map +1 -0
- package/dist/{chunk-R4MD5YMV.js → chunk-QR77BRMN.js} +154 -2434
- package/dist/chunk-QR77BRMN.js.map +1 -0
- package/dist/chunk-YVC53STN.js +997 -0
- package/dist/chunk-YVC53STN.js.map +1 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +25 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +6 -424
- package/dist/index.js +20 -775
- package/dist/index.js.map +1 -1
- package/dist/jobs/index.d.ts +158 -0
- package/dist/jobs/index.js +23 -0
- package/dist/jobs/index.js.map +1 -0
- package/dist/mcp/server.js +134 -3
- package/dist/mcp/server.js.map +1 -1
- package/dist/skills/index.d.ts +67 -0
- package/dist/skills/index.js +13 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/types/index.d.ts +343 -0
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types-B_jASYU4.d.ts +81 -0
- package/package.json +33 -3
- package/dist/chunk-R4MD5YMV.js.map +0 -1
- package/src/types/resume.ts +0 -344
- package/src/types/schema.d.ts +0 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/ats/seniority.ts","../src/jobs/query.ts","../src/jobs/geo.ts","../src/jobs/normalize.ts","../src/jobs/providers/http.ts","../src/jobs/providers/greenhouse.ts","../src/jobs/providers/lever.ts","../src/jobs/providers/ashby.ts","../src/jobs/providers/workable.ts","../src/jobs/providers/remoteok.ts","../src/jobs/providers/remotive.ts","../src/jobs/providers/wwr.ts","../src/jobs/providers/hn-whoishiring.ts","../src/jobs/providers/index.ts","../src/jobs/rank.ts","../src/jobs/companies.ts","../src/jobs/index.ts"],"sourcesContent":["import type { ResumeSchema } from '../types/resume';\nimport type { SeniorityLevel } from '../jobs/types';\nimport type { CheckStatus } from './types';\nimport { computeYoeYears } from './checks/yoe';\n\nexport const SENIORITY_ORDER: SeniorityLevel[] = [\n 'intern',\n 'junior',\n 'mid',\n 'senior',\n 'staff',\n 'principal',\n];\n\nconst SENIORITY_PATTERNS: Array<{ level: SeniorityLevel; rx: RegExp }> = [\n { level: 'principal', rx: /\\b(principal|distinguished|fellow)\\b/i },\n { level: 'staff', rx: /\\b(staff|architect|head\\s+of|director|vp\\b|chief)\\b/i },\n { level: 'senior', rx: /\\b(senior|sr\\.?|lead|tech(?:nical)?\\s*lead|tl\\b|manager)\\b/i },\n { level: 'mid', rx: /\\b(mid|ii\\b|iii\\b|engineer\\s*ii)\\b/i },\n { level: 'junior', rx: /\\b(junior|jr\\.?|associate|entry)\\b/i },\n { level: 'intern', rx: /\\b(intern|trainee|apprentice)\\b/i },\n];\n\nconst MGMT_RE =\n /\\b(engineering\\s+manager|em\\b|director|vp\\s+of\\s+engineering|head\\s+of\\s+engineering|chief)\\b/i;\n\nconst YOE_RE = /\\b(\\d+)\\s*\\+?\\s*(?:(?:to|[-–])\\s*\\d+\\s*)?\\s*years?\\b/i;\n\nexport function detectSeniorityFromTitle(title: string): SeniorityLevel | null {\n for (const { level, rx } of SENIORITY_PATTERNS) {\n if (rx.test(title)) return level;\n }\n return null;\n}\n\nexport function seniorityFromYoe(yoe: number): SeniorityLevel {\n if (yoe < 1) return 'junior';\n if (yoe < 3) return 'mid';\n if (yoe < 8) return 'senior';\n if (yoe < 12) return 'staff';\n return 'principal';\n}\n\nexport function bandLabelToLevel(label: string): SeniorityLevel | null {\n const m = /^(IC|[LEM])(\\d)$/i.exec(label);\n if (!m) return null;\n const prefix = (m[1] ?? '').toUpperCase();\n const num = parseInt(m[2] ?? '0', 10);\n if (prefix === 'L' || prefix === 'E') {\n const map: Partial<Record<number, SeniorityLevel>> = {\n 3: 'junior', 4: 'mid', 5: 'senior', 6: 'staff', 7: 'principal',\n };\n return map[num] ?? null;\n }\n if (prefix === 'IC') {\n const map: Partial<Record<number, SeniorityLevel>> = {\n 3: 'junior', 4: 'mid', 5: 'senior', 6: 'staff',\n };\n return map[num] ?? null;\n }\n if (prefix === 'M') {\n const map: Partial<Record<number, SeniorityLevel>> = {\n 1: 'mid', 2: 'senior', 3: 'staff', 4: 'principal',\n };\n return map[num] ?? null;\n }\n return null;\n}\n\nfunction firstBandLabel(text: string): SeniorityLevel | null {\n for (const m of text.matchAll(/\\b(IC|[LEM])(\\d)\\b/gi)) {\n const level = bandLabelToLevel(m[0]);\n if (level) return level;\n }\n return null;\n}\n\nexport function extractJdSeniority(jd: string, jobTitle?: string): SeniorityLevel | null {\n // Signal 1: title modifier via keyword patterns\n if (jobTitle) {\n const fromTitle = detectSeniorityFromTitle(jobTitle);\n if (fromTitle) return fromTitle;\n }\n\n // Signal 2: body level strings, then band labels (title then body)\n for (const { level, rx } of SENIORITY_PATTERNS) {\n if (rx.test(jd)) return level;\n }\n\n if (jobTitle) {\n const fromBand = firstBandLabel(jobTitle);\n if (fromBand) return fromBand;\n }\n\n const fromBodyBand = firstBandLabel(jd);\n if (fromBodyBand) return fromBodyBand;\n\n // Signal 3: numeric YOE range\n const yoeMatch = YOE_RE.exec(jd);\n if (yoeMatch) {\n return seniorityFromYoe(parseInt(yoeMatch[1] ?? '0', 10));\n }\n\n return null;\n}\n\nexport function extractCvSeniority(resume: ResumeSchema): SeniorityLevel {\n const yoe = computeYoeYears(resume.work);\n let level: SeniorityLevel = seniorityFromYoe(yoe);\n\n const titleCandidates = [\n ...(resume.work ?? []).map((w) => w.position ?? ''),\n resume.basics?.label ?? '',\n ].filter(Boolean);\n\n for (const title of titleCandidates) {\n const fromTitle = detectSeniorityFromTitle(title);\n if (fromTitle && SENIORITY_ORDER.indexOf(fromTitle) > SENIORITY_ORDER.indexOf(level)) {\n level = fromTitle;\n }\n }\n\n return level;\n}\n\nexport function gapBetween(a: SeniorityLevel, b: SeniorityLevel): number {\n return Math.abs(SENIORITY_ORDER.indexOf(a) - SENIORITY_ORDER.indexOf(b));\n}\n\nexport function scoreFromGap(gap: number): { score: number; status: CheckStatus } {\n if (gap === 0) return { score: 100, status: 'pass' };\n if (gap === 1) return { score: 90, status: 'pass' };\n if (gap === 2) return { score: 70, status: 'warn' };\n if (gap === 3) return { score: 40, status: 'warn' };\n return { score: 10, status: 'fail' };\n}\n\nexport function isManagementRole(jobTitle: string, bodyFirstLines: string): boolean {\n return MGMT_RE.test(jobTitle) || MGMT_RE.test(bodyFirstLines);\n}\n\nexport function isIcResume(resume: ResumeSchema): boolean {\n return !(resume.work ?? []).some((w) => MGMT_RE.test(w.position ?? ''));\n}\n","import type { ResumeSchema } from '../types/resume';\nimport { getSkillIndex } from '../ats/skills/index';\nimport type { SearchQuery, SeniorityLevel } from './types';\nimport {\n detectSeniorityFromTitle,\n seniorityFromYoe,\n SENIORITY_ORDER,\n} from '../ats/seniority';\n\nfunction maxSeniority(a: SeniorityLevel, b: SeniorityLevel): SeniorityLevel {\n return SENIORITY_ORDER.indexOf(a) > SENIORITY_ORDER.indexOf(b) ? a : b;\n}\n\nfunction parseDate(raw?: string): Date | null {\n if (!raw) return null;\n const d = new Date(raw);\n return isNaN(d.getTime()) ? null : d;\n}\n\nfunction computeYearsExperience(resume: ResumeSchema): number {\n const now = new Date();\n let totalMs = 0;\n for (const w of resume.work ?? []) {\n const start = parseDate(w.startDate);\n if (!start) continue;\n const end = parseDate(w.endDate) ?? now;\n if (end <= start) continue;\n totalMs += end.getTime() - start.getTime();\n }\n return Math.round((totalMs / (1000 * 60 * 60 * 24 * 365.25)) * 10) / 10;\n}\n\nfunction extractResumeText(resume: ResumeSchema): string {\n const parts: string[] = [];\n if (resume.basics?.summary) parts.push(resume.basics.summary);\n if (resume.basics?.label) parts.push(resume.basics.label);\n for (const w of resume.work ?? []) {\n if (w.position) parts.push(w.position);\n if (w.summary) parts.push(w.summary);\n parts.push(...(w.highlights ?? []));\n }\n for (const s of resume.skills ?? []) {\n if (s.name) parts.push(s.name);\n parts.push(...(s.keywords ?? []));\n }\n for (const p of resume.projects ?? []) {\n if (p.name) parts.push(p.name);\n if (p.description) parts.push(p.description);\n parts.push(...(p.highlights ?? []));\n parts.push(...(p.keywords ?? []));\n }\n return parts.join(' ');\n}\n\n/**\n * Derive a search query from the resume. Pure function — no IO.\n *\n * Top skills come from the bundled O*NET skill index (same one the ATS\n * matcher uses), ranked by occurrence and the \"hot\" flag. Seniority is the\n * max of explicit title evidence and a YOE-derived heuristic so a resume\n * with a short tenure but a \"Senior\" title still maps to senior roles.\n */\nexport function deriveSearchQuery(\n resume: ResumeSchema,\n overrides: { remoteOnly?: boolean } = {}\n): SearchQuery {\n const text = extractResumeText(resume);\n const matches = getSkillIndex().scan(text);\n const skills = matches.slice(0, 15).map((m) => m.skill.canonical);\n\n const titles = (resume.work ?? [])\n .map((w) => w.position)\n .filter((p): p is string => typeof p === 'string' && p.length > 0);\n\n const yoe = computeYearsExperience(resume);\n let seniority: SeniorityLevel = seniorityFromYoe(yoe);\n for (const title of titles) {\n const fromTitle = detectSeniorityFromTitle(title);\n if (fromTitle) seniority = maxSeniority(seniority, fromTitle);\n }\n if (resume.basics?.label) {\n const fromLabel = detectSeniorityFromTitle(resume.basics.label);\n if (fromLabel) seniority = maxSeniority(seniority, fromLabel);\n }\n\n const city = resume.basics?.location?.city;\n const countryCode = resume.basics?.location?.countryCode;\n\n const headTitle = titles[0] ?? resume.basics?.label ?? '';\n const terms = Array.from(\n new Set(\n [headTitle, ...skills.slice(0, 5)]\n .filter(Boolean)\n .map((t) => t.toLowerCase())\n .flatMap((t) => t.split(/\\s+/))\n .filter((t) => t.length > 2)\n )\n );\n\n return {\n skills,\n seniority,\n yearsExperience: yoe,\n titles,\n city,\n countryCode,\n remoteOnly: overrides.remoteOnly ?? false,\n terms,\n };\n}\n","/**\n * Remote-eligibility check. A posting marked \"remote\" is not necessarily\n * remote *for this candidate*: \"Remote, US\" means remote within the US, which a\n * Zürich-based applicant generally cannot take. We only keep a remote posting\n * when the candidate's country is plausibly covered by its stated scope.\n *\n * Bias: conservative on clear exclusions (US-only, another single country,\n * another continent → drop), permissive on the unknown (a bare \"Remote\" with no\n * region → keep, since we can't prove ineligibility).\n */\n\n/** Region tokens that, if present, include a candidate from the given country. */\nconst COUNTRY_INCLUSIVE: Record<string, RegExp> = {\n // Switzerland: European, EMEA, EEA/EFTA, DACH, or explicitly Switzerland.\n CH: /\\b(switzerland|schweiz|suisse|svizzera|europe|european|emea|eea|efta|dach|cet|cest)\\b/i,\n};\n\n/** Worldwide scopes that include everyone. */\nconst WORLDWIDE = /\\b(worldwide|world\\s?wide|anywhere|global|globally|international|fully remote)\\b/i;\n\n/**\n * Region tokens that EXCLUDE a candidate from the given country (only consulted\n * when no inclusive/worldwide token is present).\n */\nconst COUNTRY_EXCLUSIVE: Record<string, RegExp> = {\n CH: /\\b(united states|u\\.?s\\.?a?|us[-\\s]?based|us[-\\s]?only|north america|americas|canada|canadian|latam|latin america|apac|asia|australia|india|united kingdom|uk[-\\s]?only|brazil|mexico|nigeria|philippines)\\b/i,\n};\n\n/**\n * @returns true when the candidate is plausibly eligible (or scope is unknown),\n * false only when the scope clearly excludes their country.\n */\nexport function isRemoteEligible(\n location: string | undefined,\n body: string | undefined,\n countryCode: string | undefined\n): boolean {\n const cc = (countryCode ?? '').toUpperCase();\n const inclusive = COUNTRY_INCLUSIVE[cc];\n const exclusive = COUNTRY_EXCLUSIVE[cc];\n // No rules for this country → don't filter (can't make a confident call).\n if (!inclusive || !exclusive) return true;\n\n // Scope signal lives mostly in the location line; sample the body head too.\n const scope = `${location ?? ''} ${(body ?? '').slice(0, 400)}`;\n\n if (WORLDWIDE.test(scope)) return true;\n if (inclusive.test(scope)) return true;\n if (exclusive.test(scope)) return false;\n // Unknown scope: keep it, but the candidate should verify work authorization.\n return true;\n}\n","import type { JobPosting, SearchQuery } from './types';\nimport { isRemoteEligible } from './geo';\n\n/**\n * Strip HTML to plain text. Naive but sufficient for ATS scoring — the\n * scorer only needs prose for skill extraction, not exact whitespace.\n */\nexport function stripHtml(input: string): string {\n if (!input) return '';\n const noScript = input.replace(/<(script|style)[^>]*>[\\s\\S]*?<\\/\\1>/gi, ' ');\n const noTags = noScript.replace(/<[^>]+>/g, ' ');\n const decoded = noTags\n .replace(/ /g, ' ')\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/"/g, '\"')\n .replace(/'/g, \"'\")\n .replace(/&#(\\d+);/g, (_, code: string) => String.fromCharCode(parseInt(code, 10)));\n return decoded.replace(/\\s+/g, ' ').trim();\n}\n\nconst REMOTE_PATTERNS = /\\b(remote|anywhere|distributed|wfh|work[\\s-]from[\\s-]home)\\b/i;\n\nexport function looksRemote(location?: string, body?: string): boolean {\n if (location && REMOTE_PATTERNS.test(location)) return true;\n if (body && REMOTE_PATTERNS.test(body.slice(0, 500))) return true;\n return false;\n}\n\n/**\n * Stable dedupe key — same (company, title, location) from two providers\n * collapses to one entry.\n */\nexport function dedupeKey(posting: Pick<JobPosting, 'company' | 'title' | 'location'>): string {\n const norm = (s?: string) =>\n (s ?? '').toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim().replace(/\\s+/g, '-');\n return `${norm(posting.company)}::${norm(posting.title)}::${norm(posting.location)}`;\n}\n\nfunction extractLocationCountryCode(location: string | undefined): string | null {\n if (!location) return null;\n const parts = location.split(',');\n const last = parts[parts.length - 1]?.trim().toUpperCase();\n return last && last.length === 2 ? last : null;\n}\n\n/**\n * Filter postings against the derived query. Remote-only requires both that the\n * posting is remote AND that the candidate's country is plausibly eligible for\n * its remote scope (a \"Remote, US\" role is dropped for an EU-based candidate).\n * On-site postings with a clearly different country code are also dropped when\n * the candidate's countryCode is known.\n * We do not filter by skills here — the ATS scorer owns relevance.\n */\nexport function applyQueryFilters(\n postings: JobPosting[],\n query: SearchQuery\n): { postings: JobPosting[]; wrongLocationCount: number } {\n let result = postings;\n\n if (query.remoteOnly) {\n result = result.filter((p) => p.remote && isRemoteEligible(p.location, p.body, query.countryCode));\n }\n\n let wrongLocationCount = 0;\n if (query.countryCode) {\n const before = result.length;\n result = result.filter((p) => {\n if (p.remote) return true;\n const loc = extractLocationCountryCode(p.location);\n return !loc || loc === query.countryCode;\n });\n wrongLocationCount = before - result.length;\n }\n\n return { postings: result, wrongLocationCount };\n}\n","const DEFAULT_UA = 'resuml-jobs/1.0 (+https://github.com/phoinixi/resuml)';\n\nexport interface FetchOptions {\n timeoutMs: number;\n accept?: string;\n}\n\nexport async function fetchText(url: string, opts: FetchOptions): Promise<string> {\n const controller = new AbortController();\n const timer = setTimeout(() => {\n controller.abort();\n }, opts.timeoutMs);\n try {\n const res = await fetch(url, {\n signal: controller.signal,\n headers: {\n 'User-Agent': DEFAULT_UA,\n Accept: opts.accept ?? 'application/json, text/plain;q=0.9, */*;q=0.5',\n },\n });\n if (!res.ok) throw new Error(`${url} → HTTP ${res.status}`);\n return await res.text();\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function fetchJson<T>(url: string, opts: FetchOptions): Promise<T> {\n const text = await fetchText(url, { ...opts, accept: 'application/json' });\n return JSON.parse(text) as T;\n}\n","import type { JobPosting, Provider } from '../types';\nimport { looksRemote, stripHtml } from '../normalize';\nimport { fetchJson } from './http';\n\ninterface GreenhouseJob {\n id: number;\n absolute_url: string;\n title: string;\n location?: { name?: string };\n updated_at?: string;\n content?: string;\n}\n\ninterface GreenhouseResponse {\n jobs?: GreenhouseJob[];\n}\n\n/**\n * Greenhouse public board API. One request per company in the allowlist.\n * Endpoint pattern: boards-api.greenhouse.io/v1/boards/{slug}/jobs?content=true\n *\n * `content=true` inlines the JD HTML in the listing response so we avoid\n * N+1 detail fetches.\n */\nexport const greenhouseProvider: Provider = {\n id: 'greenhouse',\n needsAllowlist: true,\n async fetch(_query, { companies = [], timeoutMs }) {\n const results = await Promise.allSettled(\n companies.map((slug) => fetchCompany(slug, timeoutMs))\n );\n return results.flatMap((r) => (r.status === 'fulfilled' ? r.value : []));\n },\n};\n\nasync function fetchCompany(slug: string, timeoutMs: number): Promise<JobPosting[]> {\n const url = `https://boards-api.greenhouse.io/v1/boards/${encodeURIComponent(slug)}/jobs?content=true`;\n const data = await fetchJson<GreenhouseResponse>(url, { timeoutMs });\n const jobs = data.jobs ?? [];\n return jobs.map<JobPosting>((j) => {\n const location = j.location?.name;\n const body = stripHtml(j.content ?? '');\n return {\n id: `greenhouse:${slug}:${j.id}`,\n source: 'greenhouse',\n company: slug,\n title: j.title,\n location,\n remote: looksRemote(location, body),\n url: j.absolute_url,\n body,\n postedAt: j.updated_at,\n };\n });\n}\n","import type { JobPosting, Provider } from '../types';\nimport { looksRemote, stripHtml } from '../normalize';\nimport { fetchJson } from './http';\n\ninterface LeverPosting {\n id: string;\n text: string;\n hostedUrl: string;\n applyUrl?: string;\n categories?: { location?: string; team?: string; commitment?: string };\n createdAt?: number;\n descriptionPlain?: string;\n description?: string;\n lists?: Array<{ text?: string; content?: string }>;\n additionalPlain?: string;\n}\n\n/**\n * Lever public postings API. One request per company.\n * Endpoint: api.lever.co/v0/postings/{slug}?mode=json\n */\nexport const leverProvider: Provider = {\n id: 'lever',\n needsAllowlist: true,\n async fetch(_query, { companies = [], timeoutMs }) {\n const results = await Promise.allSettled(\n companies.map((slug) => fetchCompany(slug, timeoutMs))\n );\n return results.flatMap((r) => (r.status === 'fulfilled' ? r.value : []));\n },\n};\n\nfunction assembleBody(p: LeverPosting): string {\n const parts: string[] = [];\n if (p.descriptionPlain) parts.push(p.descriptionPlain);\n else if (p.description) parts.push(stripHtml(p.description));\n for (const list of p.lists ?? []) {\n if (list.text) parts.push(list.text);\n if (list.content) parts.push(stripHtml(list.content));\n }\n if (p.additionalPlain) parts.push(p.additionalPlain);\n return parts.join('\\n\\n');\n}\n\nasync function fetchCompany(slug: string, timeoutMs: number): Promise<JobPosting[]> {\n const url = `https://api.lever.co/v0/postings/${encodeURIComponent(slug)}?mode=json`;\n const data = await fetchJson<LeverPosting[]>(url, { timeoutMs });\n return data.map<JobPosting>((p) => {\n const location = p.categories?.location;\n const body = assembleBody(p);\n return {\n id: `lever:${slug}:${p.id}`,\n source: 'lever',\n company: slug,\n title: p.text,\n location,\n remote: looksRemote(location, body),\n url: p.hostedUrl,\n body,\n postedAt: p.createdAt ? new Date(p.createdAt).toISOString() : undefined,\n };\n });\n}\n","import type { JobPosting, Provider } from '../types';\nimport { looksRemote, stripHtml } from '../normalize';\nimport { fetchJson } from './http';\n\ninterface AshbyJob {\n id: string;\n title: string;\n locationName?: string;\n isRemote?: boolean;\n jobUrl?: string;\n descriptionHtml?: string;\n descriptionPlain?: string;\n publishedDate?: string;\n}\n\ninterface AshbyResponse {\n jobs?: AshbyJob[];\n apiVersion?: string;\n}\n\n/**\n * Ashby public board API.\n * Endpoint: api.ashbyhq.com/posting-api/job-board/{slug}?includeCompensation=true\n */\nexport const ashbyProvider: Provider = {\n id: 'ashby',\n needsAllowlist: true,\n async fetch(_query, { companies = [], timeoutMs }) {\n const results = await Promise.allSettled(\n companies.map((slug) => fetchCompany(slug, timeoutMs))\n );\n return results.flatMap((r) => (r.status === 'fulfilled' ? r.value : []));\n },\n};\n\nasync function fetchCompany(slug: string, timeoutMs: number): Promise<JobPosting[]> {\n const url = `https://api.ashbyhq.com/posting-api/job-board/${encodeURIComponent(slug)}?includeCompensation=true`;\n const data = await fetchJson<AshbyResponse>(url, { timeoutMs });\n const jobs = data.jobs ?? [];\n return jobs.map<JobPosting>((j) => {\n const location = j.locationName;\n const body = j.descriptionPlain ?? stripHtml(j.descriptionHtml ?? '');\n return {\n id: `ashby:${slug}:${j.id}`,\n source: 'ashby',\n company: slug,\n title: j.title,\n location,\n remote: j.isRemote ?? looksRemote(location, body),\n url: j.jobUrl ?? `https://jobs.ashbyhq.com/${slug}/${j.id}`,\n body,\n postedAt: j.publishedDate,\n };\n });\n}\n","import type { JobPosting, Provider } from '../types';\nimport { looksRemote, stripHtml } from '../normalize';\nimport { fetchJson } from './http';\n\ninterface WorkableJob {\n id: string;\n shortcode?: string;\n title: string;\n city?: string;\n country?: string;\n state?: string;\n remote?: boolean;\n url?: string;\n application_url?: string;\n description?: string;\n requirements?: string;\n benefits?: string;\n published_on?: string;\n}\n\ninterface WorkableResponse {\n jobs?: WorkableJob[];\n results?: WorkableJob[];\n}\n\n/**\n * Workable public widget API.\n * Endpoint: apply.workable.com/api/v1/widget/accounts/{slug}\n */\nexport const workableProvider: Provider = {\n id: 'workable',\n needsAllowlist: true,\n async fetch(_query, { companies = [], timeoutMs }) {\n const results = await Promise.allSettled(\n companies.map((slug) => fetchCompany(slug, timeoutMs))\n );\n return results.flatMap((r) => (r.status === 'fulfilled' ? r.value : []));\n },\n};\n\nfunction locationFor(j: WorkableJob): string | undefined {\n const parts = [j.city, j.state, j.country].filter(Boolean) as string[];\n return parts.length ? parts.join(', ') : undefined;\n}\n\nasync function fetchCompany(slug: string, timeoutMs: number): Promise<JobPosting[]> {\n const url = `https://apply.workable.com/api/v1/widget/accounts/${encodeURIComponent(slug)}`;\n const data = await fetchJson<WorkableResponse>(url, { timeoutMs });\n const jobs = data.jobs ?? data.results ?? [];\n return jobs.map<JobPosting>((j) => {\n const location = locationFor(j);\n const bodyParts = [j.description, j.requirements, j.benefits]\n .filter(Boolean)\n .map((s) => stripHtml(s as string));\n const body = bodyParts.join('\\n\\n');\n const postingUrl = j.url ?? j.application_url ?? `https://apply.workable.com/${slug}/j/${j.shortcode ?? j.id}/`;\n return {\n id: `workable:${slug}:${j.id}`,\n source: 'workable',\n company: slug,\n title: j.title,\n location,\n remote: j.remote ?? looksRemote(location, body),\n url: postingUrl,\n body,\n postedAt: j.published_on,\n };\n });\n}\n","import type { JobPosting, Provider } from '../types';\nimport { stripHtml } from '../normalize';\nimport { fetchJson } from './http';\n\ninterface RemoteOkEntry {\n id?: string;\n slug?: string;\n url?: string;\n company?: string;\n position?: string;\n location?: string;\n description?: string;\n tags?: string[];\n date?: string;\n salary_min?: number;\n salary_max?: number;\n legal?: string;\n}\n\n/**\n * RemoteOK feed. Single global JSON endpoint, no auth.\n * Endpoint: remoteok.com/api\n *\n * First element of the response is metadata (\"legal\"), real postings start\n * at index 1.\n */\nexport const remoteokProvider: Provider = {\n id: 'remoteok',\n needsAllowlist: false,\n async fetch(_query, { timeoutMs }) {\n const url = 'https://remoteok.com/api';\n const entries = await fetchJson<RemoteOkEntry[]>(url, { timeoutMs });\n return entries\n .filter((e) => e.id && e.position && e.company)\n .map<JobPosting>((e) => {\n const body = stripHtml(e.description ?? '');\n const comp =\n e.salary_min && e.salary_max\n ? `$${e.salary_min}–$${e.salary_max}`\n : undefined;\n return {\n id: `remoteok:${e.id}`,\n source: 'remoteok',\n company: e.company as string,\n title: e.position as string,\n location: e.location,\n remote: true,\n url: e.url ?? `https://remoteok.com/remote-jobs/${e.slug ?? e.id}`,\n body,\n postedAt: e.date,\n tags: e.tags,\n compensation: comp,\n };\n });\n },\n};\n","import type { JobPosting, Provider } from '../types';\nimport { stripHtml } from '../normalize';\nimport { fetchJson } from './http';\n\ninterface RemotiveJob {\n id: number;\n url: string;\n title: string;\n company_name: string;\n category?: string;\n tags?: string[];\n job_type?: string;\n publication_date?: string;\n candidate_required_location?: string;\n salary?: string;\n description?: string;\n}\n\ninterface RemotiveResponse {\n jobs?: RemotiveJob[];\n}\n\n/**\n * Remotive feed. Single global JSON endpoint, no auth.\n * Endpoint: remotive.com/api/remote-jobs\n */\nexport const remotiveProvider: Provider = {\n id: 'remotive',\n needsAllowlist: false,\n async fetch(_query, { timeoutMs }) {\n const url = 'https://remotive.com/api/remote-jobs';\n const data = await fetchJson<RemotiveResponse>(url, { timeoutMs });\n const jobs = data.jobs ?? [];\n return jobs.map<JobPosting>((j) => ({\n id: `remotive:${j.id}`,\n source: 'remotive',\n company: j.company_name,\n title: j.title,\n location: j.candidate_required_location,\n remote: true,\n url: j.url,\n body: stripHtml(j.description ?? ''),\n postedAt: j.publication_date,\n tags: j.tags,\n compensation: j.salary,\n }));\n },\n};\n","import type { JobPosting, Provider } from '../types';\nimport { stripHtml } from '../normalize';\nimport { fetchText } from './http';\n\nconst WWR_CATEGORIES = [\n 'programming',\n 'design',\n 'devops',\n 'management',\n 'product',\n 'customer-support',\n 'sales-and-marketing',\n];\n\n/**\n * We Work Remotely RSS feeds, one per category. Minimal regex-based XML parse:\n * the feed format is stable and we only extract well-bounded fields.\n */\nexport const wwrProvider: Provider = {\n id: 'wwr',\n needsAllowlist: false,\n async fetch(_query, { timeoutMs }) {\n const results = await Promise.allSettled(\n WWR_CATEGORIES.map((cat) => fetchCategory(cat, timeoutMs))\n );\n return results.flatMap((r) => (r.status === 'fulfilled' ? r.value : []));\n },\n};\n\nasync function fetchCategory(category: string, timeoutMs: number): Promise<JobPosting[]> {\n const url = `https://weworkremotely.com/categories/remote-${category}-jobs.rss`;\n const xml = await fetchText(url, { timeoutMs, accept: 'application/rss+xml, application/xml' });\n return parseRss(xml, category);\n}\n\nconst ITEM_RE = /<item>([\\s\\S]*?)<\\/item>/g;\nconst CDATA_RE = /<!\\[CDATA\\[([\\s\\S]*?)\\]\\]>/;\n\nfunction pickTag(block: string, tag: string): string | undefined {\n const re = new RegExp(`<${tag}>([\\\\s\\\\S]*?)<\\\\/${tag}>`);\n const m = re.exec(block);\n if (!m) return undefined;\n const raw = m[1] ?? '';\n const cdata = CDATA_RE.exec(raw);\n return (cdata && cdata[1] !== undefined ? cdata[1] : raw).trim();\n}\n\nfunction parseRss(xml: string, category: string): JobPosting[] {\n const items: JobPosting[] = [];\n let match: RegExpExecArray | null;\n while ((match = ITEM_RE.exec(xml)) !== null) {\n const block = match[1] ?? '';\n const title = pickTag(block, 'title') ?? '';\n const link = pickTag(block, 'link') ?? '';\n const guid = pickTag(block, 'guid') ?? link;\n const pubDate = pickTag(block, 'pubDate');\n const descriptionHtml = pickTag(block, 'description') ?? '';\n const body = stripHtml(descriptionHtml);\n const segments = title.split(':').map((s) => s.trim());\n const companyRaw = segments[0] ?? '';\n const titleRest = segments.slice(1);\n const company = companyRaw || 'Unknown';\n const cleanTitle = titleRest.length ? titleRest.join(': ') : title;\n items.push({\n id: `wwr:${guid}`,\n source: 'wwr',\n company,\n title: cleanTitle,\n location: 'Remote',\n remote: true,\n url: link,\n body,\n postedAt: pubDate ? new Date(pubDate).toISOString() : undefined,\n tags: [category],\n });\n }\n return items;\n}\n\nexport const __test__ = { parseRss };\n","import type { JobPosting, Provider, SearchQuery } from '../types';\nimport { looksRemote, stripHtml } from '../normalize';\nimport { fetchJson } from './http';\n\ninterface AlgoliaHit {\n objectID: string;\n author?: string;\n comment_text?: string;\n story_id?: number;\n created_at?: string;\n parent_id?: number;\n}\n\ninterface AlgoliaResponse {\n hits: AlgoliaHit[];\n}\n\ninterface AlgoliaStoryHit {\n objectID: string;\n story_id?: number;\n story_title?: string;\n title?: string;\n created_at?: string;\n}\n\n/**\n * Hacker News \"Who is hiring?\" threads, queried via the Algolia HN search API.\n * No allowlist needed; we find the latest monthly thread and pull top-level\n * comments, ranked by query relevance via Algolia's own text scoring.\n */\nexport const hnWhoisHiringProvider: Provider = {\n id: 'hn-whoishiring',\n needsAllowlist: false,\n async fetch(query, { timeoutMs }) {\n const storyId = await findLatestThread(timeoutMs);\n if (!storyId) return [];\n return fetchPostings(storyId, query, timeoutMs);\n },\n};\n\nasync function findLatestThread(timeoutMs: number): Promise<number | null> {\n const url =\n 'https://hn.algolia.com/api/v1/search?tags=story,author_whoishiring&query=who%20is%20hiring&restrictSearchableAttributes=title&hitsPerPage=5';\n const data = await fetchJson<{ hits: AlgoliaStoryHit[] }>(url, { timeoutMs });\n for (const hit of data.hits) {\n const title = (hit.story_title ?? hit.title ?? '').toLowerCase();\n if (title.includes('who is hiring')) {\n return hit.story_id ?? Number(hit.objectID);\n }\n }\n return null;\n}\n\nasync function fetchPostings(\n storyId: number,\n query: SearchQuery,\n timeoutMs: number\n): Promise<JobPosting[]> {\n const q = encodeURIComponent(query.terms.slice(0, 3).join(' ') || 'remote');\n const url = `https://hn.algolia.com/api/v1/search?tags=comment,story_${storyId}&hitsPerPage=40&query=${q}`;\n const data = await fetchJson<AlgoliaResponse>(url, { timeoutMs });\n return data.hits\n .filter((h) => typeof h.comment_text === 'string' && h.comment_text.length > 80)\n .map<JobPosting>((h) => {\n const body = stripHtml(h.comment_text as string);\n const { company, title, location } = parseHeader(body);\n return {\n id: `hn-whoishiring:${h.objectID}`,\n source: 'hn-whoishiring',\n company,\n title,\n location,\n remote: looksRemote(location, body),\n url: `https://news.ycombinator.com/item?id=${h.objectID}`,\n body,\n postedAt: h.created_at,\n };\n });\n}\n\n/**\n * HN \"Who is hiring?\" comments conventionally start with a header line like:\n * \"Acme (San Francisco, CA / Remote) | Senior Engineer | ...\"\n * We parse what we can; falling back to defaults when the format isn't met.\n */\nfunction parseHeader(body: string): { company: string; title: string; location?: string } {\n const firstLine = body.split('\\n')[0] ?? body.slice(0, 200);\n const segments = firstLine.split('|').map((s) => s.trim());\n const head = segments[0] ?? '';\n const locMatch = /\\(([^)]+)\\)/.exec(head);\n const company = head.replace(/\\s*\\([^)]+\\)/, '').trim() || 'HN posting';\n const location = locMatch ? locMatch[1] : undefined;\n const title = segments[1] ?? segments[2] ?? 'See description';\n return { company, title, location };\n}\n\nexport const __test__ = { parseHeader };\n","import type { Provider, ProviderId } from '../types';\nimport { greenhouseProvider } from './greenhouse';\nimport { leverProvider } from './lever';\nimport { ashbyProvider } from './ashby';\nimport { workableProvider } from './workable';\nimport { remoteokProvider } from './remoteok';\nimport { remotiveProvider } from './remotive';\nimport { wwrProvider } from './wwr';\nimport { hnWhoisHiringProvider } from './hn-whoishiring';\n\nconst PROVIDERS: Provider[] = [\n greenhouseProvider,\n leverProvider,\n ashbyProvider,\n workableProvider,\n remoteokProvider,\n remotiveProvider,\n wwrProvider,\n hnWhoisHiringProvider,\n];\n\nexport function listProviders(): Provider[] {\n return PROVIDERS;\n}\n\nexport function getProvider(id: ProviderId): Provider | undefined {\n return PROVIDERS.find((p) => p.id === id);\n}\n","import type { ResumeSchema } from '../types/resume';\nimport { analyzeAts } from '../ats/index';\nimport { loadConfig } from '../utils/config';\nimport type { JobPosting, RankedJob } from './types';\nimport { dedupeKey } from './normalize';\n\n/**\n * Score every posting with the existing ATS engine and sort desc by total.\n * Pure: no IO, no mutation of inputs.\n */\nexport function rankPostings(resume: ResumeSchema, postings: JobPosting[]): RankedJob[] {\n const cfg = loadConfig();\n const seen = new Map<string, RankedJob>();\n for (const posting of postings) {\n const key = dedupeKey(posting);\n const ats = analyzeAts(resume, {\n jobDescription: posting.body,\n jobTitle: posting.title,\n language: cfg.locale,\n config: cfg,\n });\n const ranked: RankedJob = { ...posting, ats, dedupeKey: key };\n const existing = seen.get(key);\n if (!existing || ranked.ats.score > existing.ats.score) {\n seen.set(key, ranked);\n }\n }\n return Array.from(seen.values()).sort((a, b) => b.ats.score - a.ats.score);\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport type { ProviderId } from './types';\n\ntype CompaniesFile = Partial<Record<ProviderId, string[]>> & { _comment?: string };\n\nconst currentDir = path.dirname(fileURLToPath(import.meta.url));\n\nconst CANDIDATE_PATHS = [\n path.resolve(currentDir, '../../data/jobs/companies.json'),\n path.resolve(currentDir, '../data/jobs/companies.json'),\n];\n\nlet cached: CompaniesFile | null = null;\n\nfunction loadCompaniesFile(): CompaniesFile {\n if (cached) return cached;\n for (const p of CANDIDATE_PATHS) {\n if (fs.existsSync(p)) {\n cached = JSON.parse(fs.readFileSync(p, 'utf-8')) as CompaniesFile;\n return cached;\n }\n }\n cached = {};\n return cached;\n}\n\nexport function getSeedCompanies(provider: ProviderId): string[] {\n const file = loadCompaniesFile();\n return file[provider] ?? [];\n}\n","import type { ResumeSchema } from '../types/resume';\nimport { deriveSearchQuery } from './query';\nimport { listProviders, getProvider } from './providers/index';\nimport { applyQueryFilters } from './normalize';\nimport { rankPostings } from './rank';\nimport { getSeedCompanies } from './companies';\nimport type {\n JobPosting,\n ProviderResult,\n SearchOptions,\n SearchResult,\n} from './types';\n\nexport type {\n JobPosting,\n ProviderId,\n ProviderResult,\n RankedJob,\n SearchOptions,\n SearchQuery,\n SearchResult,\n SeniorityLevel,\n} from './types';\nexport { deriveSearchQuery } from './query';\nexport { dedupeKey, stripHtml } from './normalize';\nexport { listProviders, getProvider } from './providers/index';\n\nconst DEFAULT_LIMIT = 20;\nconst DEFAULT_MIN_SCORE = 85;\nconst DEFAULT_TIMEOUT_MS = 8000;\n\n/**\n * Discover + score job postings against a resume.\n *\n * Pipeline:\n * 1. Derive a SearchQuery from the resume (skills, seniority, location).\n * 2. Fan out to enabled providers in parallel; per-provider errors are\n * captured in `providers[]` and never bubble out.\n * 3. Apply remote-only filter if requested.\n * 4. Score every survivor via analyzeAts(resume, { jobDescription }), dedupe\n * by (company, title, location), and sort desc by total ATS score.\n * 5. Drop entries below `minScore`, cap to `limit`.\n */\nexport async function searchJobs(\n resume: ResumeSchema,\n options: SearchOptions = {}\n): Promise<SearchResult> {\n const baseQuery = deriveSearchQuery(resume, { remoteOnly: options.remoteOnly });\n const locationCc = options.location\n ? options.location.split(',').pop()?.trim().toUpperCase()\n : undefined;\n const query =\n locationCc && locationCc.length === 2\n ? { ...baseQuery, countryCode: locationCc }\n : baseQuery;\n\n const enabled = options.providers\n ? options.providers.map(getProvider).filter((p): p is NonNullable<typeof p> => !!p)\n : listProviders();\n\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const limit = options.limit ?? DEFAULT_LIMIT;\n const minScore = options.minScore ?? DEFAULT_MIN_SCORE;\n const extraCompanies = options.extraCompanies ?? {};\n\n const providerResults: ProviderResult[] = await Promise.all(\n enabled.map(async (provider): Promise<ProviderResult> => {\n const started = Date.now();\n try {\n const companies = provider.needsAllowlist\n ? Array.from(\n new Set([\n ...getSeedCompanies(provider.id),\n ...(extraCompanies[provider.id] ?? []),\n ])\n )\n : undefined;\n const postings = await provider.fetch(query, {\n companies,\n timeoutMs,\n });\n return {\n providerId: provider.id,\n postings,\n durationMs: Date.now() - started,\n };\n } catch (e) {\n return {\n providerId: provider.id,\n postings: [],\n durationMs: Date.now() - started,\n error: e instanceof Error ? e.message : String(e),\n };\n }\n })\n );\n\n const allPostings: JobPosting[] = providerResults.flatMap((r) => r.postings);\n const fetchedCount = allPostings.length;\n\n const { postings: filtered, wrongLocationCount } = applyQueryFilters(allPostings, query);\n const ranked = rankPostings(resume, filtered);\n const offSpecialtyCount = ranked.filter((r) =>\n r.ats.tiers.match?.checks.some((c) => c.id === 'role-family-match' && c.status === 'fail')\n ).length;\n const passing = ranked.filter((r) => r.ats.score >= minScore);\n const filteredCount = ranked.length - passing.length;\n const jobs = passing.slice(0, limit);\n\n return {\n query,\n jobs,\n providers: providerResults,\n filteredCount,\n fetchedCount,\n offSpecialtyCount,\n wrongLocationCount,\n };\n}\n\n/**\n * Score a single posting body against a resume. Useful for the MCP\n * `resuml_jobs_score` tool when the agent already has the JD text in hand.\n */\nexport function scorePosting(\n resume: ResumeSchema,\n posting: Pick<JobPosting, 'body' | 'company' | 'title' | 'location' | 'url' | 'source' | 'id' | 'remote'>\n) {\n const ranked = rankPostings(resume, [\n {\n ...posting,\n tags: undefined,\n postedAt: undefined,\n compensation: undefined,\n },\n ]);\n return ranked[0];\n}\n\n/**\n * Build a prompt that asks the agent to tailor the resume to a specific\n * posting. The MCP `resuml_jobs_tailor` tool returns this string.\n */\nexport function buildTailorPrompt(posting: JobPosting): string {\n return [\n `Tailor my resume for the following job posting at ${posting.company}.`,\n '',\n `# ${posting.title}`,\n posting.location ? `Location: ${posting.location}` : '',\n `URL: ${posting.url}`,\n '',\n '## Job description',\n posting.body,\n '',\n 'Use the resuml MCP tools:',\n ' 1. resuml_validate to confirm the tailored YAML parses.',\n ' 2. resuml_ats_check with the job description above. Target score >= 80.',\n ' 3. Show the changes you made and the final score.',\n ]\n .filter(Boolean)\n .join('\\n');\n}\n"],"mappings":"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","names":["fetchCompany","fetchCompany","fetchCompany"]}
|