{"_id":"@azghr/extricate","name":"@azghr/extricate","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@azghr/extricate","version":"0.1.0","description":"Extract the first (or every) valid JSON value embedded in text or markdown fences from an LLM reply. Locates and parses; does not repair.","license":"MIT","type":"module","sideEffects":false,"main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"engines":{"node":">=18"},"scripts":{"build":"tsup src/index.ts --format esm,cjs --dts --sourcemap --clean","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit","lint":"eslint src test examples","demo":"tsx examples/demo.ts","check":"npm run typecheck && npm run lint && npm run test && npm run build","prepublishOnly":"npm run check"},"keywords":["json","extract","parse","llm","model","fence","markdown","prose","ai","extraction","clean","locate"],"devDependencies":{"@eslint/js":"^9.18.0","eslint":"^9.18.0","tsx":"^4.19.2","typescript":"^5.7.3","typescript-eslint":"^8.65.0","vitest":"^2.1.8","tsup":"^8.3.5"},"gitHead":"15b6f176abe244e50094e9e1bb94128659962253","_id":"@azghr/extricate@0.1.0","_nodeVersion":"24.12.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-MsuufuioCbIKcKnHiCHmwUc5TPQGs7/q4+hGjiiYR+lS9iANxlPoGW2hwHHRm2GH9W8MlvSHlRIKXPlgYje7ow==","shasum":"c06da431a14c9eb196abaecdb107ecc84973fec9","tarball":"https://registry.npmjs.org/@azghr/extricate/-/extricate-0.1.0.tgz","fileCount":10,"unpackedSize":62635,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIEzpnTVoCy5efGx1O5p+8k0nyJiqkl1mpovclcZjh/uQAiEA3Dz9JM0kvCJTB+Dhhbs6V26jlggTsmrk0xeBqyJ59ds="}]},"_npmUser":{"name":"azghr","email":"masgharali.eng@gmail.com"},"directories":{},"maintainers":[{"name":"azghr","email":"masgharali.eng@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/extricate_0.1.0_1784979043969_0.7970746489782157"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-25T11:30:43.840Z","0.1.0":"2026-07-25T11:30:44.086Z","modified":"2026-07-25T11:30:44.257Z"},"maintainers":[{"name":"azghr","email":"masgharali.eng@gmail.com"}],"description":"Extract the first (or every) valid JSON value embedded in text or markdown fences from an LLM reply. Locates and parses; does not repair.","keywords":["json","extract","parse","llm","model","fence","markdown","prose","ai","extraction","clean","locate"],"license":"MIT","readme":"# @azghr/extricate\n\n[![npm](https://img.shields.io/npm/v/@azghr/extricate)](https://www.npmjs.com/package/@azghr/extricate)\n[![MIT License](https://img.shields.io/npm/l/@azghr/extricate)](LICENSE)\n\nExtract the first (or every) valid JSON value embedded in text or markdown fences from an LLM reply. Locates and parses; does not repair.\n\n## The problem\n\nLLM responses often embed JSON in prose or markdown. Manual extraction is tedious. Regex fails for nested structures and escaped characters. You need reliable JSON extraction from messy text.\n\n## Install\n\n```bash\nnpm install @azghr/extricate\n# or\npnpm add @azghr/extricate\n# or\nyarn add @azghr/extricate\n```\n\n## Use\n\nExtract JSON from LLM responses:\n\n```typescript\nimport extricate from \"@azghr/extricate\";\n\nconst user = extricate('Data: {\"name\": \"Alice\", \"age\": 30} thanks!');\n// { name: \"Alice\", age: 30 }\n```\n\nExtract all JSON values:\n\n```typescript\nconst results = extricate.all('{\"id\": 1} {\"id\": 2}');\n// [{ id: 1 }, { id: 2 }]\n```\n\nParse fenced blocks:\n\n```typescript\nconst result = extricate('```json {\"confidence\": 0.92} ```');\n// result.confidence === 0.92\n```\n\n## API\n\n### `extricate<T = unknown>(text, options?): T`\n\nExtract the first valid JSON value from text.\n\n**Options:**\n- `prefer?: \"object\" | \"array\" | \"any\"` - Control which type to find (default: `\"any\"`)\n- `fences?: boolean` - Prioritize fenced code blocks (default: `true`)\n\n**Behavior:** Scans fenced blocks first, falls back to inline. Throws `NoJSONFound` if no valid JSON found.\n\n```typescript\nconst obj = extricate('[1, 2] {\"data\": true}', { prefer: \"object\" });\n// { data: true }\n```\n\n### `extricate.all<T = unknown>(text, options?): T[]`\n\nExtract all valid JSON values from text in order.\n\n```typescript\nconst results = extricate.all('{\"a\": 1} {\"b\": 2}');\n// [{ a: 1 }, { b: 2 }]\n```\n\n### `NoJSONFound`\n\nError thrown when no valid JSON can be found.\n\n```typescript\nimport { NoJSONFound } from \"@azghr/extricate\";\n\ntry {\n  extricate(\"Just plain text\");\n} catch (error) {\n  if (error instanceof NoJSONFound) {\n    console.log(\"No JSON found\");\n  }\n}\n```\n\n## Non-goals\n\n**What extricate does NOT do:**\n\n- Does NOT repair malformed JSON - only locates and parses valid JSON\n- Does NOT extract primitive values (true, false, null, numbers, strings)\n- Does NOT fix truncated structures\n\n```typescript\nextricate('{\"missing\": \"quotes}'); // throws NoJSONFound\nextricate('true null 42'); // throws NoJSONFound\n```\n\n## TypeScript note\n\n```typescript\nimport extricate from \"@azghr/extricate\";\n\ninterface User {\n  name: string;\n  age: number;\n}\n\nconst user = extricate<User>(llmResponse);\n```\n\n## Related Packages\n\n- **[@azghr/filterkit](https://www.npmjs.com/package/@azghr/filterkit)** - Type-safe filtering\n- **[@azghr/shorn](https://www.npmjs.com/package/@azghr/shorn)** - Byte-budget string truncation\n- **[@azghr/singlet](https://www.npmjs.com/package/@azghr/singlet)** - Deduplicate concurrent calls\n- **[forbear](https://www.npmjs.com/package/forbear)** - Rate-limit instructions\n- **[quiesce](https://www.npmjs.com/package/quiesce)** - Graceful shutdown\n- **[sortition](https://www.npmjs.com/package/sortition)** - A/B bucketing\n- **[staleness](https://www.npmjs.com/package/staleness)** - Stale-while-revalidate caching\n\n---\n\n*See `pnpm-workspace.yaml` for all packages.*\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-fff84966cc54a715295fe3c03f9cc7cb"}