@mieweb/ui 0.11.0-dev.49 → 0.11.0-dev.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/{chunk-HIYQ3M5V.cjs → chunk-2Y2O2PRZ.cjs} +3 -3
  2. package/dist/chunk-2Y2O2PRZ.cjs.map +1 -0
  3. package/dist/{chunk-O2EAHOXM.cjs → chunk-G56OUIGH.cjs} +482 -29
  4. package/dist/chunk-G56OUIGH.cjs.map +1 -0
  5. package/dist/chunk-GEXYN6AS.cjs +56 -0
  6. package/dist/chunk-GEXYN6AS.cjs.map +1 -0
  7. package/dist/{chunk-OGNADPM4.cjs → chunk-GQONYSGI.cjs} +10 -2
  8. package/dist/chunk-GQONYSGI.cjs.map +1 -0
  9. package/dist/{chunk-IZY4CMOO.js → chunk-H7L45BLY.js} +13 -24
  10. package/dist/chunk-H7L45BLY.js.map +1 -0
  11. package/dist/{chunk-MZA2LDS4.js → chunk-I65QJMFB.js} +4 -4
  12. package/dist/{chunk-MZA2LDS4.js.map → chunk-I65QJMFB.js.map} +1 -1
  13. package/dist/{chunk-NB2C6FSI.js → chunk-L3JA7EDU.js} +20 -3
  14. package/dist/{chunk-NB2C6FSI.js.map → chunk-L3JA7EDU.js.map} +1 -1
  15. package/dist/{chunk-UIFN2LYT.js → chunk-O3MN3TYS.js} +483 -32
  16. package/dist/chunk-O3MN3TYS.js.map +1 -0
  17. package/dist/{chunk-74ENCTIK.js → chunk-R25E7SYN.js} +9 -3
  18. package/dist/chunk-R25E7SYN.js.map +1 -0
  19. package/dist/{chunk-TRZLN32I.cjs → chunk-RDERYV5M.cjs} +14 -25
  20. package/dist/chunk-RDERYV5M.cjs.map +1 -0
  21. package/dist/{chunk-BFVYM6IT.cjs → chunk-TLXQ2E57.cjs} +6 -6
  22. package/dist/{chunk-BFVYM6IT.cjs.map → chunk-TLXQ2E57.cjs.map} +1 -1
  23. package/dist/{chunk-MQOYDQTF.js → chunk-URHUNFFC.js} +3 -3
  24. package/dist/chunk-URHUNFFC.js.map +1 -0
  25. package/dist/chunk-WSLKELR2.js +51 -0
  26. package/dist/chunk-WSLKELR2.js.map +1 -0
  27. package/dist/{chunk-5UKGOBCZ.cjs → chunk-XWGPEIVB.cjs} +20 -3
  28. package/dist/{chunk-5UKGOBCZ.cjs.map → chunk-XWGPEIVB.cjs.map} +1 -1
  29. package/dist/components/DictationButton/index.cjs +5 -5
  30. package/dist/components/DictationButton/index.js +2 -2
  31. package/dist/components/RecordButton/index.cjs +4 -4
  32. package/dist/components/RecordButton/index.d.cts +2 -2
  33. package/dist/components/RecordButton/index.d.ts +2 -2
  34. package/dist/components/RecordButton/index.js +1 -1
  35. package/dist/components/SuperChat/index.cjs +9 -7
  36. package/dist/components/SuperChat/index.cjs.map +1 -1
  37. package/dist/components/SuperChat/index.d.cts +2 -2
  38. package/dist/components/SuperChat/index.d.ts +2 -2
  39. package/dist/components/SuperChat/index.js +3 -1
  40. package/dist/components/SuperChat/index.js.map +1 -1
  41. package/dist/components/SuperChat/plugins/index.d.cts +2 -2
  42. package/dist/components/SuperChat/plugins/index.d.ts +2 -2
  43. package/dist/{hey-buddy-AHUHCDBC.js → hey-buddy-6HXWNHK2.js} +12 -7
  44. package/dist/hey-buddy-6HXWNHK2.js.map +1 -0
  45. package/dist/{hey-buddy-5WOBYZRJ.cjs → hey-buddy-BAS5O4AY.cjs} +12 -7
  46. package/dist/hey-buddy-BAS5O4AY.cjs.map +1 -0
  47. package/dist/index.cjs +2037 -1255
  48. package/dist/index.cjs.map +1 -1
  49. package/dist/index.d.cts +207 -14
  50. package/dist/index.d.ts +207 -14
  51. package/dist/index.js +1851 -1082
  52. package/dist/index.js.map +1 -1
  53. package/dist/{speaker-verify-4NEJAK6C.cjs → speaker-verify-PWTYV4JZ.cjs} +10 -10
  54. package/dist/{speaker-verify-4NEJAK6C.cjs.map → speaker-verify-PWTYV4JZ.cjs.map} +1 -1
  55. package/dist/{speaker-verify-AWSKI6DI.js → speaker-verify-REFWMPTD.js} +3 -3
  56. package/dist/{speaker-verify-AWSKI6DI.js.map → speaker-verify-REFWMPTD.js.map} +1 -1
  57. package/dist/styles.css +1 -1
  58. package/dist/tailwind-preset.cjs +4 -4
  59. package/dist/tailwind-preset.js +1 -1
  60. package/dist/{types-BfVolads.d.ts → types-ByK_dbT7.d.cts} +13 -2
  61. package/dist/{types-BfVolads.d.cts → types-ByK_dbT7.d.ts} +13 -2
  62. package/dist/whisperTranscribe-QV2EQRCD.js +5 -0
  63. package/dist/{whisperTranscribe-UBNUWXUQ.js.map → whisperTranscribe-QV2EQRCD.js.map} +1 -1
  64. package/dist/{whisperTranscribe-AV752TZI.cjs → whisperTranscribe-XL365FM4.cjs} +26 -21
  65. package/dist/{whisperTranscribe-AV752TZI.cjs.map → whisperTranscribe-XL365FM4.cjs.map} +1 -1
  66. package/package.json +2 -2
  67. package/dist/chunk-74ENCTIK.js.map +0 -1
  68. package/dist/chunk-HIYQ3M5V.cjs.map +0 -1
  69. package/dist/chunk-IZY4CMOO.js.map +0 -1
  70. package/dist/chunk-MQOYDQTF.js.map +0 -1
  71. package/dist/chunk-O2EAHOXM.cjs.map +0 -1
  72. package/dist/chunk-OGNADPM4.cjs.map +0 -1
  73. package/dist/chunk-TRZLN32I.cjs.map +0 -1
  74. package/dist/chunk-UIFN2LYT.js.map +0 -1
  75. package/dist/hey-buddy-5WOBYZRJ.cjs.map +0 -1
  76. package/dist/hey-buddy-AHUHCDBC.js.map +0 -1
  77. package/dist/whisperTranscribe-UBNUWXUQ.js +0 -4
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/RecordButton/RecordButton.tsx"],"names":[],"mappings":";;;;;AA+EA,SAAS,OAAA,CAAQ;AAAA,EACf,SAAA;AAAA,EACA,IAAA,GAAO;AACT,CAAA,EAGG;AACD,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAM,4BAAA;AAAA,MACN,OAAA,EAAQ,WAAA;AAAA,MACR,KAAA,EAAO,IAAA;AAAA,MACP,MAAA,EAAQ,IAAA;AAAA,MACR,IAAA,EAAK,MAAA;AAAA,MACL,MAAA,EAAO,cAAA;AAAA,MACP,WAAA,EAAY,GAAA;AAAA,MACZ,aAAA,EAAc,OAAA;AAAA,MACd,cAAA,EAAe,OAAA;AAAA,MACf,SAAA;AAAA,MACA,aAAA,EAAY,MAAA;AAAA,MAEZ,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,GAAE,sDAAA,EAAuD,CAAA;AAAA,wBAC/D,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,4BAAA,EAA6B,CAAA;AAAA,wBACrC,GAAA,CAAC,UAAK,EAAA,EAAG,IAAA,EAAK,IAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK;AAAA;AAAA;AAAA,GACxC;AAEJ;AAEA,SAAS,UAAA,CAAW;AAAA,EAClB,SAAA;AAAA,EACA,IAAA,GAAO;AACT,CAAA,EAGG;AACD,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAM,4BAAA;AAAA,MACN,OAAA,EAAQ,WAAA;AAAA,MACR,KAAA,EAAO,IAAA;AAAA,MACP,MAAA,EAAQ,IAAA;AAAA,MACR,IAAA,EAAK,MAAA;AAAA,MACL,MAAA,EAAO,cAAA;AAAA,MACP,WAAA,EAAY,GAAA;AAAA,MACZ,aAAA,EAAc,OAAA;AAAA,MACd,cAAA,EAAe,OAAA;AAAA,MACf,SAAA;AAAA,MACA,aAAA,EAAY,MAAA;AAAA,MAEZ,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,IAAG,GAAA,EAAI,EAAA,EAAG,MAAK,EAAA,EAAG,GAAA,EAAI,IAAG,IAAA,EAAK,CAAA;AAAA,wBACpC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,uCAAA,EAAwC,CAAA;AAAA,wBAChD,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,wBAAA,EAAyB,CAAA;AAAA,wBACjC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,gCAAA,EAAiC,CAAA;AAAA,wBACzC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,4BAAA,EAA6B,CAAA;AAAA,wBACrC,GAAA,CAAC,UAAK,EAAA,EAAG,IAAA,EAAK,IAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK;AAAA;AAAA;AAAA,GACxC;AAEJ;AAEA,SAAS,QAAA,CAAS;AAAA,EAChB,SAAA;AAAA,EACA,IAAA,GAAO;AACT,CAAA,EAGG;AACD,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAM,4BAAA;AAAA,MACN,OAAA,EAAQ,WAAA;AAAA,MACR,KAAA,EAAO,IAAA;AAAA,MACP,MAAA,EAAQ,IAAA;AAAA,MACR,IAAA,EAAK,cAAA;AAAA,MACL,SAAA;AAAA,MACA,aAAA,EAAY,MAAA;AAAA,MAEZ,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,GAAA,EAAI,CAAA,EAAE,GAAA,EAAI,KAAA,EAAM,IAAA,EAAK,MAAA,EAAO,IAAA,EAAK,EAAA,EAAG,GAAA,EAAI;AAAA;AAAA,GAClD;AAEJ;AAEA,SAAS,SAAA,CAAU;AAAA,EACjB,SAAA;AAAA,EACA,IAAA,GAAO;AACT,CAAA,EAGG;AACD,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAM,4BAAA;AAAA,MACN,OAAA,EAAQ,WAAA;AAAA,MACR,KAAA,EAAO,IAAA;AAAA,MACP,MAAA,EAAQ,IAAA;AAAA,MACR,IAAA,EAAK,MAAA;AAAA,MACL,MAAA,EAAO,cAAA;AAAA,MACP,WAAA,EAAY,KAAA;AAAA,MACZ,aAAA,EAAc,OAAA;AAAA,MACd,cAAA,EAAe,OAAA;AAAA,MACf,SAAA;AAAA,MACA,aAAA,EAAY,MAAA;AAAA,MAEZ,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAS,MAAA,EAAO,gBAAA,EAAiB;AAAA;AAAA,GACpC;AAEJ;AAEA,SAAS,cAAA,CAAe;AAAA,EACtB,SAAA;AAAA,EACA,IAAA,GAAO;AACT,CAAA,EAGG;AACD,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAM,4BAAA;AAAA,MACN,OAAA,EAAQ,WAAA;AAAA,MACR,KAAA,EAAO,IAAA;AAAA,MACP,MAAA,EAAQ,IAAA;AAAA,MACR,IAAA,EAAK,MAAA;AAAA,MACL,MAAA,EAAO,cAAA;AAAA,MACP,WAAA,EAAY,GAAA;AAAA,MACZ,aAAA,EAAc,OAAA;AAAA,MACd,cAAA,EAAe,OAAA;AAAA,MACf,SAAA,EAAW,EAAA,CAAG,cAAA,EAAgB,SAAS,CAAA;AAAA,MACvC,aAAA,EAAY,MAAA;AAAA,MAEZ,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,6BAAA,EAA8B;AAAA;AAAA,GACxC;AAEJ;AAMA,SAAS,UAAA,CAAW,EAAE,OAAA,EAAQ,EAAqC;AACjE,EAAA,MAAM,SAAA,GAAY,OAAA,KAAY,SAAA,GAAY,eAAA,GAAkB,eAAA;AAE5D,EAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,WAAA,EAAU,qBAAA;AAAA,QACV,SAAA,EAAW,EAAA,CAAG,4CAAA,EAA8C,SAAS,CAAA;AAAA,QACrE,KAAA,EAAO,EAAE,iBAAA,EAAmB,MAAA;AAAO;AAAA,KACrC;AAAA,oBACA,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,WAAA,EAAU,qBAAA;AAAA,QACV,SAAA,EAAW,EAAA,CAAG,4CAAA,EAA8C,SAAS,CAAA;AAAA,QACrE,KAAA,EAAO,EAAE,iBAAA,EAAmB,MAAA,EAAQ,gBAAgB,MAAA;AAAO;AAAA;AAC7D,GAAA,EACF,CAAA;AAEJ;AAMA,SAAS,YAAA,CAAa,EAAE,IAAA,EAAK,EAA+B;AAC1D,EAAA,MAAM,YAAY,IAAA,KAAS,IAAA,GAAO,KAAA,GAAQ,IAAA,KAAS,OAAO,KAAA,GAAQ,KAAA;AAKlE,EAAA,MAAM,eACJ,IAAA,KAAS,IAAA,GAAO,QAAA,GAAW,IAAA,KAAS,OAAO,SAAA,GAAY,MAAA;AAEzD,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,wBAAA;AAAA,MACV,SAAA,EAAU,2BAAA;AAAA,MAET,QAAA,EAAA,CAAC,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,qBACpB,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UAEC,SAAA,EAAW,EAAA;AAAA,YACT,gDAAA;AAAA,YACA;AAAA,WACF;AAAA,UACA,KAAA,EAAO;AAAA,YACL,KAAA,EAAO,UAAA;AAAA,YACP,MAAA,EAAQ,YAAA;AAAA,YACR,cAAA,EAAgB,CAAA,EAAG,CAAA,GAAI,GAAG,CAAA,CAAA;AAAA;AAC5B,SAAA;AAAA,QATK;AAAA,OAWR;AAAA;AAAA,GACH;AAEJ;AAMA,IAAM,oBAAA,GAAuB,GAAA;AAAA,EAC3B;AAAA,IACE,+DAAA;AAAA,IACA,6BAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,OAAA,EAAS;AAAA,QACP,OAAA,EAAS,EAAA;AAAA,QACT,OAAA,EAAS,UAAA;AAAA,QACT,KAAA,EAAO,EAAA;AAAA,QACP,OAAA,EAAS;AAAA,OACX;AAAA,MACA,IAAA,EAAM;AAAA,QACJ,EAAA,EAAI,SAAA;AAAA,QACJ,EAAA,EAAI,SAAA;AAAA,QACJ,EAAA,EAAI;AAAA;AACN,KACF;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,OAAA,EAAS,SAAA;AAAA,MACT,IAAA,EAAM;AAAA;AACR;AAEJ;AAEA,IAAM,SAAA,GAA8C;AAAA,EAClD,EAAA,EAAI,QAAA;AAAA,EACJ,EAAA,EAAI,QAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAMA,IAAM,WAAA,GAAgD;AAAA,EACpD,EAAA,EAAI,EAAA;AAAA,EACJ,EAAA,EAAI,EAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAMA,SAAS,cAAA,CACP,OACA,OAAA,EACQ;AACR,EAAA,MAAM,MAAA,GAGF;AAAA,IACF,OAAA,EAAS;AAAA,MACP,IAAA,EAAM,gDAAA;AAAA,MACN,SAAA,EAAW,gDAAA;AAAA,MACX,UAAA,EAAY,wCAAA;AAAA,MACZ,QAAA,EAAU,8DAAA;AAAA,MACV,KAAA,EAAO,oCAAA;AAAA,MACP,OAAA,EAAS;AAAA,KACX;AAAA,IACA,OAAA,EAAS;AAAA,MACP,IAAA,EAAM,wFAAA;AAAA,MACN,SAAA,EACE,wFAAA;AAAA,MACF,UAAA,EAAY,2DAAA;AAAA,MACZ,QAAA,EACE,iFAAA;AAAA,MACF,KAAA,EAAO,uDAAA;AAAA,MACP,OAAA,EAAS;AAAA,KACX;AAAA,IACA,KAAA,EAAO;AAAA,MACL,IAAA,EAAM,kCAAA;AAAA,MACN,SAAA,EAAW,kCAAA;AAAA,MACX,UAAA,EAAY,uCAAA;AAAA,MACZ,QAAA,EAAU,qDAAA;AAAA,MACV,KAAA,EAAO,kBAAA;AAAA,MACP,OAAA,EAAS;AAAA,KACX;AAAA,IACA,OAAA,EAAS;AAAA,MACP,IAAA,EAAM,oCAAA;AAAA,MACN,SAAA,EAAW,oCAAA;AAAA,MACX,UAAA,EAAY,0BAAA;AAAA,MACZ,QAAA,EAAU,6CAAA;AAAA,MACV,KAAA,EAAO,kBAAA;AAAA,MACP,OAAA,EAAS;AAAA;AACX,GACF;AAEA,EAAA,OAAO,MAAA,CAAO,OAAO,CAAA,CAAE,KAAK,CAAA;AAC9B;AAMA,SAAS,eAAe,OAAA,EAAyB;AAC/C,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,EAAE,CAAA;AACpC,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,EAAE,CAAA;AACpC,EAAA,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,IAAA,CAAK,UAAS,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA;AACpD;AA8CA,IAAM,YAAA,GAAqB,KAAA,CAAA,UAAA;AAAA,EACzB,CACE;AAAA,IACE,SAAA;AAAA,IACA,OAAA,GAAU,SAAA;AAAA,IACV,IAAA,GAAO,IAAA;AAAA,IACP,KAAA,EAAO,eAAA;AAAA,IACP,YAAA,GAAe,KAAA;AAAA,IACf,SAAA,GAAY,IAAA;AAAA,IACZ,QAAA;AAAA,IACA,YAAA,GAAe,KAAA;AAAA,IACf,QAAA;AAAA,IACA,aAAA;AAAA,IACA,kBAAA;AAAA,IACA,sBAAA,GAAyB,KAAA;AAAA,IACzB,mBAAA;AAAA,IACA,gBAAA;AAAA,IACA,gBAAA;AAAA,IACA,WAAA,GAAc,CAAA;AAAA,IACd,QAAA,GAAW,YAAA;AAAA,IACX,OAAA;AAAA,IACA,YAAA,EAAc,SAAA;AAAA,IACd,GAAG;AAAA,KAEL,GAAA,KACG;AAEH,IAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAC9B,eAA4B,MAAM,CAAA;AAC1C,IAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAU,eAAS,CAAC,CAAA;AAEhD,IAAA,MAAM,gBAAA,GAAyB,aAA6B,IAAI,CAAA;AAChE,IAAA,MAAM,SAAA,GAAkB,aAA2B,IAAI,CAAA;AACvD,IAAA,MAAM,SAAA,GAAkB,KAAA,CAAA,MAAA,CAAe,EAAE,CAAA;AACzC,IAAA,MAAM,QAAA,GAAiB,aAA2B,MAAS,CAAA;AAC3D,IAAA,MAAM,YAAA,GAAqB,aAAe,CAAC,CAAA;AAC3C,IAAA,MAAM,WAAA,GAAoB,KAAA,CAAA,MAAA,CAAyB,EAAE,CAAA;AAGrD,IAAA,MAAM,UAAA,GAAa,CAAC,QAAA,EAAsB,KAAA,KAAkB;AAC1D,MAAA,MAAM,EAAA,GAAK,WAAW,MAAM;AAC1B,QAAA,QAAA,EAAS;AAET,QAAA,WAAA,CAAY,UAAU,WAAA,CAAY,OAAA,CAAQ,OAAO,CAAC,CAAA,KAAM,MAAM,EAAE,CAAA;AAAA,MAClE,GAAG,KAAK,CAAA;AACR,MAAA,WAAA,CAAY,OAAA,CAAQ,KAAK,EAAE,CAAA;AAC3B,MAAA,OAAO,EAAA;AAAA,IACT,CAAA;AAEA,IAAA,MAAM,mBAAmB,MAAM;AAC7B,MAAA,WAAA,CAAY,OAAA,CAAQ,QAAQ,YAAY,CAAA;AACxC,MAAA,WAAA,CAAY,UAAU,EAAC;AAAA,IACzB,CAAA;AAGA,IAAA,MAAM,eAAe,eAAA,KAAoB,MAAA;AACzC,IAAA,MAAM,YAAA,GAAe,eAAe,eAAA,GAAkB,aAAA;AAItD,IAAA,MAAM,cAAA,GAAoC,QAAA,GACtC,UAAA,GACA,kBAAA,KAAuB,OAAA,GACrB,OAAA,GACA,kBAAA,KAAuB,cAAA,IACrB,kBAAA,KAAuB,WAAA,GACvB,YAAA,GACA,kBAAA,KAAuB,aACrB,SAAA,GACA,YAAA;AAGV,IAAM,gBAAU,MAAM;AAEpB,MAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AAGnC,MAAA,IACE,QAAA,KACE,eAAA,IAAmB,eAAA,KAAoB,UAAA,IACvC,kBAAA,CAAA,EACF;AACA,QAAA,OAAA,CAAQ,IAAA;AAAA,UACN;AAAA,SAEF;AAAA,MACF;AAGA,MAAA,IAAI,eAAA,KAAoB,MAAA,IAAa,kBAAA,KAAuB,MAAA,EAAW;AACrE,QAAA,MAAM,wBAAA,GACJ,kBAAA,KAAuB,OAAA,GACnB,OAAA,GACA,kBAAA,KAAuB,cAAA,IACrB,kBAAA,KAAuB,WAAA,GACvB,YAAA,GACA,kBAAA,KAAuB,UAAA,GACrB,SAAA,GACA,MAAA;AAEV,QAAA,IACE,wBAAA,KAA6B,MAAA,IAC7B,wBAAA,KAA6B,eAAA,EAC7B;AACA,UAAA,OAAA,CAAQ,IAAA;AAAA,YACN,CAAA,wFAAA,EACqB,eAAe,CAAA,0BAAA,EAA6B,kBAAkB,CAAA,6CAAA;AAAA,WAErF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAA,EAAG,CAAC,QAAA,EAAU,eAAA,EAAiB,kBAAkB,CAAC,CAAA;AAElD,IAAA,MAAM,QAAA,GAAW,UAAU,IAAI,CAAA;AAC/B,IAAA,MAAM,MAAA,GAAS,YAAY,IAAI,CAAA;AAC/B,IAAA,MAAM,cAAc,cAAA,KAAmB,WAAA;AACvC,IAAA,MAAM,UAAA,GACJ,cAAA,KAAmB,UAAA,IAAc,cAAA,KAAmB,YAAA;AAGtD,IAAM,gBAAU,MAAM;AACpB,MAAA,OAAO,MAAM;AACX,QAAA,IAAI,SAAS,OAAA,EAAS;AACpB,UAAA,aAAA,CAAc,SAAS,OAAO,CAAA;AAAA,QAChC;AACA,QAAA,gBAAA,EAAiB;AACjB,QAAA,IAAI,UAAU,OAAA,EAAS;AACrB,UAAA,SAAA,CAAU,OAAA,CAAQ,WAAU,CAAE,OAAA,CAAQ,CAAC,KAAA,KAAU,KAAA,CAAM,MAAM,CAAA;AAAA,QAC/D;AAAA,MACF,CAAA;AAAA,IACF,CAAA,EAAG,EAAE,CAAA;AAEL,IAAA,MAAM,aAAA,GAAsB,kBAAY,MAAM;AAC5C,MAAA,IAAI,SAAS,OAAA,EAAS;AACpB,QAAA,aAAA,CAAc,SAAS,OAAO,CAAA;AAAA,MAChC;AAEA,MAAA,IACE,gBAAA,CAAiB,OAAA,IACjB,gBAAA,CAAiB,OAAA,CAAQ,UAAU,UAAA,EACnC;AACA,QAAA,gBAAA,CAAiB,QAAQ,IAAA,EAAK;AAAA,MAChC;AAEA,MAAA,IAAI,UAAU,OAAA,EAAS;AACrB,QAAA,SAAA,CAAU,OAAA,CAAQ,WAAU,CAAE,OAAA,CAAQ,CAAC,KAAA,KAAU,KAAA,CAAM,MAAM,CAAA;AAAA,MAC/D;AAAA,IACF,CAAA,EAAG,EAAE,CAAA;AAEL,IAAA,MAAM,cAAA,GAAuB,kBAAY,YAAY;AAEnD,MAAA,IACE,QAAA,IACA,cAAA,KAAmB,WAAA,IACnB,cAAA,KAAmB,YAAA;AAEnB,QAAA;AAEF,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,GAAS,MAAM,SAAA,CAAU,YAAA,CAAa,YAAA,CAAa;AAAA,UACvD,KAAA,EAAO;AAAA,SACR,CAAA;AACD,QAAA,SAAA,CAAU,OAAA,GAAU,MAAA;AAEpB,QAAA,MAAM,OAAA,GAAU,EAAE,QAAA,EAAS;AAC3B,QAAA,IAAI,CAAC,aAAA,CAAc,eAAA,CAAgB,QAAQ,CAAA,EAAG;AAC5C,UAAA,gBAAA,CAAiB,OAAA,GAAU,IAAI,aAAA,CAAc,MAAM,CAAA;AAAA,QACrD,CAAA,MAAO;AACL,UAAA,gBAAA,CAAiB,OAAA,GAAU,IAAI,aAAA,CAAc,MAAA,EAAQ,OAAO,CAAA;AAAA,QAC9D;AAEA,QAAA,SAAA,CAAU,UAAU,EAAC;AAErB,QAAA,gBAAA,CAAiB,OAAA,CAAQ,eAAA,GAAkB,CAAC,CAAA,KAAM;AAChD,UAAA,IAAI,CAAA,CAAE,IAAA,CAAK,IAAA,GAAO,CAAA,EAAG;AACnB,YAAA,SAAA,CAAU,OAAA,CAAQ,IAAA,CAAK,CAAA,CAAE,IAAI,CAAA;AAAA,UAC/B;AAAA,QACF,CAAA;AAEA,QAAA,gBAAA,CAAiB,OAAA,CAAQ,SAAS,MAAM;AACtC,UAAA,IAAI,CAAC,YAAA,EAAc;AACjB,YAAA,gBAAA,CAAiB,YAAY,CAAA;AAAA,UAC/B;AAEA,UAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK,SAAA,CAAU,SAAS,EAAE,IAAA,EAAM,UAAU,CAAA;AAC3D,UAAA,MAAM,aAAA,GAAgB,QAAA;AAGtB,UAAA,UAAA,CAAW,MAAM;AACf,YAAA,mBAAA,GAAsB,MAAM,aAAa,CAAA;AACzC,YAAA,IAAI,CAAC,YAAA,EAAc;AACjB,cAAA,gBAAA,CAAiB,SAAS,CAAA;AAE1B,cAAA,UAAA,CAAW,MAAM;AACf,gBAAA,gBAAA,CAAiB,MAAM,CAAA;AAAA,cACzB,GAAG,IAAI,CAAA;AAAA,YACT;AACA,YAAA,WAAA,CAAY,CAAC,CAAA;AAAA,UACf,GAAG,GAAG,CAAA;AAAA,QACR,CAAA;AAEA,QAAA,gBAAA,CAAiB,OAAA,CAAQ,MAAM,GAAG,CAAA;AAClC,QAAA,YAAA,CAAa,OAAA,GAAU,KAAK,GAAA,EAAI;AAEhC,QAAA,IAAI,CAAC,YAAA,EAAc;AACjB,UAAA,gBAAA,CAAiB,WAAW,CAAA;AAAA,QAC9B;AACA,QAAA,gBAAA,IAAmB;AAEnB,QAAA,QAAA,CAAS,OAAA,GAAU,MAAA,CAAO,WAAA,CAAY,MAAM;AAC1C,UAAA,MAAM,OAAA,GAAA,CAAW,IAAA,CAAK,GAAA,EAAI,GAAI,aAAa,OAAA,IAAW,GAAA;AACtD,UAAA,WAAA,CAAY,OAAO,CAAA;AAEnB,UAAA,IAAI,WAAA,GAAc,CAAA,IAAK,OAAA,IAAW,WAAA,EAAa;AAC7C,YAAA,aAAA,EAAc;AAAA,UAChB;AAAA,QACF,GAAG,GAAG,CAAA;AAAA,MACR,SAAS,KAAA,EAAO;AACd,QAAA,gBAAA,GAAmB,KAAc,CAAA;AACjC,QAAA,IAAI,CAAC,YAAA,EAAc;AACjB,UAAA,gBAAA,CAAiB,OAAO,CAAA;AAExB,UAAA,UAAA,CAAW,MAAM;AACf,YAAA,gBAAA,CAAiB,MAAM,CAAA;AAAA,UACzB,GAAG,GAAI,CAAA;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAA,EAAG;AAAA,MACD,QAAA;AAAA,MACA,cAAA;AAAA,MACA,YAAA;AAAA,MACA,QAAA;AAAA,MACA,WAAA;AAAA,MACA,QAAA;AAAA,MACA,mBAAA;AAAA,MACA,gBAAA;AAAA,MACA,gBAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAA,MAAM,WAAA,GAAoB,KAAA,CAAA,WAAA;AAAA,MACxB,CAAC,CAAA,KAA2C;AAE1C,QAAA,OAAA,GAAU,CAAC,CAAA;AAGX,QAAA,IAAI,CAAC,YAAA,EAAc;AACjB,UAAA,IAAI,mBAAmB,WAAA,EAAa;AAClC,YAAA,aAAA,EAAc;AAAA,UAChB,CAAA,MAAA,IAAW,mBAAmB,MAAA,EAAQ;AACpC,YAAA,cAAA,EAAe;AAAA,UACjB;AAAA,QACF;AAAA,MACF,CAAA;AAAA,MACA,CAAC,OAAA,EAAS,YAAA,EAAc,cAAA,EAAgB,gBAAgB,aAAa;AAAA,KACvE;AAGA,IAAA,MAAM,aAAa,MAAM;AACvB,MAAA,QAAQ,cAAA;AAAgB,QACtB,KAAK,WAAA;AACH,UAAA,IAAI,YAAA,EAAc;AAChB,YAAA,uBAAO,GAAA,CAAC,gBAAa,IAAA,EAAY,CAAA;AAAA,UACnC;AACA,UAAA,OACE,iCAAiB,GAAA,CAAC,QAAA,EAAA,EAAS,SAAA,EAAW,QAAA,EAAU,MAAM,MAAA,EAAQ,CAAA;AAAA,QAElE,KAAK,YAAA;AACH,UAAA,uBAAO,GAAA,CAAC,cAAA,EAAA,EAAe,SAAA,EAAW,QAAA,EAAU,MAAM,MAAA,EAAQ,CAAA;AAAA,QAC5D,KAAK,UAAA;AAAA,QACL,KAAK,OAAA;AACH,UAAA,uBAAO,GAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAW,QAAA,EAAU,MAAM,MAAA,EAAQ,CAAA;AAAA,QACxD,KAAK,SAAA;AACH,UAAA,uBAAO,GAAA,CAAC,SAAA,EAAA,EAAU,SAAA,EAAW,QAAA,EAAU,MAAM,MAAA,EAAQ,CAAA;AAAA,QACvD;AACE,UAAA,OAAO,4BAAY,GAAA,CAAC,OAAA,EAAA,EAAQ,SAAA,EAAW,QAAA,EAAU,MAAM,MAAA,EAAQ,CAAA;AAAA;AACnE,IACF,CAAA;AAEA,IAAA,MAAM,eAAe,MAAM;AACzB,MAAA,QAAQ,cAAA;AAAgB,QACtB,KAAK,WAAA;AACH,UAAA,OAAO,gBAAA;AAAA,QACT,KAAK,YAAA;AACH,UAAA,OAAO,sBAAA;AAAA,QACT,KAAK,UAAA;AACH,UAAA,OAAO,uBAAA;AAAA,QACT,KAAK,OAAA;AACH,UAAA,OAAO,kBAAA;AAAA,QACT,KAAK,SAAA;AACH,UAAA,OAAO,oBAAA;AAAA,QACT;AACE,UAAA,OAAO,iBAAA;AAAA;AACX,IACF,CAAA;AAEA,IAAA,MAAM,wBAAwB,MAAM;AAClC,MAAA,IAAI,kBAAA,KAAuB,aAAa,OAAO,cAAA;AAC/C,MAAA,IAAI,kBAAA,KAAuB,gBAAgB,OAAO,iBAAA;AAClD,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAEA,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,WAAA,EAAU,eAAA;AAAA,QACV,SAAA,EAAU,yCAAA;AAAA,QAEV,QAAA,EAAA;AAAA,0BAAA,IAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cACC,GAAA;AAAA,cACA,IAAA,EAAK,QAAA;AAAA,cACL,QAAA,EAAU,UAAA;AAAA,cACV,OAAA,EAAS,WAAA;AAAA,cACR,GAAG,KAAA;AAAA,cACJ,WAAA,EAAU,uBAAA;AAAA,cACV,SAAA,EAAW,EAAA;AAAA,gBACT,oBAAA,CAAqB,EAAE,OAAA,EAAS,IAAA,EAAM,CAAA;AAAA,gBACtC,cAAA,CAAe,gBAAgB,OAAO,CAAA;AAAA,gBACtC;AAAA,eACF;AAAA,cACA,YAAA,EAAY,aAAa,YAAA,EAAa;AAAA,cACtC,cAAA,EAAc,cAAA,KAAmB,WAAA,GAAc,IAAA,GAAO,MAAA;AAAA,cACtD,WAAA,EAAW,cAAA,KAAmB,YAAA,GAAe,IAAA,GAAO,MAAA;AAAA,cAGnD,QAAA,EAAA;AAAA,gBAAA,cAAA,KAAmB,WAAA,IAAe,SAAA,oBACjC,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAkB,CAAA;AAAA,oCAI/B,MAAA,EAAA,EAAK,WAAA,EAAU,sBAAqB,SAAA,EAAU,eAAA,EAC5C,sBAAW,EACd;AAAA;AAAA;AAAA,WACF;AAAA,UAGC,gBAAgB,WAAA,oBACf,GAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,WAAA,EAAU,wBAAA;AAAA,cACV,SAAA,EAAU,iDAAA;AAAA,cAET,yBAAe,QAAQ;AAAA;AAAA,WAC1B;AAAA,UAID,sBAAA,IAA0B,uBAAsB,oBAC/C,GAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,WAAA,EAAU,6BAAA;AAAA,cACV,SAAA,EAAU,kCAAA;AAAA,cAET,QAAA,EAAA,qBAAA;AAAsB;AAAA;AACzB;AAAA;AAAA,KAEJ;AAAA,EAEJ;AACF;AAEA,YAAA,CAAa,WAAA,GAAc,cAAA","file":"chunk-MQOYDQTF.js","sourcesContent":["import * as React from 'react';\nimport { cva } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type RecordButtonState =\n | 'idle'\n | 'recording'\n | 'processing'\n | 'disabled'\n | 'error'\n | 'success';\n\nexport type RecordButtonVariant = 'default' | 'outline' | 'ghost' | 'minimal';\nexport type RecordButtonSize = 'sm' | 'md' | 'lg';\n\n/** Transcription state for integration with transcription services */\nexport type TranscriptionState =\n | 'idle'\n | 'recording'\n | 'transcribing'\n | 'streaming'\n | 'complete'\n | 'error';\n\nexport interface TranscriptionResult {\n /** The transcribed text */\n text: string;\n /** Whether this is a partial (streaming) or final result */\n isFinal: boolean;\n /** Confidence score (0-1) if available */\n confidence?: number;\n}\n\nexport interface RecordButtonProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'children'\n> {\n /** Current state of the button */\n state?: RecordButtonState;\n /** Size of the button */\n size?: RecordButtonSize;\n /** Visual style variant */\n variant?: RecordButtonVariant;\n /** Show waveform bars when recording (instead of stop icon) */\n showWaveform?: boolean;\n /** Show pulse rings when recording */\n showPulse?: boolean;\n /** Show recording duration while recording */\n showDuration?: boolean;\n /** Custom idle icon */\n idleIcon?: React.ReactNode;\n /** Custom recording icon */\n recordingIcon?: React.ReactNode;\n /** Current transcription state (for external control) */\n transcriptionState?: TranscriptionState;\n /** Show transcription state indicator */\n showTranscriptionState?: boolean;\n\n // Recording callbacks (for uncontrolled usage)\n /** Callback when recording is complete with the audio blob */\n onRecordingComplete?: (blob: Blob, duration: number) => void;\n /** Callback when recording starts */\n onRecordingStart?: () => void;\n /** Callback when a recording error occurs */\n onRecordingError?: (error: Error) => void;\n /** Maximum recording duration in seconds (0 for unlimited) */\n maxDuration?: number;\n /** Audio MIME type */\n mimeType?: string;\n}\n\n// ============================================================================\n// Icons\n// ============================================================================\n\nfunction MicIcon({\n className,\n size = 20,\n}: {\n className?: string;\n size?: number;\n}) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\" />\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" />\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\" />\n </svg>\n );\n}\n\nfunction MicOffIcon({\n className,\n size = 20,\n}: {\n className?: string;\n size?: number;\n}) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <line x1=\"2\" x2=\"22\" y1=\"2\" y2=\"22\" />\n <path d=\"M18.89 13.23A7.12 7.12 0 0 0 19 12v-2\" />\n <path d=\"M5 10v2a7 7 0 0 0 12 5\" />\n <path d=\"M15 9.34V5a3 3 0 0 0-5.68-1.33\" />\n <path d=\"M9 9v3a3 3 0 0 0 5.12 2.12\" />\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\" />\n </svg>\n );\n}\n\nfunction StopIcon({\n className,\n size = 20,\n}: {\n className?: string;\n size?: number;\n}) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill=\"currentColor\"\n className={className}\n aria-hidden=\"true\"\n >\n <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\" />\n </svg>\n );\n}\n\nfunction CheckIcon({\n className,\n size = 20,\n}: {\n className?: string;\n size?: number;\n}) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n );\n}\n\nfunction LoadingSpinner({\n className,\n size = 20,\n}: {\n className?: string;\n size?: number;\n}) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn('animate-spin', className)}\n aria-hidden=\"true\"\n >\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n );\n}\n\n// ============================================================================\n// Pulse Ring Animation (for recording state)\n// ============================================================================\n\nfunction PulseRings({ variant }: { variant: RecordButtonVariant }) {\n const ringColor = variant === 'minimal' ? 'bg-red-500/30' : 'bg-red-400/40';\n\n return (\n <>\n <span\n data-slot=\"record-button-pulse\"\n className={cn('absolute inset-0 animate-ping rounded-full', ringColor)}\n style={{ animationDuration: '1.5s' }}\n />\n <span\n data-slot=\"record-button-pulse\"\n className={cn('absolute inset-0 animate-ping rounded-full', ringColor)}\n style={{ animationDuration: '1.5s', animationDelay: '0.5s' }}\n />\n </>\n );\n}\n\n// ============================================================================\n// Waveform Animation (for recording state)\n// ============================================================================\n\nfunction WaveformBars({ size }: { size: RecordButtonSize }) {\n const barHeight = size === 'sm' ? 'h-2' : size === 'md' ? 'h-3' : 'h-4';\n // rem fallback (matching the Tailwind utility values: h-2/h-3/h-4) so the\n // bars still render if the consuming app's CSS build does not include these\n // size utilities. Using rem (not px) keeps scaling consistent with the\n // utilities and lets condensed `!important` overrides still win.\n const barHeightRem =\n size === 'sm' ? '0.5rem' : size === 'md' ? '0.75rem' : '1rem';\n\n return (\n <div\n data-slot=\"record-button-waveform\"\n className=\"flex items-center gap-0.5\"\n >\n {[0, 1, 2, 3, 4].map((i) => (\n <span\n key={i}\n className={cn(\n 'animate-waveform w-0.5 rounded-full bg-current',\n barHeight\n )}\n style={{\n width: '0.125rem',\n height: barHeightRem,\n animationDelay: `${i * 0.1}s`,\n }}\n />\n ))}\n </div>\n );\n}\n\n// ============================================================================\n// Style Variants\n// ============================================================================\n\nconst recordButtonVariants = cva(\n [\n 'relative inline-flex items-center justify-center rounded-full',\n 'transition-all duration-200',\n 'outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background',\n ],\n {\n variants: {\n variant: {\n default: '',\n outline: 'border-2',\n ghost: '',\n minimal: '',\n },\n size: {\n sm: 'size-10',\n md: 'size-12',\n lg: 'size-14',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'md',\n },\n }\n);\n\nconst iconSizes: Record<RecordButtonSize, string> = {\n sm: 'size-4',\n md: 'size-5',\n lg: 'size-6',\n};\n\n// Intrinsic px sizes mirroring `iconSizes`, applied as width/height attributes\n// so the icons render at the correct size even when a consuming app's CSS build\n// does not include the Tailwind size utilities (e.g. it only scans its own\n// source and not node_modules/@mieweb/ui).\nconst iconPxSizes: Record<RecordButtonSize, number> = {\n sm: 16,\n md: 20,\n lg: 24,\n};\n\n// ============================================================================\n// State Styles\n// ============================================================================\n\nfunction getStateStyles(\n state: RecordButtonState,\n variant: RecordButtonVariant\n): string {\n const styles: Record<\n RecordButtonVariant,\n Record<RecordButtonState, string>\n > = {\n default: {\n idle: 'bg-primary/10 text-primary hover:bg-primary/20',\n recording: 'bg-red-500/10 text-red-500 hover:bg-red-500/20',\n processing: 'bg-primary/10 text-primary cursor-wait',\n disabled: 'bg-muted text-muted-foreground cursor-not-allowed opacity-50',\n error: 'bg-destructive/10 text-destructive',\n success: 'bg-success/10 text-success',\n },\n outline: {\n idle: 'border-primary/50 text-primary bg-transparent hover:bg-primary/10 hover:border-primary',\n recording:\n 'border-red-500/50 text-red-500 bg-transparent hover:bg-red-500/10 hover:border-red-500',\n processing: 'border-primary/50 text-primary bg-transparent cursor-wait',\n disabled:\n 'border-muted text-muted-foreground bg-transparent cursor-not-allowed opacity-50',\n error: 'border-destructive/50 text-destructive bg-transparent',\n success: 'border-success/50 text-success bg-transparent',\n },\n ghost: {\n idle: 'text-primary hover:bg-primary/10',\n recording: 'text-red-500 hover:bg-red-500/10',\n processing: 'text-primary bg-primary/5 cursor-wait',\n disabled: 'text-muted-foreground cursor-not-allowed opacity-50',\n error: 'text-destructive',\n success: 'text-success',\n },\n minimal: {\n idle: 'text-primary hover:text-primary/80',\n recording: 'text-red-500 hover:text-red-500/80',\n processing: 'text-primary cursor-wait',\n disabled: 'text-muted-foreground/40 cursor-not-allowed',\n error: 'text-destructive',\n success: 'text-success',\n },\n };\n\n return styles[variant][state];\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\nfunction formatDuration(seconds: number): string {\n const mins = Math.floor(seconds / 60);\n const secs = Math.floor(seconds % 60);\n return `${mins}:${secs.toString().padStart(2, '0')}`;\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\n/**\n * A voice recording button with 6 states and 4 visual variants.\n * Supports pulse animations, waveform visualization, and transcription integration.\n *\n * ## Controlled vs Uncontrolled Mode\n *\n * **Uncontrolled mode** (default): The component manages its own recording state.\n * Use `onRecordingComplete`, `onRecordingStart`, and `onRecordingError` callbacks.\n *\n * **Controlled mode**: When the `state` prop is provided, the component becomes\n * controlled and you must manage state changes externally. Note: In controlled mode,\n * the internal MediaRecorder functionality is disabled - you must implement your own\n * recording logic.\n *\n * ## State Precedence\n *\n * When multiple state-controlling props are provided, they follow this precedence:\n * 1. `disabled` prop (highest priority)\n * 2. `transcriptionState` prop\n * 3. `state` prop\n * 4. Internal state (uncontrolled)\n *\n * @example\n * ```tsx\n * // Uncontrolled with recording callbacks\n * <RecordButton\n * onRecordingComplete={(blob, duration) => console.log('Recorded:', blob)}\n * onRecordingError={(error) => console.error('Recording failed:', error)}\n * />\n *\n * // Controlled state (requires external recording implementation)\n * <RecordButton state=\"idle\" onClick={handleClick} />\n *\n * // Different variants\n * <RecordButton variant=\"outline\" size=\"lg\" />\n *\n * // With waveform animation\n * <RecordButton state=\"recording\" showWaveform showPulse />\n * ```\n */\nconst RecordButton = React.forwardRef<HTMLButtonElement, RecordButtonProps>(\n (\n {\n className,\n variant = 'default',\n size = 'md',\n state: controlledState,\n showWaveform = false,\n showPulse = true,\n disabled,\n showDuration = false,\n idleIcon,\n recordingIcon,\n transcriptionState,\n showTranscriptionState = false,\n onRecordingComplete,\n onRecordingStart,\n onRecordingError,\n maxDuration = 0,\n mimeType = 'audio/webm',\n onClick,\n 'aria-label': ariaLabel,\n ...props\n },\n ref\n ) => {\n // Internal state for uncontrolled usage\n const [internalState, setInternalState] =\n React.useState<RecordButtonState>('idle');\n const [duration, setDuration] = React.useState(0);\n\n const mediaRecorderRef = React.useRef<MediaRecorder | null>(null);\n const streamRef = React.useRef<MediaStream | null>(null);\n const chunksRef = React.useRef<Blob[]>([]);\n const timerRef = React.useRef<number | undefined>(undefined);\n const startTimeRef = React.useRef<number>(0);\n const timeoutsRef = React.useRef<NodeJS.Timeout[]>([]);\n\n // Helper to track and manage timeouts\n const addTimeout = (callback: () => void, delay: number) => {\n const id = setTimeout(() => {\n callback();\n // Remove from tracking after execution\n timeoutsRef.current = timeoutsRef.current.filter((t) => t !== id);\n }, delay);\n timeoutsRef.current.push(id);\n return id;\n };\n\n const clearAllTimeouts = () => {\n timeoutsRef.current.forEach(clearTimeout);\n timeoutsRef.current = [];\n };\n\n // Use controlled state if provided, otherwise internal state\n const isControlled = controlledState !== undefined;\n const currentState = isControlled ? controlledState : internalState;\n\n // Map transcription state to button state if provided\n // Precedence: disabled prop → transcriptionState → state prop → internal state\n const effectiveState: RecordButtonState = disabled\n ? 'disabled'\n : transcriptionState === 'error'\n ? 'error'\n : transcriptionState === 'transcribing' ||\n transcriptionState === 'streaming'\n ? 'processing'\n : transcriptionState === 'complete'\n ? 'success'\n : currentState;\n\n // Dev mode warnings for conflicting states\n React.useEffect(() => {\n // Only warn in development\n if (typeof window === 'undefined') return;\n\n // Warn when disabled is true but other state props suggest a different visual state\n if (\n disabled &&\n ((controlledState && controlledState !== 'disabled') ||\n transcriptionState)\n ) {\n console.warn(\n '[RecordButton]: `disabled` prop takes precedence over both `state` and `transcriptionState`. ' +\n 'When `disabled` is true, the button will always appear disabled.'\n );\n }\n\n // Warn when both controlled state and transcriptionState are provided and conflict\n if (controlledState !== undefined && transcriptionState !== undefined) {\n const mappedTranscriptionState: RecordButtonState | undefined =\n transcriptionState === 'error'\n ? 'error'\n : transcriptionState === 'transcribing' ||\n transcriptionState === 'streaming'\n ? 'processing'\n : transcriptionState === 'complete'\n ? 'success'\n : undefined;\n\n if (\n mappedTranscriptionState !== undefined &&\n mappedTranscriptionState !== controlledState\n ) {\n console.warn(\n '[RecordButton]: `transcriptionState` takes precedence over `state`. ' +\n `Received state=\"${controlledState}\" and transcriptionState=\"${transcriptionState}\". ` +\n 'This may lead to unexpected visual states.'\n );\n }\n }\n }, [disabled, controlledState, transcriptionState]);\n\n const iconSize = iconSizes[size];\n const iconPx = iconPxSizes[size];\n const isRecording = effectiveState === 'recording';\n const isDisabled =\n effectiveState === 'disabled' || effectiveState === 'processing';\n\n // Cleanup on unmount\n React.useEffect(() => {\n return () => {\n if (timerRef.current) {\n clearInterval(timerRef.current);\n }\n clearAllTimeouts();\n if (streamRef.current) {\n streamRef.current.getTracks().forEach((track) => track.stop());\n }\n };\n }, []);\n\n const stopRecording = React.useCallback(() => {\n if (timerRef.current) {\n clearInterval(timerRef.current);\n }\n\n if (\n mediaRecorderRef.current &&\n mediaRecorderRef.current.state !== 'inactive'\n ) {\n mediaRecorderRef.current.stop();\n }\n\n if (streamRef.current) {\n streamRef.current.getTracks().forEach((track) => track.stop());\n }\n }, []);\n\n const startRecording = React.useCallback(async () => {\n // Guard: don't start if disabled, already recording, or processing\n if (\n disabled ||\n effectiveState === 'recording' ||\n effectiveState === 'processing'\n )\n return;\n\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: true,\n });\n streamRef.current = stream;\n\n const options = { mimeType };\n if (!MediaRecorder.isTypeSupported(mimeType)) {\n mediaRecorderRef.current = new MediaRecorder(stream);\n } else {\n mediaRecorderRef.current = new MediaRecorder(stream, options);\n }\n\n chunksRef.current = [];\n\n mediaRecorderRef.current.ondataavailable = (e) => {\n if (e.data.size > 0) {\n chunksRef.current.push(e.data);\n }\n };\n\n mediaRecorderRef.current.onstop = () => {\n if (!isControlled) {\n setInternalState('processing');\n }\n\n const blob = new Blob(chunksRef.current, { type: mimeType });\n const finalDuration = duration;\n\n // Small delay to show processing state\n addTimeout(() => {\n onRecordingComplete?.(blob, finalDuration);\n if (!isControlled) {\n setInternalState('success');\n // Reset to idle after showing success\n addTimeout(() => {\n setInternalState('idle');\n }, 1500);\n }\n setDuration(0);\n }, 200);\n };\n\n mediaRecorderRef.current.start(100);\n startTimeRef.current = Date.now();\n\n if (!isControlled) {\n setInternalState('recording');\n }\n onRecordingStart?.();\n\n timerRef.current = window.setInterval(() => {\n const elapsed = (Date.now() - startTimeRef.current) / 1000;\n setDuration(elapsed);\n\n if (maxDuration > 0 && elapsed >= maxDuration) {\n stopRecording();\n }\n }, 100);\n } catch (error) {\n onRecordingError?.(error as Error);\n if (!isControlled) {\n setInternalState('error');\n // Reset to idle after showing error\n addTimeout(() => {\n setInternalState('idle');\n }, 2000);\n }\n }\n }, [\n disabled,\n effectiveState,\n isControlled,\n mimeType,\n maxDuration,\n duration,\n onRecordingComplete,\n onRecordingStart,\n onRecordingError,\n stopRecording,\n ]);\n\n const handleClick = React.useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n // Call external onClick if provided\n onClick?.(e);\n\n // Handle internal recording logic only if not fully controlled\n if (!isControlled) {\n if (effectiveState === 'recording') {\n stopRecording();\n } else if (effectiveState === 'idle') {\n startRecording();\n }\n }\n },\n [onClick, isControlled, effectiveState, startRecording, stopRecording]\n );\n\n // Determine which icon to show\n const renderIcon = () => {\n switch (effectiveState) {\n case 'recording':\n if (showWaveform) {\n return <WaveformBars size={size} />;\n }\n return (\n recordingIcon || <StopIcon className={iconSize} size={iconPx} />\n );\n case 'processing':\n return <LoadingSpinner className={iconSize} size={iconPx} />;\n case 'disabled':\n case 'error':\n return <MicOffIcon className={iconSize} size={iconPx} />;\n case 'success':\n return <CheckIcon className={iconSize} size={iconPx} />;\n default:\n return idleIcon || <MicIcon className={iconSize} size={iconPx} />;\n }\n };\n\n const getAriaLabel = () => {\n switch (effectiveState) {\n case 'recording':\n return 'Stop recording';\n case 'processing':\n return 'Processing recording';\n case 'disabled':\n return 'Recording unavailable';\n case 'error':\n return 'Recording failed';\n case 'success':\n return 'Recording complete';\n default:\n return 'Start recording';\n }\n };\n\n const getTranscriptionLabel = () => {\n if (transcriptionState === 'streaming') return 'Listening...';\n if (transcriptionState === 'transcribing') return 'Transcribing...';\n return null;\n };\n\n return (\n <div\n data-slot=\"record-button\"\n className=\"relative inline-flex items-center gap-2\"\n >\n <button\n ref={ref}\n type=\"button\"\n disabled={isDisabled}\n onClick={handleClick}\n {...props}\n data-slot=\"record-button-trigger\"\n className={cn(\n recordButtonVariants({ variant, size }),\n getStateStyles(effectiveState, variant),\n className\n )}\n aria-label={ariaLabel ?? getAriaLabel()}\n aria-pressed={effectiveState === 'recording' ? true : undefined}\n aria-busy={effectiveState === 'processing' ? true : undefined}\n >\n {/* Pulse animation for recording state */}\n {effectiveState === 'recording' && showPulse && (\n <PulseRings variant={variant} />\n )}\n\n {/* Icon */}\n <span data-slot=\"record-button-icon\" className=\"relative z-10\">\n {renderIcon()}\n </span>\n </button>\n\n {/* Duration display */}\n {showDuration && isRecording && (\n <span\n data-slot=\"record-button-duration\"\n className=\"text-destructive font-mono text-xs tabular-nums\"\n >\n {formatDuration(duration)}\n </span>\n )}\n\n {/* Transcription state label */}\n {showTranscriptionState && getTranscriptionLabel() && (\n <span\n data-slot=\"record-button-transcription\"\n className=\"text-primary text-xs font-medium\"\n >\n {getTranscriptionLabel()}\n </span>\n )}\n </div>\n );\n }\n);\n\nRecordButton.displayName = 'RecordButton';\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport { RecordButton, recordButtonVariants, formatDuration };\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/AI/icons.tsx","../src/components/AI/CollapsiblePill.tsx","../src/components/AI/MCPToolCall.tsx","../src/components/AI/AIMessage.tsx","../src/components/ChatComposer/JumpToBottomButton.tsx"],"names":["jsxs","cn","jsx","React","cva","React2","AudioPlayer","ArrowDownIcon"],"mappings":"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","file":"chunk-O2EAHOXM.cjs","sourcesContent":["/**\n * AI Component Icons\n *\n * Shared icon components for AI features to follow DRY principles.\n */\n\nimport * as React from 'react';\nimport { cn } from '../../utils/cn';\n\n// ============================================================================\n// Sparkles Icon (Modern AI Symbol)\n// ============================================================================\n\nexport interface SparklesIconProps {\n className?: string;\n /** Size variant */\n size?: 'sm' | 'md' | 'lg';\n}\n\nconst sizeClasses = {\n sm: 'h-4 w-4',\n md: 'h-5 w-5',\n lg: 'h-7 w-7',\n};\n\n/**\n * Sparkles icon - the modern symbol for AI features\n * Used by ChatGPT, GitHub Copilot, Google Gemini, etc.\n */\nexport function SparklesIcon({ className, size = 'md' }: SparklesIconProps) {\n return (\n <svg\n aria-hidden=\"true\"\n className={cn(sizeClasses[size], className)}\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n >\n {/* Large sparkle */}\n <path d=\"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z\" />\n {/* Small sparkle */}\n <path\n d=\"M20 3v4\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n <path\n d=\"M22 5h-4\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n\n// ============================================================================\n// AI Logo Icon (Stack/Layers) - Legacy\n// ============================================================================\n\nexport interface AILogoIconProps {\n className?: string;\n /** Size variant */\n size?: 'sm' | 'md' | 'lg';\n}\n\n/**\n * The AI assistant logo - a stacked layers/prism icon\n * @deprecated Use SparklesIcon for a more recognizable AI symbol\n */\nexport function AILogoIcon({ className, size = 'md' }: AILogoIconProps) {\n return (\n <svg\n aria-hidden=\"true\"\n className={cn(sizeClasses[size], className)}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n >\n <path\n d=\"M12 2L2 7L12 12L22 7L12 2Z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n fill=\"currentColor\"\n fillOpacity=\"0.2\"\n />\n <path\n d=\"M2 17L12 22L22 17\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M2 12L12 17L22 12\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n\n// ============================================================================\n// Close Icon\n// ============================================================================\n\nexport interface CloseIconProps {\n className?: string;\n}\n\nexport function CloseIcon({ className }: CloseIconProps) {\n return (\n <svg\n aria-hidden=\"true\"\n className={cn('h-5 w-5', className)}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n );\n}\n\n// ============================================================================\n// Refresh/Clear Icon\n// ============================================================================\n\nexport interface RefreshIconProps {\n className?: string;\n}\n\nexport function RefreshIcon({ className }: RefreshIconProps) {\n return (\n <svg\n aria-hidden=\"true\"\n className={cn('h-5 w-5', className)}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99\"\n />\n </svg>\n );\n}\n\n// ============================================================================\n// Chevron Icon\n// ============================================================================\n\nexport interface ChevronIconProps {\n className?: string;\n direction?: 'up' | 'down' | 'left' | 'right';\n}\n\nconst chevronRotation = {\n up: '-rotate-180',\n down: '',\n left: 'rotate-90',\n right: '-rotate-90',\n};\n\nexport function ChevronIcon({\n className,\n direction = 'down',\n}: ChevronIconProps) {\n return (\n <svg\n aria-hidden=\"true\"\n className={cn('h-4 w-4', chevronRotation[direction], className)}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n );\n}\n\n// ============================================================================\n// Send Icon\n// ============================================================================\n\nexport interface SendIconProps {\n className?: string;\n}\n\nexport function SendIcon({ className }: SendIconProps) {\n return (\n <svg\n aria-hidden=\"true\"\n className={cn('h-5 w-5', className)}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 19l9 2-9-18-9 18 9-2zm0 0v-8\"\n />\n </svg>\n );\n}\n\n// ============================================================================\n// Spinner Icon\n// ============================================================================\n\nexport interface SpinnerIconProps {\n className?: string;\n}\n\nexport function SpinnerIcon({ className }: SpinnerIconProps) {\n return (\n <svg\n aria-hidden=\"true\"\n className={cn('h-5 w-5 animate-spin', className)}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"\n />\n </svg>\n );\n}\n","import * as React from 'react';\nimport { cn } from '../../utils/cn';\nimport { ChevronIcon } from './icons';\n\nexport interface CollapsiblePillProps {\n label: string;\n leadingIcon?: React.ReactNode;\n density?: 'standard' | 'condensed';\n defaultOpen?: boolean;\n pillClassName?: string;\n className?: string;\n /** Native tooltip shown on hover (e.g. \"Show details\") */\n title?: string;\n children?: React.ReactNode;\n}\n\nexport function CollapsiblePill({\n label,\n leadingIcon,\n density = 'standard',\n defaultOpen = false,\n pillClassName,\n className,\n title,\n children,\n}: CollapsiblePillProps) {\n const hasContent = Boolean(children);\n const [isOpen, setIsOpen] = React.useState(defaultOpen);\n const contentId = React.useId();\n\n React.useEffect(() => {\n setIsOpen(defaultOpen);\n }, [defaultOpen]);\n\n const toggle = () => {\n setIsOpen((open) => !open);\n };\n\n return (\n <div data-slot=\"collapsible-pill\" className={className}>\n <button\n type=\"button\"\n onClick={hasContent ? toggle : undefined}\n aria-expanded={hasContent ? isOpen : undefined}\n aria-controls={hasContent ? contentId : undefined}\n title={title}\n disabled={!hasContent}\n className={cn(\n 'focus-visible:ring-ring inline-flex items-center gap-1.5 border font-medium transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-1',\n density === 'condensed'\n ? 'rounded-[8px] px-2 py-0.5 text-[10px]'\n : 'rounded-[10px] px-[11px] py-1 text-[11px]',\n pillClassName\n )}\n >\n {leadingIcon}\n <span>{label}</span>\n {hasContent && (\n <ChevronIcon\n direction={isOpen ? 'down' : 'right'}\n className={\n density === 'condensed'\n ? 'h-2.5 w-2.5 opacity-60'\n : 'h-3 w-3 opacity-60'\n }\n />\n )}\n </button>\n {hasContent && (\n <div\n id={contentId}\n aria-hidden={!isOpen}\n inert={!isOpen || undefined}\n className={cn(\n 'overflow-hidden transition-[max-height,opacity] duration-300 ease-in-out',\n isOpen\n ? 'max-h-[500px] overflow-y-auto opacity-100'\n : 'max-h-0 opacity-0'\n )}\n >\n <div className=\"mt-1.5\">{children}</div>\n </div>\n )}\n </div>\n );\n}\n","/**\n * MCP Tool Call Display Component\n *\n * Renders an MCP tool invocation with status, parameters, and results.\n */\n\nimport * as React from 'react';\nimport { cva } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { CollapsiblePill } from './CollapsiblePill';\nimport type {\n MCPToolCall,\n MCPToolStatus,\n MCPToolResult,\n MCPResourceLink,\n MCPToolParameter,\n} from './types';\n\n// ============================================================================\n// Status Icon Component\n// ============================================================================\n\nconst statusIconVariants = cva(\n 'flex h-5 w-5 items-center justify-center rounded-full',\n {\n variants: {\n status: {\n pending: 'bg-neutral-200 dark:bg-neutral-700',\n running: 'bg-primary-100 dark:bg-primary-900/50',\n success: 'bg-green-100 dark:bg-green-900/50',\n error: 'bg-red-100 dark:bg-red-900/50',\n cancelled: 'bg-neutral-200 dark:bg-neutral-700',\n },\n },\n defaultVariants: {\n status: 'pending',\n },\n }\n);\n\ninterface ToolStatusIconProps {\n status: MCPToolStatus;\n className?: string;\n}\n\nfunction ToolStatusIcon({ status, className }: ToolStatusIconProps) {\n return (\n <span\n data-slot=\"ai-tool-status-icon\"\n className={cn(statusIconVariants({ status }), className)}\n >\n {status === 'pending' && (\n <svg\n aria-hidden=\"true\"\n className=\"h-3 w-3 text-neutral-500\"\n fill=\"currentColor\"\n viewBox=\"0 0 20 20\"\n >\n <circle cx=\"10\" cy=\"10\" r=\"3\" />\n </svg>\n )}\n {status === 'running' && (\n <svg\n aria-hidden=\"true\"\n className=\"text-primary-800 dark:text-primary-400 h-3 w-3 animate-spin\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n className=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n strokeWidth=\"4\"\n />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"\n />\n </svg>\n )}\n {status === 'success' && (\n <svg\n aria-hidden=\"true\"\n className=\"h-3 w-3 text-green-600 dark:text-green-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M5 13l4 4L19 7\"\n />\n </svg>\n )}\n {status === 'error' && (\n <svg\n aria-hidden=\"true\"\n className=\"h-3 w-3 text-red-600 dark:text-red-400\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n )}\n {status === 'cancelled' && (\n <svg\n aria-hidden=\"true\"\n className=\"h-3 w-3 text-neutral-500\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"3\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M18 12H6\" />\n </svg>\n )}\n </span>\n );\n}\n\n// ============================================================================\n// Tool Icon Component\n// ============================================================================\n\nconst TOOL_ICONS: Record<string, React.ReactNode> = {\n // Patient tools\n create_patient: (\n <svg\n aria-hidden=\"true\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M18 7.5v3m0 0v3m0-3h3m-3 0h-3m-2.25-4.125a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zM3 19.235v-.11a6.375 6.375 0 0112.75 0v.109A12.318 12.318 0 019.374 21c-2.331 0-4.512-.645-6.374-1.766z\"\n />\n </svg>\n ),\n get_patient: (\n <svg\n aria-hidden=\"true\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z\"\n />\n </svg>\n ),\n search_patients: (\n <svg\n aria-hidden=\"true\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z\"\n />\n </svg>\n ),\n // Appointment tools\n schedule_appointment: (\n <svg\n aria-hidden=\"true\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5m-9-6h.008v.008H12v-.008zM12 15h.008v.008H12V15zm0 2.25h.008v.008H12v-.008zM9.75 15h.008v.008H9.75V15zm0 2.25h.008v.008H9.75v-.008zM7.5 15h.008v.008H7.5V15zm0 2.25h.008v.008H7.5v-.008zm6.75-4.5h.008v.008h-.008v-.008zm0 2.25h.008v.008h-.008V15zm0 2.25h.008v.008h-.008v-.008zm2.25-4.5h.008v.008H16.5v-.008zm0 2.25h.008v.008H16.5V15z\"\n />\n </svg>\n ),\n // Document tools\n create_document: (\n <svg\n aria-hidden=\"true\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m3.75 9v6m3-3H9m1.5-12H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z\"\n />\n </svg>\n ),\n // Provider tools\n search_providers: (\n <svg\n aria-hidden=\"true\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M15 10.5a3 3 0 11-6 0 3 3 0 016 0z\"\n />\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M19.5 10.5c0 7.142-7.5 11.25-7.5 11.25S4.5 17.642 4.5 10.5a7.5 7.5 0 1115 0z\"\n />\n </svg>\n ),\n // Default tool icon\n default: (\n <svg\n aria-hidden=\"true\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M11.42 15.17L17.25 21A2.652 2.652 0 0021 17.25l-5.877-5.877M11.42 15.17l2.496-3.03c.317-.384.74-.626 1.208-.766M11.42 15.17l-4.655 5.653a2.548 2.548 0 11-3.586-3.586l6.837-5.63m5.108-.233c.55-.164 1.163-.188 1.743-.14a4.5 4.5 0 004.486-6.336l-3.276 3.277a3.004 3.004 0 01-2.25-2.25l3.276-3.276a4.5 4.5 0 00-6.336 4.486c.091 1.076-.071 2.264-.904 2.95l-.102.085m-1.745 1.437L5.909 7.5H4.5L2.25 3.75l1.5-1.5L7.5 4.5v1.409l4.26 4.26m-1.745 1.437l1.745-1.437m6.615 8.206L15.75 15.75M4.867 19.125h.008v.008h-.008v-.008z\"\n />\n </svg>\n ),\n};\n\nfunction getToolIcon(toolName: string): React.ReactNode {\n return TOOL_ICONS[toolName] || TOOL_ICONS.default;\n}\n\n// ============================================================================\n// Resource Link Component\n// ============================================================================\n\nexport interface ResourceLinkProps {\n link: MCPResourceLink;\n onClick?: (link: MCPResourceLink) => void;\n className?: string;\n}\n\nexport function ResourceLink({ link, onClick, className }: ResourceLinkProps) {\n const handleClick = (e: React.MouseEvent) => {\n if (onClick) {\n e.preventDefault();\n onClick(link);\n }\n };\n\n const linkTypeIcons: Record<string, React.ReactNode> = {\n patient: (\n <svg\n aria-hidden=\"true\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z\"\n />\n </svg>\n ),\n document: (\n <svg\n aria-hidden=\"true\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z\"\n />\n </svg>\n ),\n appointment: (\n <svg\n aria-hidden=\"true\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5\"\n />\n </svg>\n ),\n order: (\n <svg\n aria-hidden=\"true\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M9 12h3.75M9 15h3.75M9 18h3.75m3 .75H18a2.25 2.25 0 002.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 00-1.123-.08m-5.801 0c-.065.21-.1.433-.1.664 0 .414.336.75.75.75h4.5a.75.75 0 00.75-.75 2.25 2.25 0 00-.1-.664m-5.8 0A2.251 2.251 0 0113.5 2.25H15c1.012 0 1.867.668 2.15 1.586m-5.8 0c-.376.023-.75.05-1.124.08C9.095 4.01 8.25 4.973 8.25 6.108V8.25m0 0H4.875c-.621 0-1.125.504-1.125 1.125v11.25c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V9.375c0-.621-.504-1.125-1.125-1.125H8.25z\"\n />\n </svg>\n ),\n provider: (\n <svg\n aria-hidden=\"true\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M15 10.5a3 3 0 11-6 0 3 3 0 016 0z\"\n />\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M19.5 10.5c0 7.142-7.5 11.25-7.5 11.25S4.5 17.642 4.5 10.5a7.5 7.5 0 1115 0z\"\n />\n </svg>\n ),\n external: (\n <svg\n aria-hidden=\"true\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25\"\n />\n </svg>\n ),\n internal: (\n <svg\n aria-hidden=\"true\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M13.19 8.688a4.5 4.5 0 011.242 7.244l-4.5 4.5a4.5 4.5 0 01-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 00-6.364-6.364l-4.5 4.5a4.5 4.5 0 001.242 7.244\"\n />\n </svg>\n ),\n };\n\n const icon = link.type ? linkTypeIcons[link.type] : linkTypeIcons.internal;\n\n return (\n <a\n href={link.href}\n onClick={handleClick}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-md px-2.5 py-1.5',\n 'bg-primary-50 text-primary-900 hover:bg-primary-100',\n 'dark:bg-primary-900/30 dark:text-primary-300 dark:hover:bg-primary-900/50',\n 'text-sm font-medium transition-colors',\n 'focus:ring-primary-500 focus:ring-2 focus:ring-offset-2 focus:outline-none',\n 'dark:focus:ring-offset-neutral-900',\n className\n )}\n >\n {icon}\n <span>{link.label}</span>\n {link.type === 'external' && (\n <svg\n aria-hidden=\"true\"\n className=\"h-3 w-3 opacity-60\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M4.5 19.5l15-15m0 0H8.25m11.25 0v11.25\"\n />\n </svg>\n )}\n </a>\n );\n}\n\n// ============================================================================\n// Tool Result Component\n// ============================================================================\n\ninterface ToolResultDisplayProps {\n result: MCPToolResult;\n onLinkClick?: (link: MCPResourceLink) => void;\n className?: string;\n}\n\nfunction ToolResultDisplay({\n result,\n onLinkClick,\n className,\n}: ToolResultDisplayProps) {\n if (result.type === 'error') {\n return (\n <div\n className={cn(\n 'mt-2 rounded-md bg-red-50 p-3 dark:bg-red-900/20',\n className\n )}\n >\n <p className=\"text-sm text-red-700 dark:text-red-300\">\n {typeof result.data === 'string'\n ? String(result.data)\n : 'An error occurred'}\n </p>\n </div>\n );\n }\n\n return (\n <div className={cn('space-y-2', className)}>\n {result.summary && (\n <p className=\"text-sm text-neutral-700 dark:text-neutral-300\">\n {result.summary}\n </p>\n )}\n\n {result.link && <ResourceLink link={result.link} onClick={onLinkClick} />}\n\n {result.resources && result.resources.length > 0 && (\n <div className=\"flex flex-wrap gap-2\">\n {result.resources.map((resource) => (\n <ResourceLink\n key={resource.id}\n link={{\n href: resource.uri || '#',\n label: resource.name,\n type: resource.type as MCPResourceLink['type'],\n }}\n onClick={onLinkClick}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\n// ============================================================================\n// MCP Tool Call Component\n// ============================================================================\n\n// Human-readable tool names\nconst TOOL_FRIENDLY_NAMES: Record<string, string> = {\n create_patient: 'Creating patient',\n get_patient: 'Looking up patient',\n search_patients: 'Searching patients',\n update_patient: 'Updating patient',\n delete_patient: 'Removing patient',\n schedule_appointment: 'Scheduling appointment',\n cancel_appointment: 'Canceling appointment',\n update_appointment: 'Updating appointment',\n create_document: 'Creating document',\n upload_document: 'Uploading document',\n get_document: 'Retrieving document',\n search_documents: 'Searching documents',\n create_order: 'Creating order',\n send_message: 'Sending message',\n search: 'Searching',\n search_providers: 'Searching for providers',\n};\n\nfunction getToolFriendlyName(toolName: string, status: MCPToolStatus): string {\n const baseName = TOOL_FRIENDLY_NAMES[toolName] || toolName.replace(/_/g, ' ');\n\n // Adjust tense based on status\n if (status === 'success') {\n // Past tense approximation — check longer prefixes first to avoid\n // partial matches (e.g. \"Searching for\" before \"Searching\")\n if (baseName.startsWith('Creating'))\n return baseName.replace('Creating', 'Created');\n if (baseName.startsWith('Scheduling'))\n return baseName.replace('Scheduling', 'Scheduled');\n if (baseName.startsWith('Searching for'))\n return baseName.replace('Searching for', 'Found');\n if (baseName.startsWith('Searching'))\n return baseName.replace('Searching', 'Found');\n if (baseName.startsWith('Looking'))\n return baseName.replace('Looking', 'Found');\n if (baseName.startsWith('Updating'))\n return baseName.replace('Updating', 'Updated');\n if (baseName.startsWith('Removing'))\n return baseName.replace('Removing', 'Removed');\n if (baseName.startsWith('Canceling'))\n return baseName.replace('Canceling', 'Canceled');\n if (baseName.startsWith('Retrieving'))\n return baseName.replace('Retrieving', 'Retrieved');\n if (baseName.startsWith('Uploading'))\n return baseName.replace('Uploading', 'Uploaded');\n if (baseName.startsWith('Sending'))\n return baseName.replace('Sending', 'Sent');\n }\n return baseName;\n}\n\n// Generate a user-friendly summary from parameters\nfunction getParameterSummary(\n toolName: string,\n params: MCPToolParameter[]\n): string | null {\n const paramMap = Object.fromEntries(params.map((p) => [p.name, p.value]));\n\n // Patient creation\n if (\n toolName === 'create_patient' &&\n paramMap.firstName &&\n paramMap.lastName\n ) {\n return `${paramMap.firstName} ${paramMap.lastName}`;\n }\n\n // Search\n if (toolName.includes('search') && paramMap.query) {\n return `\"${paramMap.query}\"`;\n }\n\n // Appointment\n if (toolName.includes('appointment') && paramMap.patientName) {\n const date = paramMap.preferredDate || paramMap.date;\n return date\n ? `${paramMap.patientName} on ${date}`\n : String(paramMap.patientName);\n }\n\n // Provider search\n if (toolName === 'search_providers' && paramMap.zipcode) {\n const service = paramMap.service;\n return service\n ? `${service} near ${paramMap.zipcode}`\n : `near ${paramMap.zipcode}`;\n }\n\n return null;\n}\n\n// Pill header colors per status (Ozwell-style status pill)\nconst statusPillClasses: Record<MCPToolStatus, string> = {\n pending:\n 'bg-neutral-100 border-neutral-200 text-neutral-600 dark:bg-neutral-800 dark:border-neutral-700 dark:text-neutral-400',\n running:\n 'bg-primary-50 border-primary-200 text-primary-800 dark:bg-primary-900/20 dark:border-primary-800 dark:text-primary-300',\n success:\n 'bg-green-50 border-green-200 text-green-700 dark:bg-green-900/20 dark:border-green-800 dark:text-green-300',\n error:\n 'bg-red-50 border-red-200 text-red-700 dark:bg-red-900/20 dark:border-red-800 dark:text-red-300',\n cancelled:\n 'bg-neutral-100 border-neutral-200 text-neutral-400 opacity-60 dark:bg-neutral-800 dark:border-neutral-700 dark:text-neutral-400',\n};\n\nexport interface MCPToolCallDisplayProps {\n /** The tool call to display */\n toolCall: MCPToolCall;\n /** Compact (condensed) sizing — tighter pill and box */\n compact?: boolean;\n /** Whether to include raw parameters inside the detail box */\n showParameters?: boolean;\n /** Whether clicking the pill can expand/collapse the entire detail box */\n collapsible?: boolean;\n /** Default collapsed state. By default, completed tool calls start expanded. */\n defaultCollapsed?: boolean;\n /** Hide the whole tool-call display (mirrors Ozwell's debug flag) */\n hidden?: boolean;\n /** Callback when a resource link is clicked */\n onLinkClick?: (link: MCPResourceLink) => void;\n /** Additional class name */\n className?: string;\n}\n\n/**\n * Displays an MCP tool call with its status, parameters, and results.\n * Shows a user-friendly summary by default, with technical details available on expand.\n */\nexport function MCPToolCallDisplay({\n toolCall,\n showParameters = true,\n collapsible = true,\n defaultCollapsed,\n compact,\n hidden = false,\n onLinkClick,\n className,\n}: MCPToolCallDisplayProps) {\n const formatDuration = (ms?: number) => {\n if (!ms) return null;\n if (ms < 1000) return `${ms}ms`;\n return `${(ms / 1000).toFixed(1)}s`;\n };\n\n const friendlyName = getToolFriendlyName(toolCall.toolName, toolCall.status);\n const durationLabel = formatDuration(toolCall.duration);\n const paramSummary = getParameterSummary(\n toolCall.toolName,\n toolCall.parameters\n );\n\n // While running, show the input summary in the pill (e.g. \"Creating patient\n // · John Smith\"). On success the name already appears as the result link, so\n // show the duration instead to avoid duplication.\n const detailBit =\n toolCall.status === 'success'\n ? durationLabel\n : (paramSummary ?? durationLabel);\n const pillLabel = detailBit ? `${friendlyName} · ${detailBit}` : friendlyName;\n\n const hasParams = showParameters && toolCall.parameters.length > 0;\n const hasBoxContent = Boolean(toolCall.result || toolCall.error || hasParams);\n const isCompleted =\n toolCall.status === 'success' || toolCall.status === 'error';\n const effectiveDefaultCollapsed = defaultCollapsed ?? !isCompleted;\n\n if (hidden) return null;\n\n // Everything the pill reveals in one click: result, links, and raw params.\n const box = (\n <div\n className={cn(\n 'w-full max-w-md space-y-2 rounded-lg border border-neutral-200 bg-neutral-50 dark:border-neutral-700 dark:bg-neutral-800/50',\n compact ? 'p-2' : 'p-3'\n )}\n >\n {/* Result Summary & Links */}\n {toolCall.result && (\n <div data-slot=\"ai-tool-result\">\n <ToolResultDisplay\n result={toolCall.result}\n onLinkClick={onLinkClick}\n />\n </div>\n )}\n\n {/* Error */}\n {toolCall.error && (\n <div className=\"rounded-md bg-red-100 p-2 dark:bg-red-900/30\">\n <p className=\"text-sm text-red-700 dark:text-red-300\">\n {toolCall.error}\n </p>\n </div>\n )}\n\n {/* Raw parameters — revealed together with the box */}\n {hasParams && (\n <div\n data-slot=\"ai-tool-parameters\"\n className=\"rounded-md bg-neutral-100 p-2 dark:bg-neutral-800\"\n >\n <h4 className=\"mb-1.5 text-xs font-medium tracking-wide text-neutral-600 uppercase dark:text-neutral-400\">\n Parameters\n </h4>\n <div className=\"space-y-0.5\">\n {toolCall.parameters.map((param) => (\n <div key={param.name} className=\"flex items-start gap-2 text-xs\">\n <span className=\"font-mono text-neutral-600 dark:text-neutral-400\">\n {param.name}:\n </span>\n <span className=\"font-mono text-neutral-700 dark:text-neutral-300\">\n {typeof param.value === 'string'\n ? param.value\n : JSON.stringify(param.value)}\n </span>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n\n const staticPill = (\n <span\n data-slot=\"ai-tool-pill\"\n className={cn(\n 'inline-flex items-center gap-1.5 border font-medium',\n compact\n ? 'rounded-[8px] px-2 py-0.5 text-[10px]'\n : 'rounded-[10px] px-[11px] py-1 text-[11px]',\n statusPillClasses[toolCall.status]\n )}\n >\n <ToolStatusIcon status={toolCall.status} />\n <span>{pillLabel}</span>\n </span>\n );\n\n return (\n <div data-slot=\"ai-tool-call\" className={className}>\n {!hasBoxContent ? (\n staticPill\n ) : collapsible ? (\n // Pill click reveals the whole box (result + params) in one go.\n <CollapsiblePill\n label={pillLabel}\n leadingIcon={<ToolStatusIcon status={toolCall.status} />}\n density={compact ? 'condensed' : 'standard'}\n defaultOpen={!effectiveDefaultCollapsed}\n pillClassName={statusPillClasses[toolCall.status]}\n title=\"Toggle details\"\n >\n {box}\n </CollapsiblePill>\n ) : (\n // Non-collapsible: pill + box always visible.\n <div className=\"space-y-1.5\">\n {staticPill}\n {box}\n </div>\n )}\n </div>\n );\n}\n\nexport { ToolStatusIcon, getToolIcon };\n","/**\n * AI Message Component\n *\n * Renders AI chat messages with support for text, tool calls, and streaming.\n */\n\nimport * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport type {\n AIMessage,\n AIMessageContent,\n AIRenderMessageFooter,\n AIRenderTextContent,\n MCPResourceLink,\n} from './types';\nimport { MCPToolCallDisplay } from './MCPToolCall';\nimport { SparklesIcon } from './icons';\nimport { CollapsiblePill } from './CollapsiblePill';\nimport { AudioPlayer } from '../AudioPlayer';\n\n// ============================================================================\n// Avatar Component\n// ============================================================================\n\nconst avatarVariants = cva(\n 'flex shrink-0 items-center justify-center rounded-full',\n {\n variants: {\n role: {\n user: 'bg-primary-100 text-primary-900 dark:bg-primary-900/50 dark:text-primary-300',\n assistant: 'bg-primary-800 text-white dark:bg-primary-800',\n system:\n 'bg-neutral-200 text-neutral-600 dark:bg-neutral-700 dark:text-neutral-400',\n tool: 'bg-amber-100 text-amber-700 dark:bg-amber-900/50 dark:text-amber-300',\n },\n size: {\n sm: 'h-6 w-6 text-xs',\n md: 'h-8 w-8 text-sm',\n lg: 'h-10 w-10 text-base',\n },\n },\n defaultVariants: {\n role: 'user',\n size: 'md',\n },\n }\n);\n\ninterface MessageAvatarProps extends VariantProps<typeof avatarVariants> {\n userName?: string;\n className?: string;\n}\n\nfunction MessageAvatar({\n role,\n size,\n userName,\n className,\n}: MessageAvatarProps) {\n const getInitials = (name?: string) => {\n if (!name) return '?';\n return name\n .split(' ')\n .map((n) => n[0])\n .join('')\n .substring(0, 2)\n .toUpperCase();\n };\n\n return (\n <div\n data-slot=\"ai-message-avatar\"\n className={cn(avatarVariants({ role, size }), className)}\n >\n {role === 'assistant' ? (\n <SparklesIcon size=\"md\" />\n ) : role === 'user' ? (\n <span className=\"font-medium\">{getInitials(userName)}</span>\n ) : role === 'system' ? (\n <svg\n aria-hidden=\"true\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z\"\n />\n </svg>\n ) : (\n <svg\n aria-hidden=\"true\"\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M11.42 15.17L17.25 21A2.652 2.652 0 0021 17.25l-5.877-5.877M11.42 15.17l2.496-3.03c.317-.384.74-.626 1.208-.766M11.42 15.17l-4.655 5.653a2.548 2.548 0 11-3.586-3.586l6.837-5.63m5.108-.233c.55-.164 1.163-.188 1.743-.14a4.5 4.5 0 004.486-6.336l-3.276 3.277a3.004 3.004 0 01-2.25-2.25l3.276-3.276a4.5 4.5 0 00-6.336 4.486c.091 1.076-.071 2.264-.904 2.95l-.102.085m-1.745 1.437L5.909 7.5H4.5L2.25 3.75l1.5-1.5L7.5 4.5v1.409l4.26 4.26m-1.745 1.437l1.745-1.437m6.615 8.206L15.75 15.75M4.867 19.125h.008v.008h-.008v-.008z\"\n />\n </svg>\n )}\n </div>\n );\n}\n\n// ============================================================================\n// Typing Indicator\n// ============================================================================\n\nfunction AITypingIndicator({ className }: { className?: string }) {\n const dotStyle = {\n width: '6px',\n height: '6px',\n minWidth: '6px',\n minHeight: '6px',\n flexShrink: 0,\n };\n\n return (\n <div\n data-slot=\"ai-typing-indicator\"\n className={cn('inline-flex items-center justify-center gap-2', className)}\n >\n <span\n className=\"rounded-full bg-neutral-500 dark:bg-neutral-400\"\n style={{\n ...dotStyle,\n animation: 'typing-dot 1.4s infinite ease-in-out both',\n animationDelay: '-0.32s',\n }}\n />\n <span\n className=\"rounded-full bg-neutral-500 dark:bg-neutral-400\"\n style={{\n ...dotStyle,\n animation: 'typing-dot 1.4s infinite ease-in-out both',\n animationDelay: '-0.16s',\n }}\n />\n <span\n className=\"rounded-full bg-neutral-500 dark:bg-neutral-400\"\n style={{\n ...dotStyle,\n animation: 'typing-dot 1.4s infinite ease-in-out both',\n }}\n />\n <style>{`\n @keyframes typing-dot {\n 0%, 80%, 100% { opacity: 0.4; }\n 40% { opacity: 1; }\n }\n `}</style>\n </div>\n );\n}\n\n// ============================================================================\n// Thinking Block\n// ============================================================================\n\nfunction ThinkingBlock({\n text,\n streaming,\n defaultCollapsed = false,\n}: {\n text: string;\n streaming: boolean;\n defaultCollapsed?: boolean;\n}) {\n const startedAt = React.useRef(Date.now());\n const [elapsed, setElapsed] = React.useState<number | null>(null);\n // Set once on the streaming → done transition so the pill auto-collapses\n // when thinking finishes; the user can still re-expand it afterwards.\n const [autoCollapsed, setAutoCollapsed] = React.useState(false);\n const prevStreaming = React.useRef(streaming);\n\n React.useEffect(() => {\n if (prevStreaming.current && !streaming) {\n setElapsed(Math.round((Date.now() - startedAt.current) / 1000));\n setAutoCollapsed(true);\n } else if (!prevStreaming.current && streaming) {\n // Re-streaming in the same block: re-expand for the new thinking pass.\n startedAt.current = Date.now();\n setAutoCollapsed(false);\n }\n prevStreaming.current = streaming;\n }, [streaming]);\n\n const label = streaming\n ? 'Thinking'\n : elapsed !== null && elapsed > 0\n ? `Thought for ${elapsed}s`\n : 'Thought';\n\n const dot = streaming ? (\n <span\n aria-hidden=\"true\"\n className=\"inline-block h-1.5 w-1.5 animate-pulse rounded-full bg-violet-500 dark:bg-violet-400\"\n />\n ) : null;\n\n return (\n <div data-slot=\"ai-message-thinking\">\n <CollapsiblePill\n label={label}\n leadingIcon={dot}\n defaultOpen={!defaultCollapsed && !autoCollapsed}\n pillClassName=\"bg-violet-50 border-violet-200 text-violet-600 hover:bg-violet-100 dark:bg-violet-950/30 dark:border-violet-800 dark:text-violet-400 dark:hover:bg-violet-950/50 focus-visible:ring-violet-500\"\n >\n <div className=\"border-s-2 border-violet-200 ps-3 text-[13px] leading-relaxed text-neutral-600 italic dark:border-violet-700 dark:text-neutral-400\">\n {text}\n </div>\n </CollapsiblePill>\n </div>\n );\n}\n\n// ============================================================================\n// Content Block Renderer\n// ============================================================================\n\ninterface ContentBlockProps {\n content: AIMessageContent;\n onLinkClick?: (link: MCPResourceLink) => void;\n messageId: string;\n streaming: boolean;\n role: AIMessage['role'];\n renderTextContent?: AIRenderTextContent;\n}\n\nfunction ContentBlock({\n content,\n onLinkClick,\n messageId,\n streaming,\n role,\n renderTextContent,\n}: ContentBlockProps) {\n if (content.type === 'text' && content.text) {\n if (renderTextContent) {\n return (\n <div className=\"prose prose-sm dark:prose-invert max-w-none\">\n {renderTextContent(content.text, { messageId, streaming, role })}\n </div>\n );\n }\n return (\n <div className=\"prose prose-sm dark:prose-invert max-w-none\">\n <p className=\"whitespace-pre-wrap\">{content.text}</p>\n </div>\n );\n }\n\n if (content.type === 'tool_use' && content.toolCall) {\n return (\n <MCPToolCallDisplay\n toolCall={content.toolCall}\n onLinkClick={onLinkClick}\n defaultCollapsed={content.collapsed}\n />\n );\n }\n\n if (content.type === 'thinking' && content.text) {\n return (\n <ThinkingBlock\n text={content.text}\n streaming={streaming}\n defaultCollapsed={content.collapsed ?? false}\n />\n );\n }\n\n if (content.type === 'code' && content.text) {\n return (\n <pre\n data-slot=\"ai-message-code\"\n className=\"rounded-lg bg-neutral-900 p-3 text-sm dark:bg-neutral-950\"\n >\n <code\n className={content.language ? `language-${content.language}` : ''}\n >\n {content.text}\n </code>\n </pre>\n );\n }\n\n if (content.type === 'audio' && content.audioUrl) {\n // Guard against `javascript:` URLs, mirroring the image/file blocks.\n if (/^\\s*javascript:/i.test(content.audioUrl)) {\n return null;\n }\n return (\n <AudioPlayer\n src={content.audioUrl}\n title={content.text || 'Audio recording'}\n variant=\"waveform\"\n showTime\n showPlaybackRate\n fallbackDuration={content.duration}\n />\n );\n }\n\n if (content.type === 'video' && content.videoUrl) {\n // Guard against `javascript:` URLs, mirroring the audio/image/file blocks.\n if (/^\\s*javascript:/i.test(content.videoUrl)) {\n return null;\n }\n return (\n <video\n src={content.videoUrl}\n controls\n preload=\"metadata\"\n aria-label={content.text || 'Video recording'}\n className=\"my-1 max-h-80 w-full rounded-lg bg-black\"\n >\n {/* Recorded clips carry no caption track; present for a11y compliance. */}\n <track kind=\"captions\" />\n </video>\n );\n }\n\n if (content.type === 'image' && content.imageUrl) {\n const safeHref = /^\\s*javascript:/i.test(content.imageUrl)\n ? undefined\n : content.imageUrl;\n return (\n <a\n href={safeHref}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"block w-fit transition-transform hover:scale-[1.02]\"\n aria-label={`View ${content.name || 'Uploaded image'}`}\n >\n <img\n src={content.imageUrl}\n alt={content.name || 'Uploaded image'}\n loading=\"lazy\"\n className=\"my-1 max-h-64 w-auto rounded-lg object-cover\"\n />\n </a>\n );\n }\n\n if (content.type === 'file') {\n const sizeLabel =\n typeof content.fileSize === 'number'\n ? formatFileSize(content.fileSize)\n : undefined;\n const card = (\n <div className=\"my-1 flex items-center gap-3 rounded-lg bg-neutral-100 p-3 transition-colors dark:bg-neutral-800\">\n <div className=\"rounded-lg bg-neutral-200 p-2 dark:bg-neutral-700\">\n <svg\n aria-hidden=\"true\"\n className=\"h-6 w-6\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n strokeWidth={2}\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n d=\"M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z\"\n />\n </svg>\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium\">\n {content.name || 'Document'}\n </p>\n {sizeLabel && <p className=\"text-xs opacity-70\">{sizeLabel}</p>}\n </div>\n </div>\n );\n\n if (content.fileUrl) {\n const safeFileHref = /^\\s*javascript:/i.test(content.fileUrl)\n ? undefined\n : content.fileUrl;\n return (\n <a\n href={safeFileHref}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"block w-fit no-underline\"\n >\n {card}\n </a>\n );\n }\n return card;\n }\n\n return null;\n}\n\n/** Human-readable file size (e.g. \"1.2 MB\"). */\nfunction formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\n// ============================================================================\n// AI Message Component\n// ============================================================================\n\nconst messageVariants = cva('flex gap-3', {\n variants: {\n role: {\n user: 'flex-row-reverse',\n assistant: 'flex-row',\n system: 'flex-row justify-center',\n tool: 'flex-row',\n },\n },\n defaultVariants: {\n role: 'assistant',\n },\n});\n\nconst bubbleVariants = cva('rounded-2xl px-4 py-2.5 w-fit max-w-[85%]', {\n variants: {\n variant: {\n user: 'bg-primary-800 text-white dark:bg-primary-800',\n assistant:\n 'bg-neutral-100 text-neutral-900 dark:bg-neutral-800 dark:text-white',\n system:\n 'bg-neutral-100 text-neutral-600 dark:bg-neutral-800 dark:text-neutral-400 text-center text-sm max-w-[95%]',\n tool: 'bg-transparent p-0 max-w-full w-full',\n },\n },\n defaultVariants: {\n variant: 'assistant',\n },\n});\n\nexport interface ChatBubbleProps\n extends\n React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof bubbleVariants> {\n /** Show error styling (red border). */\n hasError?: boolean;\n /**\n * Optional inline-start border accent color. Used by multi-participant\n * surfaces (e.g. SuperChat) to tint a speaker's bubble; AI chat leaves it\n * unset.\n */\n accent?: string;\n}\n\n/**\n * The shared chat bubble shell. This is the single source of truth for how a\n * chat message bubble looks across the library (AI chat, SuperChat, etc.).\n * Presentational only — callers render their own content inside.\n */\nconst ChatBubble = React.forwardRef<HTMLDivElement, ChatBubbleProps>(\n (\n { className, variant, hasError, accent, style, children, ...props },\n ref\n ) => {\n return (\n <div\n ref={ref}\n data-slot=\"chat-bubble\"\n className={cn(\n bubbleVariants({ variant }),\n hasError && 'border border-red-300 dark:border-red-700',\n className\n )}\n style={\n accent\n ? { borderInlineStart: `3px solid ${accent}`, ...style }\n : style\n }\n {...props}\n >\n {children}\n </div>\n );\n }\n);\n\nChatBubble.displayName = 'ChatBubble';\n\nexport interface AIMessageDisplayProps {\n /** The message to display */\n message: AIMessage;\n /** User name for user messages */\n userName?: string;\n /** Whether to show the avatar. `tool` messages never show one. */\n showAvatar?: boolean;\n /** Whether to show timestamp */\n showTimestamp?: boolean;\n /** Callback when a resource link is clicked */\n onLinkClick?: (link: MCPResourceLink) => void;\n /**\n * Optional renderer for `text` content blocks (e.g. Markdown). Called per\n * text block with `{ messageId, streaming, role }`. Host must sanitize.\n */\n renderTextContent?: AIRenderTextContent;\n /**\n * Optional renderer for a per-message footer shown below the bubble (e.g.\n * message action controls). Aligned with the message (right for user, left\n * for assistant).\n */\n renderMessageFooter?: AIRenderMessageFooter;\n /** Additional class name */\n className?: string;\n}\n\n/**\n * Displays an AI chat message with support for text, tool calls, and streaming.\n */\nexport function AIMessageDisplay({\n message,\n userName,\n showAvatar = true,\n showTimestamp = false,\n onLinkClick,\n renderTextContent,\n renderMessageFooter,\n className,\n}: AIMessageDisplayProps) {\n const isStreaming = message.status === 'streaming';\n const hasContent = message.content.length > 0;\n const messageFooter = renderMessageFooter?.(message);\n\n const formatTime = (timestamp: Date | string) => {\n const date = new Date(timestamp);\n return date.toLocaleTimeString(undefined, {\n hour: 'numeric',\n minute: '2-digit',\n });\n };\n\n // Tool messages render just the tool call: no bubble and no avatar. They sit\n // between the assistant's own messages, so a per-call avatar only repeats\n // who is speaking and pushes the conversation out of view.\n if (message.role === 'tool') {\n return (\n <div\n data-slot=\"ai-message\"\n className={cn(messageVariants({ role: message.role }), className)}\n >\n <div className=\"min-w-0 flex-1 space-y-2\">\n {message.content.map((content, index) => (\n <ContentBlock\n key={index}\n content={content}\n onLinkClick={onLinkClick}\n messageId={message.id}\n streaming={isStreaming}\n role={message.role}\n renderTextContent={renderTextContent}\n />\n ))}\n </div>\n </div>\n );\n }\n\n return (\n <div\n data-slot=\"ai-message\"\n className={cn(messageVariants({ role: message.role }), className)}\n >\n {showAvatar && message.role !== 'system' && (\n <MessageAvatar role={message.role} userName={userName} />\n )}\n\n <div\n className={cn(\n 'flex min-w-0 flex-1 flex-col gap-1',\n message.role === 'user' && 'items-end'\n )}\n >\n <ChatBubble\n data-slot=\"ai-message-bubble\"\n variant={message.role}\n hasError={message.status === 'error'}\n >\n {hasContent ? (\n <div className=\"space-y-3\">\n {message.content.map((content, index) => (\n <ContentBlock\n key={index}\n content={content}\n onLinkClick={onLinkClick}\n messageId={message.id}\n streaming={isStreaming}\n role={message.role}\n renderTextContent={renderTextContent}\n />\n ))}\n </div>\n ) : isStreaming ? (\n <div className=\"flex items-center justify-center\">\n <AITypingIndicator />\n </div>\n ) : null}\n </ChatBubble>\n\n {messageFooter != null && messageFooter !== false && (\n <div data-slot=\"ai-message-footer\" className=\"w-fit max-w-[85%]\">\n {messageFooter}\n </div>\n )}\n\n {showTimestamp && (\n <span\n data-slot=\"ai-message-timestamp\"\n className=\"px-2 text-xs text-neutral-500\"\n >\n {formatTime(message.timestamp)}\n </span>\n )}\n\n {message.status === 'error' && (\n <span className=\"px-2 text-xs text-red-500\">\n {message.role === 'user' ? 'Failed to send' : 'An error occurred'}\n </span>\n )}\n </div>\n </div>\n );\n}\n\nexport { MessageAvatar, AITypingIndicator, ChatBubble, bubbleVariants };\n","/**\n * Jump-to-bottom — shared scroll-anchoring affordance for chat threads.\n *\n * Lives in the ChatComposer module (the shared chat infrastructure) so both\n * SuperChat and AIChat — and eventually Messaging — can use it without\n * reaching into another module's internals. Pairs with the\n * `useStickToBottom` hook (`src/hooks/useStickToBottom.ts`).\n */\n\nimport * as React from 'react';\nimport { ArrowDown as ArrowDownIcon } from 'lucide-react';\nimport { cn } from '../../utils/cn';\n\ninterface JumpToBottomButtonProps {\n /** Show the \"New messages\" hint — unseen messages arrived below. */\n hasNewMessages: boolean;\n onClick: () => void;\n /**\n * `data-slot` attribute — each chat surface keeps its own slot namespace\n * (e.g. `superchat-jump-to-bottom`, `ai-chat-jump-to-bottom`).\n */\n dataSlot: string;\n}\n\n/**\n * Floating control shown over the thread whenever the user has scrolled up:\n * more content exists below (possibly still streaming in), and activating the\n * button returns to the newest message and resumes bottom-pinning. Absolutely\n * positioned within the thread viewport wrapper — never `fixed`, so it stays\n * inside embedded layouts.\n */\nexport function JumpToBottomButton({\n hasNewMessages,\n onClick,\n dataSlot,\n}: JumpToBottomButtonProps) {\n return (\n <button\n type=\"button\"\n data-slot={dataSlot}\n onClick={onClick}\n aria-label={\n hasNewMessages ? 'New messages — scroll to bottom' : 'Scroll to bottom'\n }\n className={cn(\n 'absolute bottom-3 left-1/2 z-20 -translate-x-1/2',\n 'flex items-center gap-1.5 rounded-full border border-neutral-200 bg-white p-2 text-xs font-medium text-neutral-600 shadow-lg',\n 'hover:bg-neutral-50 hover:text-neutral-800',\n 'focus-visible:ring-primary-500 focus:outline-none focus-visible:ring-2',\n 'dark:border-neutral-700 dark:bg-neutral-800 dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-100',\n hasNewMessages && 'ps-3'\n )}\n >\n {hasNewMessages && <span>New messages</span>}\n <ArrowDownIcon size={16} aria-hidden=\"true\" />\n </button>\n );\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/AI/voiceprintStore.ts"],"names":[],"mappings":";;;AAaA,IAAM,OAAA,GAAU,cAAA;AAChB,IAAM,KAAA,GAAQ,aAAA;AACd,IAAM,UAAA,GAAa,CAAA;AAEZ,SAAS,oBAAA,CAAqB,KAAa,SAAA,EAA4B;AAC5E,EAAA,IAAI,SAAA,KAAc,QAAW,OAAO,GAAA;AAGpC,EAAA,MAAM,EAAA,GAAK,UAAU,IAAA,EAAK;AAC1B,EAAA,IAAI,GAAG,MAAA,KAAW,CAAA;AAChB,IAAA,MAAM,IAAI,MAAM,wCAAwC,CAAA;AAC1D,EAAA,OAAO,CAAA,EAAG,GAAG,CAAA,CAAA,EAAI,kBAAA,CAAmB,EAAE,CAAC,CAAA,CAAA;AACzC;AAEA,SAAS,MAAA,GAA+B;AACtC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,IAAA,MAAM,GAAA,GAAM,SAAA,CAAU,IAAA,CAAK,OAAA,EAAS,UAAU,CAAA;AAC9C,IAAA,GAAA,CAAI,kBAAkB,MAAM;AAC1B,MAAA,IAAI,CAAC,GAAA,CAAI,MAAA,CAAO,gBAAA,CAAiB,SAAS,KAAK,CAAA;AAC7C,QAAA,GAAA,CAAI,MAAA,CAAO,kBAAkB,KAAK,CAAA;AAAA,IACtC,CAAA;AACA,IAAA,GAAA,CAAI,SAAA,GAAY,MAAM,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA;AACxC,IAAA,GAAA,CAAI,OAAA,GAAU,MAAM,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA;AAGpC,IAAA,GAAA,CAAI,YAAY,MACd,MAAA;AAAA,MACE,IAAI,MAAM,4DAA4D;AAAA,KACxE;AAAA,EACJ,CAAC,CAAA;AACH;AAEA,SAAS,OAAU,GAAA,EAAqC;AACtD,EAAA,OAAO,QAAO,CAAE,IAAA;AAAA,IACd,CAAC,EAAA,KACC,IAAI,OAAA,CAAuB,CAAC,SAAS,MAAA,KAAW;AAC9C,MAAA,MAAM,GAAA,GAAM,EAAA,CACT,WAAA,CAAY,KAAA,EAAO,UAAU,EAC7B,WAAA,CAAY,KAAK,CAAA,CACjB,GAAA,CAAI,GAAG,CAAA;AACV,MAAA,GAAA,CAAI,YAAY,MAAM;AACpB,QAAA,OAAA,CAAQ,IAAI,MAAuB,CAAA;AACnC,QAAA,EAAA,CAAG,KAAA,EAAM;AAAA,MACX,CAAA;AACA,MAAA,GAAA,CAAI,UAAU,MAAM;AAClB,QAAA,MAAA,CAAO,IAAI,KAAK,CAAA;AAChB,QAAA,EAAA,CAAG,KAAA,EAAM;AAAA,MACX,CAAA;AAAA,IACF,CAAC;AAAA,GACL;AACF;AAEA,SAAS,MAAA,CAAO,KAAa,KAAA,EAA+B;AAC1D,EAAA,OAAO,QAAO,CAAE,IAAA;AAAA,IACd,CAAC,EAAA,KACC,IAAI,OAAA,CAAc,CAAC,SAAS,MAAA,KAAW;AACrC,MAAA,MAAM,EAAA,GAAK,EAAA,CAAG,WAAA,CAAY,KAAA,EAAO,WAAW,CAAA;AAC5C,MAAA,EAAA,CAAG,WAAA,CAAY,KAAK,CAAA,CAAE,GAAA,CAAI,OAAO,GAAG,CAAA;AACpC,MAAA,EAAA,CAAG,aAAa,MAAM;AACpB,QAAA,OAAA,EAAQ;AACR,QAAA,EAAA,CAAG,KAAA,EAAM;AAAA,MACX,CAAA;AACA,MAAA,EAAA,CAAG,UAAU,MAAM;AACjB,QAAA,MAAA,CAAO,GAAG,KAAK,CAAA;AACf,QAAA,EAAA,CAAG,KAAA,EAAM;AAAA,MACX,CAAA;AACA,MAAA,EAAA,CAAG,UAAU,MAAM;AACjB,QAAA,MAAA,CAAO,GAAG,KAAK,CAAA;AACf,QAAA,EAAA,CAAG,KAAA,EAAM;AAAA,MACX,CAAA;AAAA,IACF,CAAC;AAAA,GACL;AACF;AAEA,SAAS,OAAO,GAAA,EAA4B;AAC1C,EAAA,OAAO,QAAO,CAAE,IAAA;AAAA,IACd,CAAC,EAAA,KACC,IAAI,OAAA,CAAc,CAAC,SAAS,MAAA,KAAW;AACrC,MAAA,MAAM,EAAA,GAAK,EAAA,CAAG,WAAA,CAAY,KAAA,EAAO,WAAW,CAAA;AAC5C,MAAA,EAAA,CAAG,WAAA,CAAY,KAAK,CAAA,CAAE,MAAA,CAAO,GAAG,CAAA;AAChC,MAAA,EAAA,CAAG,aAAa,MAAM;AACpB,QAAA,OAAA,EAAQ;AACR,QAAA,EAAA,CAAG,KAAA,EAAM;AAAA,MACX,CAAA;AACA,MAAA,EAAA,CAAG,UAAU,MAAM;AACjB,QAAA,MAAA,CAAO,GAAG,KAAK,CAAA;AACf,QAAA,EAAA,CAAG,KAAA,EAAM;AAAA,MACX,CAAA;AACA,MAAA,EAAA,CAAG,UAAU,MAAM;AACjB,QAAA,MAAA,CAAO,GAAG,KAAK,CAAA;AACf,QAAA,EAAA,CAAG,KAAA,EAAM;AAAA,MACX,CAAA;AAAA,IACF,CAAC;AAAA,GACL;AACF;AAOA,eAAsB,cAAA,CACpB,KACA,aAAA,EACwB;AACxB,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAW,MAAM,MAAA,CAAU,GAAG,CAAA;AACpC,IAAA,IAAI,QAAA,KAAa,QAAW,OAAO,QAAA;AACnC,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,IAAI,GAAA,GAAqB,IAAA;AACzB,MAAA,IAAI;AACF,QAAA,GAAA,GAAM,YAAA,CAAa,QAAQ,GAAG,CAAA;AAAA,MAChC,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA,IAAI,OAAO,IAAA,EAAM;AACf,QAAA,IAAI,QAAA;AACJ,QAAA,IAAI;AACF,UAAA,QAAA,GAAW,cAAc,GAAG,CAAA;AAAA,QAC9B,CAAA,CAAA,MAAQ;AAEN,UAAA,IAAI;AACF,YAAA,YAAA,CAAa,WAAW,GAAG,CAAA;AAAA,UAC7B,CAAA,CAAA,MAAQ;AAAA,UAER;AACA,UAAA,OAAO,KAAA,CAAA;AAAA,QACT;AACA,QAAA,IAAI;AACF,UAAA,MAAM,MAAA,CAAO,KAAK,QAAQ,CAAA;AAAA,QAC5B,CAAA,CAAA,MAAQ;AAAA,QAER;AACA,QAAA,IAAI;AACF,UAAA,YAAA,CAAa,WAAW,GAAG,CAAA;AAAA,QAC7B,CAAA,CAAA,MAAQ;AAAA,QAER;AACA,QAAA,OAAO,QAAA;AAAA,MACT;AAAA,IACF;AACA,IAAA,OAAO,KAAA,CAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAGA,eAAsB,cAAA,CACpB,KACA,KAAA,EACe;AACf,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,EACzB,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAGA,eAAsB,iBAAiB,GAAA,EAA4B;AACjE,EAAA,IAAI;AACF,IAAA,MAAM,OAAO,GAAG,CAAA;AAAA,EAClB,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,IAAI;AACF,IAAA,YAAA,CAAa,WAAW,GAAG,CAAA;AAAA,EAC7B,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAIA,IAAM,QAAA,GAAW,kBAAA;AAIjB,SAAS,gBAAgB,GAAA,EAA6C;AACpE,EAAA,IAAI,CAAA;AACJ,EAAA,IAAI;AACF,IAAA,CAAA,GAAK,IAAA,CAAK,KAAA,CAAM,GAAA,IAAO,IAAI,KAAK,EAAC;AAAA,EACnC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,GAAA,mBAAsC,MAAA,CAAO,MAAA,CAAO,IAAI,CAAA;AAC9D,EAAA,KAAA,MAAW,CAAA,IAAK,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA;AAC3B,IAAA,GAAA,CAAI,CAAC,CAAA,GAAA,CAAK,CAAA,CAAE,CAAC,CAAA,IAAK,EAAC,EAAG,GAAA,CAAI,CAAC,CAAA,KAAM,YAAA,CAAa,IAAA,CAAK,CAAC,CAAC,CAAA;AACvD,EAAA,OAAO,GAAA;AACT;AAEO,SAAS,eACd,SAAA,EACyC;AACzC,EAAA,OAAO,cAAA;AAAA,IACL,oBAAA,CAAqB,UAAU,SAAS,CAAA;AAAA,IACxC,SAAA,KAAc,SAAY,eAAA,GAAkB,KAAA;AAAA,IAC5C,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,IAAK,EAAE,CAAA;AACvB;AAEO,SAAS,cAAA,CACd,KACA,SAAA,EACe;AACf,EAAA,OAAO,cAAA,CAAe,oBAAA,CAAqB,QAAA,EAAU,SAAS,GAAG,GAAG,CAAA;AACtE;AAEO,SAAS,gBAAgB,SAAA,EAAmC;AACjE,EAAA,OAAO,gBAAA,CAAiB,oBAAA,CAAqB,QAAA,EAAU,SAAS,CAAC,CAAA;AACnE","file":"chunk-OGNADPM4.cjs","sourcesContent":["/**\n * IndexedDB store for on-device voiceprints (enrollment vectors), replacing localStorage for this data.\n *\n * Why IndexedDB and not localStorage: it's asynchronous (off the main thread), stores `Float32Array`\n * natively via structured clone (no JSON-stringifying embeddings into bloated number arrays), and isn't\n * capped at ~5 MB. Why not OPFS: these are small *structured records* keyed by id, not large files —\n * IndexedDB is the right tool; OPFS is for the big model files.\n *\n * One object store, keyed by a string id; values are any structured-cloneable object, so `Float32Array`s\n * survive the round-trip intact. On first read of a key it migrates a legacy localStorage value (if a\n * parser is supplied) and then clears it.\n */\n\nconst DB_NAME = 'ozwell-voice';\nconst STORE = 'voiceprints';\nconst DB_VERSION = 1;\n\nexport function voiceprintStorageKey(key: string, namespace?: string): string {\n if (namespace === undefined) return key;\n // Trim before encoding so accidental whitespace (\"user-a \" vs \"user-a\") can't silently split a\n // user's voiceprints across distinct stores.\n const ns = namespace.trim();\n if (ns.length === 0)\n throw new Error('Voiceprint namespace must not be empty');\n return `${key}:${encodeURIComponent(ns)}`;\n}\n\nfunction openDb(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const req = indexedDB.open(DB_NAME, DB_VERSION);\n req.onupgradeneeded = () => {\n if (!req.result.objectStoreNames.contains(STORE))\n req.result.createObjectStore(STORE);\n };\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n // If another tab holds an open connection during a version upgrade, the open stays \"blocked\" and\n // would otherwise hang forever — surface it instead so callers hit their catch/fallback paths.\n req.onblocked = () =>\n reject(\n new Error('IndexedDB open blocked (another tab holds an upgrade lock)')\n );\n });\n}\n\nfunction idbGet<T>(key: string): Promise<T | undefined> {\n return openDb().then(\n (db) =>\n new Promise<T | undefined>((resolve, reject) => {\n const req = db\n .transaction(STORE, 'readonly')\n .objectStore(STORE)\n .get(key);\n req.onsuccess = () => {\n resolve(req.result as T | undefined);\n db.close();\n };\n req.onerror = () => {\n reject(req.error);\n db.close();\n };\n })\n );\n}\n\nfunction idbSet(key: string, value: unknown): Promise<void> {\n return openDb().then(\n (db) =>\n new Promise<void>((resolve, reject) => {\n const tx = db.transaction(STORE, 'readwrite');\n tx.objectStore(STORE).put(value, key);\n tx.oncomplete = () => {\n resolve();\n db.close();\n };\n tx.onerror = () => {\n reject(tx.error);\n db.close();\n };\n tx.onabort = () => {\n reject(tx.error);\n db.close();\n }; // else an aborted tx leaves the promise pending\n })\n );\n}\n\nfunction idbDel(key: string): Promise<void> {\n return openDb().then(\n (db) =>\n new Promise<void>((resolve, reject) => {\n const tx = db.transaction(STORE, 'readwrite');\n tx.objectStore(STORE).delete(key);\n tx.oncomplete = () => {\n resolve();\n db.close();\n };\n tx.onerror = () => {\n reject(tx.error);\n db.close();\n };\n tx.onabort = () => {\n reject(tx.error);\n db.close();\n }; // else an aborted tx leaves the promise pending\n })\n );\n}\n\n/**\n * Read a voiceprint record. If IndexedDB has nothing for `key` but localStorage does, migrate it via\n * `migrateLegacy` (parse the old JSON string → the new shape), persist it to IndexedDB, and clear the\n * localStorage copy. Returns `undefined` if neither has it. Never throws (best-effort storage).\n */\nexport async function getVoiceprints<T>(\n key: string,\n migrateLegacy?: (raw: string) => T\n): Promise<T | undefined> {\n try {\n const existing = await idbGet<T>(key);\n if (existing !== undefined) return existing;\n if (migrateLegacy) {\n let raw: string | null = null;\n try {\n raw = localStorage.getItem(key);\n } catch {\n /* ignore */\n }\n if (raw != null) {\n let migrated: T;\n try {\n migrated = migrateLegacy(raw);\n } catch {\n // Corrupt legacy value — drop it so we don't retry the failing migration on every load.\n try {\n localStorage.removeItem(key);\n } catch {\n /* ignore */\n }\n return undefined;\n }\n try {\n await idbSet(key, migrated);\n } catch {\n /* persist is best-effort; still return the migrated value */\n }\n try {\n localStorage.removeItem(key);\n } catch {\n /* ignore */\n }\n return migrated;\n }\n }\n return undefined;\n } catch {\n return undefined;\n }\n}\n\n/** Persist a voiceprint record (Float32Arrays stored natively). Best-effort — resolves even on failure. */\nexport async function setVoiceprints(\n key: string,\n value: unknown\n): Promise<void> {\n try {\n await idbSet(key, value);\n } catch {\n /* best-effort */\n }\n}\n\n/** Remove a voiceprint record (and any stale localStorage copy). */\nexport async function clearVoiceprints(key: string): Promise<void> {\n try {\n await idbDel(key);\n } catch {\n /* ignore */\n }\n try {\n localStorage.removeItem(key);\n } catch {\n /* ignore */\n }\n}\n\n// --- WHAT phrase-prints: per-phrase wake-embedding templates (the WHAT gate). Previously each story kept\n// its own copy of these load/save helpers against localStorage; centralized here on IndexedDB. ---\nconst WHAT_KEY = 'ozwellWhatPrints';\n\n// Legacy localStorage format: JSON `{ phrase: number[][] }`. New IndexedDB format stores Float32Array[]\n// natively, so migration just rehydrates the number arrays once.\nfunction parseLegacyWhat(raw: string): Record<string, Float32Array[]> {\n let o: Record<string, number[][]>;\n try {\n o = (JSON.parse(raw || '{}') || {}) as Record<string, number[][]>;\n } catch {\n return {};\n }\n // Null-prototype output + Object.keys so a legacy `__proto__` key can't pollute Object.prototype.\n const out: Record<string, Float32Array[]> = Object.create(null);\n for (const k of Object.keys(o))\n out[k] = (o[k] || []).map((a) => Float32Array.from(a));\n return out;\n}\n\nexport function loadWhatPrints(\n namespace?: string\n): Promise<Record<string, Float32Array[]>> {\n return getVoiceprints<Record<string, Float32Array[]>>(\n voiceprintStorageKey(WHAT_KEY, namespace),\n namespace === undefined ? parseLegacyWhat : undefined\n ).then((v) => v ?? {});\n}\n\nexport function saveWhatPrints(\n map: Record<string, Float32Array[]>,\n namespace?: string\n): Promise<void> {\n return setVoiceprints(voiceprintStorageKey(WHAT_KEY, namespace), map);\n}\n\nexport function clearWhatPrints(namespace?: string): Promise<void> {\n return clearVoiceprints(voiceprintStorageKey(WHAT_KEY, namespace));\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/AI/modelCache.ts","../src/components/AI/ozwellChat.ts","../src/components/AI/whisperTranscribe.ts"],"names":["o"],"mappings":"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","file":"chunk-TRZLN32I.cjs","sourcesContent":["/**\n * Registers the model-cache service worker. In this repo the SW file lives at\n * `.storybook/public/ozwell-model-sw.js` and is served at `/ozwell-model-sw.js` by Storybook only — a\n * consumer that wants caching outside Storybook must serve/copy the SW at the `swUrl` path passed below.\n *\n * Why: cache the wake-word + speaker-verification model assets across app opens so a returning user\n * loads them from disk instead of re-downloading. The service worker fetches the full file itself and\n * serves a complete copy on later opens.\n * NOTE: Whisper turbo caching is handled SEPARATELY by transformers.js (it streams the model into the\n * Cache API, and the model is hosted on Cloudflare R2 which sends Content-Length) — the SW intentionally\n * does NOT intercept the Whisper weight files. See ozwell-model-sw.js / AI/MODEL-HOSTING.md.\n *\n * Idempotent and best-effort: safe to call from multiple mount points; no-ops without SW support.\n * The SW intercepts on the NEXT load (it activates + claims after first registration), so the very\n * first visit still downloads normally; subsequent opens are cache hits.\n */\nconst registered = new Set<string>();\n\nexport function registerModelServiceWorker(\n swUrl = '/ozwell-model-sw.js'\n): void {\n // Bail BEFORE memoizing if SW is unavailable (SSR / unsupported), so we don't mark the URL \"registered\"\n // and then skip the real registration once running in a proper browser.\n if (typeof navigator === 'undefined' || !('serviceWorker' in navigator))\n return;\n if (registered.has(swUrl)) return; // memoize per-URL, so a different swUrl isn't silently ignored\n registered.add(swUrl);\n navigator.serviceWorker.register(swUrl).then(\n () => console.log('[modelCache] model service worker registered'),\n (e) => {\n // Un-memoize on failure (404 in local dev, transient offline/CSP) so a later call can retry this\n // session instead of caching staying disabled until a full reload.\n registered.delete(swUrl);\n console.warn(\n '[modelCache] SW registration failed (models will still load, just not cached):',\n e\n );\n }\n );\n}\n","/**\n * Ozwell chat backend — the real call that replaces the demo stub.\n *\n * Mirrors the ozwellai-api TypeScript SDK (clients/typescript/src/index.ts) with plain `fetch`,\n * so there's no SDK dependency to install: OpenAI-compatible POST /v1/chat/completions, Bearer auth,\n * `messages` array in / `choices[0].message.content` (or streamed `delta.content`) out.\n *\n * KEY HANDLING (deliberate): the API key is NEVER hardcoded or committed. It's read at runtime from\n * - `window.__ozwell` (e.g. `window.__ozwell = { apiKey: 'sk-...' }` in the console), or\n * - `localStorage['ozwellConfig']` (JSON, survives reloads).\n * If no key is configured, `isOzwellConfigured()` is false and the chat falls back to its canned reply —\n * so this file is always safe to push and the demo still works keyless. For a PUBLIC deploy the key\n * should live server-side behind a proxy (a browser-direct Bearer key is visible to anyone with the page);\n * point `baseURL` at that proxy then. See AI/MODEL-HOSTING.md / the hosted-demo plan.\n */\n\nexport interface OzwellMessage {\n role: 'system' | 'user' | 'assistant';\n content: string;\n}\n\nexport interface OzwellConfig {\n /** API base. Defaults to https://api.ozwell.ai (or http://localhost:11434 when apiKey === 'ollama'). */\n baseURL: string;\n /** Bearer key. Empty = not configured → callers fall back to the stub. */\n apiKey: string;\n /** Model id. */\n model: string;\n /** System prompt prepended to the conversation (omit by setting to ''). */\n system: string;\n /** Sampling temperature. */\n temperature: number;\n}\n\nconst DEFAULT_BASE = 'https://api.ozwell.ai';\nconst OLLAMA_BASE = 'http://localhost:11434';\nconst DEFAULTS = {\n model: 'gpt-4o-mini',\n system:\n 'You are Ozwell, a concise and helpful clinical assistant. Answer briefly and clearly.',\n temperature: 0.7,\n};\n\n// Storybook renders each story in an IFRAME, so a console-set `window.__ozwell` usually lands on the\n// parent frame, not the story's. Check current → parent → top (all same-origin, so safe). localStorage\n// is shared across same-origin frames, so the localStorage form always works regardless of frame.\nfunction readWindowGlobal(): Partial<OzwellConfig> {\n if (typeof window === 'undefined') return {}; // SSR / Node — no window\n const get = (w?: Window | null): Partial<OzwellConfig> | undefined => {\n try {\n return (w as unknown as { __ozwell?: Partial<OzwellConfig> })?.__ozwell;\n } catch {\n return undefined;\n }\n };\n return get(window) || get(window.parent) || get(window.top) || {};\n}\n// Copy only safe, own keys from parsed/external config (drop __proto__/constructor/prototype). Object\n// spread alone can't pollute Object.prototype (CreateDataProperty semantics), but the rest of this PR's\n// config parsers (voiceprintStore, diarize) filter dangerous keys — keep this one consistent.\nfunction sanitizeConfig(o: unknown): Partial<OzwellConfig> {\n if (!o || typeof o !== 'object') return {};\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(o)) {\n if (k === '__proto__' || k === 'constructor' || k === 'prototype') continue;\n out[k] = (o as Record<string, unknown>)[k];\n }\n return out as Partial<OzwellConfig>;\n}\nfunction readRaw(): Partial<OzwellConfig> {\n let stored: Partial<OzwellConfig> = {};\n try {\n stored = sanitizeConfig(\n JSON.parse(localStorage.getItem('ozwellConfig') || '{}')\n );\n } catch {\n /* ignore bad JSON */\n }\n return { ...stored, ...sanitizeConfig(readWindowGlobal()) }; // window override wins over localStorage\n}\n\n/** Resolve the effective config from runtime sources + defaults. */\nexport function getOzwellConfig(): OzwellConfig {\n const c = readRaw();\n const apiKey = c.apiKey || '';\n const baseURL =\n c.baseURL || (apiKey === 'ollama' ? OLLAMA_BASE : DEFAULT_BASE);\n return {\n baseURL,\n apiKey,\n model: c.model || DEFAULTS.model,\n system: c.system ?? DEFAULTS.system,\n // Coerce: temperature set via console/localStorage often arrives as a string; a string in the request\n // body can be rejected by OpenAI-compatible servers. Fall back to the default if it's not a real number —\n // and guard the empty/whitespace string explicitly, since Number('') is 0 (a valid-looking temperature)\n // and would silently pin sampling to 0 instead of using the default.\n temperature:\n c.temperature != null &&\n String(c.temperature).trim() !== '' &&\n Number.isFinite(Number(c.temperature))\n ? Number(c.temperature)\n : DEFAULTS.temperature,\n };\n}\n\n/** True once a key is configured — gate the real call on this; otherwise keep the stub reply. */\nexport function isOzwellConfigured(): boolean {\n return !!getOzwellConfig().apiKey;\n}\n\n/** Map AIChat's message blocks to the API's role/content shape (user+assistant text only) for multi-turn. */\nexport function toOzwellMessages(\n msgs: { role: string; content: { type?: string; text?: string }[] }[]\n): OzwellMessage[] {\n const out: OzwellMessage[] = [];\n for (const m of msgs) {\n if (m.role !== 'user' && m.role !== 'assistant') continue;\n const text = (m.content || [])\n .map((c) => c.text || '')\n .join(' ')\n .trim();\n if (text) out.push({ role: m.role, content: text });\n }\n return out;\n}\n\nfunction withSystem(\n messages: OzwellMessage[],\n system: string\n): OzwellMessage[] {\n if (!system || messages.some((m) => m.role === 'system')) return messages;\n return [{ role: 'system', content: system }, ...messages];\n}\n\nfunction buildRequest(\n messages: OzwellMessage[] | string,\n cfg: OzwellConfig,\n stream: boolean\n) {\n const msgs =\n typeof messages === 'string'\n ? [{ role: 'user' as const, content: messages }]\n : messages;\n return {\n url: `${cfg.baseURL.replace(/\\/$/, '')}/v1/chat/completions`,\n headers: {\n 'Content-Type': 'application/json',\n // 'ollama' is a sentinel that points baseURL at the local Ollama server, not a real credential —\n // don't send it as a Bearer token (some local OpenAI-compatible servers reject unexpected auth).\n ...(cfg.apiKey && cfg.apiKey !== 'ollama'\n ? { Authorization: `Bearer ${cfg.apiKey}` }\n : {}),\n } as Record<string, string>,\n body: JSON.stringify({\n model: cfg.model,\n messages: withSystem(msgs, cfg.system),\n temperature: cfg.temperature,\n stream,\n }),\n };\n}\n\nexport interface AskOpts extends Partial<OzwellConfig> {\n signal?: AbortSignal;\n}\n\n/**\n * Merge call-time opts over the runtime config. The `apiKey: 'ollama'` sentinel switches baseURL to the\n * local Ollama server inside getOzwellConfig(); honor it when the caller passes it via opts too (without\n * also passing a baseURL), so the request doesn't target the non-Ollama default.\n */\nfunction resolveConfig(opts: AskOpts): OzwellConfig {\n const cfg = { ...getOzwellConfig(), ...opts };\n // When the caller overrides the apiKey but not the baseURL (and there's no explicit baseURL in the\n // runtime config either), re-derive the baseURL from the EFFECTIVE apiKey. Otherwise a runtime config\n // using the 'ollama' sentinel would keep a real key pointed at the Ollama server (and vice-versa). An\n // explicit baseURL — from opts or the runtime config — is always respected.\n if (opts.apiKey && !opts.baseURL && !readRaw().baseURL) {\n cfg.baseURL = cfg.apiKey === 'ollama' ? OLLAMA_BASE : DEFAULT_BASE;\n }\n return cfg;\n}\n\n/** One-shot (non-streaming) completion → the answer text. Throws on HTTP error. */\nexport async function askOzwell(\n messages: OzwellMessage[] | string,\n opts: AskOpts = {}\n): Promise<string> {\n const cfg = resolveConfig(opts);\n const req = buildRequest(messages, cfg, false);\n const res = await fetch(req.url, {\n method: 'POST',\n headers: req.headers,\n body: req.body,\n signal: opts.signal,\n });\n if (!res.ok) throw new Error(`Ozwell API ${res.status}: ${res.statusText}`);\n const data = await res.json();\n return (data?.choices?.[0]?.message?.content ?? '').trim();\n}\n\n/**\n * Streaming completion (SSE). Calls `onToken(delta, full)` as text arrives and resolves with the full text.\n * Token-by-token is the natural fit for a spoken/hands-free reply. Throws on HTTP error.\n */\nexport async function askOzwellStream(\n messages: OzwellMessage[] | string,\n onToken: (delta: string, full: string) => void,\n opts: AskOpts = {}\n): Promise<string> {\n const cfg = resolveConfig(opts);\n const req = buildRequest(messages, cfg, true);\n const res = await fetch(req.url, {\n method: 'POST',\n headers: req.headers,\n body: req.body,\n signal: opts.signal,\n });\n if (!res.ok || !res.body)\n throw new Error(`Ozwell API ${res.status}: ${res.statusText}`);\n\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n let buf = '';\n let full = '';\n // Process one SSE event's `data:` lines; returns true once the terminal [DONE] frame is seen.\n const processEvent = (ev: string): boolean => {\n for (const line of ev.split(/\\r?\\n/)) {\n if (!line.startsWith('data:')) continue;\n const payload = line.slice(5).trim();\n if (payload === '[DONE]') return true;\n try {\n const json = JSON.parse(payload);\n const delta: string = json?.choices?.[0]?.delta?.content || '';\n if (delta) {\n full += delta;\n onToken(delta, full);\n }\n } catch {\n /* keep-alive / partial line — ignore */\n }\n }\n return false;\n };\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n buf += decoder.decode(value, { stream: true });\n const events = buf.split(/\\r?\\n\\r?\\n/); // SSE events are separated by a blank line (handle CRLF too)\n buf = events.pop() || ''; // keep the trailing partial event for the next chunk\n for (const ev of events) if (processEvent(ev)) return full;\n }\n // Stream ended: flush the decoder (a final multi-byte UTF-8 char can be split across chunks) and\n // process any trailing event that arrived WITHOUT a blank line, so the last token(s) aren't dropped.\n buf += decoder.decode();\n if (buf.trim()) processEvent(buf);\n } finally {\n // Release the connection promptly on BOTH normal completion and the early `[DONE]` return, so we\n // don't hold the socket open or fight a caller's AbortController. cancel() also releases the lock.\n try {\n await reader.cancel();\n } catch {\n /* stream already closed/errored — nothing to release */\n }\n }\n return full;\n}\n","/**\n * On-device Whisper transcription (Transformers.js from CDN, no install).\n * Shared by the AIChat voice story and the hands-free composition.\n *\n * Whisper runs in a dedicated Web Worker (see WORKER_SRC below) so its heavy download + model\n * instantiation + inference never runs on the main thread. That matters because the on-device WAKE\n * detector runs its ONNX inference on the main thread (single-threaded WASM); before this, loading the\n * ~1.3 GB turbo model starved the wake loop and \"hey ozwell\" wasn't detected until Whisper had loaded.\n * The worker relocates the compute only — same models, same output, same PHI-safe on-device path (audio\n * never leaves the page). The public API here is unchanged; callers don't know a worker exists.\n *\n * transcribeBlob(blob) — decode a recorded blob → 16 kHz mono → transcribe in the worker → text.\n * transcribeGate(samples) — a SECOND, fast (base.en) model used only for the hands-free \"stop-confirm\"\n * check. Independent of the dictation model so the heavy turbo stays the final-transcription path.\n */\nimport { registerModelServiceWorker } from './modelCache';\nimport { getOzwellConfig } from './ozwellChat';\nimport type { TranscriptSegment } from './diarize';\n\nconst HF_HOST = 'https://huggingface.co';\nconst HF_PATH = '{model}/resolve/{revision}/';\n// turbo's weights are served from our Cloudflare R2 bucket, which sends a Content-Length header so\n// transformers.js can stream it into the Cache API (HuggingFace Xet doesn't → re-downloads ~1.3GB each\n// open). This is the DEFAULT; it's runtime-overridable (see whisperHost) so the hosting cutover is a\n// pure-config swap, consistent with the wake/speaker assets and the transformers CDN. See MODEL-HOSTING.md.\nconst R2_HOST = 'https://pub-64db68afc2cb4e108ff06e7e583f09d1.r2.dev';\n\n// Where the turbo Whisper weights load from. Defaults to R2_HOST, overridable at runtime so a consumer can\n// repoint EVERY model to a mieweb-owned host with zero source edits — mirrors `window.__ozwellAssets`\n// (wake/speaker) and `window.__ozwellTransformersUrl` (the ESM). Checks current → parent → top frame\n// (Storybook iframe) → localStorage `ozwellConfig.whisperHost`. Trailing slash trimmed (the worker adds it).\nfunction whisperHost(): string {\n if (typeof window === 'undefined') return R2_HOST;\n const fromWin = (w?: Window | null): string | undefined => {\n try {\n return (w as unknown as { __ozwellWhisperHost?: string })\n ?.__ozwellWhisperHost;\n } catch {\n return undefined;\n }\n };\n const win = fromWin(window) || fromWin(window.parent) || fromWin(window.top);\n if (win) return win.replace(/\\/$/, '');\n try {\n const h = JSON.parse(\n localStorage.getItem('ozwellConfig') || '{}'\n ).whisperHost;\n if (h) return String(h).replace(/\\/$/, '');\n } catch {\n /* ignore */\n }\n return R2_HOST;\n}\n\nconst SMALL_MODELS: Record<string, string> = {\n tiny: 'Xenova/whisper-tiny.en',\n 'tiny.en': 'Xenova/whisper-tiny.en',\n base: 'Xenova/whisper-base.en',\n 'base.en': 'Xenova/whisper-base.en',\n small: 'Xenova/whisper-small.en',\n 'small.en': 'Xenova/whisper-small.en',\n};\nconst GATE_MODEL = 'Xenova/whisper-base.en'; // stop-confirm: fast + reliable on the single word \"done\"\n\n// Optional model override, read from the same ozwellConfig used by the chat. Set\n// `{ ..., whisper: 'base.en' }` to force the small (~75 MB) English model instead of the heavy turbo\n// one — much faster to download and runs even when browser storage is tight/over-quota. Checks current →\n// parent → top frame (Storybook iframe) and localStorage. Resolved HERE (main thread) and passed into the\n// worker, which can't read window/localStorage.\nfunction whisperPref(): string | null {\n if (typeof window === 'undefined') return null; // SSR / Node — no window/localStorage\n const fromWin = (w?: Window | null): string | undefined => {\n try {\n return (w as unknown as { __ozwell?: { whisper?: string } })?.__ozwell\n ?.whisper;\n } catch {\n return undefined;\n }\n };\n const win = fromWin(window) || fromWin(window.parent) || fromWin(window.top);\n if (win) return win;\n try {\n return (\n JSON.parse(localStorage.getItem('ozwellConfig') || '{}').whisper || null\n );\n } catch {\n return null;\n }\n}\n\n// Optional inference-device override for the small English models: set\n// `window.__ozwell.whisperDevice = 'wasm'` (or `ozwellConfig.whisperDevice` in localStorage) to skip the\n// WebGPU attempt. WebGPU on software/broken adapters (headless & automation browsers, some VMs) can\n// \"succeed\" while computing garbage tokens — wasm is slower but always correct. Same window→parent→top→\n// localStorage resolution as the model pref.\nfunction whisperDevice(): string | null {\n if (typeof window === 'undefined') return null;\n const fromWin = (w?: Window | null): string | undefined => {\n try {\n return (w as unknown as { __ozwell?: { whisperDevice?: string } })\n ?.__ozwell?.whisperDevice;\n } catch {\n return undefined;\n }\n };\n const win = fromWin(window) || fromWin(window.parent) || fromWin(window.top);\n if (win) return win;\n try {\n return (\n JSON.parse(localStorage.getItem('ozwellConfig') || '{}').whisperDevice ||\n null\n );\n } catch {\n return null;\n }\n}\n\n// Optional dtype override for the small English models' WebGPU attempt (default 'q8'). The q8 WebGPU\n// kernels miscompute on some Chrome/driver combos while fp16/fp32 work (turbo's fp16/q4 path is fine on\n// the same machines) — set `window.__ozwell.whisperDtype = 'fp16'` to trade a larger download for\n// correct GPU inference. The wasm fallback always uses q8 (CPU arithmetic is deterministic).\nfunction whisperDtype(): string | null {\n if (typeof window === 'undefined') return null;\n const fromWin = (w?: Window | null): string | undefined => {\n try {\n return (w as unknown as { __ozwell?: { whisperDtype?: string } })\n ?.__ozwell?.whisperDtype;\n } catch {\n return undefined;\n }\n };\n const win = fromWin(window) || fromWin(window.parent) || fromWin(window.top);\n if (win) return win;\n try {\n return (\n JSON.parse(localStorage.getItem('ozwellConfig') || '{}').whisperDtype ||\n null\n );\n } catch {\n return null;\n }\n}\n\n// Pinned to an EXACT validated version (a floating `@3` lets jsDelivr serve newer 3.x that can break at\n// runtime). Override the ESM URL for strict-CSP / offline / self-hosted setups via\n// `window.__ozwellTransformersUrl` or `localStorage['ozwellTransformersUrl']`.\nconst DEFAULT_TRANSFORMERS_URL =\n 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.8.1';\nfunction transformersUrl(): string {\n try {\n const w = (window as unknown as { __ozwellTransformersUrl?: string })\n .__ozwellTransformersUrl;\n if (w) return w;\n const ls = localStorage.getItem('ozwellTransformersUrl');\n if (ls) return ls;\n } catch {\n /* ignore */\n }\n return DEFAULT_TRANSFORMERS_URL;\n}\n\n// --- dictation-model load progress, surfaced to the UI (the ~1.3GB turbo download is the slow one) ---\nexport interface WhisperLoadState {\n /** A load is in flight. */ active: boolean;\n /** Overall fraction 0..1 (averaged over the model's files). */ progress: number;\n /** The model is loaded. */ done: boolean;\n}\nlet dictationLoad: WhisperLoadState = {\n active: false,\n progress: 0,\n done: false,\n};\nconst loadListeners = new Set<() => void>();\nfunction setDictationLoad(patch: Partial<WhisperLoadState>): void {\n dictationLoad = { ...dictationLoad, ...patch };\n loadListeners.forEach((l) => l());\n}\n/** Current dictation-model load state (for a progress indicator). */\nexport function getDictationLoad(): WhisperLoadState {\n return dictationLoad;\n}\n/** Subscribe to dictation-model load changes; returns an unsubscribe. Pair with getDictationLoad in\n * React.useSyncExternalStore. */\nexport function subscribeDictationLoad(cb: () => void): () => void {\n loadListeners.add(cb);\n return () => {\n loadListeners.delete(cb);\n };\n}\n\n// ---------------------------------------------------------------------------------------------------------\n// The Whisper worker. Inlined as a string + spawned from a Blob URL so it bundles cleanly in the tsup-built\n// library (no reliance on the consumer's bundler handling worker URLs). It's a MODULE worker so it can\n// `import()` transformers.js from the CDN. Config (URLs, model prefs) is passed in via the 'init' message\n// because a worker can't read window/localStorage. Message protocol:\n// main→worker: {type:'init', cfg} · {type:'warm'} · {type:'warmGate'} · {type:'transcribe', id, want, samples}\n// worker→main: {type:'loadState', patch} · {type:'progress', frac} · {type:'result', id, text, chunks} · {type:'error', id, message}\n// A model load mutates the SHARED env.remoteHost (turbo→whisperHost, english→HF), read per-file as\n// transformers.js fetches — so every load is serialized through one chain to avoid mid-download clobber.\nconst WORKER_SRC = `\nlet cfg = null, modP = null, pipeP = null, gateP = null, isMulti = false;\nlet chain = Promise.resolve();\nconst serialize = (fn) => { const r = chain.then(fn, fn); chain = r.then(() => {}, () => {}); return r; };\n\nfunction getMod() {\n if (modP) return modP;\n modP = (async () => {\n const mod = await import(cfg.transformersUrl);\n mod.env.allowLocalModels = false;\n // transformers.js's OWN cache STREAMS the model straight to the Cache API (how whisper-web caches this\n // 1.2GB turbo model). A hand-rolled SW that buffers the whole file chokes (QuotaExceeded).\n mod.env.useBrowserCache = true;\n mod.env.backends.onnx.wasm.numThreads = 1;\n try { if (navigator.storage && navigator.storage.persist) await navigator.storage.persist(); } catch (e) {}\n return mod;\n })();\n return modP;\n}\n\nfunction progressCb() {\n const frac = {};\n const report = () => {\n const v = Object.values(frac);\n self.postMessage({ type: 'progress', frac: v.length ? v.reduce((a, b) => a + b, 0) / v.length : 0 });\n };\n return (p) => {\n if (!p || !p.file) return;\n if (p.status === 'initiate') { frac[p.file] = frac[p.file] || 0; report(); }\n else if (p.status === 'done') { frac[p.file] = 1; report(); }\n else if (p.status === 'progress' && typeof p.progress === 'number') { frac[p.file] = p.progress / 100; report(); }\n };\n}\n\nasync function buildEnglish(modelId) {\n const mod = await getMod();\n mod.env.remoteHost = cfg.hfHost;\n mod.env.remotePathTemplate = cfg.hfPath;\n if ((cfg.whisperDevice || '').toLowerCase() !== 'wasm') {\n try {\n const gpuDtype = cfg.whisperDtype || 'q8';\n const pipe = await mod.pipeline('automatic-speech-recognition', modelId, { device: 'webgpu', dtype: gpuDtype, progress_callback: progressCb() });\n console.log('[whisper] ready (' + modelId + ' / WebGPU ' + gpuDtype + ', worker)');\n return pipe;\n } catch (e) { /* fall through to wasm */ }\n }\n const pipe = await mod.pipeline('automatic-speech-recognition', modelId, { dtype: 'q8', progress_callback: progressCb() });\n console.log('[whisper] ready (' + modelId + ' / wasm, worker)');\n return pipe;\n}\n\nasync function buildTurbo() {\n const mod = await getMod();\n mod.env.remoteHost = cfg.whisperHost;\n mod.env.remotePathTemplate = '{model}/';\n const pipe = await mod.pipeline('automatic-speech-recognition', 'whisper-turbo', {\n device: 'webgpu',\n dtype: { encoder_model: 'fp16', decoder_model_merged: 'q4' },\n progress_callback: progressCb(),\n });\n isMulti = true;\n console.log('[whisper] ready (turbo / worker)');\n return pipe;\n}\n\nfunction loadWhisper() {\n if (pipeP) return pipeP;\n self.postMessage({ type: 'loadState', patch: { active: true, progress: 0, done: false } });\n pipeP = (async () => {\n const pref = (cfg.whisperPref || '').toLowerCase();\n if (pref && pref !== 'turbo' && cfg.smallModels[pref]) {\n console.log('[whisper] loading ' + pref + ' (forced via ozwellConfig.whisper)…');\n return serialize(() => buildEnglish(cfg.smallModels[pref]));\n }\n console.log('[whisper] loading turbo…');\n try { return await serialize(() => buildTurbo()); }\n catch (e) {\n console.log('[whisper] turbo unavailable (' + (e && e.message ? e.message : e) + ') → base.en fallback');\n return serialize(() => buildEnglish(cfg.gateModel));\n }\n })();\n pipeP.then(\n () => self.postMessage({ type: 'loadState', patch: { active: false, progress: 1, done: true } }),\n () => { pipeP = null; self.postMessage({ type: 'loadState', patch: { active: false } }); }\n );\n return pipeP;\n}\n\nfunction loadGate() {\n if (gateP) return gateP;\n console.log('[whisper] loading stop-confirm gate (base.en)…');\n gateP = serialize(() => buildEnglish(cfg.gateModel));\n gateP.catch(() => { gateP = null; });\n return gateP;\n}\n\nself.onmessage = async (e) => {\n const m = e.data;\n if (!m) return;\n if (m.type === 'init') { cfg = m.cfg; return; }\n if (m.type === 'warm') { loadWhisper().catch(() => {}); return; }\n if (m.type === 'warmGate') { loadGate().catch(() => {}); return; }\n if (m.type === 'transcribe') {\n try {\n let pipe, opts;\n if (m.want === 'gate') { pipe = await loadGate(); opts = { chunk_length_s: 30 }; }\n else {\n pipe = await loadWhisper();\n if (m.want === 'segments' || m.want === 'words') opts = Object.assign({ chunk_length_s: 30, return_timestamps: m.want === 'words' ? 'word' : true }, isMulti ? { language: 'english', task: 'transcribe' } : {});\n else opts = isMulti ? { chunk_length_s: 30, language: 'english', task: 'transcribe' } : { chunk_length_s: 30 };\n }\n const out = await pipe(m.samples, opts);\n self.postMessage({ type: 'result', id: m.id, text: (out && out.text ? out.text : '').trim(), chunks: (out && out.chunks) || null });\n } catch (err) {\n self.postMessage({ type: 'error', id: m.id, message: err && err.message ? err.message : String(err) });\n }\n }\n};\n`;\n\ntype WorkerResult = {\n text: string;\n chunks: { timestamp: [number, number | null]; text?: string }[] | null;\n};\nlet worker: Worker | null = null;\nlet reqId = 0;\nconst pending = new Map<\n number,\n { resolve: (r: WorkerResult) => void; reject: (e: Error) => void }\n>();\n\nfunction buildWorkerCfg() {\n return {\n transformersUrl: transformersUrl(),\n whisperHost: whisperHost(),\n whisperPref: whisperPref(),\n whisperDevice: whisperDevice(),\n whisperDtype: whisperDtype(),\n hfHost: HF_HOST,\n hfPath: HF_PATH,\n smallModels: SMALL_MODELS,\n gateModel: GATE_MODEL,\n };\n}\n\nfunction getWorker(): Worker {\n if (worker) return worker;\n registerModelServiceWorker(); // main-thread SW registration (caches the wake/sherpa models)\n const url = URL.createObjectURL(\n new Blob([WORKER_SRC], { type: 'application/javascript' })\n );\n const w = new Worker(url, { type: 'module' });\n w.onmessage = (e: MessageEvent) => {\n const m = e.data;\n if (!m) return;\n if (m.type === 'loadState') {\n setDictationLoad(m.patch);\n return;\n }\n if (m.type === 'progress') {\n setDictationLoad({ progress: m.frac });\n return;\n }\n if (m.type === 'result') {\n const p = pending.get(m.id);\n if (p) {\n pending.delete(m.id);\n p.resolve({ text: m.text, chunks: m.chunks });\n }\n return;\n }\n if (m.type === 'error') {\n const p = pending.get(m.id);\n if (p) {\n pending.delete(m.id);\n p.reject(new Error(m.message));\n }\n return;\n }\n };\n w.onerror = (e) => {\n // A worker-level failure (e.g. the transformers.js import blocked by CSP) — fail any in-flight calls so\n // callers fall back instead of hanging, and reset the load indicator.\n const err = new Error(\n `whisper worker error: ${e.message || 'failed to load'}`\n );\n pending.forEach((p) => p.reject(err));\n pending.clear();\n setDictationLoad({ active: false });\n };\n w.postMessage({ type: 'init', cfg: buildWorkerCfg() });\n worker = w;\n return worker;\n}\n\n// Post a transcribe request to the worker; the 16 kHz mono samples are TRANSFERRED (zero-copy). Resolves\n// with the worker's { text, chunks }.\nfunction callWorker(\n want: 'text' | 'segments' | 'words' | 'gate',\n samples: Float32Array\n): Promise<WorkerResult> {\n const w = getWorker();\n const id = ++reqId;\n return new Promise<WorkerResult>((resolve, reject) => {\n pending.set(id, { resolve, reject });\n w.postMessage({ type: 'transcribe', id, want, samples }, [samples.buffer]);\n });\n}\n\n/** True only once the dictation model has actually finished loading (not merely started, not rejected). */\nexport function isWhisperLoaded(): boolean {\n return getDictationLoad().done;\n}\n\n/** Terminate the whisper worker so the next call spawns a fresh one with current config\n * (model pref / device / hosts re-read from window+localStorage). Model weights stay in the\n * browser Cache API, so a respawn re-instantiates in seconds rather than re-downloading.\n * Lets callers switch models/devices at runtime or recover from a bad pipeline (e.g. WebGPU\n * computing garbage on a broken adapter). In-flight requests are rejected. */\nexport function resetWhisperWorker(): void {\n if (!worker) return;\n const err = new Error('whisper worker reset');\n pending.forEach((p) => p.reject(err));\n pending.clear();\n worker.terminate();\n worker = null;\n setDictationLoad({ active: false, progress: 0, done: false });\n}\n\n/** Start loading the dictation model NOW (in the worker) so the first dictation doesn't pay the load. */\nexport function warmWhisper(): void {\n getWorker().postMessage({ type: 'warm' });\n}\n\n/** Start loading the stop-confirm gate model (base.en) in the worker. Warm this BEFORE warmWhisper so the\n * fast model isn't queued behind slow turbo. */\nexport function warmStopGate(): void {\n getWorker().postMessage({ type: 'warmGate' });\n}\n\n// Downmix all channels of a decoded buffer to mono (average), so stereo recordings don't lose half the\n// signal. Single-channel buffers pass through.\nfunction downmixToMono(audio: AudioBuffer): Float32Array {\n if (audio.numberOfChannels <= 1) return audio.getChannelData(0);\n const n = audio.length;\n const out = new Float32Array(n);\n for (let ch = 0; ch < audio.numberOfChannels; ch++) {\n const data = audio.getChannelData(ch);\n for (let i = 0; i < n; i++) out[i] += data[i];\n }\n for (let i = 0; i < n; i++) out[i] /= audio.numberOfChannels;\n return out;\n}\n\n// Linear-resample mono audio to 16 kHz (what Whisper wants). Shared by the blob + raw-samples paths. Always\n// returns a fresh, standalone Float32Array (safe to transfer to the worker).\nfunction resampleTo16kMono(\n src: Float32Array,\n sampleRate: number\n): Float32Array {\n const ratio = 16000 / sampleRate;\n const n = Math.round(src.length * ratio);\n const out = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n const t = i / ratio;\n const i0 = Math.floor(t);\n const i1 = Math.min(i0 + 1, src.length - 1);\n out[i] = src[i0] + (src[i1] - src[i0]) * (t - i0);\n }\n return out;\n}\n\n// Decode a recorded Blob → 16 kHz mono Float32 (what Whisper + TitaNet want). decodeAudioData needs the\n// main thread (no AudioContext in workers), but it's cheap; the heavy inference is what moved off-thread.\n// try/finally so a failed decode still closes the AudioContext (they'd otherwise leak across retries).\nexport async function decodeTo16kMono(blob: Blob): Promise<Float32Array> {\n const Ctx =\n window.AudioContext ||\n (window as unknown as { webkitAudioContext: typeof AudioContext })\n .webkitAudioContext;\n const ctx = new Ctx();\n try {\n const audio = await ctx.decodeAudioData(await blob.arrayBuffer());\n return resampleTo16kMono(downmixToMono(audio), audio.sampleRate);\n } finally {\n void ctx.close();\n }\n}\n\n/** Encode 16 kHz mono Float32 samples as a 16-bit PCM WAV blob, so a trimmed clip can flow back through the\n * existing blob-based transcribe/diarize/server paths (which decode it). */\nfunction encodeWav16kMono(samples: Float32Array): Blob {\n const sr = 16000;\n const buf = new ArrayBuffer(44 + samples.length * 2);\n const view = new DataView(buf);\n const str = (o: number, s: string) => {\n for (let i = 0; i < s.length; i++) view.setUint8(o + i, s.charCodeAt(i));\n };\n str(0, 'RIFF');\n view.setUint32(4, 36 + samples.length * 2, true);\n str(8, 'WAVE');\n str(12, 'fmt ');\n view.setUint32(16, 16, true);\n view.setUint16(20, 1, true);\n view.setUint16(22, 1, true);\n view.setUint32(24, sr, true);\n view.setUint32(28, sr * 2, true);\n view.setUint16(32, 2, true);\n view.setUint16(34, 16, true);\n str(36, 'data');\n view.setUint32(40, samples.length * 2, true);\n let o = 44;\n for (let i = 0; i < samples.length; i++) {\n const s = Math.max(-1, Math.min(1, samples[i]));\n view.setInt16(o, s < 0 ? s * 0x8000 : s * 0x7fff, true);\n o += 2;\n }\n return new Blob([buf], { type: 'audio/wav' });\n}\n\n/**\n * Trim the spoken \"ozwell i'm done\" off the END of a clip BEFORE it reaches ASR. Whisper mishears the phrase\n * differently every time (\"all was well\" / \"I was long done\" / …), so stripping the transcript text can\n * never catch them all — the reliable fix is to cut the audio so the phrase is never transcribed.\n *\n * `phraseHintSec` (from the wake detector's detection run) is an estimate of the phrase's length. When\n * given, the cut is anchored at `end - phraseHintSec` and snapped to the nearest pause within ~0.35 s — so\n * it works whether or not the speaker paused (the pause-independent case that pure energy can't handle).\n * Without a hint, it walks back from the end to the last natural pause (energy only). Capped so it never\n * removes too much. Returns a trimmed WAV blob (or the original on failure / nothing sensible to cut). Only\n * call on a PHRASE-triggered stop — not a manual button stop, where there's no phrase to remove.\n */\nexport async function trimTrailingStopPhrase(\n blob: Blob,\n phraseHintSec = 0\n): Promise<Blob> {\n let samples: Float32Array;\n try {\n samples = await decodeTo16kMono(blob);\n } catch {\n return blob;\n }\n const SR = 16000;\n const n = samples.length;\n if (n < SR * 0.8) return blob; // too short to safely trim\n\n // Short-time energy (RMS) per 30 ms frame.\n const fr = Math.round(SR * 0.03);\n const nf = Math.ceil(n / fr);\n const e = new Float32Array(nf);\n let peak = 0;\n for (let f = 0; f < nf; f++) {\n const a = f * fr,\n b = Math.min(n, a + fr);\n let s = 0;\n for (let i = a; i < b; i++) s += samples[i] * samples[i];\n e[f] = Math.sqrt(s / (b - a));\n if (e[f] > peak) peak = e[f];\n }\n const sil = Math.max(0.008, peak * 0.15); // \"silence\" threshold, adaptive to the clip's level\n const minGap = Math.max(1, Math.round((0.15 * SR) / fr)); // a real pause = >= ~150 ms of silence\n const maxTrimFrames = Math.round((2.2 * SR) / fr); // never cut more than ~2.2 s\n const floor = Math.max(0, nf - maxTrimFrames);\n\n let cutFrame: number;\n if (phraseHintSec > 0.2) {\n // Detector-anchored: the phrase is the last ~phraseHintSec. Snap to the nearest quiet frame within a\n // window of that anchor (catches the pause/word-boundary before the phrase even when it's very brief);\n // if none is near, cut at the anchor itself. Pause-independent.\n const anchor = Math.max(0, nf - Math.round((phraseHintSec * SR) / fr));\n const win = Math.round((0.35 * SR) / fr);\n let best = -1,\n bestDist = Infinity;\n for (\n let f = Math.max(0, anchor - win);\n f <= Math.min(nf - 1, anchor + win);\n f++\n ) {\n if (e[f] < sil) {\n const dist = Math.abs(f - anchor);\n if (dist < bestDist) {\n bestDist = dist;\n best = f;\n }\n }\n }\n cutFrame = best >= 0 ? best : anchor;\n } else {\n // Energy-only fallback: walk back from the end to the last sustained pause.\n let k = nf - 1;\n while (k >= floor && e[k] < sil) k--; // skip any trailing quiet after \"done\"\n cutFrame = -1;\n while (k >= floor) {\n if (e[k] < sil) {\n let m = k;\n while (m >= floor && e[m] < sil) m--; // measure this silence run\n if (k - m >= minGap) {\n cutFrame = k + 1;\n break;\n } // sustained pause → the phrase starts after it\n k = m; // micro-pause inside the phrase → keep going back\n } else k--;\n }\n if (cutFrame < 0) cutFrame = Math.max(0, nf - Math.round((1.1 * SR) / fr)); // no pause → conservative fixed trim\n }\n cutFrame = Math.max(cutFrame, floor); // enforce the max-trim cap\n const cutSample = Math.min(n, cutFrame * fr);\n if (cutSample < SR * 0.2) return blob; // would leave almost nothing — bail (text-strip covers it)\n return encodeWav16kMono(samples.subarray(0, cutSample));\n}\n\nexport async function transcribeBlob(\n blob: Blob,\n trimEndSeconds = 0\n): Promise<string> {\n let samples = await decodeTo16kMono(blob);\n if (trimEndSeconds > 0) {\n const cut = Math.round(trimEndSeconds * 16000);\n if (samples.length > cut + 16000)\n samples = samples.slice(0, samples.length - cut); // keep >=1s (slice = standalone buffer)\n }\n const out = await callWorker('text', samples);\n return (out.text ?? '').trim();\n}\n\n/** Transcribe raw mono samples (any sample rate) → text. For the live dictation caption, where we re-run\n * the growing utterance every couple seconds; the FINAL send still uses transcribeBlob. */\nexport async function transcribeSamples(\n samples: Float32Array,\n sampleRate: number\n): Promise<string> {\n const out = await callWorker('text', resampleTo16kMono(samples, sampleRate));\n return (out.text ?? '').trim();\n}\n\n/** Map raw worker chunks (`{ timestamp: [s, e], text }`) to TranscriptSegments in seconds. */\nfunction chunksToSegments(chunks: WorkerResult['chunks']): TranscriptSegment[] {\n return (chunks ?? [])\n .map((c) => ({\n start: c.timestamp?.[0] ?? 0,\n end: c.timestamp?.[1] ?? c.timestamp?.[0] ?? 0,\n text: (c.text ?? '').trim(),\n }))\n .filter((s) => s.text);\n}\n\n/** Transcribe with timestamps → segments `[{ start, end, text }]`, for diarization (align speaker turns to\n * text). Returns 16 kHz-relative seconds. See `useDiarization`. */\nexport async function transcribeSegments(\n blob: Blob\n): Promise<TranscriptSegment[]> {\n const samples = await decodeTo16kMono(blob);\n const out = await callWorker('segments', samples);\n return chunksToSegments(out.chunks);\n}\n\n/** Transcribe with WORD-level timestamps → `[{ start, end, text }]` (seconds), one entry per word — the\n * shape word-level editors (MediaEditor) need. Uses transformers.js `return_timestamps: 'word'`\n * (cross-attention alignment). Some models/runtimes reject word-level alignment — callers should catch\n * and fall back to `transcribeSegments`. */\nexport async function transcribeWords(\n blob: Blob\n): Promise<TranscriptSegment[]> {\n return transcribeWordsFromSamples(await decodeTo16kMono(blob));\n}\n\n/** Word-level transcription from already-decoded 16 kHz mono samples. Lets callers decode once (with\n * their own status/timeout handling) and retry/fall back without re-decoding. NOTE: samples are\n * transferred to the worker — pass a copy (`samples.slice()`) if you need them again. */\nexport async function transcribeWordsFromSamples(\n samples: Float32Array\n): Promise<TranscriptSegment[]> {\n const out = await callWorker('words', samples);\n return chunksToSegments(out.chunks);\n}\n\n/** Segment-level transcription from already-decoded 16 kHz mono samples (see transcribeWordsFromSamples). */\nexport async function transcribeSegmentsFromSamples(\n samples: Float32Array\n): Promise<TranscriptSegment[]> {\n const out = await callWorker('segments', samples);\n return chunksToSegments(out.chunks);\n}\n\n// Server-ASR model id (override via localStorage ozwellConfig.serverWhisper); defaults to the\n// OpenAI-compatible 'whisper-1'.\nfunction serverAsrModel(): string {\n try {\n return (\n JSON.parse(localStorage.getItem('ozwellConfig') || '{}').serverWhisper ||\n 'whisper-1'\n );\n } catch {\n return 'whisper-1';\n }\n}\n\n/** Server-side transcription: POST the recorded audio to the OpenAI-compatible /v1/audio/transcriptions\n * endpoint (same baseURL/apiKey as the chat). NOTE: audio LEAVES the browser — the on-device path\n * (transcribeBlob) is the PHI-safe default; this is the experiment alternative. Throws on HTTP error so\n * the caller can fall back to on-device. */\nexport async function transcribeServer(blob: Blob): Promise<string> {\n const cfg = getOzwellConfig();\n const form = new FormData();\n form.append('file', blob, 'audio.webm');\n form.append('model', serverAsrModel());\n const url = `${cfg.baseURL.replace(/\\/$/, '')}/v1/audio/transcriptions`;\n const headers: Record<string, string> = {};\n if (cfg.apiKey && cfg.apiKey !== 'ollama')\n headers.Authorization = `Bearer ${cfg.apiKey}`;\n const res = await fetch(url, { method: 'POST', headers, body: form });\n if (!res.ok) {\n // statusText is often empty — include a short body snippet so the failure is actionable (the caller\n // still catches this and falls back to on-device transcription).\n const body = await res.text().catch(() => '');\n throw new Error(\n `Server ASR ${res.status}: ${res.statusText || body.slice(0, 200) || 'request failed'}`\n );\n }\n const data = await res.json();\n return (typeof data?.text === 'string' ? data.text : '').trim();\n}\n\n/** Stop-confirm gate: transcribe a short raw-sample window (e.g. the rolling recorder's last ~2s) with the\n * FAST model and return the text. Used to verify a \"ozwell i'm done\" wake actually ended with \"done\"\n * before committing the stop. Cheap — accuracy on the lone word \"done\" is all it needs. */\nexport async function transcribeGate(\n samples: Float32Array,\n sampleRate: number\n): Promise<string> {\n const out = await callWorker('gate', resampleTo16kMono(samples, sampleRate));\n return (out.text ?? '').trim();\n}\n\n/** Peel a trailing \"ozwell i'm done\"-style stop phrase off the end of a transcript. Mirrors the\n * standalone demo: handles Whisper's mishearings (Ozwell / As well / All('s/was) well / Also / Oswald /\n * \"I am done\") including the bare word alone. Bare \"as well\" is NOT stripped (too common) unless joined\n * to \"i'm done\". */\nexport function stripStopPhrase(text: string): string {\n // All whitespace quantifiers are BOUNDED ({0,4}/{1,4}) so backtracking through the optional groups\n // stays constant — ReDoS hardening (transcript words are never separated by more than a couple of\n // spaces, so behavior is unchanged). The trailing-junk trim below uses a linear char walk for the\n // same reason (see trimTrailingPunct — the actual CodeQL js/polynomial-redos finding).\n const tail =\n /(?:\\b(?:oz\\s{0,4}well|all(?:['’]?s|\\s{1,4}was)?\\s{0,4}well|as\\s{0,4}well|also|oswald)\\b[\\s,]{0,6}i(?:['’]?m|\\s{1,4}am)\\s{1,4}done\\b|\\b(?:oz\\s{0,4}well|all(?:['’]?s|\\s{1,4}was)?\\s{0,4}well|oswald)\\b|\\bi(?:['’]?m|\\s{1,4}am)\\s{1,4}done\\b|\\b(?:that\\s{1,4}was\\s{1,4}|was\\s{1,4})?well\\s{1,4}done\\b|\\bthat['’]?s?\\s{1,4}(?:was\\s{1,4})?all\\b|\\bthank(?:s|\\s{1,4}you)(?:\\s{1,4}for\\s{1,4}watching)?\\b|\\bbye\\b)[\\s.,!?-]{0,24}$/i;\n let prev: string | null = null;\n let t = text;\n while (t !== prev && t) {\n prev = t;\n t = trimTrailingPunct(t.replace(tail, ''));\n }\n return t.trim();\n}\n\n/** Strip trailing whitespace/punctuation with a linear char walk. The regex form `/[\\s.,!?-]+$/` restarts\n * its scan at every position of a long trailing run (quadratic on adversarial input — the CodeQL\n * js/polynomial-redos finding on stripStopPhrase). Testing one char at a time can't backtrack. */\nfunction trimTrailingPunct(s: string): string {\n let end = s.length;\n while (end > 0 && /[\\s.,!?-]/.test(s[end - 1])) end--;\n return end === s.length ? s : s.slice(0, end);\n}\n\n/** True if a transcript ENDS with a clear \"done\" stop (\"…done\" / \"…I'm done\" / \"…all done\" / \"…well done\"),\n * tolerating trailing punctuation. Deliberately STRICTER than stripStopPhrase: the stop-confirm gate must\n * NOT fire on a bare \"ozwell\" or a mid-sentence \"done\" — \"we're almost done here\" ends on \"here\", so no\n * match. Favors precision: a missed real stop just means \"say it again\"; a false stop loses dictation. */\nexport function endsWithDone(text: string): boolean {\n // Whitespace bounded for the same polynomial-backtracking reason as stripStopPhrase's tail regex.\n return /\\b(?:i(?:['’]?m|\\s{1,4}am)\\s{1,4}|all\\s{1,4}|well\\s{1,4})?done\\b[\\s.,!?-]{0,24}$/i.test(\n text\n );\n}\n"]}