{"_id":"@cariva/medical-sdk","_rev":"7-60e4407fe50d9b12a2caefc3e744c7cb","name":"@cariva/medical-sdk","dist-tags":{"latest":"1.2.0"},"versions":{"1.0.0":{"name":"@cariva/medical-sdk","version":"1.0.0","keywords":["cariva","medical","asr","speech-recognition","icd10","isomorphic","node","browser"],"author":{"name":"Cariva"},"license":"Apache-2.0","_id":"@cariva/medical-sdk@1.0.0","maintainers":[{"name":"piyawatcariva","email":"piyawak@cariva.co.th"},{"name":"patcharas.cariva","email":"patcharas@cariva.co.th"},{"name":"menner159","email":"kraisornk@cariva.co.th"}],"homepage":"https://gitlab-ce.arv.co.th/cloud_arv/health-tech/partner-solution/cariva-medical-sdk#readme","dist":{"shasum":"9032caa5108cb41b13ef6b2e1105e52ac0f14579","tarball":"https://registry.npmjs.org/@cariva/medical-sdk/-/medical-sdk-1.0.0.tgz","fileCount":30,"integrity":"sha512-2XNGrNwT641J5bMEBcT/s51sVvavu4RYpwPlEBa4wYTP1BEk1dCJ65LfQLrO13Ui0f72UuDE43t3uqvbDloB7g==","signatures":[{"sig":"MEQCIByq2TP65DIdahrPvy7HxlXac9oA2EZlNrOkPy7QuGCkAiBxc5FTXO6SZSO49KwQkP+3qopi/0Tw1LRPA5KqyJBDvQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":971656},"main":"./dist/node/index.cjs","type":"module","types":"./dist/types/entries/browser.d.ts","module":"./dist/browser/index.js","engines":{"node":">=22.0.0","pnpm":">=11.0.0"},"exports":{".":{"node":{"types":"./dist/types/entries/node.d.ts","import":"./dist/node/index.js","require":"./dist/node/index.cjs"},"types":"./dist/types/entries/browser.d.ts","import":"./dist/browser/index.js","browser":{"types":"./dist/types/entries/browser.d.ts","import":"./dist/browser/index.js","default":"./dist/browser/index.umd.js"},"default":"./dist/node/index.cjs"},"./package.json":"./package.json"},"gitHead":"1d22f497975599b8effcb9be5db44dca68749b4c","scripts":{"dev":"pnpm run build:node --watch","lint":"eslint . --ext .ts,.js --max-warnings 0","test":"vitest run","build":"pnpm run build:types && pnpm run build:node && pnpm run build:browser","check":"pnpm type-check && pnpm lint && pnpm format:check","clean":"rm -rf dist tsconfig.tsbuildinfo *.tsbuildinfo vite.config.*.timestamp-*.mjs","smoke":"node scripts/smoke-node.mjs","format":"prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"","dry-run":"pnpm run build && npm pack --dry-run","prepare":"husky","release":"pnpm check && pnpm build && changeset publish","lint:fix":"eslint . --ext .ts,.js --fix","prebuild":"pnpm run clean","changeset":"changeset","clean:all":"rm -rf node_modules dist pnpm-lock.yaml && pnpm store prune","build:node":"vite build --config vite.config.node.ts","publish:qa":"node scripts/publish.js qa","test:watch":"vitest","type-check":"tsc --noEmit","build:types":"tsc -p tsconfig.build.json","publish:dev":"node scripts/publish.js dev","publish:uat":"node scripts/publish.js uat","format:check":"prettier --check \"**/*.{ts,tsx,js,jsx,json,md}\"","publish:prod":"node scripts/publish.js prod","build:browser":"vite build --config vite.config.browser.ts","version:major":"changeset && changeset version && pnpm install","version:minor":"changeset && changeset version && pnpm install","version:patch":"changeset version && pnpm install"},"_npmUser":{"name":"menner159","email":"kraisornk@cariva.co.th"},"repository":{"url":"git+https://gitlab-ce.arv.co.th/cloud_arv/health-tech/partner-solution/cariva-medical-sdk.git","type":"git"},"_npmVersion":"10.9.2","description":"Unified Cariva Medical SDK for Node.js and browsers - ASR, ICD-10, and more (single install, auto platform detection)","directories":{},"sideEffects":false,"_nodeVersion":"22.16.0","dependencies":{"lamejs":"^1.2.1","ffmpeg-static":"^5.2.0","music-metadata":"^10.5.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"packageManager":"pnpm@11.4.0","devDependencies":{"vite":"^5.1.4","husky":"^9.0.11","eslint":"^8.57.0","terser":"^5.42.0","vitest":"^1.2.2","prettier":"^3.3.3","@types/web":"^0.0.138","typescript":"^5.8.2","@types/node":"^22.0.0","@changesets/cli":"^2.27.1","@typescript-eslint/parser":"^6.21.0","@typescript-eslint/eslint-plugin":"^6.21.0"},"_npmOperationalInternal":{"tmp":"tmp/medical-sdk_1.0.0_1786437984496_0.7501092639739695","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@cariva/medical-sdk","version":"1.0.1","keywords":["cariva","medical","asr","speech-recognition","icd10","isomorphic","node","browser"],"author":{"name":"Cariva"},"license":"Apache-2.0","_id":"@cariva/medical-sdk@1.0.1","maintainers":[{"name":"piyawatcariva","email":"piyawak@cariva.co.th"},{"name":"patcharas.cariva","email":"patcharas@cariva.co.th"},{"name":"menner159","email":"kraisornk@cariva.co.th"}],"dist":{"shasum":"04297d34839622faccbc05cc6eefa664ea7d9489","tarball":"https://registry.npmjs.org/@cariva/medical-sdk/-/medical-sdk-1.0.1.tgz","fileCount":30,"integrity":"sha512-bnLZQ+gj/qAu/lS2Gtqhhtnuvyb4buXcX4JpihsjoLP01dAMR0L0xY/hHPvrRWLKFxgogCcoq31LjHeMtoEXpg==","signatures":[{"sig":"MEYCIQDCzVreGVlmY9MTqDZqdMy7JVbrD75eW6IRhgXkSmrETAIhALKPus9tMfIAxZaGUUFnYfcmNXCPaZQ+E1KT6OSYGAEf","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":972215},"main":"./dist/node/index.cjs","type":"module","types":"./dist/types/entries/browser.d.ts","module":"./dist/browser/index.js","engines":{"node":">=22.0.0","pnpm":">=11.0.0"},"exports":{".":{"node":{"types":"./dist/types/entries/node.d.ts","import":"./dist/node/index.js","require":"./dist/node/index.cjs"},"types":"./dist/types/entries/browser.d.ts","import":"./dist/browser/index.js","browser":{"types":"./dist/types/entries/browser.d.ts","import":"./dist/browser/index.js","default":"./dist/browser/index.umd.js"},"default":"./dist/node/index.cjs"},"./package.json":"./package.json"},"gitHead":"074e17c14cb2e49be1eadddb5030732c6533af6d","scripts":{"dev":"pnpm run build:node --watch","lint":"eslint . --ext .ts,.js --max-warnings 0","test":"vitest run","build":"pnpm run build:types && pnpm run build:node && pnpm run build:browser","check":"pnpm type-check && pnpm lint && pnpm format:check","clean":"rm -rf dist tsconfig.tsbuildinfo *.tsbuildinfo vite.config.*.timestamp-*.mjs","smoke":"node scripts/smoke-node.mjs","format":"prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"","dry-run":"pnpm run build && npm pack --dry-run","prepare":"husky","release":"pnpm check && pnpm build && changeset publish","lint:fix":"eslint . --ext .ts,.js --fix","prebuild":"pnpm run clean","changeset":"changeset","clean:all":"rm -rf node_modules dist pnpm-lock.yaml && pnpm store prune","build:node":"vite build --config vite.config.node.ts","publish:qa":"node scripts/publish.js qa","test:watch":"vitest","type-check":"tsc --noEmit","build:types":"tsc -p tsconfig.build.json","publish:dev":"node scripts/publish.js dev","publish:uat":"node scripts/publish.js uat","format:check":"prettier --check \"**/*.{ts,tsx,js,jsx,json,md}\"","publish:prod":"node scripts/publish.js prod","build:browser":"vite build --config vite.config.browser.ts","version:major":"changeset && changeset version && pnpm install","version:minor":"changeset && changeset version && pnpm install","version:patch":"changeset version && pnpm install"},"_npmUser":{"name":"menner159","email":"kraisornk@cariva.co.th"},"_npmVersion":"10.9.2","description":"Unified Cariva Medical SDK for Node.js and browsers - ASR, ICD-10, and more (single install, auto platform detection)","directories":{},"sideEffects":false,"_nodeVersion":"22.16.0","dependencies":{"lamejs":"^1.2.1","ffmpeg-static":"^5.2.0","music-metadata":"^10.5.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"packageManager":"pnpm@11.4.0","devDependencies":{"vite":"^5.1.4","husky":"^9.0.11","eslint":"^8.57.0","terser":"^5.42.0","vitest":"^1.2.2","prettier":"^3.3.3","@types/web":"^0.0.138","typescript":"^5.8.2","@types/node":"^22.0.0","@changesets/cli":"^2.27.1","@typescript-eslint/parser":"^6.21.0","@typescript-eslint/eslint-plugin":"^6.21.0"},"_npmOperationalInternal":{"tmp":"tmp/medical-sdk_1.0.1_1786442725728_0.8686400516723836","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@cariva/medical-sdk","version":"1.0.2","keywords":["cariva","medical","asr","speech-recognition","icd10","isomorphic","node","browser"],"author":{"name":"Cariva"},"license":"Apache-2.0","_id":"@cariva/medical-sdk@1.0.2","maintainers":[{"name":"piyawatcariva","email":"piyawak@cariva.co.th"},{"name":"patcharas.cariva","email":"patcharas@cariva.co.th"},{"name":"menner159","email":"kraisornk@cariva.co.th"}],"dist":{"shasum":"65ea8624c27f232055a85bef30deae8c5a57d76a","tarball":"https://registry.npmjs.org/@cariva/medical-sdk/-/medical-sdk-1.0.2.tgz","fileCount":30,"integrity":"sha512-suW/DOrgNWZHua6WJDPDW8WJYTK1207tAKNovG15sudAgOA4DWQqBmwfkLdlFibKv9CPBLemabXe0wywlC3nOw==","signatures":[{"sig":"MEUCIQCwu7A84cd1LNNzE7xcTat/TZcSNZLeA/58VdRRxahPXgIgL2ua8lp+wyWGJIy7M+qbUQp8bVJC98wpR34tppswOm4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":974761},"main":"./dist/node/index.cjs","type":"module","types":"./dist/types/entries/browser.d.ts","module":"./dist/browser/index.js","engines":{"node":">=22.0.0","pnpm":">=11.0.0"},"exports":{".":{"node":{"types":"./dist/types/entries/node.d.ts","import":"./dist/node/index.js","require":"./dist/node/index.cjs"},"types":"./dist/types/entries/browser.d.ts","import":"./dist/browser/index.js","browser":{"types":"./dist/types/entries/browser.d.ts","import":"./dist/browser/index.js","default":"./dist/browser/index.umd.js"},"default":"./dist/node/index.cjs"},"./package.json":"./package.json"},"gitHead":"c9cca5a47ae78235105ceb47ad0deb4a617408ce","scripts":{"dev":"pnpm run build:node --watch","lint":"eslint . --ext .ts,.js --max-warnings 0","test":"vitest run","build":"pnpm run build:types && pnpm run build:node && pnpm run build:browser","check":"pnpm type-check && pnpm lint && pnpm format:check","clean":"rm -rf dist tsconfig.tsbuildinfo *.tsbuildinfo vite.config.*.timestamp-*.mjs","smoke":"node scripts/smoke-node.mjs","format":"prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"","dry-run":"pnpm run build && npm pack --dry-run","prepare":"husky","release":"pnpm check && pnpm build && changeset publish","lint:fix":"eslint . --ext .ts,.js --fix","prebuild":"pnpm run clean","changeset":"changeset","clean:all":"rm -rf node_modules dist pnpm-lock.yaml && pnpm store prune","build:node":"vite build --config vite.config.node.ts","publish:qa":"node scripts/publish.js qa","test:watch":"vitest","type-check":"tsc --noEmit","build:types":"tsc -p tsconfig.build.json","publish:dev":"node scripts/publish.js dev","publish:uat":"node scripts/publish.js uat","format:check":"prettier --check \"**/*.{ts,tsx,js,jsx,json,md}\"","publish:prod":"node scripts/publish.js prod","build:browser":"vite build --config vite.config.browser.ts","version:major":"changeset && changeset version && pnpm install","version:minor":"changeset && changeset version && pnpm install","version:patch":"changeset version && pnpm install"},"_npmUser":{"name":"menner159","email":"kraisornk@cariva.co.th"},"_npmVersion":"10.9.2","description":"Unified Cariva Medical SDK for Node.js and browsers - ASR, ICD-10, and more (single install, auto platform detection)","directories":{},"sideEffects":false,"_nodeVersion":"22.16.0","dependencies":{"lamejs":"^1.2.1","music-metadata":"^10.5.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"packageManager":"pnpm@11.4.0","devDependencies":{"vite":"^5.1.4","husky":"^9.0.11","eslint":"^8.57.0","terser":"^5.42.0","vitest":"^1.2.2","prettier":"^3.3.3","@types/web":"^0.0.138","typescript":"^5.8.2","@types/node":"^22.0.0","ffmpeg-static":"^5.2.0","@changesets/cli":"^2.27.1","@typescript-eslint/parser":"^6.21.0","@typescript-eslint/eslint-plugin":"^6.21.0"},"_npmOperationalInternal":{"tmp":"tmp/medical-sdk_1.0.2_1786699371907_0.5680558961642119","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@cariva/medical-sdk","version":"1.0.3","keywords":["cariva","medical","asr","speech-recognition","icd10","isomorphic","node","browser"],"author":{"name":"Cariva"},"license":"Apache-2.0","_id":"@cariva/medical-sdk@1.0.3","maintainers":[{"name":"piyawatcariva","email":"piyawak@cariva.co.th"},{"name":"patcharas.cariva","email":"patcharas@cariva.co.th"},{"name":"menner159","email":"kraisornk@cariva.co.th"}],"dist":{"shasum":"88fd9e87f5f64687ea20c0b6db17f36aaba43f48","tarball":"https://registry.npmjs.org/@cariva/medical-sdk/-/medical-sdk-1.0.3.tgz","fileCount":30,"integrity":"sha512-xvB1a+yCjaXaD/OKSOBx1c8XgAPczuYk5QRSkp0AcoSfu35LOrivljDdhLycaGhT99bhwJuHTQsgHqtB92/cEA==","signatures":[{"sig":"MEQCIGyIXgows2dt3Ek6Q7DcuVGC+e6r+VIdu+yB8Ml12HBnAiAQX2wRgD5uapIBjeoJ/SLO7ZTiS2a5H8iX5/fgaISPJQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":981849},"main":"./dist/node/index.cjs","type":"module","types":"./dist/types/entries/browser.d.ts","module":"./dist/browser/index.js","engines":{"node":">=22.0.0","pnpm":">=11.0.0"},"exports":{".":{"node":{"types":"./dist/types/entries/node.d.ts","import":"./dist/node/index.js","require":"./dist/node/index.cjs"},"types":"./dist/types/entries/browser.d.ts","import":"./dist/browser/index.js","browser":{"types":"./dist/types/entries/browser.d.ts","import":"./dist/browser/index.js","default":"./dist/browser/index.umd.js"},"default":"./dist/node/index.cjs"},"./package.json":"./package.json"},"gitHead":"742f784ae425a36b4325bc347f8cceb37d12f2bf","scripts":{"dev":"pnpm run build:node --watch","lint":"eslint . --ext .ts,.js --max-warnings 0","test":"vitest run","build":"pnpm run build:types && pnpm run build:node && pnpm run build:browser","check":"pnpm type-check && pnpm lint && pnpm format:check","clean":"rm -rf dist tsconfig.tsbuildinfo *.tsbuildinfo vite.config.*.timestamp-*.mjs","smoke":"node scripts/smoke-node.mjs","format":"prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"","dry-run":"pnpm run build && npm pack --dry-run","prepare":"husky","release":"pnpm check && pnpm build && changeset publish","lint:fix":"eslint . --ext .ts,.js --fix","prebuild":"pnpm run clean","changeset":"changeset","clean:all":"rm -rf node_modules dist pnpm-lock.yaml && pnpm store prune","build:node":"vite build --config vite.config.node.ts","publish:qa":"node scripts/publish.js qa","test:watch":"vitest","type-check":"tsc --noEmit","build:types":"tsc -p tsconfig.build.json","publish:dev":"node scripts/publish.js dev","publish:uat":"node scripts/publish.js uat","format:check":"prettier --check \"**/*.{ts,tsx,js,jsx,json,md}\"","publish:prod":"node scripts/publish.js prod","build:browser":"vite build --config vite.config.browser.ts","version:major":"changeset && changeset version && pnpm install","version:minor":"changeset && changeset version && pnpm install","version:patch":"changeset version && pnpm install"},"_npmUser":{"name":"menner159","email":"kraisornk@cariva.co.th"},"_npmVersion":"10.9.2","description":"Unified Cariva Medical SDK for Node.js and browsers - ASR, ICD-10, and more (single install, auto platform detection)","directories":{},"sideEffects":false,"_nodeVersion":"22.16.0","dependencies":{"lamejs":"^1.2.1","music-metadata":"^10.5.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"packageManager":"pnpm@11.4.0","devDependencies":{"vite":"^5.1.4","husky":"^9.0.11","eslint":"^8.57.0","terser":"^5.42.0","vitest":"^1.2.2","prettier":"^3.3.3","@types/web":"^0.0.138","typescript":"^5.8.2","@types/node":"^22.0.0","ffmpeg-static":"^5.2.0","@changesets/cli":"^2.27.1","@typescript-eslint/parser":"^6.21.0","@typescript-eslint/eslint-plugin":"^6.21.0"},"_npmOperationalInternal":{"tmp":"tmp/medical-sdk_1.0.3_1787132969346_0.19949694432597798","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@cariva/medical-sdk","version":"1.0.4","keywords":["cariva","medical","asr","speech-recognition","icd code","isomorphic","node","browser"],"author":{"name":"Cariva"},"license":"Apache-2.0","_id":"@cariva/medical-sdk@1.0.4","maintainers":[{"name":"piyawatcariva","email":"piyawak@cariva.co.th"},{"name":"patcharas.cariva","email":"patcharas@cariva.co.th"},{"name":"menner159","email":"kraisornk@cariva.co.th"}],"dist":{"shasum":"4814193f1bc29c8d346dccf54e6f20c04aa7c00d","tarball":"https://registry.npmjs.org/@cariva/medical-sdk/-/medical-sdk-1.0.4.tgz","fileCount":30,"integrity":"sha512-UvPLZ327e9JU+3oZcyZulnd4WZn9xeLC5IqVilF3g9DXW0CPYx2ReA1k4N7sPHrAtP9i1yPqbhNqrijlxl3KqQ==","signatures":[{"sig":"MEYCIQCMZ8Bvu2IR8+1bvV3JkqklCYnEP77hxaPN9CNFEDETVgIhAK1tRx2yl8nOOEu5WAZibi0LHinAaLG6o9g3fdIgmGx0","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1031667},"main":"./dist/node/index.cjs","type":"module","types":"./dist/types/entries/browser.d.ts","module":"./dist/browser/index.js","engines":{"node":">=22.0.0","pnpm":">=11.0.0"},"exports":{".":{"node":{"types":"./dist/types/entries/node.d.ts","import":"./dist/node/index.js","require":"./dist/node/index.cjs"},"types":"./dist/types/entries/browser.d.ts","import":"./dist/browser/index.js","browser":{"types":"./dist/types/entries/browser.d.ts","import":"./dist/browser/index.js","default":"./dist/browser/index.umd.js"},"default":"./dist/node/index.cjs"},"./package.json":"./package.json"},"gitHead":"e3292e2c0b2f6d7cf759f7a17130a046622d4b8a","scripts":{"dev":"pnpm run build:node --watch","lint":"eslint . --ext .ts,.js --max-warnings 0","test":"vitest run","build":"pnpm run build:types && pnpm run build:node && pnpm run build:browser","check":"pnpm type-check && pnpm lint && pnpm format:check","clean":"rm -rf dist tsconfig.tsbuildinfo *.tsbuildinfo vite.config.*.timestamp-*.mjs","smoke":"node scripts/smoke-node.mjs","format":"prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"","dry-run":"pnpm run build && npm pack --dry-run","prepare":"husky","release":"pnpm check && pnpm build && changeset publish","lint:fix":"eslint . --ext .ts,.js --fix","prebuild":"pnpm run clean","changeset":"changeset","clean:all":"rm -rf node_modules dist pnpm-lock.yaml && pnpm store prune","build:node":"vite build --config vite.config.node.ts","publish:qa":"node scripts/publish.js qa","test:watch":"vitest","type-check":"tsc --noEmit","build:types":"tsc -p tsconfig.build.json","publish:dev":"node scripts/publish.js dev","publish:uat":"node scripts/publish.js uat","format:check":"prettier --check \"**/*.{ts,tsx,js,jsx,json,md}\"","publish:prod":"node scripts/publish.js prod","build:browser":"vite build --config vite.config.browser.ts","version:major":"changeset && changeset version && pnpm install","version:minor":"changeset && changeset version && pnpm install","version:patch":"changeset version && pnpm install"},"_npmUser":{"name":"menner159","email":"kraisornk@cariva.co.th"},"_npmVersion":"10.9.2","description":"Unified Cariva Medical SDK for Node.js and browsers - ASR, ICD Code, and more (single install, auto platform detection)","directories":{},"sideEffects":false,"_nodeVersion":"22.16.0","dependencies":{"lamejs":"^1.2.1","music-metadata":"^10.5.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"packageManager":"pnpm@11.4.0","devDependencies":{"vite":"^5.1.4","husky":"^9.0.11","eslint":"^8.57.0","terser":"^5.42.0","vitest":"^1.2.2","prettier":"^3.3.3","@types/web":"^0.0.138","typescript":"^5.8.2","@types/node":"^22.0.0","ffmpeg-static":"^5.2.0","@changesets/cli":"^2.27.1","@typescript-eslint/parser":"^6.21.0","@typescript-eslint/eslint-plugin":"^6.21.0"},"_npmOperationalInternal":{"tmp":"tmp/medical-sdk_1.0.4_1787818235384_0.43616234946394283","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@cariva/medical-sdk","version":"1.1.0","keywords":["cariva","medical","asr","speech-recognition","icd code","isomorphic","node","browser"],"author":{"name":"Cariva"},"license":"Apache-2.0","_id":"@cariva/medical-sdk@1.1.0","maintainers":[{"name":"piyawatcariva","email":"piyawak@cariva.co.th"},{"name":"patcharas.cariva","email":"patcharas@cariva.co.th"},{"name":"menner159","email":"kraisornk@cariva.co.th"}],"dist":{"shasum":"919317fbdfdf4059d57a0e780d2bf050116d9b66","tarball":"https://registry.npmjs.org/@cariva/medical-sdk/-/medical-sdk-1.1.0.tgz","fileCount":30,"integrity":"sha512-W4s2JinEQIFvvEBJKLRG1Zesdy335Jw7tncdjgCFE3eZKmABZ86R08mMyR8cxHjFYoY4KDPDHawIEZYNd7I4iA==","signatures":[{"sig":"MEUCIQCyeicJsmqnL0ojiJ0/Hc1cnySAmrbcfSTCtkQdjMVp3AIgPhUzOGBi+r9KiUcWzOIqPt+3N71zVwVu0+mTB29rMCg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQC6J6ozwGeSRFfmIuZDXTVcgY8TH/J1adn/dvHe9XZMUAIgKoQBr/R4DrF4PJLNkeoLnUuR3PAIiEPXvQC2iaEs1W0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1064125},"main":"./dist/node/index.cjs","type":"module","types":"./dist/types/entries/browser.d.ts","module":"./dist/browser/index.js","engines":{"node":">=22.0.0","pnpm":">=11.0.0"},"exports":{".":{"node":{"types":"./dist/types/entries/node.d.ts","import":"./dist/node/index.js","require":"./dist/node/index.cjs"},"types":"./dist/types/entries/browser.d.ts","import":"./dist/browser/index.js","browser":{"types":"./dist/types/entries/browser.d.ts","import":"./dist/browser/index.js","default":"./dist/browser/index.umd.js"},"default":"./dist/node/index.cjs"},"./package.json":"./package.json"},"gitHead":"311fe7d1a41ce988fa51402add858649c797d387","scripts":{"dev":"pnpm run build:node --watch","lint":"eslint . --ext .ts,.js --max-warnings 0","test":"vitest run","build":"pnpm run build:types && pnpm run build:node && pnpm run build:browser","check":"pnpm type-check && pnpm lint && pnpm format:check","clean":"rm -rf dist tsconfig.tsbuildinfo *.tsbuildinfo vite.config.*.timestamp-*.mjs","smoke":"node scripts/smoke-node.mjs","format":"prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"","dry-run":"pnpm run build && npm pack --dry-run","prepare":"husky","release":"pnpm check && pnpm build && changeset publish","lint:fix":"eslint . --ext .ts,.js --fix","prebuild":"pnpm run clean","changeset":"changeset","clean:all":"rm -rf node_modules dist pnpm-lock.yaml && pnpm store prune","build:node":"vite build --config vite.config.node.ts","publish:qa":"node scripts/publish.js qa","test:watch":"vitest","type-check":"tsc --noEmit","build:types":"tsc -p tsconfig.build.json","publish:dev":"node scripts/publish.js dev","publish:uat":"node scripts/publish.js uat","format:check":"prettier --check \"**/*.{ts,tsx,js,jsx,json,md}\"","publish:prod":"node scripts/publish.js prod","build:browser":"vite build --config vite.config.browser.ts","version:major":"changeset && changeset version && pnpm install","version:minor":"changeset && changeset version && pnpm install","version:patch":"changeset version && pnpm install"},"_npmUser":{"name":"menner159","email":"kraisornk@cariva.co.th"},"_npmVersion":"10.9.2","description":"Unified Cariva Medical SDK for Node.js and browsers - ASR, ICD Code, and more (single install, auto platform detection)","directories":{},"sideEffects":false,"_nodeVersion":"22.16.0","dependencies":{"lamejs":"^1.2.1","music-metadata":"^10.5.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"packageManager":"pnpm@11.4.0","devDependencies":{"vite":"^5.1.4","husky":"^9.0.11","eslint":"^8.57.0","terser":"^5.42.0","vitest":"^1.2.2","prettier":"^3.3.3","@types/web":"^0.0.138","typescript":"^5.8.2","@types/node":"^22.0.0","ffmpeg-static":"^5.2.0","@changesets/cli":"^2.27.1","@typescript-eslint/parser":"^6.21.0","@typescript-eslint/eslint-plugin":"^6.21.0"},"_npmOperationalInternal":{"tmp":"tmp/medical-sdk_1.1.0_1789532272785_0.7972922442629569","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"_id":"@cariva/medical-sdk@1.2.0","dist":{"shasum":"2af9c8e4a68114892d8f16853cbfda193a54b758","tarball":"https://registry.npmjs.org/@cariva/medical-sdk/-/medical-sdk-1.2.0.tgz","fileCount":30,"integrity":"sha512-f3WL0YPKNGRIAnh9iybsMjOB00w1j/JqnS8jlq+knZX9Sdku9L9fAwfK+c4gZc6WpzjJshOtbsYg7ukjBNxkKw==","signatures":[{"sig":"MEYCIQCPLW2r5msOkgmHtGY4vyIbHpzQ6QlOuA+yfKr6Fj0IHwIhAM3HZVfZdbDyPGxZvd4YiTgGDgkmXfpBoQ2bWf3LC9jJ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIER/HyB4cqAQvrjQusJOYnbNQRrfxrHVKlzR2Ta8Nu0dAiBq0UqKku21HLRcp5p0mmDxCGvcDmN5IiamFP6rDwR2dQ=="}],"unpackedSize":1065898},"main":"./dist/node/index.cjs","name":"@cariva/medical-sdk","type":"module","types":"./dist/types/entries/browser.d.ts","author":{"name":"Cariva"},"module":"./dist/browser/index.js","engines":{"node":">=22.0.0","pnpm":">=11.0.0"},"exports":{".":{"node":{"types":"./dist/types/entries/node.d.ts","import":"./dist/node/index.js","require":"./dist/node/index.cjs"},"types":"./dist/types/entries/browser.d.ts","import":"./dist/browser/index.js","browser":{"types":"./dist/types/entries/browser.d.ts","import":"./dist/browser/index.js","default":"./dist/browser/index.umd.js"},"default":"./dist/node/index.cjs"},"./package.json":"./package.json"},"gitHead":"becc0adaad2a6ecc47acbbe382ff213f01818ba1","license":"Apache-2.0","scripts":{"dev":"pnpm run build:node --watch","lint":"eslint . --ext .ts,.js --max-warnings 0","test":"vitest run","build":"pnpm run build:types && pnpm run build:node && pnpm run build:browser","check":"pnpm type-check && pnpm lint && pnpm format:check","clean":"rm -rf dist tsconfig.tsbuildinfo *.tsbuildinfo vite.config.*.timestamp-*.mjs","smoke":"node scripts/smoke-node.mjs","format":"prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"","dry-run":"pnpm run build && npm pack --dry-run","prepare":"husky","release":"pnpm check && pnpm build && changeset publish","lint:fix":"eslint . --ext .ts,.js --fix","prebuild":"pnpm run clean","changeset":"changeset","clean:all":"rm -rf node_modules dist pnpm-lock.yaml && pnpm store prune","build:node":"vite build --config vite.config.node.ts","publish:qa":"node scripts/publish.js qa","test:watch":"vitest","type-check":"tsc --noEmit","build:types":"tsc -p tsconfig.build.json","publish:dev":"node scripts/publish.js dev","publish:uat":"node scripts/publish.js uat","format:check":"prettier --check \"**/*.{ts,tsx,js,jsx,json,md}\"","publish:prod":"node scripts/publish.js prod","build:browser":"vite build --config vite.config.browser.ts","version:major":"changeset && changeset version && pnpm install","version:minor":"changeset && changeset version && pnpm install","version:patch":"changeset version && pnpm install"},"version":"1.2.0","_npmUser":{"name":"menner159","email":"kraisornk@cariva.co.th"},"keywords":["cariva","medical","asr","speech-recognition","icd code","isomorphic","node","browser"],"_npmVersion":"10.9.2","description":"Unified Cariva Medical SDK for Node.js and browsers - ASR, ICD Code, and more (single install, auto platform detection)","directories":{},"maintainers":[{"name":"piyawatcariva","email":"piyawak@cariva.co.th"},{"name":"patcharas.cariva","email":"patcharas@cariva.co.th"},{"name":"menner159","email":"kraisornk@cariva.co.th"}],"sideEffects":false,"_nodeVersion":"22.16.0","dependencies":{"lamejs":"^1.2.1","music-metadata":"^10.5.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"packageManager":"pnpm@11.4.0","devDependencies":{"vite":"^5.1.4","husky":"^9.0.11","eslint":"^8.57.0","terser":"^5.42.0","vitest":"^1.2.2","prettier":"^3.3.3","@types/web":"^0.0.138","typescript":"^5.8.2","@types/node":"^22.0.0","ffmpeg-static":"^5.2.0","@changesets/cli":"^2.27.1","@typescript-eslint/parser":"^6.21.0","@typescript-eslint/eslint-plugin":"^6.21.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/medical-sdk_1.2.0_1790567734065_0.49660829380697535"}}},"time":{"created":"2026-08-11T08:46:24.350Z","modified":"2026-09-28T03:55:34.655Z","1.0.0":"2026-08-11T08:46:24.751Z","1.0.1":"2026-08-11T10:05:25.899Z","1.0.2":"2026-08-14T09:22:52.075Z","1.0.3":"2026-08-19T09:49:29.530Z","1.0.4":"2026-08-27T08:10:35.518Z","1.1.0":"2026-09-16T04:17:52.881Z","1.2.0":"2026-09-28T03:55:34.178Z"},"author":{"name":"Cariva"},"license":"Apache-2.0","keywords":["cariva","medical","asr","speech-recognition","icd code","isomorphic","node","browser"],"description":"Unified Cariva Medical SDK for Node.js and browsers - ASR, ICD Code, and more (single install, auto platform detection)","maintainers":[{"name":"piyawatcariva","email":"piyawak@cariva.co.th"},{"name":"patcharas.cariva","email":"patcharas@cariva.co.th"},{"name":"menner159","email":"kraisornk@cariva.co.th"}],"readme":"# @cariva/medical-sdk\n\n[![npm version](https://badge.fury.io/js/@cariva%2Fmedical-sdk.svg)](https://www.npmjs.com/package/@cariva/medical-sdk)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Node](https://img.shields.io/badge/Node.js-%E2%89%A522-green.svg)](https://nodejs.org/)\n[![Browser](https://img.shields.io/badge/Browser-ES2020%2B-green.svg)](https://caniuse.com/es6)\n\nTurn a recorded consultation into a structured medical document. One install, same API on Node.js\nand in the browser — the right build is selected automatically.\n\n[Install](#install) · [Quick start](#quick-start) · [Authentication](#authentication) ·\n[Modes](#modes) · [Options](#options) · [`process()`](#processaudio-options) ·\n[Result shapes](#result-shapes) · [Errors](#errors) · [Audio](#audio-handling) ·\n[Diagnosis Code (ICD)](#diagnosis-code-icd) · [Migrating](#migrating-from-the-legacy-sdks)\n\n## Install\n\n```bash\nnpm install @cariva/medical-sdk\n```\n\n<details>\n<summary>Without a bundler (CDN / <code>&lt;script&gt;</code>)</summary>\n\n```html\n<script src=\"https://unpkg.com/@cariva/medical-sdk@1.2.0/dist/browser/index.umd.js\"></script>\n<script>\n  const asr = new CarivaMedicalSDK.ASR({\n    key: 'YOUR_KEY',\n    secret: 'YOUR_SECRET',\n    mode: 'doc-ipd-soap',\n  });\n  const icd = new CarivaMedicalSDK.ICD({\n    key: 'YOUR_KEY',\n    secret: 'YOUR_SECRET',\n  });\n</script>\n```\n\nThe UMD build exposes `window.CarivaMedicalSDK` (`.ASR`, `.ICD`). Pin an exact version in\nproduction.\n\n</details>\n\n## Quick start\n\n```ts\nimport { ASR } from '@cariva/medical-sdk';\n\nconst asr = new ASR({\n  key: 'YOUR_KEY',\n  secret: 'YOUR_SECRET',\n  mode: 'doc-ipd-soap',\n  lang: 'th',\n});\n\n// audio: a File from <input>, a Blob from MediaRecorder, or file bytes on Node\nconst result = await asr.process(audio, {\n  onProgress: p => console.log(`upload ${p.percentage}%`),\n  onProcessing: step => console.log(step),\n});\n\nconsole.log(result.data.assessment); // typed as SOAPData\n```\n\nOne `process()` call runs everything — compress, upload, poll — and resolves only when the note is\nready. There is no task to track and nothing to poll yourself.\n\n`result.data` is typed from the `mode` you passed — no type argument, no cast. When the mode is only\nknown at runtime, `switch` on `result.mode` for the same narrowing:\n\n```ts\nconst asr = new ASR({ key, secret, mode }); // `mode: ASRMode`, picked at runtime\nconst result = await asr.process(audio);\n\nswitch (result.mode) {\n  case 'doc-ipd-soap':\n    render(result.data.assessment); // SOAPData\n    break;\n  case 'radiology':\n    render(result.data.impression); // RadiologyData\n    break;\n}\n```\n\nOn Node, wrap the bytes in a `Blob`:\n\n```ts\nimport { readFile } from 'node:fs/promises';\n\nconst audio = new Blob([await readFile('./consultation.wav')], { type: 'audio/wav' });\n```\n\n## Authentication\n\nPass **either** `key` + `secret` **or** `accessToken`. Mixing the two, or passing neither, is a type\nerror in TypeScript and a `ValidationError` at runtime.\n\n```ts\nnew ASR({ key, secret, mode }); // API key + secret (HMAC)\nnew ASR({ accessToken, mode }); // bearer token\n```\n\nCredentials are issued per application — ask your Cariva contact if you do not have a pair yet.\n\nKeep secrets out of client-side bundles — in the browser, prefer a short-lived `accessToken` issued\nby your own backend.\n\n## Modes\n\nThe mode decides which service runs and what `result.data` contains. Pick one when constructing.\n\n| Mode                                     | Produces                     | Result type                                 |\n| ---------------------------------------- | ---------------------------- | ------------------------------------------- |\n| `doc-ipd-soap`                           | IPD SOAP note                | `SOAPData`                                  |\n| `doc-opd-clinicalrecord`                 | OPD clinical record          | `OPDClinicalRecordData`                     |\n| `nur-opd-nursenote-faie-start` / `-end`  | Nursing note (FAIE)          | `NurseNoteFaieStartData` / `…FaieEndData`   |\n| `nur-opd-nursenote-adpie-start` / `-end` | Nursing note (ADPIE)         | `NurseNoteAdpieStartData` / `…AdpieEndData` |\n| `center-form`                            | Center form                  | `CenterFormData`                            |\n| `radiology`                              | Radiology report             | `RadiologyData`                             |\n| `medical-mom`                            | Minutes of a medical meeting | `MedicalMOMData`                            |\n| `med-format`                             | Med Format report            | `MedFormatData`                             |\n\n`soap` and `medclerk` also appear in autocomplete — legacy aliases of `doc-ipd-soap` and\n`doc-opd-clinicalrecord`. They still work; prefer the full names.\n\n## Options\n\nEverything except `mode`, the credentials, and `timeout` can also be passed per call to `process()`,\nwhere it overrides the constructor value for that run.\n\n| Option          | Type                      | Default         | Per call | Notes                                              |\n| --------------- | ------------------------- | --------------- | :------: | -------------------------------------------------- |\n| `mode`          | `ASRMode`                 | — _(required)_  |          | See [Modes](#modes)                                |\n| `key` `secret`  | `string`                  | —               |          | HMAC credentials                                   |\n| `accessToken`   | `string`                  | —               |          | Bearer token, instead of `key` + `secret`          |\n| `lang`          | `string`                  | service default |    ✓     | `'th'`, `'en'`, …                                  |\n| `specialty`     | `ASRSpecialty`            | —               |    ✓     | Biases the model — see [Specialties](#specialties) |\n| `prefix`        | `string`                  | —               |    ✓     | Forwarded to the service with the task             |\n| `suggestion`    | `boolean`                 | —               |    ✓     | Forwarded to the service with the task             |\n| `newLineString` | `string \\| null`          | `null`          |    ✓     | Replaces `\\n` in the returned text                 |\n| `taskPayload`   | `Record<string, unknown>` | —               |    ✓     | Extra fields for the create-task request           |\n| `uploadConfig`  | `UploadRetryConfig`       | see below       |    ✓     | Retry behavior for the audio upload — see below    |\n| `timeout`       | `number` (ms)             | `300000`        |          | Request timeout and polling limit (5 min)          |\n\n`uploadConfig` controls automatic retry of the audio upload step on transient failures — a network\nerror, any 5xx, plus 408 and 429. The rest of the 4xx range is not retried: an expired signed URL or\na signature mismatch fails identically on every attempt. Cancelling via `cancel()` stops retrying\nimmediately and raises `ABORTED`.\n\n| Field            | Type      | Default          |\n| ---------------- | --------- | ---------------- |\n| `autoRetry`      | `boolean` | `true`           |\n| `retryCount`     | `number`  | `3`              |\n| `retryDelayMs`   | `number`  | `3000` (3 sec)   |\n| `stallTimeoutMs` | `number`  | `30000` (30 sec) |\n\nSet `autoRetry: false` to opt out entirely — the upload gets exactly one attempt and any failure\nsurfaces straight away. It overrides `retryCount`, so there is no need to zero that as well.\n`stallTimeoutMs` still applies: it is what stops a dead connection from hanging forever, which is a\nseparate concern from whether to try again.\n\n`stallTimeoutMs` bounds an attempt that has gone quiet — a phone moving from wifi to cellular can\nleave a socket open with no bytes moving, which no status code ever reports. It times the _silence_,\nnot the whole upload, so a large file on a slow link is left alone as long as it keeps progressing;\nan attempt that goes fully silent is aborted and retried like any other transient failure. The\nwindow restarts once the body is fully sent, so the wait for the server's reply is bounded too\nwithout a slow acknowledgement throwing away an upload that already landed. Browsers only: the Node\nfetch fallback reports no upload progress to measure a stall against, and relies on the runtime's\nown socket timeouts instead.\n\nNothing has to be configured to get the retries — these are all opt-in adjustments:\n\n```ts\n// Every run from this instance, rather than per call.\nconst asr = new ASR({\n  key,\n  secret,\n  mode: 'doc-ipd-soap',\n  uploadConfig: { retryCount: 5, retryDelayMs: 5000 },\n});\n\n// Per call, overriding whatever the constructor set. Pass only the fields you\n// want to change — the rest keep their defaults.\nawait asr.process(longRecording, {\n  uploadConfig: { retryCount: 5, stallTimeoutMs: 60_000 },\n});\n\n// Off, for callers that would rather drive the retries themselves.\nawait asr.process(audio, { uploadConfig: { autoRetry: false } });\n```\n\nReuse a policy across calls by naming it — `UploadRetryConfig` is exported:\n\n```ts\nimport type { UploadRetryConfig } from '@cariva/medical-sdk';\n\nconst POOR_NETWORK: UploadRetryConfig = {\n  retryCount: 5,\n  retryDelayMs: 5000,\n  stallTimeoutMs: 60_000,\n};\n\nawait asr.process(audio, { uploadConfig: POOR_NETWORK });\n```\n\nA failure that survives every attempt arrives as `AUDIO_UPLOAD_FAILED`, with a `message` already\nwritten for a user to read. Offering a retry button is still worth it: by the time they press it the\nconnection may be back.\n\n```ts\ntry {\n  const result = await asr.process(audio, {\n    onProgress: p => setPercent(p.percentage),\n  });\n  render(result.data);\n} catch (err) {\n  if (err instanceof CarivaError && err.code === 'AUDIO_UPLOAD_FAILED') {\n    toast(err.message); // \"Unable to upload audio. Please check your…\"\n    showRetryButton();\n  } else if (err instanceof CarivaError && err.code === 'ABORTED') {\n    // cancel() — the user's own doing, so say nothing\n  }\n}\n```\n\nOne thing to handle in the UI: a retry is a fresh upload, so `onProgress` restarts at 0 and the bar\nvisibly jumps backwards. Watch for a percentage lower than the last one if that needs explaining.\n\n```ts\nonProgress: p => {\n  if (p.percentage < lastPercent) setStatus('Resending…');\n  lastPercent = p.percentage;\n  setPercent(p.percentage);\n};\n```\n\n## `process(audio, options?)`\n\nResolves with the completed result, or throws — see [Errors](#errors). `audio` is a `Blob` or\n`File`. Beyond the options above it takes two callbacks:\n\n| Callback       | Fires         | Argument                                               |\n| -------------- | ------------- | ------------------------------------------------------ |\n| `onProgress`   | During upload | `{ percentage, loaded, total }`                        |\n| `onProcessing` | On each step  | `'Preparing audio...'`, `'Uploading audio file...'`, … |\n\nThe result:\n\n```ts\n{\n  mode: ASRMode; // the mode that produced this result — switch on it\n  data: …; // that mode's payload — see Result shapes\n  status: 'COMPLETED'; // anything else threw instead of resolving\n  taskId: string;\n  error?: string;\n  progress?: number;\n  createdAt?: string;\n  updatedAt?: string;\n  completedAt?: string;\n}\n```\n\n`data` is not optional and `status` is not a union: `process()` resolves only on a completed task,\nso there is nothing to guard against at the call site. A completed task that arrives without a\npayload throws `MISSING_RESULT_DATA` instead of resolving with an empty result.\n\nTo name the result type — passing it between functions, storing it in state — use `ASRResult<Mode>`:\n\n```ts\nfunction render(result: ASRResult<'doc-ipd-soap'>) {\n  result.data.assessment;\n}\n```\n\n## Result shapes\n\nFields marked `?` may be absent.\n\n<details open>\n<summary><b>Doctor modes</b></summary>\n\n```ts\n// doc-ipd-soap\ninterface SOAPData {\n  fastTranscription: string;\n  subjective?: string;\n  objective?: string;\n  assessment?: string;\n  plan?: string;\n}\n\n// doc-opd-clinicalrecord\ninterface OPDClinicalRecordData {\n  fastTranscription: string;\n  rawNote: string;\n  chiefComplaint: string;\n  presentIllness: string;\n  diagnosis: string;\n  pastMedicalHistory: string;\n  familyHistory: string;\n  personalHistory?: string;\n  currentMedication?: string;\n  physicalExamination: {\n    generalAppearance: string;\n    heent: string;\n    cardiovascular: string;\n    respiratory: string;\n    gastrointestinal: string;\n    neurological: string;\n    vitalSign: string;\n    other: string;\n  };\n  investigation: string;\n  treatment: string;\n  plan: string;\n  recommendation?: string;\n}\n```\n\n</details>\n\n<details>\n<summary><b>Nursing modes</b></summary>\n\n```ts\n// nur-opd-nursenote-faie-start\ninterface NurseNoteFaieStartData {\n  fastTranscription: string;\n  rawNote: string;\n  focus: string;\n  assessment: string;\n  intervention: string;\n  vitalSigns: {\n    heartRate: string;\n    respiratoryRate: string;\n    bloodPressure: string;\n    bodyTemperature: string;\n    oxygenSaturation: string;\n  };\n}\n\n// nur-opd-nursenote-faie-end\ninterface NurseNoteFaieEndData {\n  fastTranscription: string;\n  rawNote: string;\n  evaluation: string;\n  vitalSigns: {\n    heartRate: string;\n    respiratoryRate: string;\n    bloodPressure: string;\n    bodyTemperature: string;\n    oxygenSaturation: string;\n  };\n}\n\n// nur-opd-nursenote-adpie-start\ninterface NurseNoteAdpieStartData {\n  fastTranscription: string;\n  rawNote: string;\n  assessment: {\n    objective: string;\n    subjective: string;\n  };\n  diagnosis: string;\n  planning: string;\n  intervention: string;\n}\n\n// nur-opd-nursenote-adpie-end\ninterface NurseNoteAdpieEndData {\n  fastTranscription: string;\n  rawNote: string;\n  evaluation: string;\n}\n```\n\n</details>\n\n<details>\n<summary><b>Radiology mode</b></summary>\n\n```ts\n// radiology — fields are empty strings until the task completes\ninterface RadiologyData {\n  modality: string;\n  requestDetails: string;\n  technique: string;\n  findings: string;\n  impression: string;\n}\n```\n\n</details>\n\n<details>\n<summary><b>Minutes of meeting mode</b></summary>\n\n```ts\n// medical-mom — a ward round, case conference, or handover written up as\n// meeting minutes rather than as a patient record\ninterface MedicalMOMData {\n  fastTranscription: string;\n  rawNote: string;\n  minutesOfMeeting: string;\n}\n```\n\n</details>\n\n<details>\n<summary><b>Med Format mode</b></summary>\n\n```ts\n// med-format — audio is the only input; pass `lang` to choose the report language\ninterface MedFormatData {\n  requestDetails: string;\n  modality: string;\n  technique: string;\n  findings: string;\n  impression: string;\n}\n```\n\nRequires the **Med Format ASR** permission (`asrMedFormat`) on your application. Without it the\ncreate step is rejected with a `403` (`asr-api/forbidden-application-service`) and nothing runs.\n\n</details>\n\n<details>\n<summary><b>Center form mode</b></summary>\n\n```ts\n// center-form\ninterface CenterFormData {\n  [key: string]: unknown;\n}\n```\n\n</details>\n\nNeed the text without knowing the shape? `extractTranscript(result)` returns the best available\nfield, or `''` — see [Chaining](#chaining-asr-result--diagnosis-code-icd-10).\n\n## Rating a result\n\nBinary, like a thumbs up or down. Call it after `process()`; it rates the task that just finished.\n\n```ts\nawait asr.rate(5);\nawait asr.rate(1, 'transcript cut off', ['RESULT_MISMATCH', 'PART_OF_THE_RESULT_IS_MISSING']);\n```\n\n| Parameter  | Type                | Notes                                         |\n| ---------- | ------------------- | --------------------------------------------- |\n| `score`    | `1 \\| 5`            | `5` positive, `1` negative — no scale between |\n| `comment?` | `string`            | Free-text feedback                            |\n| `reasons?` | `ASRRatingReason[]` | Why it was downvoted                          |\n\n| `ASRRatingReason`               | Meaning           |\n| ------------------------------- | ----------------- |\n| `SLOW_PROCESSING`               | Took too long     |\n| `RESULT_MISMATCH`               | Incorrect content |\n| `PART_OF_THE_RESULT_IS_MISSING` | Missing details   |\n| `EXTRA_CONTENT_IN_RESULT`       | Extra content     |\n\n## Instance API\n\n```ts\nawait asr.cancel(); // stop the in-flight task and reset\nawait asr.create(); // cancel + reset, ready for the next recording\n\nasr.taskId; // current task id ('' before the first task)\nasr.status; // last known task status\nasr.isProcessing; // true while a run is in flight\n```\n\nCancelling makes the in-flight `process()` reject with `ABORTED`, so keep it inside the same `try`\nas the call. A request that merely ran out of time is `REQUEST_TIMEOUT`, not `ABORTED`.\n\n## Errors\n\nEverything thrown extends `CarivaError`, which carries `code`, `status`, and `details` — `details`\nholds the API's error payload, or the original exception when the SDK wrapped one.\n\n| Class             | Raised when                                                   |\n| ----------------- | ------------------------------------------------------------- |\n| `ValidationError` | Missing or conflicting credentials, missing `mode`, bad input |\n| `ProcessingError` | The audio could not be prepared, or the upload failed         |\n| `CarivaError`     | Everything else — API errors, timeouts, failed tasks          |\n\nWhich call throws what:\n\n| Call             | Throws                                                                             |\n| ---------------- | ---------------------------------------------------------------------------------- |\n| `new ASR(...)`   | `ValidationError` for bad config — construct it where you can catch it             |\n| `process(audio)` | Any of the codes below                                                             |\n| `rate(score, …)` | `NO_TASK_ID` before a task has completed, `ValidationError` for a score not 1 or 5 |\n| `cancel()`       | Never — a server-side cancel that fails is a console warning                       |\n\n```ts\nimport { CarivaError, ProcessingError, ValidationError } from '@cariva/medical-sdk';\n\ntry {\n  await asr.process(audio);\n} catch (err) {\n  if (err instanceof ValidationError) {\n    // bad config or input — a bug on your side, retrying will not help\n  } else if (err instanceof ProcessingError) {\n    // the audio never made it to the service\n  } else if (err instanceof CarivaError) {\n    console.log(err.code, err.status); // 'TRANSCRIPTION_FAILED', 500, …\n  }\n}\n```\n\nBranch on `err.code` when you need more than the class — it says which step failed:\n\n| Code                      | Raised when                                                             | Worth retrying                 |\n| ------------------------- | ----------------------------------------------------------------------- | ------------------------------ |\n| `VALIDATION_ERROR`        | Bad credentials, missing `mode`, bad argument                           | No — fix the call              |\n| `AUDIO_PROCESSING_FAILED` | The recording could not be prepared for upload                          | No — the same file fails again |\n| `asr/create-task-error`   | The service refused the task — quota, permission, or a rejected payload | Read `err.status` first        |\n| `AUDIO_UPLOAD_FAILED`     | The audio upload failed after exhausting `uploadConfig` retries         | Yes, e.g. with a longer delay  |\n| `TRANSCRIPTION_FAILED`    | The task ran and failed; `err.message` carries the service's reason     | Rarely — usually the recording |\n| `PROCESSING_TIMED_OUT`    | Still unfinished after `timeout` (5 minutes by default)                 | Yes, or raise `timeout`        |\n| `REQUEST_TIMEOUT`         | A single request ran out of time (status 408), after any poll retries   | Yes                            |\n| `ABORTED`                 | `cancel()` or an `AbortSignal` ended the run                            | You asked for it               |\n| `MISSING_RESULT_DATA`     | The task completed with no payload                                      | Yes                            |\n| `PROCESS_FAILED`          | Anything the pipeline did not classify                                  | Yes                            |\n\nThe codes the SDK raises autocomplete on `err.code`; codes the API returns come through unchanged,\nso treat the list as the common cases rather than a closed set.\n\n`ABORTED` is only the caller's own cancellation. A request that simply ran out of time used to\nreport the same code; it now reports `REQUEST_TIMEOUT` with status 408. Code that branched on\n`ABORTED` to catch a hung request will stop matching.\n\nStatus polls during `process()` and `getIcd*Code()` retry the same transient failures as the audio\nupload — network errors, 5xx, 408 and 429 — up to three times, three seconds apart. A hung status\nrequest is abandoned after thirty seconds and retried, rather than occupying the whole five-minute\nwindow. Nothing to configure. A 4xx, or a task the service reports as `FAILED` / `CANCELLED`, is\nstill raised on the first poll that says so. If the overall `timeout` elapses while those retries\nare in flight, the run reports `PROCESSING_TIMED_OUT` rather than the last request failure.\n\n## Specialties\n\nPass one as `specialty` to bias the model toward that domain. The list is autocomplete, not a\nwhitelist — a value the service adds before the SDK knows about it is still accepted.\n\n| Key                | Label                            |\n| ------------------ | -------------------------------- |\n| `gen-practitioner` | General Practitioner (GP)        |\n| `gen-med`          | General Medicine                 |\n| `med-cardio`       | Cardiology                       |\n| `med-pulmonary`    | Pulmonology                      |\n| `med-gastro`       | Gastroenterology (GI)            |\n| `med-neuro`        | Neurology                        |\n| `med-nephro`       | Nephrology                       |\n| `med-onco`         | Oncology                         |\n| `med-endo`         | Endocrinology                    |\n| `med-skin`         | Dermatology (Skin)               |\n| `med-allergy`      | Allergy and Immunology           |\n| `surgery`          | General Surgery                  |\n| `orthopedic`       | Orthopedic                       |\n| `gen-ped`          | General Pediatrics               |\n| `ophthalmology`    | Ophthalmology (Eye)              |\n| `otolaryngology`   | Otolaryngology (ENT)             |\n| `ob-gyn`           | Obstetrics & Gynecology (OB-GYN) |\n| `emergency`        | Emergency (ER)                   |\n| `other`            | Other specialists                |\n\n## Audio handling\n\nRecordings are normalised to mono 16 kHz MP3 at 48 kbps before upload — the format the recogniser\nconsumes, and roughly a 29x reduction from a stereo 44.1 kHz WAV. Hand `process()` whatever you\nrecorded; there is nothing to configure and no encoder to install. If any step fails the SDK falls\nback to a larger format and ultimately to the original file, so pre-processing never blocks a\ntranscription.\n\nA recording is uploaded untouched when there is nothing to gain from encoding it: when it is already\nmono at or below 16 kHz, or already recorded at a lower bitrate than the encoder would produce —\nwhich covers most phone voice memos.\n\n### ffmpeg on a Node server (optional)\n\n`npm install @cariva/medical-sdk` is the whole installation. In the browser there is nothing more to\nthink about. On a Node server, one optional addition is worth knowing about.\n\nThe encoder is pure JavaScript, so **WAV compresses with no setup at all**. Decoding an\nalready-compressed recording — M4A, MP3, OGG, WebM — needs ffmpeg, which this SDK does not install.\nWithout one, those formats upload exactly as they were recorded: the transcript is identical, the\nupload is just larger. Nothing errors and nothing warns.\n\nAdd ffmpeg when your server receives compressed audio that is **not** already mono at ≤16 kHz or ≤48\nkbps — a phone M4A or a `MediaRecorder` WebM usually is not, so expect roughly 2–3x less bandwidth\nper upload. Install it in the image, not as a package:\n\n```dockerfile\nRUN apk add --no-cache ffmpeg                    # Alpine\nRUN apt-get update && apt-get install -y ffmpeg  # Debian/Ubuntu\n```\n\nThe SDK finds it on `PATH` by itself — no configuration, no code change. Verify with\n`ffmpeg -version`.\n\n> If you cannot change the image (serverless, for instance), `ffmpeg-static` in your own\n> dependencies works too, and the SDK picks it up the same way. Be aware that it downloads a 45 MB\n> binary from an install script, and npm 12, pnpm 10+, and Bun all block those by default — so you\n> will have to allow that build in your own project.\n\n## Diagnosis Code (ICD)\n\nTurns a clinical note into ICD codes and looks codes up by keyword. The same `ICD` class handles\nICD-10, ICD-9, and combined ICD-9+ICD-10 — select the system with the optional **`modes`** array on\nevery call. When `modes` is omitted the default is `[\"icd10\"]`, keeping backward-compatibility with\nthe legacy `ICD10` class.\n\n```ts\nimport { ICD } from '@cariva/medical-sdk';\n\nconst icd = new ICD({ key: 'YOUR_KEY', secret: 'YOUR_SECRET', baseUrl: 'https://…' });\n\n// ICD-10\nconst { primary } = await icd.getIcdOpdCode('runny nose and cough');\nconsole.log(primary?.code, primary?.description); // J00  Acute nasopharyngitis\n\nconst { primary: p } = await icd.getIcdOpdCode(['icd10'], 'runny nose and cough');\n\n// ICD-9\nconst { principal, secondary } = await icd.getIcdOpdCode(['icd9'], 'appendectomy');\nconsole.log(principal?.code, principal?.orStatus); // 47.0  true\n\n// Combined ICD-10 + ICD-9\nconst result = await icd.getIcdOpdCode(['icd10', 'icd9'], 'appendectomy');\nconsole.log(result.icd10.primary?.code); // K35.9\nconsole.log(result.icd9.principal?.orStatus); // true\n```\n\nThe constructor takes the same `key` / `secret` or `accessToken` credentials as `ASR`. `baseUrl` is\nrequired (the ICD service has its own host, separate from ASR).\n\n```ts\nnew ICD({ key, secret, baseUrl }); // API key + secret (HMAC)\nnew ICD({ accessToken, baseUrl }); // bearer token\nnew ICD({ key, secret, baseUrl, timeout: 60_000 }); // custom timeout (ms, default 300 000)\n```\n\n### Modes\n\nThe first argument of every method is an **optional** `modes` array that selects the coding\nsystem(s). When omitted it defaults to `[\"icd10\"]`. **Order does not matter** — `[\"icd9\",\"icd10\"]`\nis identical to `[\"icd10\",\"icd9\"]`.\n\n| `modes`                | Systems                           | Combined endpoint |\n| ---------------------- | --------------------------------- | ----------------- |\n| omitted or `[\"icd10\"]` | ICD-10 diagnosis codes            | —                 |\n| `[\"icd9\"]`             | ICD-9 procedure / diagnosis codes | —                 |\n| `[\"icd10\",\"icd9\"]`     | Both in one async task            | ✓ (coding only)   |\n\n> Search and suggest-block accept only a single system (`[\"icd10\"]` or `[\"icd9\"]`). Passing\n> `[\"icd10\",\"icd9\"]` to those methods throws a `ValidationError`.\n\n### Which call do you need?\n\n| You have                      | Call                                                                | You get back                          |\n| ----------------------------- | ------------------------------------------------------------------- | ------------------------------------- |\n| Outpatient note, as free text | `getIcdOpdCode(modes?, note, options?)`                             | see [Coding results](#coding-results) |\n| Inpatient record, in sections | `getIcdIpdCode(modes?, records, options?)`                          | see [Coding results](#coding-results) |\n| A keyword to look up          | `searchIcdOpd(modes?, query, options?)` / `searchIcdIpd`            | flat list of matches                  |\n| A code, and want related ones | `suggestBlockIcdOpd(modes?, code, options?)` / `suggestBlockIcdIpd` | flat list of related codes            |\n\nOutpatient and inpatient are permissioned and billed separately — use the correct pair for the\nencounter type.\n\nBoth coding methods are **asynchronous tasks**: the SDK creates the task, polls until it completes,\nand resolves with the result. A dropped status request is retried a few times rather than failing\nthe run; see [Errors](#errors). The default timeout is 5 minutes (`300 000` ms); pass a custom\n`timeout` to the constructor to change it.\n\n### Types\n\nThe **return type is inferred from `modes`** — no cast required. When `modes` is omitted the return\ntype is always the ICD-10 variant.\n\n```ts\n// modes → inferred return type\nicd.getIcdOpdCode(note); // Promise<ICD10OpdCodeResult>  (modes omitted)\nicd.getIcdOpdCode(['icd10'], note); // Promise<ICD10OpdCodeResult>\nicd.getIcdOpdCode(['icd9'], note); // Promise<ICD9CodeResult>\nicd.getIcdOpdCode(['icd10', 'icd9'], note); // Promise<ICD9Icd10OpdCodeResult>\n\nicd.searchIcdOpd(query); // Promise<ICD10SearchEntry[]>  (modes omitted)\nicd.searchIcdOpd(['icd10'], query); // Promise<ICD10SearchEntry[]>\nicd.searchIcdOpd(['icd9'], query); // Promise<ICD9Entry[]>\n```\n\nThe generic utility types let you name the result in your own functions:\n\n```ts\nimport type { ICDOpdCodeResult } from '@cariva/medical-sdk';\n\nfunction render(r: ICDOpdCodeResult<['icd10']>) {\n  r.primary?.code; // typed as ICD10OpdCodeResult\n}\n```\n\n**ICD-10 entry types**\n\n```ts\ninterface ICD10Entry {\n  code: string; // 'J00'\n  description: string; // 'Acute nasopharyngitis [common cold]'\n}\n\ninterface ICD10SearchEntry extends ICD10Entry {\n  display?: string;\n}\n```\n\n**ICD-9 entry type**\n\n```ts\ninterface ICD9Entry {\n  code: string;\n  description: string;\n  orStatus?: boolean;\n  drgStatus?: boolean;\n}\n```\n\n**Coding result types per mode**\n\n| `modes`            | OPD result               | IPD result               |\n| ------------------ | ------------------------ | ------------------------ |\n| `[\"icd10\"]`        | `ICD10OpdCodeResult`     | `ICD10IpdCodeResult`     |\n| `[\"icd9\"]`         | `ICD9CodeResult`         | `ICD9CodeResult`         |\n| `[\"icd10\",\"icd9\"]` | `ICD9Icd10OpdCodeResult` | `ICD9Icd10IpdCodeResult` |\n\n### Coding results\n\n#### `modes: [\"icd10\"]` — outpatient\n\n```ts\ninterface ICD10OpdCodeResult {\n  primary: ICD10Entry | null;\n  secondary: ICD10Entry[];\n  externalCause: ICD10Entry[];\n}\n```\n\n#### `modes: [\"icd10\"]` — inpatient\n\n```ts\ninterface ICD10IpdCodeResult {\n  principal: ICD10Entry | null;\n  comorbidity: ICD10Entry[];\n  complication: ICD10Entry[];\n  otherDiagnosis: ICD10Entry[];\n  externalCause: ICD10Entry[];\n}\n```\n\n#### `modes: [\"icd9\"]` — outpatient or inpatient\n\n```ts\ninterface ICD9CodeResult {\n  principal: ICD9Entry | null;\n  secondary: ICD9Entry[];\n}\n```\n\n#### `modes: [\"icd10\",\"icd9\"]` — outpatient\n\n```ts\ninterface ICD9Icd10OpdCodeResult {\n  icd9: {\n    principal: ICD9Entry | null;\n    secondary: ICD9Entry[];\n  };\n  icd10: {\n    primary: ICD10Entry | null;\n    secondary: ICD10Entry[];\n    externalCause: ICD10Entry[];\n  };\n}\n```\n\n#### `modes: [\"icd10\",\"icd9\"]` — inpatient\n\n```ts\ninterface ICD9Icd10IpdCodeResult {\n  icd9: {\n    principal: ICD9Entry | null;\n    secondary: ICD9Entry[];\n  };\n  icd10: {\n    principal: ICD10Entry | null;\n    comorbidity: ICD10Entry[];\n    complication: ICD10Entry[];\n    otherDiagnosis: ICD10Entry[];\n    externalCause: ICD10Entry[];\n  };\n}\n```\n\n### Coding an encounter\n\n#### OPD: `getIcdOpdCode(modes, note, options?)`\n\n```ts\n// ICD-10 only\nconst { primary, secondary, externalCause } = await icd.getIcdOpdCode(\n  ['icd10'],\n  'Runny nose, cough and mild fever for two days.',\n  { patientProfile: { age: 35, sex: 'female' } }\n);\nconsole.log(primary); // { code: 'J00', description: 'Acute nasopharyngitis [common cold]' }\n\n// ICD-9 only\nconst { principal, secondary } = await icd.getIcdOpdCode(['icd9'], 'appendectomy');\nconsole.log(principal); // { code: '47.0', description: 'Appendectomy', orStatus: true, drgStatus: false }\n\n// Combined ICD-10 + ICD-9\nconst combined = await icd.getIcdOpdCode(['icd10', 'icd9'], 'appendectomy');\nconsole.log(combined.icd10.primary?.code); // 'K35.9'\nconsole.log(combined.icd9.principal?.orStatus); // true\n```\n\n#### IPD: `getIcdIpdCode(modes, records, options?)`\n\nInput is the record split into named sections. Combined mode is supported here too:\n\n```ts\nconst records = [\n  { name: 'Chief complaint', content: 'Fever and cough for 3 days' },\n  {\n    name: 'Assessment',\n    content: 'Community acquired pneumonia. Known type 2 diabetes. Fall at home.',\n  },\n];\n\n// ICD-10\nconst { principal, comorbidity, complication, otherDiagnosis, externalCause } =\n  await icd.getIcdIpdCode(['icd10'], records);\nconsole.log(principal); // { code: 'J18.9', description: 'Pneumonia, unspecified' }\nconsole.log(comorbidity); // [{ code: 'E11.9', description: 'Type 2 diabetes mellitus without complications' }]\nconsole.log(complication); // [{ code: 'J96.00', description: 'Acute respiratory failure, unspecified whether with hypoxia or hypercapnia' }]\nconsole.log(otherDiagnosis); // [{ code: 'E87.6', description: 'Hypokalaemia' }]\nconsole.log(externalCause); // [{ code: 'W19.9', description: 'Unspecified fall, unspecified place' }]\n\n// ICD-9\nconst { principal: icd9Principal, secondary } = await icd.getIcdIpdCode(['icd9'], records);\nconsole.log(icd9Principal); // { code: '96.71', description: 'Continuous invasive mechanical ventilation for less than 96 consecutive hours', orStatus: false, drgStatus: true }\nconsole.log(secondary); // []\n\n// Combined\nconst both = await icd.getIcdIpdCode(['icd10', 'icd9'], records);\nconsole.log(both.icd10.principal?.code); // 'J18.9'\nconsole.log(both.icd10.comorbidity); // [{ code: 'E11.9', description: 'Type 2 diabetes mellitus without complications' }]\nconsole.log(both.icd10.complication); // [{ code: 'J96.00', description: 'Acute respiratory failure, unspecified whether with hypoxia or hypercapnia' }]\nconsole.log(both.icd10.otherDiagnosis); // [{ code: 'E87.6', description: 'Hypokalaemia' }]\nconsole.log(both.icd10.externalCause); // [{ code: 'W19.9', description: 'Unspecified fall, unspecified place' }]\nconsole.log(both.icd9.principal?.drgStatus); // true / false\nconsole.log(both.icd9.secondary); // []\n```\n\n**Options** — `getIcdOpdCode`, `getIcdIpdCode`\n\n| Option           | Type                          | Notes                                                                                   |\n| ---------------- | ----------------------------- | --------------------------------------------------------------------------------------- |\n| `patientProfile` | `{ age?, sex?, isPregnant? }` | `age` ≤ 0 is ignored. With `isPregnant: true`, `sex` is required and cannot be `'male'` |\n| `signal`         | `AbortSignal`                 | Stops the run immediately — no further status polls                                     |\n\n### Searching by keyword\n\n`searchIcdOpd` and `searchIcdIpd` perform a catalogue lookup — they are not coding a note, so there\nis no `primary` in the result. Pass `[\"icd10\"]` or `[\"icd9\"]`; combined is not supported.\n\n```ts\n// ICD-10 OPD search\nconst matches = await icd.searchIcdOpd(['icd10'], 'pneumonia', { searchBy: 'text' });\n// [{ code: 'J18', description: 'Pneumonia', display: 'J18 Pneumonia' }]\n\n// ICD-9 IPD search\nconst icd9matches = await icd.searchIcdIpd(['icd9'], '47');\n// [{ code: '47.0', description: 'Appendectomy', orStatus: true, drgStatus: false }]\n```\n\n**Options** — `searchIcdOpd`, `searchIcdIpd`\n\n| Option     | Type                        | Notes               |\n| ---------- | --------------------------- | ------------------- |\n| `searchBy` | `'code' \\| 'text' \\| 'all'` | Default `'all'`     |\n| `signal`   | `AbortSignal`               | Cancels the request |\n\n### Suggesting related codes\n\n`suggestBlockIcdOpd` and `suggestBlockIcdIpd` take a code you already have and return codes commonly\nseen alongside it. Pass `[\"icd10\"]` or `[\"icd9\"]`; combined is not supported.\n\n```ts\n// ICD-10 OPD — hypertension → codes seen alongside it\nconst related = await icd.suggestBlockIcdOpd(['icd10'], 'I10');\n// [{ code: 'I15.8', description: 'Other secondary hypertension' }]\n\n// ICD-9 IPD — codes alongside an appendectomy\nconst icd9related = await icd.suggestBlockIcdIpd(['icd9'], '47.0');\n// [{ code: '47.1', description: 'Incidental appendectomy', orStatus: true, drgStatus: false }]\n```\n\n**Options** — `suggestBlockIcdOpd`, `suggestBlockIcdIpd`\n\n| Option   | Type          | Notes               |\n| -------- | ------------- | ------------------- |\n| `signal` | `AbortSignal` | Cancels the request |\n\n### ICD errors\n\nFailures throw the same `CarivaError` family as ASR — see [Errors](#errors). Aborting via `signal`\nrejects with `ABORTED` at once and sends no further status polls. Blank input, an empty\n`structuredRecords` list, an invalid `patientProfile`, an empty `modes` array, an unknown system\nname, or a combined `modes` on a search/suggest call all throw `ValidationError` before any request\ngoes out.\n\n| Call                                 | Error code                      |\n| ------------------------------------ | ------------------------------- |\n| `getIcdOpdCode(['icd10'], …)`        | `icd10/opd-code-error`          |\n| `getIcdIpdCode(['icd10'], …)`        | `icd10/ipd-code-error`          |\n| `getIcdOpdCode(['icd9'], …)`         | `icd9/opd-code-error`           |\n| `getIcdIpdCode(['icd9'], …)`         | `icd9/ipd-code-error`           |\n| `getIcdOpdCode(['icd10','icd9'], …)` | `icd9-icd10/opd-code-error`     |\n| `getIcdIpdCode(['icd10','icd9'], …)` | `icd9-icd10/ipd-code-error`     |\n| `searchIcdOpd(['icd10'], …)`         | `icd10/search-opd-error`        |\n| `searchIcdIpd(['icd10'], …)`         | `icd10/search-ipd-error`        |\n| `searchIcdOpd(['icd9'], …)`          | `icd9/search-opd-error`         |\n| `searchIcdIpd(['icd9'], …)`          | `icd9/search-ipd-error`         |\n| `suggestBlockIcdOpd(['icd10'], …)`   | `icd10/suggest-block-opd-error` |\n| `suggestBlockIcdIpd(['icd10'], …)`   | `icd10/suggest-block-ipd-error` |\n| `suggestBlockIcdOpd(['icd9'], …)`    | `icd9/suggest-block-opd-error`  |\n| `suggestBlockIcdIpd(['icd9'], …)`    | `icd9/suggest-block-ipd-error`  |\n\n## Chaining: ASR result → Diagnosis Code (ICD)\n\n```ts\nimport { ASR, ICD, extractTranscript } from '@cariva/medical-sdk';\n\nconst asr = new ASR({ key, secret, mode: 'doc-ipd-soap' });\nconst icd = new ICD({ key, secret, baseUrl: 'https://…' });\n\nconst asrResult = await asr.process(audio);\n\n// ICD-10 from the transcription\nconst { primary } = await icd.getIcdOpdCode(['icd10'], extractTranscript(asrResult));\n\n// ICD-9 from the transcription\nconst { principal } = await icd.getIcdOpdCode(['icd9'], extractTranscript(asrResult));\n\n// Combined ICD-10 + ICD-9 from a structured IPD record\nconst both = await icd.getIcdIpdCode(\n  ['icd10', 'icd9'],\n  [{ name: 'Assessment', content: asrResult.data.assessment ?? '' }]\n);\n```\n\n## Requirements\n\n- **Node.js** ≥ 22 — global `fetch`, `File`, `Blob`, stable WebCrypto\n- **Browsers** — ES2020+ with the Web Audio API\n- **Bundlers** — Vite, webpack, esbuild, Rollup, Next.js, or anything that reads `exports`\n\n## Migrating from the legacy SDKs\n\nThis package replaces `@cariva/asr-sdk-browser` and `@cariva/asr-sdk-node` with one package that\nruns on both.\n\n```bash\nnpm uninstall @cariva/asr-sdk-browser @cariva/asr-sdk-node\nnpm install @cariva/medical-sdk\n```\n\n```diff\n- import { ASR } from '@cariva/asr-sdk-browser';\n+ import { ASR } from '@cariva/medical-sdk';\n\n  const asr = new ASR({\n    key, secret,\n-   version: '1',\n    mode: 'doc-ipd-soap',\n  });\n\n- const result = await asr.process('/path/to/audio.wav');\n+ const bytes = await readFile('/path/to/audio.wav');\n+ const result = await asr.process(new Blob([bytes], { type: 'audio/wav' }));\n\n- await asr.cancelASRTask();\n+ await asr.cancel();\n- await asr.rateASRTask(5, 'good');\n+ await asr.rate(5, 'good');\n```\n\n| What             | Legacy `asr-sdk-*`                       | `medical-sdk` 1.0                 |\n| ---------------- | ---------------------------------------- | --------------------------------- |\n| Package          | one per platform                         | one for both                      |\n| Config `version` | required                                 | removed                           |\n| Audio on Node    | file path `string`, system `lame` binary | `Blob` / `File`, no binary needed |\n| UMD global       | `window.CarivaASRBrowser`                | `window.CarivaMedicalSDK`         |\n| CDN path         | `/dist/index.umd.js`                     | `/dist/browser/index.umd.js`      |\n\nRenamed:\n\n| Legacy               | Now                          |\n| -------------------- | ---------------------------- |\n| `cancelASRTask()`    | `cancel()`                   |\n| `rateASRTask()`      | `rate()`                     |\n| `clearTask()`        | _(removed — use `cancel()`)_ |\n| `ASRError`           | `CarivaError`                |\n| `ASRValidationError` | `ValidationError`            |\n| `ASRProcessingError` | `ProcessingError`            |\n| `Mode`               | `ASRMode`                    |\n| `MedicalSpecialty`   | `ASRSpecialty`               |\n| `TaskStatus`         | `ASRTaskStatus`              |\n| `TaskStatusResponse` | `ASRResult`                  |\n| `CreateTaskResponse` | `ASRCreateTaskResponse`      |\n| `AsrResponseMap`     | `ASRResponseMap`             |\n| `MedClerkData`       | `OPDClinicalRecordData`      |\n\n### Migrating from `ICD10` to `ICD`\n\nThe old `ICD10` class has been replaced by a unified `ICD` class that handles ICD-10, ICD-9, and\ncombined ICD-9+ICD-10 through an **optional** `modes` array.\n\n**Minimal migration** — just swap the class and add `baseUrl`; all calls work without passing\n`modes` because it defaults to `[\"icd10\"]`:\n\n```diff\n- import { ICD10 } from '@cariva/medical-sdk';\n+ import { ICD } from '@cariva/medical-sdk';\n\n- const icd = new ICD10({ key, secret });\n+ const icd = new ICD({ key, secret, baseUrl: 'https://…' });\n\n  // No other changes needed — modes defaults to [\"icd10\"]\n- const { primary } = await icd.getOpdCode(note);\n+ const { primary } = await icd.getIcdOpdCode(note);\n```\n\n**Explicit modes** — recommended when you want to be clear about which system is used or when you\nneed ICD-9 or combined:\n\n```diff\n- const { primary } = await icd.getOpdCode(note);\n+ const { primary } = await icd.getIcdOpdCode(['icd10'], note);\n\n- const { primary } = await icd.getIpdCode(records);\n+ const { principal } = await icd.getIcdIpdCode(['icd10'], records);\n\n- const hits = await icd.searchOpd(query, { searchBy: 'text' });\n+ const hits = await icd.searchIcdOpd(['icd10'], query, { searchBy: 'text' });\n\n- const related = await icd.suggestBlockOpd(code);\n+ const related = await icd.suggestBlockIcdOpd(['icd10'], code);\n```\n\nAuthentication, the `patientProfile` option, and every payload shape for ICD-10 are unchanged. The\nnew ICD-9 fields `orStatus` and `drgStatus` only appear when `modes` includes `'icd9'`.\n\n## License\n\nApache-2.0\n","readmeFilename":"README.md"}