{"_id":"@amars1238/llm-parse","_rev":"4-f82e182b0770677ff5d618adf7d631ae","name":"@amars1238/llm-parse","dist-tags":{"latest":"0.1.3"},"versions":{"0.1.0":{"name":"@amars1238/llm-parse","version":"0.1.0","keywords":["llm","json","parse","validate"],"license":"MIT","_id":"@amars1238/llm-parse@0.1.0","maintainers":[{"name":"amars1238","email":"Amarkarthiks@gmail.com"}],"dist":{"shasum":"927409a588dae706b60186b6294214bafdd874cf","tarball":"https://registry.npmjs.org/@amars1238/llm-parse/-/llm-parse-0.1.0.tgz","fileCount":42,"integrity":"sha512-0qgvXUviTOFwZVJ7V6igJyEOJO7RVJULvp3imBm9DDsvYmLZ5u2G2T/kpzF3FF0t7qjoRG3mXEDE0PJ2zlhmXA==","signatures":[{"sig":"MEQCIEjQIqS+hWeqZmvD9WmdfbMQPbMKQSPEQI4F3gIVYZruAiA8qTJMBRFnnl2q/rlmGsm7m/foKSkCUHTW42DrkHOS8g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":36115},"main":"./dist/cjs/index.js","types":"./dist/esm/index.d.ts","module":"./dist/esm/index.js","exports":{".":{"types":"./dist/esm/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"8302f9f5adb07aeac391e3e2cccaf4edc9eb03f6","scripts":{"test":"npx tsx --test tests/index.test.ts","build":"tsc -p tsconfig.json && tsc -p tsconfig.cjs.json","test:build":"node --test dist/esm/index.test.js","prepublishOnly":"npm test && npm run build"},"_npmUser":{"name":"amars1238","email":"Amarkarthiks@gmail.com"},"_npmVersion":"11.11.0","description":"Lightweight zero-dependency parser and validator for LLM JSON output","directories":{},"_nodeVersion":"24.14.1","_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","typescript":"^6.0.2"},"_npmOperationalInternal":{"tmp":"tmp/llm-parse_0.1.0_1776222490382_0.9247802325120513","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@amars1238/llm-parse","version":"0.1.1","keywords":["llm","json","parse","validate"],"license":"MIT","_id":"@amars1238/llm-parse@0.1.1","maintainers":[{"name":"amars1238","email":"Amarkarthiks@gmail.com"}],"dist":{"shasum":"b2e94e6b51aab910a432e68cb4cf874c36684cba","tarball":"https://registry.npmjs.org/@amars1238/llm-parse/-/llm-parse-0.1.1.tgz","fileCount":42,"integrity":"sha512-MUCtNjWVzXFMQgVcBu7Wz4adsWh9zFfFaqhUbwUIh0n+iVlLOo1XbHazVmgTjcO85RMVU7tTsLdXGGw5LDjoNg==","signatures":[{"sig":"MEUCIHpfnM7kBlKEpiIxoBgfXUSZR51D0BtrGCRYCrnwkBp0AiEA2DltmQTDtaF/DjkM7nmKjVAfdnfeVq2AKbyRAaIG8HU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":38177},"main":"./dist/cjs/index.js","types":"./dist/esm/index.d.ts","module":"./dist/esm/index.js","exports":{".":{"types":"./dist/esm/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"a958a75381ac3977af2fce300035c3cc4c879f28","scripts":{"test":"npx tsx --test tests/index.test.ts","build":"tsc -p tsconfig.json && tsc -p tsconfig.cjs.json","test:build":"node --test dist/esm/index.test.js","prepublishOnly":"npm test && npm run build"},"_npmUser":{"name":"amars1238","email":"Amarkarthiks@gmail.com"},"_npmVersion":"11.11.0","description":"Lightweight zero-dependency parser and validator for LLM JSON output","directories":{},"_nodeVersion":"24.14.1","_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","typescript":"^6.0.2"},"_npmOperationalInternal":{"tmp":"tmp/llm-parse_0.1.1_1776223960604_0.39257248938644596","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@amars1238/llm-parse","version":"0.1.2","keywords":["llm","json","parse","validate"],"license":"MIT","_id":"@amars1238/llm-parse@0.1.2","maintainers":[{"name":"amars1238","email":"Amarkarthiks@gmail.com"}],"dist":{"shasum":"5e4145688b92d2f4585465e89de2c3d478ad29f9","tarball":"https://registry.npmjs.org/@amars1238/llm-parse/-/llm-parse-0.1.2.tgz","fileCount":43,"integrity":"sha512-c7GxrE0wwfMqrluYblky924NLzEAkDrcMPT/coTHti/XAvyjmhkYCY9KCj2UkAumN2eJDLsixEfA1z3sLvXH3w==","signatures":[{"sig":"MEUCICIx9MRBpyIMwnn0SggvFoqrGKCfZG2TD0YULMx4jHWEAiEAxYIyuAHgSYknA8hU9LHZuL+PdbnD4kU4NMB4iPOUa/I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":38275},"main":"./dist/cjs/index.js","type":"module","types":"./dist/esm/index.d.ts","module":"./dist/esm/index.js","exports":{".":{"types":"./dist/esm/index.d.ts","import":"./dist/esm/index.js","require":"./dist/cjs/index.js"}},"gitHead":"a74d01f5e4708af1bee7de9b714ac17b628af1fe","scripts":{"test":"npx tsx --test tests/index.test.ts","build":"tsc -p tsconfig.json && tsc -p tsconfig.cjs.json && echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json","test:build":"node --test dist/esm/index.test.js","prepublishOnly":"npm test && npm run build"},"_npmUser":{"name":"amars1238","email":"Amarkarthiks@gmail.com"},"_npmVersion":"11.11.0","description":"Lightweight zero-dependency parser and validator for LLM JSON output","directories":{},"_nodeVersion":"24.14.1","_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","typescript":"^6.0.2"},"_npmOperationalInternal":{"tmp":"tmp/llm-parse_0.1.2_1776224185260_0.7388393984091481","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@amars1238/llm-parse","version":"0.1.3","description":"Lightweight zero-dependency parser and validator for LLM JSON output","main":"./dist/cjs/index.js","module":"./dist/esm/index.js","types":"./dist/esm/index.d.ts","exports":{".":{"import":"./dist/esm/index.js","require":"./dist/cjs/index.js","types":"./dist/esm/index.d.ts"}},"type":"module","scripts":{"build":"tsc -p tsconfig.json && tsc -p tsconfig.cjs.json && echo '{\"type\":\"commonjs\"}' > dist/cjs/package.json","test":"npx tsx --test tests/index.test.ts","test:build":"node --test dist/esm/index.test.js","prepublishOnly":"npm test && npm run build"},"keywords":["llm","json","parse","validate"],"license":"MIT","devDependencies":{"tsx":"^4.21.0","typescript":"^6.0.2"},"gitHead":"ed7757027c0c78af54872ab4b2947c2f6fe2674c","_id":"@amars1238/llm-parse@0.1.3","_nodeVersion":"24.14.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-1O1Po1jomjUU/BaYVoU+MgmSkWgXogSlDWhNNfJ+pvwvCV7A7LUR7s9gc0zuEnxAtymu4rcxgqYTJfm17cIDTQ==","shasum":"34f263a4133e17b9d7f03d45f902e14f00fc9b27","tarball":"https://registry.npmjs.org/@amars1238/llm-parse/-/llm-parse-0.1.3.tgz","fileCount":43,"unpackedSize":38953,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCIB7qsFRS8uNI7xAB/bVZDM1bOFhRkqSIeg7Gz/iadJAIgPTDaH86itP0FizlKjS73pTpum0zkZDNzLqJXTkrMxm8="}]},"_npmUser":{"name":"amars1238","email":"Amarkarthiks@gmail.com"},"directories":{},"maintainers":[{"name":"amars1238","email":"Amarkarthiks@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/llm-parse_0.1.3_1776224483843_0.18706687772614528"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-15T03:08:10.254Z","modified":"2026-04-15T03:41:24.151Z","0.1.0":"2026-04-15T03:08:10.747Z","0.1.1":"2026-04-15T03:32:40.787Z","0.1.2":"2026-04-15T03:36:25.411Z","0.1.3":"2026-04-15T03:41:24.052Z"},"license":"MIT","keywords":["llm","json","parse","validate"],"description":"Lightweight zero-dependency parser and validator for LLM JSON output","maintainers":[{"name":"amars1238","email":"Amarkarthiks@gmail.com"}],"readme":"# llm-parse\n\nLLMs don't return clean JSON. They wrap it in markdown fences, preface it with\n\"Sure, here's the data:\", append \"Hope that helps!\", and occasionally stringify\nnumbers as `\"42\"` instead of `42`. Every production LLM integration has a\nhand-rolled version of the same cleanup code.\n\nExisting validators (Instructor, Guardrails, zod-gpt) solve this — but they\npull in dozens of dependencies and hundreds of kilobytes to do it. If all you\nneed is reliable JSON extraction and lightweight field validation, that's a lot\nof weight.\n\n**llm-parse** is the minimal alternative: strip fences, extract JSON, validate\nfields. Zero runtime dependencies. ~3 kB minified.\n\n```bash\nnpm install @amars1238/llm-parse\n```\n\n---\n\n## Examples\n\n### 1. Fenced JSON from a chat model\n\nModels like GPT-4 and Claude habitually wrap JSON in markdown code blocks.\n`llmParse` strips the fences before parsing.\n\n```typescript\nimport llmParse from '@amars1238/llm-parse';\n\nconst raw = `\nSure! Here is the JSON you asked for:\n\n\\`\\`\\`json\n{\n  \"name\": \"Alice\",\n  \"role\": \"engineer\"\n}\n\\`\\`\\`\n`;\n\nconst result = llmParse(raw);\n// → { name: 'Alice', role: 'engineer' }\n```\n\n### 2. Schema validation — catching bad output before it reaches your app\n\nPass a schema to validate field types and required fields. In non-strict mode\n(the default), validation errors are available without throwing.\n\n```typescript\nimport llmParse, { validate, ParseError } from '@amars1238/llm-parse';\nimport type { Schema } from 'llm-parse';\n\nconst schema: Schema = {\n  name:  { type: 'string',  required: true },\n  score: { type: 'number',  required: true },\n  tags:  { type: 'array' },\n};\n\n// JSON buried after explanation text — extracted automatically\nconst raw = 'Here is the structured output: {\"name\":\"Bob\",\"score\":91,\"tags\":[\"a\",\"b\"]}';\n\nconst data = llmParse(raw, schema) as { name: string; score: number; tags: string[] };\n// → { name: 'Bob', score: 91, tags: ['a', 'b'] }\n\n// Check validation separately without strict mode\nconst { valid, errors } = validate(schema, { name: 'Bob' }); // missing score\n// → { valid: false, errors: ['\"score\" is required'] }\n```\n\n### 3. Coercion + strict mode — enforcing a contract\n\nModels sometimes return numbers as strings (`\"score\": \"91\"`). Coerce mode\nfixes unambiguous mismatches. Strict mode turns any remaining validation\nfailure into a thrown `ParseError`.\n\n```typescript\nimport llmParse, { ParseError } from 'llm-parse';\n\nconst schema = {\n  score:  { type: 'number',  required: true },\n  active: { type: 'boolean', required: true },\n};\n\ntry {\n  // Model returned numbers and booleans as strings\n  const result = llmParse(\n    '{\"score\":\"91\",\"active\":\"true\"}',\n    schema,\n    { coerce: true, strict: true },\n  );\n  // → { score: 91, active: true }\n} catch (e) {\n  if (e instanceof ParseError) {\n    console.error('LLM output did not match schema:', e.message);\n    console.error('Original output was:', e.raw);\n  }\n}\n```\n\n---\n\n## Why llm-parse?\n\n| | **llm-parse** | zod-gpt | Instructor (JS) | Guardrails (Python) |\n|---|:---:|:---:|:---:|:---:|\n| Runtime dependencies | **0** | 1 (zod) | 5+ | 20+ |\n| Bundle size (min) | **~3 kB** | ~55 kB | ~200 kB | N/A |\n| Fence stripping | ✅ | ❌ | ✅ | ✅ |\n| Buried JSON extraction | ✅ | ❌ | ❌ | ❌ |\n| Type coercion | ✅ | ❌ | ❌ | ✅ |\n| Zero config | ✅ | ❌ | ❌ | ❌ |\n| Streaming support | ❌ | ✅ | ✅ | ✅ |\n| Retry on failure | ❌ | ✅ | ✅ | ✅ |\n\n**The trade-off is explicit.** If you need automatic retries, streaming\nvalidation, or provider-specific features, use Instructor or Guardrails.\nIf you need a reliable `JSON.parse` that actually works on LLM output without\nadding a dependency tree, use llm-parse.\n\n---\n\n## API\n\n### `llmParse(text, schema?, options?)`\n\nStrips fences, extracts JSON from surrounding text, parses it, and optionally\nvalidates against a schema.\n\n```typescript\nllmParse(text: string, schema?: Schema, options?: LLMParseOptions): unknown\n```\n\n| Parameter | Type | Default | Description |\n|---|---|---|---|\n| `text` | `string` | — | Raw LLM output |\n| `schema` | `Schema` | `undefined` | Field type constraints |\n| `options.strict` | `boolean` | `false` | Throw `ParseError` on validation failure |\n| `options.coerce` | `boolean` | `false` | Cast `\"42\"` → `42`, `\"true\"` → `true` (strings only — non-string values are left unchanged) |\n\nReturns `unknown`. Cast to your type after validation.\n\nThrows `ParseError` if the text cannot be parsed as JSON, or if `strict: true`\nand validation fails.\n\n---\n\n### `validate(schema, data)`\n\nValidates a plain object against a schema. Never throws.\n\n```typescript\nvalidate(schema: Schema, data: Record<string, unknown>): ValidationResult\n// → { valid: boolean, errors: string[] }\n```\n\n---\n\n### `Schema`\n\n```typescript\ntype Schema = Record<string, {\n  type: 'string' | 'number' | 'boolean' | 'array' | 'object';\n  required?: boolean;\n}>\n```\n\n---\n\n### `ParseError`\n\n```typescript\nclass ParseError extends Error {\n  raw: string; // the original unmodified input text\n}\n```\n\nThrown by `llmParse` when JSON parsing fails, or when `strict: true` and\nschema validation fails. `raw` always holds the original text before any\nfence-stripping or extraction.\n\n---\n\n## How it works\n\n1. **`stripFences`** — removes ` ```json ` / ` ``` ` wrappers (handles extra\n   whitespace, Windows line endings, trailing newlines)\n2. **`extractJSON`** — scans for the first `{` or `[` and last matching `}` or\n   `]`, discarding any surrounding prose\n3. **`JSON.parse`** — parses the cleaned string; wraps any error in `ParseError`\n4. **`coerceData`** *(optional)* — walks the parsed object, casting string\n   values to the schema's expected type where unambiguous\n5. **`validate`** *(optional)* — checks types and required fields, returns an\n   error list without throwing\n\nSteps 1–3 happen inside `parseJSON`. Steps 4–5 are applied by `llmParse` when\na schema is provided.\n","readmeFilename":"README.md"}