{"_id":"@edwinfom/resume-intel","_rev":"9-432a3d715e3ffbfe14dd8de68c53f887","name":"@edwinfom/resume-intel","dist-tags":{"beta":"0.1.1-beta.1","hotfix":"0.1.2-hotfix.1","latest":"0.2.1"},"versions":{"0.1.0":{"name":"@edwinfom/resume-intel","version":"0.1.0","keywords":["resume","cv","parser","pdf","llm","ai","deepseek","openai","json-resume","extraction","typescript"],"author":{"name":"Edwin Fom","email":"edwinfom@example.com"},"license":"MIT","_id":"@edwinfom/resume-intel@0.1.0","maintainers":[{"name":"edwinfom","email":"edwinfom05@gmail.com"}],"homepage":"https://github.com/edwinfom/resume-intel#readme","bugs":{"url":"https://github.com/edwinfom/resume-intel/issues"},"dist":{"shasum":"6fd3a1fc5277a54ddcefd889a429d2f3e927ca7a","tarball":"https://registry.npmjs.org/@edwinfom/resume-intel/-/resume-intel-0.1.0.tgz","fileCount":8,"integrity":"sha512-JRb+qhF88WNFwTfF5VlvZogVR3MsaGWueDnxe2+GSYdncqA2yV3uVKa87fAXFW79wnre4r09N9FwJQ8poGb3eg==","signatures":[{"sig":"MEYCIQDKNY/vTycSPRzEyhqkab7iDNEQpSrtQFuR+YuFxyUvQQIhAIATuabLyQAdkqXbP/T9OB19ZF+/fZMxM57DKQI6lg0U","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":280369},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"dev":"tsup --watch","lint":"eslint src tests","test":"vitest run","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"edwinfom","email":"edwinfom05@gmail.com"},"repository":{"url":"git+https://github.com/edwinfom/resume-intel.git","type":"git"},"_npmVersion":"11.6.2","description":"LLM-first resume parsing infrastructure. Agnostic, structured, production-ready.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ai":"^4.1.0","zod":"^3.24.1","jsonrepair":"^3.11.1","pdfjs-dist":"^4.9.155","tesseract.js":"^7.0.0","@napi-rs/canvas":"^0.1.100","zod-to-json-schema":"^3.24.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^3.0.4","typescript":"^5.7.3","@types/node":"^22.10.7","@ai-sdk/openai":"^1.1.9","@ai-sdk/anthropic":"^1.1.6","@vitest/coverage-v8":"^3.0.4"},"peerDependencies":{"ai":">=4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/resume-intel_0.1.0_1777378110158_0.42153179034987764","host":"s3://npm-registry-packages-npm-production"}},"0.1.1-beta.1":{"name":"@edwinfom/resume-intel","version":"0.1.1-beta.1","keywords":["resume","cv","parser","pdf","llm","ai","deepseek","openai","json-resume","extraction","typescript"],"author":{"name":"Edwin Fom","email":"edwinfom05@gmail.com"},"license":"MIT","_id":"@edwinfom/resume-intel@0.1.1-beta.1","maintainers":[{"name":"edwinfom","email":"edwinfom05@gmail.com"}],"homepage":"https://packages.edwinfom.dev","bugs":{"url":"https://github.com/Edwinfom00/resume-intel/issues"},"dist":{"shasum":"e4e47a5b218e5b1e98d4106902de495861a981a4","tarball":"https://registry.npmjs.org/@edwinfom/resume-intel/-/resume-intel-0.1.1-beta.1.tgz","fileCount":10,"integrity":"sha512-dW/NuOttUB9th+GIc5cz8ANyh5F+G0sACrnmNeOzBjLfLwanGzIufo6buf+4MKzY/YzBN3AYMmFV+CvWmR4aHQ==","signatures":[{"sig":"MEYCIQCUI4n01iqdCRS++0fmIc4aqUMHfpZxbpGtpWHW4GnktwIhAK5a6RoehkB+fttrLlbMrxvV3vLRULGyzDMkyy6Ys+9v","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":323926},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"c1363cb65c498fac815310b4fa248290f7716062","scripts":{"dev":"tsup --watch","lint":"eslint src tests","test":"vitest run","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"edwinfom","email":"edwinfom05@gmail.com"},"repository":{"url":"git+https://github.com/Edwinfom00/resume-intel.git","type":"git"},"_npmVersion":"11.6.2","description":"LLM-first resume parsing infrastructure. Agnostic, structured, production-ready.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ai":"^4.1.0","zod":"^3.24.1","jsonrepair":"^3.11.1","pdfjs-dist":"^4.9.155","tesseract.js":"^7.0.0","@napi-rs/canvas":"^0.1.100","zod-to-json-schema":"^3.24.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"tsup":"^8.3.5","vitest":"^3.0.4","typescript":"^5.7.3","@types/node":"^22.10.7","@ai-sdk/openai":"^1.1.9","@ai-sdk/anthropic":"^1.1.6","@vitest/coverage-v8":"^3.0.4"},"peerDependencies":{"ai":">=4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/resume-intel_0.1.1-beta.1_1777387154597_0.037628482257688","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@edwinfom/resume-intel","version":"0.1.1","keywords":["resume","cv","parser","pdf","llm","ai","deepseek","openai","json-resume","extraction","typescript"],"author":{"name":"Edwin Fom","email":"edwinfom05@gmail.com"},"license":"MIT","_id":"@edwinfom/resume-intel@0.1.1","maintainers":[{"name":"edwinfom","email":"edwinfom05@gmail.com"}],"homepage":"https://packages.edwinfom.dev","bugs":{"url":"https://github.com/Edwinfom00/resume-intel/issues"},"dist":{"shasum":"230e7dc9283a3f11a1084b5dec3f90717070d66f","tarball":"https://registry.npmjs.org/@edwinfom/resume-intel/-/resume-intel-0.1.1.tgz","fileCount":10,"integrity":"sha512-6ZObs7J0JDpzrbXl3dryN/d7ndLKuuEr4OtoK3f5P+sd4C0NdOLmNff59FGIlpxh0vTth3A4NVaZOQBlMrzS3g==","signatures":[{"sig":"MEYCIQDsIiXI0SVdqCIntKum3tTuH8wuW9Qlt1+TaKSTQ3z+RgIhAK6CaFYjkLaaWSHIn9okjLlYBfmpjLqnOvV1p8M2sebv","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":323919},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"c1363cb65c498fac815310b4fa248290f7716062","scripts":{"dev":"tsup --watch","lint":"eslint src tests","test":"vitest run","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"edwinfom","email":"edwinfom05@gmail.com"},"repository":{"url":"git+https://github.com/Edwinfom00/resume-intel.git","type":"git"},"_npmVersion":"11.6.2","description":"LLM-first resume parsing infrastructure. Agnostic, structured, production-ready.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ai":"^4.1.0","zod":"^3.24.1","jsonrepair":"^3.11.1","pdfjs-dist":"^4.9.155","tesseract.js":"^7.0.0","@napi-rs/canvas":"^0.1.100","zod-to-json-schema":"^3.24.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^3.0.4","typescript":"^5.7.3","@types/node":"^22.10.7","@ai-sdk/openai":"^1.1.9","@ai-sdk/anthropic":"^1.1.6","@vitest/coverage-v8":"^3.0.4"},"peerDependencies":{"ai":">=4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/resume-intel_0.1.1_1777387354220_0.8977131422961195","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@edwinfom/resume-intel","version":"0.1.2","keywords":["resume","cv","parser","pdf","llm","ai","deepseek","openai","json-resume","extraction","typescript"],"author":{"name":"Edwin Fom","email":"edwinfom05@gmail.com"},"license":"MIT","_id":"@edwinfom/resume-intel@0.1.2","maintainers":[{"name":"edwinfom","email":"edwinfom05@gmail.com"}],"homepage":"https://packages.edwinfom.dev","bugs":{"url":"https://github.com/Edwinfom00/resume-intel/issues"},"bin":{"resume-intel":"dist/cli.js"},"dist":{"shasum":"caa8908848cb64a0bee2419a51e6d22e4d61b428","tarball":"https://registry.npmjs.org/@edwinfom/resume-intel/-/resume-intel-0.1.2.tgz","fileCount":11,"integrity":"sha512-Y9yLHqOYKVS86HcCxetY3R7p/TFM7ROyzBfotMaabsX5J3yZHqzUKC8YuCuYdzI36UH0PoQ4tjoNcg5bI6RO8A==","signatures":[{"sig":"MEUCIEEs5rCaMCpuodsC5lphCLFVo3a48sUhz7MdGrNFl3F6AiEA5MAkx3x/q0YwHB69OZGkPYDhnUx7cxx7+AFdPdpafFs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":390105},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"c1363cb65c498fac815310b4fa248290f7716062","scripts":{"dev":"tsup --watch","lint":"eslint src tests","test":"vitest run","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"edwinfom","email":"edwinfom05@gmail.com"},"repository":{"url":"git+https://github.com/Edwinfom00/resume-intel.git","type":"git"},"_npmVersion":"11.6.2","description":"LLM-first resume parsing infrastructure. Agnostic, structured, production-ready.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ai":"^4.1.0","zod":"^3.24.1","jsonrepair":"^3.11.1","pdfjs-dist":"^4.9.155","tesseract.js":"^7.0.0","@napi-rs/canvas":"^0.1.100","zod-to-json-schema":"^3.24.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^3.0.4","typescript":"^5.7.3","@types/node":"^22.10.7","@ai-sdk/openai":"^1.1.9","@ai-sdk/anthropic":"^1.1.6","@vitest/coverage-v8":"^3.0.4"},"peerDependencies":{"ai":">=4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/resume-intel_0.1.2_1777540336954_0.38552383625322606","host":"s3://npm-registry-packages-npm-production"}},"0.1.2-hotfix.1":{"name":"@edwinfom/resume-intel","version":"0.1.2-hotfix.1","keywords":["resume","cv","parser","pdf","llm","ai","deepseek","openai","json-resume","extraction","typescript"],"author":{"name":"Edwin Fom","email":"edwinfom05@gmail.com"},"license":"MIT","_id":"@edwinfom/resume-intel@0.1.2-hotfix.1","maintainers":[{"name":"edwinfom","email":"edwinfom05@gmail.com"}],"homepage":"https://packages.edwinfom.dev","bugs":{"url":"https://github.com/Edwinfom00/resume-intel/issues"},"bin":{"resume-intel":"dist/cli.js"},"dist":{"shasum":"eb090559d697797d123eff6e73a68a1725a85fec","tarball":"https://registry.npmjs.org/@edwinfom/resume-intel/-/resume-intel-0.1.2-hotfix.1.tgz","fileCount":11,"integrity":"sha512-OKUdrwcbRWtgluJ6ymjekAMBakkLl1sdxXaxvw4AvIawNfC578J3fxdU+12SiULvn6MO2A2Emmgc0ZdvEyLq0Q==","signatures":[{"sig":"MEYCIQCQWkpgrS6OC4ipgOlJOanZ+T0Peg6ieQIOwFmLdPtAkAIhAPBAujSTsXufr8zqx5FMUGDVvuT7d9xUnjsaRh+EgJrb","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":395855},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"addd734ada2cc82f781143c7b4cf84050b797bd8","scripts":{"dev":"tsup --watch","lint":"eslint src tests","test":"vitest run","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build && npm run typecheck"},"_npmUser":{"name":"edwinfom","email":"edwinfom05@gmail.com"},"repository":{"url":"git+https://github.com/Edwinfom00/resume-intel.git","type":"git"},"_npmVersion":"11.6.2","description":"LLM-first resume parsing infrastructure. Agnostic, structured, production-ready.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ai":"^4.1.0","zod":"^3.24.1","jsonrepair":"^3.11.1","pdfjs-dist":"^4.9.155","tesseract.js":"^7.0.0","@napi-rs/canvas":"^0.1.100","zod-to-json-schema":"^3.24.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"tsup":"^8.3.5","vitest":"^3.0.4","typescript":"^5.7.3","@types/node":"^22.10.7","@ai-sdk/openai":"^1.1.9","@ai-sdk/anthropic":"^1.1.6","@vitest/coverage-v8":"^3.0.4"},"peerDependencies":{"ai":">=4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/resume-intel_0.1.2-hotfix.1_1777544576519_0.5249143989741385","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@edwinfom/resume-intel","version":"0.1.3","keywords":["resume","cv","parser","pdf","llm","ai","deepseek","openai","json-resume","extraction","typescript"],"author":{"name":"Edwin Fom","email":"edwinfom05@gmail.com"},"license":"MIT","_id":"@edwinfom/resume-intel@0.1.3","maintainers":[{"name":"edwinfom","email":"edwinfom05@gmail.com"}],"homepage":"https://packages.edwinfom.dev","bugs":{"url":"https://github.com/Edwinfom00/resume-intel/issues"},"bin":{"resume-intel":"dist/cli.js"},"dist":{"shasum":"d8ab9325dea17ad8e62d924d9f9a5b71294eb5e4","tarball":"https://registry.npmjs.org/@edwinfom/resume-intel/-/resume-intel-0.1.3.tgz","fileCount":11,"integrity":"sha512-Qu02BqSS0SoQGHsXnvbv4uD+tgI6nNRlQN+HRNzsewD1wpeF9IV+TOX2WtphvoBWADXw0u4QaF9dFoTZ8dHMEg==","signatures":[{"sig":"MEQCIDuH9s2dCXNH1qQeBBhU05YDafj0QYwzdcpXK79sxMfdAiATNFRDkMB/OB6N/q2DEo/qpu3BrZ+qUSkWjCD117MnMg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":463768},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"50c93b899513c04785ec5851e6f439f2599394d7","scripts":{"dev":"tsup --watch","lint":"eslint src tests","test":"vitest run","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build && npm run typecheck"},"_npmUser":{"name":"edwinfom","email":"edwinfom05@gmail.com"},"repository":{"url":"git+https://github.com/Edwinfom00/resume-intel.git","type":"git"},"_npmVersion":"11.6.2","description":"LLM-first resume parsing infrastructure. Agnostic, structured, production-ready.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ai":"^4.1.0","zod":"^3.24.1","jsonrepair":"^3.11.1","pdfjs-dist":"^4.9.155","tesseract.js":"^7.0.0","@napi-rs/canvas":"^0.1.100","zod-to-json-schema":"^3.24.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^3.0.4","typescript":"^5.7.3","@types/node":"^22.10.7","@ai-sdk/openai":"^1.1.9","@ai-sdk/anthropic":"^1.1.6","@vitest/coverage-v8":"^3.0.4"},"peerDependencies":{"ai":">=4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/resume-intel_0.1.3_1777909187790_0.23616481659473298","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@edwinfom/resume-intel","version":"0.2.0","keywords":["resume","cv","parser","pdf","llm","ai","deepseek","openai","json-resume","extraction","typescript"],"author":{"name":"Edwin Fom","email":"edwinfom05@gmail.com"},"license":"MIT","_id":"@edwinfom/resume-intel@0.2.0","maintainers":[{"name":"edwinfom","email":"edwinfom05@gmail.com"}],"homepage":"https://packages.edwinfom.dev","bugs":{"url":"https://github.com/Edwinfom00/resume-intel/issues"},"bin":{"resume-intel":"dist/cli.js"},"dist":{"shasum":"b1abb6727cdfb39772456f511d496c707c41356b","tarball":"https://registry.npmjs.org/@edwinfom/resume-intel/-/resume-intel-0.2.0.tgz","fileCount":11,"integrity":"sha512-dfnOU5PNts4eBWMq2x+e0AoWv3/JTb1RhIasZqtEj+d3NZCejK4OMgEXzj7bPU8GqONDhVZPf8NxSfk34i8FDw==","signatures":[{"sig":"MEYCIQDX8WD0lV9X3N51n0PWzSKXlBesHRggETjVrq4HenORGQIhAIlodkrW2rlZy70lQNvYLfgE3fu2CY18XlHA00QUI9hC","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":531418},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20.0.0"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"2b398eb9a3bed5da6178675520d47f13a333836d","scripts":{"dev":"tsup --watch","lint":"eslint src tests","test":"vitest run","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","test:watch":"vitest","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build && npm run typecheck"},"_npmUser":{"name":"edwinfom","email":"edwinfom05@gmail.com"},"repository":{"url":"git+https://github.com/Edwinfom00/resume-intel.git","type":"git"},"_npmVersion":"11.6.2","description":"LLM-first resume parsing infrastructure. Agnostic, structured, production-ready.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"ai":"^4.1.0","zod":"^3.24.1","jsonrepair":"^3.11.1","pdfjs-dist":"^4.9.155","tesseract.js":"^7.0.0","@napi-rs/canvas":"^0.1.100","zod-to-json-schema":"^3.24.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","vitest":"^3.0.4","typescript":"^5.7.3","@types/node":"^22.10.7","@ai-sdk/openai":"^1.1.9","@ai-sdk/anthropic":"^1.1.6","@vitest/coverage-v8":"^3.0.4"},"peerDependencies":{"ai":">=4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/resume-intel_0.2.0_1778146041823_0.1347318895760754","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@edwinfom/resume-intel","version":"0.2.1","description":"LLM-first resume parsing infrastructure. Agnostic, structured, production-ready.","keywords":["resume","cv","parser","pdf","llm","ai","deepseek","openai","json-resume","extraction","typescript"],"author":{"name":"Edwin Fom","email":"edwinfom05@gmail.com"},"license":"MIT","homepage":"https://packages.edwinfom.dev","repository":{"type":"git","url":"git+https://github.com/Edwinfom00/resume-intel.git"},"bugs":{"url":"https://github.com/Edwinfom00/resume-intel/issues"},"bin":{"resume-intel":"dist/cli.js"},"type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"build":"tsup","dev":"tsup --watch","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage","lint":"eslint src tests","typecheck":"tsc --noEmit","clean":"rm -rf dist","prepublishOnly":"npm run build && npm run typecheck"},"dependencies":{"@napi-rs/canvas":"^0.1.100","ai":"^4.1.0","jsonrepair":"^3.11.1","pdfjs-dist":"^4.9.155","tesseract.js":"^7.0.0","zod":"^3.24.1","zod-to-json-schema":"^3.24.1"},"devDependencies":{"@ai-sdk/anthropic":"^1.1.6","@ai-sdk/openai":"^1.1.9","@types/node":"^22.10.7","@vitest/coverage-v8":"^3.0.4","tsup":"^8.3.5","typescript":"^5.7.3","vitest":"^3.0.4"},"peerDependencies":{"ai":">=4.0.0"},"engines":{"node":">=20.0.0"},"gitHead":"3e80b7257c6f4c71b9887065db5bf7f6d0c38efb","_id":"@edwinfom/resume-intel@0.2.1","_nodeVersion":"24.12.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-O0qyTtAwiBfvxTOzsFMwWxmH/yVuK/PtkY0FighS4hLHs+fE1t71Y3Z6yziGqGl74ViUocczIZ6e9u4qq8trzA==","shasum":"31e56405a76f455aadfb72b1d18c32f7c2c04e69","tarball":"https://registry.npmjs.org/@edwinfom/resume-intel/-/resume-intel-0.2.1.tgz","fileCount":11,"unpackedSize":591655,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFGihAf5GmWG/hcBxJJTJaboJPmS6jpFIbMhPJQ/GZ12AiEA9RFSxi5hwy2/UkoQUy0J55TpS54n5vzV1dwgZ9K/msU="}]},"_npmUser":{"name":"edwinfom","email":"edwinfom05@gmail.com"},"directories":{},"maintainers":[{"name":"edwinfom","email":"edwinfom05@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/resume-intel_0.2.1_1778856631584_0.41950792073296084"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-28T12:08:30.097Z","modified":"2026-05-15T14:50:32.166Z","0.1.0":"2026-04-28T12:08:30.351Z","0.1.1-beta.1":"2026-04-28T14:39:14.789Z","0.1.1":"2026-04-28T14:42:34.461Z","0.1.2":"2026-04-30T09:12:17.080Z","0.1.2-hotfix.1":"2026-04-30T10:22:56.685Z","0.1.3":"2026-05-04T15:39:47.958Z","0.2.0":"2026-05-07T09:27:21.965Z","0.2.1":"2026-05-15T14:50:31.736Z"},"bugs":{"url":"https://github.com/Edwinfom00/resume-intel/issues"},"author":{"name":"Edwin Fom","email":"edwinfom05@gmail.com"},"license":"MIT","homepage":"https://packages.edwinfom.dev","keywords":["resume","cv","parser","pdf","llm","ai","deepseek","openai","json-resume","extraction","typescript"],"repository":{"type":"git","url":"git+https://github.com/Edwinfom00/resume-intel.git"},"description":"LLM-first resume parsing infrastructure. Agnostic, structured, production-ready.","maintainers":[{"name":"edwinfom","email":"edwinfom05@gmail.com"}],"readme":"# @edwinfom/resume-intel\r\n\r\n> LLM-first resume parsing infrastructure.  \r\n> Model-agnostic · Spatial extraction · OCR fallback · 15 sections · Streaming · CLI included\r\n\r\n[![npm version](https://badge.fury.io/js/%40edwinfom%2Fresume-intel.svg)](https://www.npmjs.com/package/@edwinfom/resume-intel)\r\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue)](https://www.typescriptlang.org/)\r\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\r\n\r\n**[Documentation](https://packages.edwinfom.dev/resume-intel)** · **[npm](https://www.npmjs.com/package/@edwinfom/resume-intel)** · **[GitHub](https://github.com/Edwinfom00/resume-intel)** · **[Changelog](./CHANGELOG.md)**\r\n\r\n---\r\n\r\n## What's new in v0.2.1\r\n\r\n- **`redactPii` option** — redacts email, phone, addresses, and URLs before sending to the LLM. Real values are reinjected after extraction. GDPR-friendly.\r\n- **`confidenceScore` in `sectionResults`** — per-section reliability signal (0.0–1.0) based on retry count and field completeness.\r\n- **`redactPii`, `reinjectPii`, `describePiiRedaction` exports** — utility functions for custom redaction pipelines.\r\n\r\n---\r\n\r\n## What's new in v0.2.0\r\n\r\n- **`streamResume()`** — AsyncGenerator that yields events as each section is extracted. Update your UI progressively instead of waiting 15-20 seconds for the full result.\r\n- **`YYYY-01` date fix** — `\"2025-01\"` → `\"2025\"` (month-only padding now stripped)\r\n- **Empty arrays removed** — `volunteer: []`, `interests: []` are now omitted from output\r\n- **Empty skill categories removed** — skills with no keywords are filtered out\r\n- **`StreamResumeEvent` type export**\r\n\r\n---\r\n\r\n## The Problem\r\n\r\nExtracting structured data from resume PDFs is harder than it looks.\r\n\r\nMost tools either use brittle regex patterns that break on modern CV designs, or they wrap a single AI provider's API and lock you in forever. Neither approach is production-ready.\r\n\r\nHere's what actually goes wrong in practice:\r\n\r\n- **Multi-column layouts** — column 1 and column 2 get interleaved. Dates mix with job descriptions. The LLM receives semantic chaos and hallucinates.\r\n- **DeepSeek and similar models can't read raw PDFs** — they are text-only models. You must extract and clean the text first, or every call fails silently.\r\n- **LLMs produce broken JSON** — missing closing braces, trailing commas, JSON wrapped in markdown fences. Without a repair layer, your pipeline crashes.\r\n- **Vendor lock-in** — if your parser only works with Claude or GPT-4, you can't switch to a cheaper or local model without rewriting your integration.\r\n- **Scanned PDFs** — no text layer at all. A basic extractor returns an empty string and you never know why.\r\n- **Serverless deployments** — file-path based worker resolution breaks on Vercel and AWS Lambda.\r\n\r\n`resume-intel` solves all of this with a four-layer pipeline: spatial extraction, OCR fallback, parallel task decomposition, and resilient JSON validation.\r\n\r\n---\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm install @edwinfom/resume-intel ai\r\n# or\r\npnpm add @edwinfom/resume-intel ai\r\n```\r\n\r\nInstall the AI provider SDK you want to use:\r\n\r\n```bash\r\nnpm install @ai-sdk/deepseek   # DeepSeek — recommended\r\nnpm install @ai-sdk/openai     # OpenAI\r\nnpm install @ai-sdk/anthropic  # Anthropic\r\nnpm install @ai-sdk/google     # Google Gemini\r\n```\r\n\r\nFor Ollama (local models), use `@ai-sdk/openai` with a custom `baseURL` — no extra package needed.\r\n\r\n---\r\n\r\n## Serverless Environments (Vercel, AWS Lambda)\r\n\r\nTesseract.js requires WASM files that are **not bundled** by Vercel and AWS Lambda. If your PDF is scanned and OCR triggers, you will get:\r\n\r\n```\r\nENOENT: no such file or directory, open '/var/task/node_modules/tesseract.js-core/tesseract-core-relaxedsimd.wasm'\r\n```\r\n\r\n**Fix:** set `disableOcr: true` in your serverless function.\r\n\r\n```typescript\r\n// app/api/parse-resume/route.ts (Next.js App Router)\r\nconst result = await parseResume(pdfBuffer, {\r\n  model,\r\n  disableOcr: true, // required on Vercel — WASM not available in serverless\r\n})\r\n\r\n// Auto-detect serverless environment\r\nconst result = await parseResume(pdfBuffer, {\r\n  model,\r\n  disableOcr: !!process.env.VERCEL || !!process.env.AWS_LAMBDA_FUNCTION_NAME,\r\n})\r\n```\r\n\r\nWhen `disableOcr: true`:\r\n- Text-native PDFs → extracted normally\r\n- Scanned PDFs → throws `OcrNotEnabledError` with a clear message\r\n\r\n---\r\n\r\n## PII Redaction (GDPR mode)\r\n\r\nSet `redactPii: true` to prevent personal data from being sent to the LLM in plaintext. Email addresses, phone numbers, physical addresses, and URLs are replaced with deterministic placeholders before the LLM call. The real values are reinjected into the structured output after extraction.\r\n\r\n```typescript\r\nconst result = await parseResume(buffer, {\r\n  model,\r\n  redactPii: true,\r\n})\r\n\r\n// The LLM never sees \"john.doe@gmail.com\" — it processes \"__PII_EMAIL_0__\"\r\n// The final output still contains the real email address\r\nconsole.log(result.data.basics?.email) // \"john.doe@gmail.com\"\r\n```\r\n\r\nWorks with both `parseResume()` and `streamResume()`. The redaction is transparent — the output is identical to a non-redacted run.\r\n\r\nFor advanced use cases, the redaction utilities are exported:\r\n\r\n```typescript\r\nimport { redactPii, reinjectPii, describePiiRedaction } from '@edwinfom/resume-intel'\r\n\r\nconst { redactedText, placeholders } = redactPii(rawText)\r\nconsole.log(describePiiRedaction({ redactedText, placeholders }))\r\n// \"2 emails, 3 urls, 1 phone\"\r\n\r\nconst restored = reinjectPii(extractedData, placeholders)\r\n```\r\n\r\n---\r\n\r\n## Quick Start\r\n\r\n```typescript\r\nimport { parseResume } from '@edwinfom/resume-intel'\r\nimport { createDeepSeek } from '@ai-sdk/deepseek'\r\nimport { readFileSync } from 'node:fs'\r\n\r\nconst result = await parseResume(readFileSync('./resume.pdf'), {\r\n  model: createDeepSeek({ apiKey: process.env.DEEPSEEK_API_KEY })('deepseek-chat'),\r\n})\r\n\r\nconsole.log(result.data.basics?.name)            // \"Jane Doe\"\r\nconsole.log(result.data.work?.length)            // 3\r\nconsole.log(result.data.certificates?.length)    // 2\r\nconsole.log(result.meta.ocrFallback)             // true if scanned PDF\r\nconsole.log(result.meta.sectionsRequested)       // ['basics', 'work', ...]\r\nconsole.log(result.meta.tokenUsage?.totalTokens) // 1850\r\n```\r\n\r\n---\r\n\r\n## Streaming\r\n\r\n`streamResume()` yields events as each section is extracted. Your UI updates progressively instead of waiting for the full result.\r\n\r\n```typescript\r\nimport { streamResume } from '@edwinfom/resume-intel'\r\nimport { createDeepSeek } from '@ai-sdk/deepseek'\r\n\r\nfor await (const event of streamResume(readFileSync('./resume.pdf'), {\r\n  model: createDeepSeek({ apiKey: process.env.DEEPSEEK_API_KEY })('deepseek-chat'),\r\n})) {\r\n  if (event.type === 'section') {\r\n    console.log(`${event.section} extracted`)\r\n    updateUI(event.section, event.data) // update your UI immediately\r\n  }\r\n  if (event.type === 'error') {\r\n    console.warn(`${event.section} failed: ${event.error}`)\r\n  }\r\n  if (event.type === 'done') {\r\n    console.log('Complete:', event.result.data.basics?.name)\r\n    console.log('Duration:', event.result.meta.durationMs, 'ms')\r\n  }\r\n}\r\n```\r\n\r\n**Event types:**\r\n\r\n| Event | When | Fields |\r\n|---|---|---|\r\n| `section` | After each section is extracted | `section`, `data`, `success` |\r\n| `error` | When a section fails after all retries | `section`, `error` |\r\n| `done` | When all sections are complete | `result` (full `ResumeIntelResult`) |\r\n\r\n`streamResume()` accepts the same options as `parseResume()`.\r\n\r\n---\r\n\r\n## CLI\r\n\r\nParse resume PDFs directly from the terminal:\r\n\r\n```bash\r\n# Install globally\r\nnpm install -g @edwinfom/resume-intel ai @ai-sdk/deepseek\r\n\r\n# Parse a resume\r\nDEEPSEEK_API_KEY=sk-... resume-intel parse resume.pdf\r\n\r\n# Extract only specific sections\r\nresume-intel parse resume.pdf --sections basics,work,education\r\n\r\n# Write JSON output to file\r\nresume-intel parse resume.pdf --out result.json\r\n\r\n# Use a different model\r\nresume-intel parse resume.pdf --model openai:gpt-4o-mini\r\n\r\n# Raw JSON for piping\r\nresume-intel parse resume.pdf --output json | jq .data.basics.name\r\n\r\n# Show help\r\nresume-intel --help\r\n```\r\n\r\n---\r\n\r\n## Selecting Sections\r\n\r\nBy default, 8 sections are extracted. Use the `sections` option to extract only what you need:\r\n\r\n```typescript\r\nimport { parseResume, ALL_SECTIONS, DEFAULT_SECTIONS } from '@edwinfom/resume-intel'\r\n\r\n// Extract only basics and work — saves tokens\r\nconst result = await parseResume(buffer, {\r\n  model,\r\n  sections: ['basics', 'work'],\r\n})\r\n\r\n// Extract all 12 available sections\r\nconst result = await parseResume(buffer, {\r\n  model,\r\n  sections: [...ALL_SECTIONS],\r\n})\r\n```\r\n\r\n**Available sections:** `basics`, `work`, `education`, `skills`, `languages`, `projects`, `awards`, `certificates`, `publications`, `volunteer`, `interests`, `references`\r\n\r\n**Default sections:** `basics`, `work`, `education`, `skills`, `languages`, `projects`, `certificates`, `volunteer`\r\n\r\n---\r\n\r\n## Custom Output Schema\r\n\r\nReplace the default JSON Resume schema with your own Zod schema:\r\n\r\n```typescript\r\nimport { z } from 'zod'\r\n\r\nconst result = await parseResume(buffer, {\r\n  model,\r\n  outputSchema: z.object({\r\n    fullName: z.string(),\r\n    email: z.string().email().optional(),\r\n    skills: z.array(z.string()),\r\n    yearsOfExperience: z.number().optional(),\r\n  }),\r\n  useTaskDecomposition: false, // single-shot works best with custom schemas\r\n})\r\n\r\nconsole.log(result.data.fullName)\r\nconsole.log(result.data.skills)\r\n```\r\n\r\n---\r\n\r\n## Model Agnosticism\r\n\r\nThe model is just a parameter. Swap it without touching anything else.\r\n\r\n```typescript\r\n// DeepSeek V3 — fast and cheap (recommended default)\r\nconst result = await parseResume(buffer, {\r\n  model: createDeepSeek({ apiKey: process.env.DEEPSEEK_API_KEY })('deepseek-chat'),\r\n})\r\n\r\n// OpenAI\r\nconst result = await parseResume(buffer, {\r\n  model: createOpenAI({ apiKey: process.env.OPENAI_API_KEY })('gpt-4o-mini'),\r\n})\r\n\r\n// Ollama — fully local, no API key, no data leaves your machine\r\nconst result = await parseResume(buffer, {\r\n  model: createOpenAI({ baseURL: 'http://localhost:11434/v1', apiKey: 'ollama' })('llama3.1'),\r\n})\r\n```\r\n\r\n---\r\n\r\n## Output Format\r\n\r\nThe output conforms to the [JSON Resume v1 specification](https://jsonresume.org/schema/).\r\n\r\n```typescript\r\n{\r\n  data: {\r\n    basics: { name, label, email, phone, url, summary, location, profiles },\r\n    work: [{ name, position, startDate, endDate, highlights }],\r\n    education: [{ institution, studyType, area, startDate, endDate }],\r\n    skills: [{ name, keywords }],\r\n    languages: [{ language, fluency }],\r\n    projects: [{ name, description, url }],\r\n    certificates: [{ name, issuer, date }],\r\n    volunteer: [{ organization, position, startDate }],\r\n    awards: [...],\r\n    publications: [...],\r\n    interests: [...],\r\n    references: [...]\r\n  },\r\n  meta: {\r\n    durationMs: 2340,\r\n    ocrFallback: false,\r\n    layoutStrategy: 'spatial',\r\n    pageCount: 2,\r\n    sectionsRequested: ['basics', 'work', 'education', 'skills', 'languages',\r\n                        'projects', 'certificates', 'volunteer'],\r\n    tokenUsage: { promptTokens: 1200, completionTokens: 650, totalTokens: 1850 },\r\n    sectionResults: [\r\n      { section: 'basics', success: true, retryCount: 0, error: null },\r\n      { section: 'work',   success: true, retryCount: 0, error: null },\r\n    ]\r\n  }\r\n}\r\n```\r\n\r\n---\r\n\r\n## API Reference\r\n\r\n### `parseResume(input, options)`\r\n\r\n| Parameter | Type | Default | Description |\r\n|---|---|---|---|\r\n| `input` | `Buffer \\| ArrayBuffer \\| Uint8Array` | required | PDF file content |\r\n| `options.model` | `LanguageModel` | required | Any Vercel AI SDK compatible model |\r\n| `options.sections` | `ResumeSectionKey[]` | 8 default sections | Which sections to extract |\r\n| `options.outputSchema` | `ZodType` | JSON Resume v1 | Custom Zod schema for output |\r\n| `options.maxRetries` | `number` | `3` | Max self-correction attempts per section |\r\n| `options.layoutStrategy` | `'spatial' \\| 'linear'` | `'spatial'` | PDF text extraction strategy |\r\n| `options.useTaskDecomposition` | `boolean` | `true` | Parallel per-section extraction |\r\n| `options.systemPromptPrefix` | `string` | `''` | Custom instructions before extraction prompts |\r\n| `options.disableOcr` | `boolean` | `false` | Disable OCR fallback — required on Vercel/Lambda |\r\n| `options.maxConcurrency` | `number` | `undefined` | Limit parallel section calls (useful for rate-limited APIs) |\r\n| `options.onProgress` | `(section, success) => void` | — | Called after each section extraction |\r\n| `options.ocrLanguage` | `string` | `'eng'` | Tesseract language code for non-English CVs |\r\n| `options.abortSignal` | `AbortSignal` | — | Cancellation signal |\r\n| `options.redactPii` | `boolean` | `false` | Redact PII before LLM submission, reinject after extraction |\r\n\r\n### Exports\r\n\r\n```typescript\r\nimport {\r\n  parseResume,          // main function\r\n  streamResume,         // streaming function — yields events as sections are extracted\r\n  JsonResumeSchema,     // Zod schema for JSON Resume v1\r\n  SectionSchemas,       // individual section schemas\r\n  ALL_SECTIONS,         // all 12 section keys\r\n  DEFAULT_SECTIONS,     // the 8 default sections\r\n  normalizeDate,        // normalize a date string (strips -01 padding, returns null for \"Present\")\r\n  cleanUrl,             // validate and clean a URL string\r\n  redactPii,            // redact PII from text, returns { redactedText, placeholders }\r\n  reinjectPii,          // reinject PII placeholders back into extracted data\r\n  describePiiRedaction, // human-readable summary of what was redacted\r\n  ResumeExtractionError,\r\n  OcrNotEnabledError,\r\n} from '@edwinfom/resume-intel'\r\n\r\nimport type {\r\n  StreamResumeEvent,    // union type for streaming events\r\n} from '@edwinfom/resume-intel'\r\n```\r\n\r\n---\r\n\r\n## Error Handling\r\n\r\n```typescript\r\nimport { parseResume, OcrNotEnabledError, ResumeExtractionError } from '@edwinfom/resume-intel'\r\n\r\ntry {\r\n  const result = await parseResume(buffer, { model })\r\n} catch (error) {\r\n  if (error instanceof OcrNotEnabledError) {\r\n    console.error('OCR failed:', error.message)\r\n  } else if (error instanceof ResumeExtractionError) {\r\n    console.error('Extraction failed after retries:', error.message)\r\n    console.error('Root cause:', error.cause?.message)\r\n  }\r\n}\r\n```\r\n\r\n---\r\n\r\n## Choosing the Right Model\r\n\r\n| Model | Speed | Cost | Best for |\r\n|---|---|---|---|\r\n| `deepseek-chat` (V3) | Fast | ~$0.27/M tokens | Most CVs — recommended default |\r\n| `gpt-4o-mini` | Fast | Low | Good accuracy, widely available |\r\n| `claude-3-5-haiku` | Fast | Low | Complex or non-standard formats |\r\n| `gemini-1.5-flash` | Very fast | Very low | High volume processing |\r\n| `llama3.1` (Ollama) | Slow | Free | Privacy-sensitive data, local dev |\r\n| `deepseek-reasoner` (R1) | Slow | High | Avoid — schema echo problem on extraction |\r\n\r\n---\r\n\r\n## Why Not Just Use [other package]?\r\n\r\n| Package | What's wrong |\r\n|---|---|\r\n| `pdf-parse` | Destroys multi-column layout. Crashes in Node 20+ ESM. No LLM integration. |\r\n| `pdfjs-dist` directly | No spatial reconstruction. No LLM integration. Worker conflicts. |\r\n| `@racsodev/cv-pdf-to-json` | Hard-coded to Anthropic Claude. Cannot use DeepSeek, Ollama, or any other model. |\r\n| `simple-resume-parser` | Regex-based. Fails on any CV that doesn't match its expected patterns. |\r\n\r\n---\r\n\r\n## Roadmap\r\n\r\n- [x] Spatial PDF extraction with multi-column support\r\n- [x] Automatic OCR fallback (Tesseract.js + `@napi-rs/canvas`)\r\n- [x] Model-agnostic adapter via Vercel AI SDK\r\n- [x] JSON Resume v1 output schema\r\n- [x] Zod validation + `jsonrepair` + self-correcting retry loop\r\n- [x] Per-section `maxTokens`, `temperature: 0`, OCR text cleaning\r\n- [x] Per-section retry with self-correction\r\n- [x] Post-extraction deduplication\r\n- [x] **v0.1.2** — 15 sections, `sections` option, `outputSchema` option, CLI, serverless worker fix\r\n- [x] **v0.1.2-hotfix.1** — `disableOcr` option — prevents Tesseract WASM crash on Vercel/Lambda\r\n- [x] **v0.1.3** — Output normalizer (date padding, truncated URLs, invalid profiles, \"Present\" endDate)\r\n- [x] **v0.1.3** — Work section fix (personal projects as work experience now included)\r\n- [x] **v0.1.3** — `maxConcurrency`, `onProgress`, `ocrLanguage` options\r\n- [x] **v0.1.3** — Improved scan detection heuristic (block count + char density)\r\n- [x] **v0.2.0** — `streamResume()` — AsyncGenerator streaming API\r\n- [x] **v0.2.0** — `YYYY-01` date fix, empty arrays removed, empty skill categories removed\r\n- [x] **v0.2.1** — `redactPii` option — PII redaction before LLM submission (GDPR-friendly)\r\n- [x] **v0.2.1** — `confidenceScore` in `sectionResults` — per-section reliability signal\r\n- [ ] **v0.3** — Bounding box metadata in output (for PDF highlight UI)\r\n\r\n---\r\n\r\n## Contributing\r\n\r\nIssues and PRs are welcome. Please open an issue before submitting a large change.\r\n\r\n---\r\n\r\n## License\r\n\r\nMIT © [Edwin Fom](https://github.com/Edwinfom00)\r\n","readmeFilename":"README.md"}