@hourslabs/domovoi 0.1.0

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 (74) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +4 -0
  3. package/README.md +312 -0
  4. package/dist/cache.d.ts +102 -0
  5. package/dist/cache.d.ts.map +1 -0
  6. package/dist/calibration/index.d.ts +45 -0
  7. package/dist/calibration/index.d.ts.map +1 -0
  8. package/dist/calibration/index.js +95 -0
  9. package/dist/calibration/index.js.map +1 -0
  10. package/dist/engine/abort.d.ts +43 -0
  11. package/dist/engine/abort.d.ts.map +1 -0
  12. package/dist/engine/config.d.ts +79 -0
  13. package/dist/engine/config.d.ts.map +1 -0
  14. package/dist/engine/decide.d.ts +18 -0
  15. package/dist/engine/decide.d.ts.map +1 -0
  16. package/dist/engine/distribution.d.ts +18 -0
  17. package/dist/engine/distribution.d.ts.map +1 -0
  18. package/dist/engine/error-recording.d.ts +35 -0
  19. package/dist/engine/error-recording.d.ts.map +1 -0
  20. package/dist/engine/finalize.d.ts +12 -0
  21. package/dist/engine/finalize.d.ts.map +1 -0
  22. package/dist/engine/hooks.d.ts +12 -0
  23. package/dist/engine/hooks.d.ts.map +1 -0
  24. package/dist/engine/index.d.ts +7 -0
  25. package/dist/engine/index.d.ts.map +1 -0
  26. package/dist/engine/meta.d.ts +37 -0
  27. package/dist/engine/meta.d.ts.map +1 -0
  28. package/dist/engine/threshold.d.ts +31 -0
  29. package/dist/engine/threshold.d.ts.map +1 -0
  30. package/dist/env.d.ts +46 -0
  31. package/dist/env.d.ts.map +1 -0
  32. package/dist/errors.d.ts +66 -0
  33. package/dist/errors.d.ts.map +1 -0
  34. package/dist/hash.d.ts +27 -0
  35. package/dist/hash.d.ts.map +1 -0
  36. package/dist/index.d.ts +34 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +1263 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/prompt.d.ts +14 -0
  41. package/dist/prompt.d.ts.map +1 -0
  42. package/dist/providers/index.d.ts +6 -0
  43. package/dist/providers/index.d.ts.map +1 -0
  44. package/dist/providers/index.js +301 -0
  45. package/dist/providers/index.js.map +1 -0
  46. package/dist/providers/openai/adapter.d.ts +25 -0
  47. package/dist/providers/openai/adapter.d.ts.map +1 -0
  48. package/dist/providers/openai/distribution.d.ts +26 -0
  49. package/dist/providers/openai/distribution.d.ts.map +1 -0
  50. package/dist/providers/openai/factory.d.ts +76 -0
  51. package/dist/providers/openai/factory.d.ts.map +1 -0
  52. package/dist/providers/openai/index.d.ts +6 -0
  53. package/dist/providers/openai/index.d.ts.map +1 -0
  54. package/dist/providers/provider.d.ts +50 -0
  55. package/dist/providers/provider.d.ts.map +1 -0
  56. package/dist/testing/index.d.ts +40 -0
  57. package/dist/testing/index.d.ts.map +1 -0
  58. package/dist/testing/index.js +34 -0
  59. package/dist/testing/index.js.map +1 -0
  60. package/dist/tokenizer.d.ts +56 -0
  61. package/dist/tokenizer.d.ts.map +1 -0
  62. package/dist/types.d.ts +180 -0
  63. package/dist/types.d.ts.map +1 -0
  64. package/dist/validate.d.ts +47 -0
  65. package/dist/validate.d.ts.map +1 -0
  66. package/dist/verbs/boolean.d.ts +26 -0
  67. package/dist/verbs/boolean.d.ts.map +1 -0
  68. package/dist/verbs/classifier.d.ts +63 -0
  69. package/dist/verbs/classifier.d.ts.map +1 -0
  70. package/dist/verbs/classify.d.ts +24 -0
  71. package/dist/verbs/classify.d.ts.map +1 -0
  72. package/dist/verdict.d.ts +38 -0
  73. package/dist/verdict.d.ts.map +1 -0
  74. package/package.json +108 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hash.ts","../src/cache.ts","../src/errors.ts","../src/calibration/index.ts","../src/prompt.ts","../src/validate.ts","../src/engine/config.ts","../src/engine/meta.ts","../src/engine/abort.ts","../src/engine/distribution.ts","../src/engine/hooks.ts","../src/engine/error-recording.ts","../src/engine/finalize.ts","../src/engine/threshold.ts","../src/engine/decide.ts","../src/tokenizer.ts","../src/providers/openai/distribution.ts","../src/providers/openai/adapter.ts","../src/providers/openai/factory.ts","../src/env.ts","../src/verbs/boolean.ts","../src/verbs/classifier.ts","../src/verbs/classify.ts","../src/verdict.ts","../src/index.ts"],"names":["verdict"],"mappings":";;;;;AAYO,SAAS,OAAO,CAAA,EAAmB;AACxC,EAAA,OAAO,WAAW,QAAQ,CAAA,CAAE,OAAO,CAAC,CAAA,CAAE,OAAO,KAAK,CAAA;AACpD;AAYO,SAAS,cAAc,KAAA,EAAwB;AACpD,EAAA,OAAO,IAAA,CAAK,SAAA,CAAU,YAAA,CAAa,KAAK,CAAC,CAAA;AAC3C;AAEA,SAAS,aAAa,KAAA,EAAyB;AAC7C,EAAA,IAAI,KAAA,KAAU,MAAM,OAAO,IAAA;AAC3B,EAAA,IAAI,MAAM,OAAA,CAAQ,KAAK,GAAG,OAAO,KAAA,CAAM,IAAI,YAAY,CAAA;AACvD,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,EAAA,MAAM,MAAA,GAAS,KAAA;AACf,EAAA,OAAO,MAAA,CAAO,WAAA;AAAA,IACZ,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CACf,IAAA,GACA,MAAA,CAAO,CAAC,GAAA,KAAQ,MAAA,CAAO,GAAG,CAAA,KAAM,MAAS,CAAA,CACzC,GAAA,CAAI,CAAC,GAAA,KAAQ,CAAC,GAAA,EAAK,aAAa,MAAA,CAAO,GAAG,CAAC,CAAC,CAAU;AAAA,GAC3D;AACF;AAMO,SAAS,eAAe,KAAA,EAAuB;AACpD,EAAA,OAAO,KAAA,CAAM,SAAA,CAAU,KAAK,CAAA,CAAE,IAAA,EAAK;AACrC;;;AC7BO,IAAM,oBAAA,GAAuB,CAAA;AA0B7B,SAAS,gBAAgB,MAAA,EAAgC;AAC9D,EAAA,OAAO,MAAA;AAAA,IACL,aAAA,CAAc;AAAA,MACZ,oBAAA,EAAsB,oBAAA;AAAA,MACtB,aAAa,MAAA,CAAO,UAAA;AAAA,MACpB,UAAU,MAAA,CAAO,OAAA;AAAA,MACjB,cAAc,MAAA,CAAO,WAAA;AAAA,MACrB,eAAe,MAAA,CAAO,YAAA;AAAA,MACtB,gBAAgB,MAAA,CAAO,aAAA;AAAA,MACvB,aAAa,MAAA,CAAO,WAAA;AAAA,MACpB,sBAAsB,MAAA,CAAO,kBAAA;AAAA,MAC7B,UAAA,EAAY,MAAA,CAAO,cAAA,CAAe,MAAA,CAAO,cAAc,CAAC;AAAA,KACzD;AAAA,GACH;AACF;AAQO,SAAS,qBAAuC,CAAA,EAA4B;AACjF,EAAA,MAAM,KAAA,GAAqB;AAAA,IACzB,aAAA,EAAe,oBAAA;AAAA,IACf,YAAA,EAAc,CAAA;AAAA,IACd,QAAA,EAAU,KAAK,GAAA;AAAI,GACrB;AACA,EAAA,OAAO,IAAA,CAAK,UAAU,KAAK,CAAA;AAC7B;AAMO,SAAS,uBAAyC,GAAA,EAA0C;AACjG,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC7B,IAAA,IAAI,MAAA,CAAO,aAAA,KAAkB,oBAAA,EAAsB,OAAO,KAAA,CAAA;AAC1D,IAAA,OAAO,MAAA,CAAO,YAAA;AAAA,EAChB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAgDO,SAAS,YAAY,OAAA,EAGT;AACjB,EAAA,MAAM,UAAA,GAAa,SAAS,UAAA,IAAc,GAAA;AAC1C,EAAA,MAAM,eAAe,OAAA,EAAS,YAAA;AAG9B,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAmB;AACrC,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,IAAI,MAAA,GAAS,CAAA;AACb,EAAA,IAAI,SAAA,GAAY,CAAA;AAEhB,EAAA,SAAS,UAAU,KAAA,EAAuB;AACxC,IAAA,OAAO,MAAM,SAAA,KAAc,MAAA,IAAa,KAAA,CAAM,SAAA,IAAa,KAAK,GAAA,EAAI;AAAA,EACtE;AAEA,EAAA,OAAO;AAAA,IACL,MAAM,IAAI,GAAA,EAA0C;AAClD,MAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AAC3B,MAAA,IAAI,UAAU,MAAA,EAAW;AACvB,QAAA,MAAA,EAAA;AACA,QAAA,OAAO,MAAA;AAAA,MACT;AACA,MAAA,IAAI,SAAA,CAAU,KAAK,CAAA,EAAG;AACpB,QAAA,KAAA,CAAM,OAAO,GAAG,CAAA;AAChB,QAAA,MAAA,EAAA;AACA,QAAA,OAAO,MAAA;AAAA,MACT;AACA,MAAA,KAAA,CAAM,OAAO,GAAG,CAAA;AAChB,MAAA,KAAA,CAAM,GAAA,CAAI,KAAK,KAAK,CAAA;AACpB,MAAA,IAAA,EAAA;AACA,MAAA,OAAO,KAAA,CAAM,KAAA;AAAA,IACf,CAAA;AAAA,IAEA,MAAM,GAAA,CAAI,GAAA,EAAa,KAAA,EAAe,KAAA,EAA+B;AACnE,MAAA,MAAM,MAAM,KAAA,IAAS,YAAA;AACrB,MAAA,MAAM,YAAY,GAAA,KAAQ,MAAA,GAAY,IAAA,CAAK,GAAA,KAAQ,GAAA,GAAM,MAAA;AACzD,MAAA,IAAI,MAAM,GAAA,CAAI,GAAG,CAAA,EAAG,KAAA,CAAM,OAAO,GAAG,CAAA;AACpC,MAAA,KAAA,CAAM,GAAA,CAAI,GAAA,EAAK,EAAE,KAAA,EAAO,WAAW,CAAA;AACnC,MAAA,OAAO,KAAA,CAAM,OAAO,UAAA,EAAY;AAC9B,QAAA,MAAM,MAAA,GAAS,KAAA,CAAM,IAAA,EAAK,CAAE,MAAK,CAAE,KAAA;AACnC,QAAA,IAAI,WAAW,MAAA,EAAW;AAC1B,QAAA,KAAA,CAAM,OAAO,MAAM,CAAA;AACnB,QAAA,SAAA,EAAA;AAAA,MACF;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,OAAO,GAAA,EAA4B;AACvC,MAAA,KAAA,CAAM,OAAO,GAAG,CAAA;AAAA,IAClB,CAAA;AAAA,IAEA,KAAA,GAAoB;AAClB,MAAA,OAAO;AAAA,QACL,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,IAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAAA,GACF;AACF;AAMO,IAAM,WAAN,MAAkB;AAAA,EACN,GAAA,uBAAU,GAAA,EAAwB;AAAA,EAEnD,MAAM,GAAA,CAAI,GAAA,EAAa,OAAA,EAAuC;AAC5D,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA;AACjC,IAAA,IAAI,QAAA,KAAa,QAAW,OAAO,QAAA;AACnC,IAAA,MAAM,OAAA,GAAU,OAAA,EAAQ,CAAE,OAAA,CAAQ,MAAM;AACtC,MAAA,IAAA,CAAK,GAAA,CAAI,OAAO,GAAG,CAAA;AAAA,IACrB,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,GAAA,EAAK,OAAO,CAAA;AACzB,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA,EAGA,OAAO,GAAA,EAAmB;AACxB,IAAA,IAAA,CAAK,GAAA,CAAI,OAAO,GAAG,CAAA;AAAA,EACrB;AACF,CAAA;;;ACjLO,IAAM,YAAA,GAAN,cAA2B,KAAA,CAAM;AAAA,EAC7B,IAAA;AAAA,EAET,WAAA,CAAY,SAAiB,OAAA,EAA8C;AACzE,IAAA,KAAA,CAAM,OAAA,EAAS,SAAS,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAM,GAAI,MAAS,CAAA;AAClF,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,SAAS,IAAA,IAAQ,aAAA;AAAA,EAC/B;AACF;AAEO,IAAM,aAAA,GAAN,cAA4B,YAAA,CAAa;AAAA,EAC9C,WAAA,CAAY,SAAiB,OAAA,EAA8C;AACzE,IAAA,KAAA,CAAM,SAAS,OAAO,CAAA;AACtB,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AAAA,EACd;AACF;AAEO,IAAM,WAAA,GAAN,cAA0B,YAAA,CAAa;AAAA,EAC5C,WAAA,CAAY,SAAiB,OAAA,EAA8C;AACzE,IAAA,KAAA,CAAM,SAAS,OAAO,CAAA;AACtB,IAAA,IAAA,CAAK,IAAA,GAAO,aAAA;AAAA,EACd;AACF;AAEO,IAAM,oBAAA,GAAN,cAAmC,YAAA,CAAa;AAAA,EAC5C,kBAAA;AAAA,EACA,SAAA;AAAA,EACA,KAAA;AAAA,EAET,WAAA,CACE,SACA,OAAA,EAMA;AACA,IAAA,KAAA,CAAM,OAAA,EAAS,EAAE,IAAA,EAAM,OAAA,CAAQ,OAAO,KAAA,EAAO,OAAA,CAAQ,OAAO,CAAA;AAC5D,IAAA,IAAA,CAAK,IAAA,GAAO,sBAAA;AACZ,IAAA,IAAA,CAAK,QAAQ,OAAA,CAAQ,KAAA;AACrB,IAAA,IAAA,CAAK,qBAAqB,OAAA,CAAQ,kBAAA;AAClC,IAAA,IAAA,CAAK,YAAY,OAAA,CAAQ,SAAA;AAAA,EAC3B;AACF;AAOO,SAAS,0BAA0B,MAAA,EAA+B;AACvE,EAAA,IAAI,MAAA,YAAkB,cAAc,OAAO,MAAA;AAC3C,EAAA,IAAI,kBAAkB,KAAA,EAAO;AAC3B,IAAA,OAAO,IAAI,aAAA,CAAc,MAAA,CAAO,OAAA,IAAW,sBAAA,EAAwB;AAAA,MACjE,IAAA,EAAM,kBAAA;AAAA,MACN,KAAA,EAAO;AAAA,KACR,CAAA;AAAA,EACH;AACA,EAAA,OAAO,IAAI,aAAA,CAAc,MAAA,CAAO,MAAM,CAAA,EAAG;AAAA,IACvC,IAAA,EAAM,kBAAA;AAAA,IACN,KAAA,EAAO;AAAA,GACR,CAAA;AACH;AAMO,SAAS,eAAe,GAAA,EAM7B;AACA,EAAA,IAAI,EAAE,eAAe,KAAA,CAAA,EAAQ;AAC3B,IAAA,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,OAAA,EAAS,MAAA,CAAO,GAAG,CAAA,EAAE;AAAA,EAC/C;AACA,EAAA,MAAM,IAAA,GAAO,GAAA,YAAe,YAAA,GAAe,GAAA,CAAI,IAAA,GAAO,MAAA;AACtD,EAAA,MAAM,QAAQ,GAAA,CAAI,KAAA,KAAU,SAAY,cAAA,CAAe,GAAA,CAAI,KAAK,CAAA,GAAI,MAAA;AACpE,EAAA,OAAO;AAAA,IACL,MAAM,GAAA,CAAI,IAAA;AAAA,IACV,SAAS,GAAA,CAAI,OAAA;AAAA,IACb,GAAI,IAAA,KAAS,MAAA,GAAY,EAAE,IAAA,KAAS,EAAC;AAAA,IACrC,GAAI,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,KAAU,EAAC;AAAA,IACvC,GAAI,IAAI,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,EAAO,GAAA,CAAI,KAAA,EAAM,GAAI;AAAC,GACxD;AACF;;;AC9GO,IAAM,QAAA,GAAuB;AAAA,EAClC,IAAA,EAAM,UAAA;AAAA,EACN,MAAwB,CAAA,EAAqC;AAC3D,IAAA,OAAO,CAAA;AAAA,EACT;AACF,CAAA;AAgGO,SAAS,qBAAqB,CAAA,EAAwB;AAC3D,EAAA,OAAO,EAAE,IAAA,KAAS,UAAA;AACpB;;;ACnHA,IAAM,qBAAA,GAAwB,oBAAA;AAEvB,IAAM,eAAA,GAAkC;AAAA,EAC7C,YAAA,EAAc,mFAAA;AAAA,EACd,YAAA,EAAc,CAAC,KAAA,EAAe,MAAA,EAA2B,aACvD,QAAA,KAAa,MAAA,GAAY,KAAA,GAAQ,CAAA,EAAG,QAAQ;AAAA,EAAK,KAAK,CAAA,CAAA;AAAA,EACxD,YAAA,EAAc;AAChB,CAAA;AAGO,SAAS,kBAAA,CACd,UACA,KAAA,EACoB;AACpB,EAAA,IAAI,QAAA,CAAS,YAAA,KAAiB,MAAA,EAAW,OAAO,MAAA;AAChD,EAAA,OAAO,SAAS,YAAA,CAAa,OAAA,CAAQ,gBAAgB,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC,CAAA;AACvE;AAGO,SAAS,gBAAA,CACd,QAAA,EACA,KAAA,EACA,KAAA,EACA,QAAA,EACQ;AACR,EAAA,OAAO,QAAA,CAAS,YAAA,CAAa,KAAA,EAAO,KAAA,EAAO,QAAQ,CAAA;AACrD;;;ACpBO,SAAS,cAAc,KAAA,EAAgC;AAC5D,EAAA,IAAI,KAAA,CAAM,SAAS,CAAA,EAAG;AACpB,IAAA,MAAM,IAAI,WAAA,CAAY,CAAA,gDAAA,EAAmD,KAAA,CAAM,MAAM,CAAA,CAAA,CAAA,EAAK;AAAA,MACxF,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACA,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,MAAM,KAAA,GAAQ,MAAM,CAAC,CAAA;AACrB,IAAA,IAAI,KAAA,KAAU,KAAA,CAAM,IAAA,EAAK,EAAG;AAC1B,MAAA,MAAM,IAAI,WAAA;AAAA,QACR,iCAAiC,CAAC,CAAA,kCAAA,EAAqC,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA,CAAA,CAAA;AAAA,QAC5F,EAAE,MAAM,eAAA;AAAgB,OAC1B;AAAA,IACF;AACA,IAAA,MAAM,UAAA,GAAa,KAAA,CAAM,SAAA,CAAU,KAAK,CAAA;AACxC,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,MAAM,IAAI,WAAA,CAAY,CAAA,8BAAA,EAAiC,CAAC,CAAA,UAAA,CAAA,EAAc;AAAA,QACpE,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AACA,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,UAAU,CAAA,EAAG;AACxB,MAAA,MAAM,IAAI,WAAA,CAAY,CAAA,yCAAA,EAA4C,KAAK,SAAA,CAAU,KAAK,CAAC,CAAA,CAAA,CAAA,EAAK;AAAA,QAC1F,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AACA,IAAA,IAAA,CAAK,IAAI,UAAU,CAAA;AAAA,EACrB;AACF;AAMO,SAAS,kBAAA,CACd,YACA,WAAA,EACM;AACN,EAAA,MAAM,CAAA,GAAI,UAAA;AAOV,EAAA,SAAA,CAAU,MAAA,EAAQ,EAAE,IAAI,CAAA;AACxB,EAAA,IAAI,EAAE,WAAA,KAAgB,MAAA,EAAW,SAAA,CAAU,aAAA,EAAe,EAAE,WAAW,CAAA;AAEvE,EAAA,IAAI,gBAAgB,CAAA,EAAG;AACrB,IAAA,IAAI,CAAA,CAAE,QAAQ,MAAA,EAAW;AACvB,MAAA,MAAM,IAAI,YAAY,8CAAA,EAAgD;AAAA,QACpE,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,IACH;AACA,IAAA,SAAA,CAAU,KAAA,EAAO,EAAE,GAAG,CAAA;AACtB,IAAA,IAAI,EAAE,CAAA,CAAE,IAAA,GAAO,CAAA,CAAE,GAAA,CAAA,EAAM;AACrB,MAAA,MAAM,IAAI,WAAA;AAAA,QACR,CAAA,qDAAA,EAAwD,CAAA,CAAE,IAAI,CAAA,MAAA,EAAS,EAAE,GAAG,CAAA,CAAA,CAAA;AAAA,QAC5E,EAAE,MAAM,oBAAA;AAAqB,OAC/B;AAAA,IACF;AAAA,EACF,CAAA,MAAO;AACL,IAAA,IAAI,CAAA,CAAE,WAAW,MAAA,EAAW;AAC1B,MAAA,IAAI,CAAA,CAAE,MAAA,GAAS,CAAA,IAAK,CAAA,CAAE,MAAA,GAAS,KAAK,MAAA,CAAO,KAAA,CAAM,CAAA,CAAE,MAAM,CAAA,EAAG;AAC1D,QAAA,MAAM,IAAI,WAAA,CAAY,CAAA,yCAAA,EAA4C,CAAA,CAAE,MAAM,CAAA,CAAA,CAAA,EAAK;AAAA,UAC7E,IAAA,EAAM;AAAA,SACP,CAAA;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,SAAA,CAAU,MAAc,KAAA,EAAqB;AACpD,EAAA,IAAI,OAAO,KAAA,CAAM,KAAK,KAAK,KAAA,GAAQ,CAAA,IAAK,QAAQ,CAAA,EAAG;AACjD,IAAA,MAAM,IAAI,WAAA,CAAY,CAAA,WAAA,EAAc,IAAI,CAAA,kCAAA,EAAqC,KAAK,CAAA,CAAA,CAAA,EAAK;AAAA,MACrF,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACF;AAEA,IAAM,qBAAA,GAAwB,mBAAA;AAEvB,SAAS,uBAAuB,IAAA,EAAoB;AACzD,EAAA,IAAI,CAAC,qBAAA,CAAsB,IAAA,CAAK,IAAI,CAAA,EAAG;AACrC,IAAA,MAAM,IAAI,WAAA;AAAA,MACR,CAAA,oDAAA,EAAuD,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA,CAAA,CAAA;AAAA,MAC3E,EAAE,MAAM,yBAAA;AAA0B,KACpC;AAAA,EACF;AACF;AAQO,SAAS,qBAAA,CACd,WACA,WAAA,EACM;AACN,EAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EAAG;AAC1B,IAAA,MAAM,IAAI,YAAY,wDAAA,EAA0D;AAAA,MAC9E,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,YAAA,GAAe,UAClB,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,YAAA,CAAa,uBAAuB,UAAU,CAAA,CAC9D,IAAI,CAAC,CAAA,MAAO,EAAE,EAAA,EAAI,CAAA,CAAE,IAAI,GAAA,EAAK,CAAA,CAAE,YAAA,CAAa,cAAA,EAAe,CAAE,CAAA;AAEhE,EAAA,IAAI,YAAA,CAAa,WAAW,CAAA,EAAG;AAE/B,EAAA,MAAM,MAAM,YAAA,CAAa,MAAA;AAAA,IACvB,CAAC,GAAA,EAAK,CAAA,KAAO,EAAE,GAAA,GAAM,GAAA,CAAI,MAAM,CAAA,GAAI,GAAA;AAAA,IACnC,aAAa,CAAC;AAAA,GAChB;AAEA,EAAA,IAAI,WAAA,GAAc,IAAI,GAAA,EAAK;AACzB,IAAA,MAAM,IAAI,WAAA;AAAA,MACR,wBAAwB,WAAW,CAAA,mBAAA,EAAsB,IAAI,EAAE,CAAA,cAAA,EAAiB,IAAI,GAAG,CAAA,6CAAA,CAAA;AAAA,MACvF,EAAE,MAAM,0BAAA;AAA2B,KACrC;AAAA,EACF;AACF;AAMO,SAAS,+BAAA,CACd,sBACA,SAAA,EACM;AACN,EAAA,IAAI,oBAAA,EAAsB;AAC1B,EAAA,MAAM,WAAA,GAAc,UAAU,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,YAAA,CAAa,uBAAuB,cAAc,CAAA;AAC9F,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,MAAM,IAAI,WAAA;AAAA,MACR,CAAA,SAAA,EAAY,YAAY,EAAE,CAAA,mMAAA,CAAA;AAAA,MAC1B,EAAE,MAAM,yBAAA;AAA0B,KACpC;AAAA,EACF;AACF;AAEA,IAAM,aAAA,GAAgB,IAAA;AASf,SAAS,oBAAA,CACd,GACA,KAAA,EACM;AACN,EAAA,IAAI,MAAA,CAAO,KAAA,CAAM,CAAA,CAAE,QAAQ,CAAA,IAAK,EAAE,QAAA,GAAW,CAAA,IAAK,CAAA,CAAE,QAAA,GAAW,CAAA,EAAG;AAChE,IAAA,MAAM,IAAI,aAAA,CAAc,CAAA,+BAAA,EAAkC,CAAA,CAAE,QAAQ,CAAA,qBAAA,CAAA,EAAyB;AAAA,MAC3F,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,QAAQ,CAAA,CAAE,KAAA;AAChB,EAAA,KAAA,MAAW,CAAC,KAAA,EAAO,IAAI,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AACjD,IAAA,IAAI,SAAS,MAAA,EAAW;AACxB,IAAA,IAAI,OAAO,KAAA,CAAM,IAAI,KAAK,IAAA,GAAO,CAAA,IAAK,OAAO,CAAA,EAAG;AAC9C,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,iCAAiC,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,KAAK,IAAI,CAAA,qBAAA,CAAA;AAAA,QAC/D,EAAE,MAAM,sBAAA;AAAuB,OACjC;AAAA,IACF;AAAA,EACF;AAGA,EAAA,KAAA,MAAW,SAAS,KAAA,EAAO;AACzB,IAAA,IAAI,EAAE,SAAS,KAAA,CAAA,EAAQ;AACrB,MAAA,KAAA,CAAM,KAAK,CAAA,GAAI,CAAA;AAAA,IACjB;AAAA,EACF;AAEA,EAAA,IAAI,GAAA,GAAM,CAAA;AACV,EAAA,KAAA,MAAW,SAAS,KAAA,EAAO;AACzB,IAAA,GAAA,IAAO,KAAA,CAAM,KAAK,CAAA,IAAK,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,IAAA,CAAK,GAAA,CAAI,GAAA,GAAM,CAAC,IAAI,aAAA,EAAe;AACrC,IAAA,MAAM,IAAI,aAAA;AAAA,MACR,6BAA6B,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAC,qBAAkB,aAAa,CAAA,CAAA,CAAA;AAAA,MAC1E,EAAE,MAAM,sBAAA;AAAuB,KACjC;AAAA,EACF;AACF;;;ACxLO,IAAM,2BAAA,GAA8B,GAAA;AACpC,IAAM,wBAAA,GAA2B,GAAA;AAoDjC,SAAS,aAA+B,KAAA,EAA8C;AAC3F,EAAA,OAAO;AAAA,IACL,OAAO,KAAA,CAAM,KAAA;AAAA,IACb,YAAY,KAAA,CAAM,UAAA;AAAA,IAClB,WAAW,KAAA,CAAM,SAAA;AAAA,IACjB,UAAA,EAAY,MAAM,UAAA,IAAc,QAAA;AAAA,IAChC,KAAA,EAAO,KAAA,CAAM,KAAA,IAAS,WAAA,EAAY;AAAA,IAClC,QAAA,EAAU,MAAM,QAAA,IAAY,eAAA;AAAA,IAC5B,GAAI,MAAM,QAAA,KAAa,MAAA,GAAY,EAAE,QAAA,EAAU,KAAA,CAAM,QAAA,EAAS,GAAI,EAAC;AAAA,IACnE,GAAI,MAAM,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,EAAQ,KAAA,CAAM,MAAA,EAAO,GAAI,EAAC;AAAA,IAC7D,aAAA,EAAe,MAAM,aAAA,IAAiB,UAAA;AAAA,IACtC,GAAI,MAAM,eAAA,KAAoB,MAAA,GAAY,EAAE,eAAA,EAAiB,KAAA,CAAM,eAAA,EAAgB,GAAI,EAAC;AAAA,IACxF,GAAI,MAAM,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,EAAO,KAAA,CAAM,KAAA,EAAM,GAAI,EAAC;AAAA,IAC1D,kBAAA,EAAoB,MAAM,kBAAA,IAAsB,EAAA;AAAA,IAChD,WAAA,EAAa;AAAA,GACf;AACF;AAkBO,SAAS,yBACd,KAAA,EACM;AACN,EAAA,IAAI,KAAA,CAAM,IAAA,KAAS,MAAA,EAAW,sBAAA,CAAuB,MAAM,IAAI,CAAA;AAC/D,EAAA,aAAA,CAAc,MAAM,KAAK,CAAA;AACzB,EAAA,qBAAA,CAAsB,KAAA,CAAM,SAAA,EAAW,KAAA,CAAM,KAAA,CAAM,MAAM,CAAA;AACzD,EAAA,kBAAA,CAAmB,KAAA,CAAM,UAAA,EAAY,KAAA,CAAM,KAAA,CAAM,MAAM,CAAA;AACvD,EAAA,+BAAA,CAAgC,oBAAA,CAAqB,KAAA,CAAM,UAAU,CAAA,EAAG,MAAM,SAAS,CAAA;AACvF,EAAA,KAAA,MAAW,QAAA,IAAY,MAAM,SAAA,EAAW;AACtC,IAAA,QAAA,CAAS,QAAA,GAAW,MAAM,KAAK,CAAA;AAAA,EACjC;AACF;;;AC/FO,SAAS,eAAA,GAA+B;AAC7C,EAAA,OAAO;AAAA,IACL,oBAAoB,EAAC;AAAA,IACrB,gBAAgB,EAAC;AAAA,IACjB,WAAA,EAAa,KAAK,GAAA,EAAI;AAAA,IACtB,QAAA,EAAU;AAAA,GACZ;AACF;AAMO,SAAS,SAAA,CAAU,SAAsB,QAAA,EAAiC;AAC/E,EAAA,OAAO;AAAA,IACL,cAAc,QAAA,CAAS,EAAA;AAAA,IACvB,kBAAA,EAAoB,CAAC,GAAG,OAAA,CAAQ,kBAAkB,CAAA;AAAA,IAClD,cAAA,EAAgB,CAAC,GAAG,OAAA,CAAQ,cAAc,CAAA;AAAA,IAC1C,SAAA,EAAW,IAAA,CAAK,GAAA,EAAI,GAAI,OAAA,CAAQ,WAAA;AAAA,IAChC,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,eAAA,EAAiB,SAAS,YAAA,CAAa,mBAAA;AAAA,IACvC,kBAAA,EAAoB,SAAS,YAAA,CAAa;AAAA,GAC5C;AACF;AAQO,SAAS,mBAAA,CACd,SACA,gBAAA,EACa;AACb,EAAA,MAAM,eAAe,gBAAA,EAAkB,EAAA,IAAM,QAAQ,kBAAA,CAAmB,EAAA,CAAG,EAAE,CAAA,IAAK,EAAA;AAClF,EAAA,OAAO;AAAA,IACL,YAAA;AAAA,IACA,kBAAA,EAAoB,CAAC,GAAG,OAAA,CAAQ,kBAAkB,CAAA;AAAA,IAClD,cAAA,EAAgB,CAAC,GAAG,OAAA,CAAQ,cAAc,CAAA;AAAA,IAC1C,SAAA,EAAW,IAAA,CAAK,GAAA,EAAI,GAAI,OAAA,CAAQ,WAAA;AAAA,IAChC,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,eAAA,EAAiB,gBAAA,EAAkB,YAAA,CAAa,mBAAA,IAAuB,MAAA;AAAA,IACvE,kBAAA,EAAoB,gBAAA,EAAkB,YAAA,CAAa,kBAAA,IAAsB;AAAA,GAC3E;AACF;;;AC/CO,SAAS,YAAY,MAAA,EAAqD;AAC/E,EAAA,IAAI,MAAA,KAAW,MAAA,IAAa,CAAC,MAAA,CAAO,SAAS,OAAO,MAAA;AACpD,EAAA,MAAM,SAAS,MAAA,CAAO,MAAA;AACtB,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,EAAU,OAAO,MAAA;AACvC,EAAA,IAAI,MAAA,YAAkB,KAAA,EAAO,OAAO,MAAA,CAAO,OAAA;AAC3C,EAAA,IAAI,MAAA,KAAW,MAAA,EAAW,OAAO,MAAA,CAAO,MAAM,CAAA;AAC9C,EAAA,OAAO,SAAA;AACT;AAMO,SAAS,eAAe,MAAA,EAA8B;AAC3D,EAAA,MAAM,SAAS,MAAA,CAAO,MAAA;AACtB,EAAA,OAAO,MAAA,YAAkB,KAAA,IAAS,MAAA,CAAO,IAAA,KAAS,cAAA;AACpD;AAEO,SAAS,qBAAA,CACd,IAAA,EACA,MAAA,EACA,QAAA,EACY;AACZ,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IACN,MAAA,EAAQ,EAAE,IAAA,EAAM,WAAA,EAAa,MAAA,EAAO;AAAA,IACpC,IAAA,EAAM,mBAAA,CAAoB,IAAA,EAAM,QAAQ;AAAA,GAC1C;AACF;AASO,SAAS,2BAAA,CACd,IAAA,EACA,KAAA,EACA,MAAA,EACA,QAAA,EACwB;AACxB,EAAA,IAAI,MAAA,KAAW,SAAS,OAAO,MAAA;AAC/B,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IACN,MAAA,EAAQ,EAAE,IAAA,EAAM,kBAAA,EAAoB,KAAA,EAAM;AAAA,IAC1C,IAAA,EAAM,mBAAA,CAAoB,IAAA,EAAM,QAAQ;AAAA,GAC1C;AACF;AAOO,SAAS,wBAAwB,UAAA,EAAsC;AAC5E,EAAA,MAAM,GAAA,GAAM,IAAI,KAAA,CAAM,UAAA,CAAW,OAAO,CAAA;AACxC,EAAA,GAAA,CAAI,OAAO,UAAA,CAAW,IAAA;AACtB,EAAA,IAAI,UAAA,CAAW,KAAA,KAAU,MAAA,EAAW,GAAA,CAAI,QAAQ,UAAA,CAAW,KAAA;AAC3D,EAAA,IAAI,UAAA,CAAW,UAAU,MAAA,EAAW;AAClC,IAAA,MAAA,CAAO,cAAA,CAAe,KAAK,OAAA,EAAS;AAAA,MAClC,KAAA,EAAO,uBAAA,CAAwB,UAAA,CAAW,KAAK,CAAA;AAAA,MAC/C,UAAA,EAAY,KAAA;AAAA,MACZ,QAAA,EAAU;AAAA,KACX,CAAA;AAAA,EACH;AACA,EAAA,OAAO,GAAA;AACT;;;ACtEA,IAAM,cAAA,GAAiB,IAAI,QAAA,EAA+B;AAEnD,SAAS,uBAAA,CACd,QAAA,EACA,cAAA,EACA,MAAA,EACQ;AACR,EAAA,OAAO,eAAA,CAAgB;AAAA,IACrB,YAAY,QAAA,CAAS,EAAA;AAAA,IACrB,SAAS,QAAA,CAAS,OAAA;AAAA,IAClB,aAAa,QAAA,CAAS,WAAA;AAAA,IACtB,YAAA,EAAc,OAAO,QAAA,CAAS,YAAA;AAAA,IAC9B,eAAe,MAAA,CAAO,KAAA;AAAA,IACtB,aAAa,MAAA,CAAO,WAAA;AAAA,IACpB,oBAAoB,MAAA,CAAO,kBAAA;AAAA,IAC3B;AAAA,GACD,CAAA;AACH;AAEO,SAAS,YAAA,CACd,YACA,aAAA,EACa;AACb,EAAA,MAAM,OAAA,GAAyB,CAAC,aAAa,CAAA;AAC7C,EAAA,IAAI,UAAA,KAAe,MAAA,EAAW,OAAA,CAAQ,IAAA,CAAK,UAAU,CAAA;AACrD,EAAA,OAAO,WAAA,CAAY,IAAI,OAAO,CAAA;AAChC;AAEA,eAAsB,iBACpB,QAAA,EACA,cAAA,EACA,MAAA,EACA,IAAA,EACA,QACA,QAAA,EAC0B;AAC1B,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,KAAA,CAAM,IAAI,QAAQ,CAAA;AAC9C,EAAA,IAAI,WAAW,MAAA,EAAW;AACxB,IAAA,MAAM,MAAA,GAAS,uBAA0B,MAAM,CAAA;AAC/C,IAAA,IAAI,WAAW,MAAA,EAAW;AACxB,MAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,EAEF;AACA,EAAA,MAAM,QAAQ,MAAM,UAAA,CAAW,UAAU,cAAA,EAAgB,MAAA,EAAQ,QAAQ,QAAQ,CAAA;AACjF,EAAA,MAAM,OAAO,KAAA,CAAM,GAAA,CAAI,QAAA,EAAU,oBAAA,CAAqB,KAAK,CAAC,CAAA;AAC5D,EAAA,OAAO,KAAA;AACT;AAEA,eAAe,UAAA,CACb,QAAA,EACA,cAAA,EACA,MAAA,EACA,QACA,QAAA,EAC0B;AAC1B,EAAA,OAAO,cAAA,CAAe,GAAA;AAAA,IAAI,QAAA;AAAA,IAAU,MAClC,QAAA,CAAS,MAAA,CAAU,cAAA,EAAgB,OAAO,KAAA,EAAO;AAAA,MAC/C,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,aAAa,MAAA,CAAO,WAAA;AAAA,MACpB,SAAA,EAAW,MAAA,CAAO,MAAA,EAAQ,gBAAA,IAAoB,2BAAA;AAAA,MAC9C;AAAA,KACD;AAAA,GACH;AACF;AAMO,SAAS,eAAe,QAAA,EAAwB;AACrD,EAAA,cAAA,CAAe,OAAO,QAAQ,CAAA;AAChC;;;ACpFO,SAAS,aAAA,CAAc,OAAwB,IAAA,EAAuB;AAC3E,EAAA,IAAI,OAAO,MAAA,EAAW;AACtB,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAU,EAAA,CAAiD,GAAG,IAAI,CAAA;AACxE,IAAA,IAAI,kBAAkB,OAAA,EAAS;AAC7B,MAAA,MAAA,CAAO,MAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACvB;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;;;ACqBO,SAAS,uBAAA,CACd,KACA,QAAA,EACA,IAAA,EACA,QACA,UAAA,EACA,aAAA,EACA,KAAA,EACA,YAAA,EACA,QAAA,EACmB;AACnB,EAAA,IAAI,aAAA,CAAc,OAAA,IAAW,cAAA,CAAe,aAAa,CAAA,EAAG;AAC1D,IAAA,MAAM,OAAA,GAAU,2BAAA;AAAA,MACd,IAAA;AAAA,MACA,kBAAA;AAAA,MACA,MAAA,CAAO,aAAA;AAAA,MACP;AAAA,KACF;AACA,IAAA,IAAI,YAAY,MAAA,EAAW,OAAO,EAAE,IAAA,EAAM,WAAW,OAAA,EAAQ;AAC7D,IAAA,MAAM,IAAI,qBAAqB,2BAAA,EAA6B;AAAA,MAC1D,KAAA,EAAO,kBAAA;AAAA,MACP,oBAAoB,IAAA,CAAK,kBAAA;AAAA,MACzB,SAAA,EAAW,IAAA,CAAK,GAAA,EAAI,GAAI,YAAA;AAAA,MACxB,KAAA,EAAO;AAAA,KACR,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,SAAA,GAAY,YAAY,UAAU,CAAA;AACxC,EAAA,IAAI,cAAc,MAAA,EAAW;AAC3B,IAAA,MAAM,OAAA,GAAU,qBAAA,CAAyB,IAAA,EAAM,SAAA,EAAW,QAAQ,CAAA;AAClE,IAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,OAAA,EAAQ;AAAA,EACpC;AAEA,EAAA,OAAO,oBAAoB,GAAA,EAAK,QAAA,EAAU,IAAA,EAAM,MAAA,EAAQ,OAAO,QAAQ,CAAA;AACzE;AAEA,SAAS,oBACP,GAAA,EACA,QAAA,EACA,IAAA,EACA,MAAA,EACA,OACA,QAAA,EACmB;AACnB,EAAA,MAAM,OAAA,GAAU,0BAA0B,GAAG,CAAA;AAC7C,EAAA,IAAI,EAAE,mBAAmB,aAAA,CAAA,EAAgB;AAEvC,IAAA,MAAM,OAAA;AAAA,EACR;AACA,EAAA,IAAA,CAAK,cAAA,CAAe,IAAA,CAAK,EAAE,UAAA,EAAY,QAAA,CAAS,IAAI,KAAA,EAAO,cAAA,CAAe,OAAO,CAAA,EAAG,CAAA;AACpF,EAAA,aAAA,CAAc,MAAA,CAAO,iBAAiB,OAAA,EAAS;AAAA,IAC7C,YAAY,QAAA,CAAS,EAAA;AAAA,IACrB,SAAS,KAAA,GAAQ;AAAA,GAClB,CAAA;AACD,EAAA,cAAA,CAAe,QAAQ,CAAA;AACvB,EAAA,OAAO,EAAE,MAAM,UAAA,EAAW;AAC5B;AAEO,SAAS,sBACd,GAAA,EACA,QAAA,EACA,IAAA,EACA,MAAA,EACA,OACA,QAAA,EACmB;AACnB,EAAA,MAAM,OAAA,GAAU,0BAA0B,GAAG,CAAA;AAC7C,EAAA,IAAI,EAAE,OAAA,YAAmB,aAAA,CAAA,EAAgB,MAAM,OAAA;AAC/C,EAAA,IAAA,CAAK,cAAA,CAAe,IAAA,CAAK,EAAE,UAAA,EAAY,QAAA,CAAS,IAAI,KAAA,EAAO,cAAA,CAAe,OAAO,CAAA,EAAG,CAAA;AACpF,EAAA,aAAA,CAAc,MAAA,CAAO,iBAAiB,OAAA,EAAS;AAAA,IAC7C,YAAY,QAAA,CAAS,EAAA;AAAA,IACrB,SAAS,KAAA,GAAQ;AAAA,GAClB,CAAA;AACD,EAAA,cAAA,CAAe,QAAQ,CAAA;AACvB,EAAA,OAAO,EAAE,MAAM,UAAA,EAAW;AAC5B;;;ACxGO,SAAS,gBAAA,CACd,IAAA,EACA,YAAA,EACA,cAAA,EACA,MAAA,EACwB;AACxB,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,EAAI,GAAI,YAAA;AAC7B,EAAA,IAAI,OAAA,GAAU,gBAAgB,OAAO,MAAA;AACrC,EAAA,MAAM,OAAA,GAAU,2BAAA,CAA+B,IAAA,EAAM,eAAA,EAAiB,OAAO,aAAa,CAAA;AAC1F,EAAA,IAAI,OAAA,KAAY,QAAW,OAAO,OAAA;AAClC,EAAA,MAAM,IAAI,qBAAqB,wBAAA,EAA0B;AAAA,IACvD,KAAA,EAAO,eAAA;AAAA,IACP,oBAAoB,IAAA,CAAK,kBAAA;AAAA,IACzB,SAAA,EAAW;AAAA,GACZ,CAAA;AACH;AAEO,SAAS,qBAAA,CACd,MACA,MAAA,EACY;AACZ,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IACN,MAAA,EAAQ,EAAE,IAAA,EAAM,WAAA,EAAa,MAAA,EAAO;AAAA,IACpC,IAAA,EAAM,oBAAoB,IAAI;AAAA,GAChC;AACF;AAEO,SAAS,sBAAA,CACd,IAAA,EACA,cAAA,EACA,QAAA,EACA,MAAA,EACY;AAEZ,EAAA,MAAM,UAAA,GACJ,cAAA,KAAmB,MAAA,IACnB,IAAA,CAAK,cAAA,CAAe,MAAA,GAAS,CAAA,IAC7B,IAAA,CAAK,cAAA,CAAe,MAAA,KAAW,IAAA,CAAK,kBAAA,CAAmB,MAAA;AAEzD,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,IAAI,MAAA,CAAO,kBAAkB,OAAA,EAAS;AACpC,MAAA,MAAM,MAAA,GAAS,KAAK,cAAA,CAAe,GAAA,CAAI,CAAC,CAAA,KAAM,uBAAA,CAAwB,CAAA,CAAE,KAAK,CAAC,CAAA;AAC9E,MAAA,MAAM,IAAI,cAAA,CAAe,MAAA,EAAQ,uBAAuB,CAAA;AAAA,IAC1D;AACA,IAAA,MAAMA,QAAAA,GAAsB;AAAA,MAC1B,IAAA,EAAM,SAAA;AAAA,MACN,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,kBAAA;AAAA,QACN,QAAQ,IAAA,CAAK,cAAA,CAAe,IAAI,CAAC,CAAA,KAAM,EAAE,KAAK;AAAA,OAChD;AAAA,MACA,IAAA,EAAM,oBAAoB,IAAI;AAAA,KAChC;AACA,IAAA,aAAA,CAAc,MAAA,CAAO,KAAA,EAAO,QAAA,EAAUA,QAAO,CAAA;AAC7C,IAAA,OAAOA,QAAAA;AAAA,EACT;AAIA,EAAA,MAAM,OAAA,GAAsB;AAAA,IAC1B,IAAA,EAAM,SAAA;AAAA,IACN,MAAA,EAAQ;AAAA,MACN,IAAA,EAAM,iBAAA;AAAA,MACN,kBAAkB,cAAA,IAAkB,EAAE,OAAO,EAAC,EAA+B,UAAU,CAAA,EAAE;AAAA,MACzF,kBAAA,EAAoB;AAAA,KACtB;AAAA,IACA,IAAA,EAAM,oBAAoB,IAAI;AAAA,GAChC;AACA,EAAA,aAAA,CAAc,MAAA,CAAO,KAAA,EAAO,QAAA,EAAU,OAAO,CAAA;AAC7C,EAAA,OAAO,OAAA;AACT;;;AC1DA,IAAM,oBAAA,GAAuB,GAAA;AAStB,SAAS,eAAA,CACd,CAAA,EACA,UAAA,EACA,KAAA,EACoB;AACpB,EAAA,MAAM,CAAA,GAAI,UAAA;AACV,EAAA,MAAM,MAAA,GAAS,sBAAA,CAAuB,CAAA,EAAG,KAAK,CAAA;AAC9C,EAAA,MAAM,GAAA,GAAM,OAAO,CAAC,CAAA;AACpB,EAAA,MAAM,MAAA,GAAS,OAAO,CAAC,CAAA;AAEvB,EAAA,MAAM,WAAA,GAAc,EAAE,WAAA,IAAe,oBAAA;AACrC,EAAA,IAAI,CAAA,CAAE,WAAW,WAAA,EAAa;AAC5B,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,qBAAA;AAAA,MACN,UAAU,CAAA,CAAE,QAAA;AAAA,MACZ,mBAAmB,GAAA,CAAI,KAAA;AAAA,MACvB,2BAA2B,GAAA,CAAI;AAAA,KACjC;AAAA,EACF;AAEA,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,IAAK,CAAA,CAAE,QAAQ,MAAA,EAAW;AAC7C,IAAA,OAAO,mBAAA,CAAoB,GAAA,EAAK,MAAA,EAAQ,CAAC,CAAA;AAAA,EAC3C;AAEA,EAAA,OAAO,mBAAA,CAAoB,GAAA,EAAK,MAAA,EAAQ,CAAC,CAAA;AAC3C;AAEA,SAAS,sBAAA,CACP,GACA,KAAA,EAC8B;AAG9B,EAAA,MAAM,QAAQ,CAAA,CAAE,KAAA;AAChB,EAAA,MAAM,KAAA,GAAsC,KAAA,CAAM,GAAA,CAAI,CAAC,KAAA,MAAW;AAAA,IAChE,KAAA;AAAA,IACA,IAAA,EAAM,MAAM,KAAK;AAAA,GACnB,CAAE,CAAA;AACF,EAAA,KAAA,CAAM,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,IAAA,GAAO,EAAE,IAAI,CAAA;AACpC,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,mBAAA,CACP,GAAA,EACA,MAAA,EACA,CAAA,EACoB;AACpB,EAAA,IAAI,GAAA,CAAI,IAAA,IAAQ,CAAA,CAAE,IAAA,EAAM;AACtB,IAAA,OAAO,EAAE,MAAM,YAAA,EAAc,KAAA,EAAO,IAAI,KAAA,EAAO,WAAA,EAAa,IAAI,IAAA,EAAK;AAAA,EACvE;AACA,EAAA,IAAI,EAAE,GAAA,KAAQ,MAAA,IAAa,GAAA,CAAI,IAAA,IAAQ,EAAE,GAAA,EAAK;AAC5C,IAAA,OAAO,EAAE,MAAM,YAAA,EAAc,KAAA,EAAO,OAAO,KAAA,EAAO,WAAA,EAAa,OAAO,IAAA,EAAK;AAAA,EAC7E;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,WAAA,EAAa,GAAA,EAAK,GAAA,CAAI,KAAA,EAAO,WAAA,EAAa,GAAA,CAAI,IAAA,EAAM,QAAA,EAAU,MAAA,CAAO,KAAA,EAAM;AAC5F;AAEA,SAAS,mBAAA,CACP,GAAA,EACA,MAAA,EACA,CAAA,EACoB;AACpB,EAAA,IAAI,GAAA,CAAI,IAAA,GAAO,CAAA,CAAE,IAAA,EAAM;AACrB,IAAA,OAAO,EAAE,IAAA,EAAM,WAAA,EAAa,GAAA,EAAK,GAAA,CAAI,KAAA,EAAO,WAAA,EAAa,GAAA,CAAI,IAAA,EAAM,QAAA,EAAU,MAAA,CAAO,KAAA,EAAM;AAAA,EAC5F;AACA,EAAA,IAAI,CAAA,CAAE,WAAW,MAAA,IAAa,GAAA,CAAI,OAAO,MAAA,CAAO,IAAA,GAAO,EAAE,MAAA,EAAQ;AAC/D,IAAA,OAAO,EAAE,IAAA,EAAM,WAAA,EAAa,GAAA,EAAK,GAAA,CAAI,KAAA,EAAO,WAAA,EAAa,GAAA,CAAI,IAAA,EAAM,QAAA,EAAU,MAAA,CAAO,KAAA,EAAM;AAAA,EAC5F;AACA,EAAA,OAAO,EAAE,MAAM,YAAA,EAAc,KAAA,EAAO,IAAI,KAAA,EAAO,WAAA,EAAa,IAAI,IAAA,EAAK;AACvE;;;ACnEA,eAAsB,MAAA,CACpB,cAAA,EACA,MAAA,EACA,MAAA,EACqB;AACrB,EAAA,MAAM,OAAO,eAAA,EAAgB;AAE7B,EAAA,MAAM,QAAA,GAAW,YAAY,MAAM,CAAA;AACnC,EAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,IAAA,OAAO,qBAAA,CAAsB,MAAM,QAAQ,CAAA;AAAA,EAC7C;AAEA,EAAA,aAAA,CAAc,MAAA,CAAO,KAAA,EAAO,MAAA,EAAQ,cAAA,EAAgB;AAAA,IAClD,WAAW,MAAA,CAAO,SAAA,CAAU,IAAI,CAAC,CAAA,KAAM,EAAE,EAAE;AAAA,GAC5C,CAAA;AAED,EAAA,MAAM,MAAA,GAAS,cAAc,MAAM,CAAA;AACnC,EAAA,MAAM,YAAA,GAAe,KAAK,GAAA,EAAI;AAC9B,EAAA,IAAI,cAAA;AACJ,EAAA,IAAI,QAAA,GAAW,CAAA;AAEf,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,SAAA,CAAU,QAAQ,CAAA,EAAA,EAAK;AAChD,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,SAAA,CAAU,CAAC,CAAA;AACnC,IAAA,IAAI,QAAA,IAAY,OAAO,QAAA,EAAU;AACjC,IAAA,QAAA,EAAA;AACA,IAAA,IAAA,CAAK,kBAAA,CAAmB,IAAA,CAAK,QAAA,CAAS,EAAE,CAAA;AAExC,IAAA,MAAM,qBAAqB,gBAAA,CAAiB,IAAA,EAAM,YAAA,EAAc,MAAA,CAAO,gBAAgB,MAAM,CAAA;AAC7F,IAAA,IAAI,uBAAuB,MAAA,EAAW;AACpC,MAAA,aAAA,CAAc,MAAA,CAAO,KAAA,EAAO,QAAA,EAAU,kBAAkB,CAAA;AACxD,MAAA,OAAO,kBAAA;AAAA,IACT;AAEA,IAAA,MAAM,QAAA,GAAW,YAAY,MAAM,CAAA;AACnC,IAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,MAAA,MAAM,OAAA,GAAU,qBAAA,CAAyB,IAAA,EAAM,QAAA,EAAU,QAAQ,CAAA;AACjE,MAAA,aAAA,CAAc,MAAA,CAAO,KAAA,EAAO,QAAA,EAAU,OAAO,CAAA;AAC7C,MAAA,OAAO,OAAA;AAAA,IACT;AAEA,IAAA,MAAM,cAAA,GAAiB,CAAA,KAAM,MAAA,CAAO,SAAA,CAAU,MAAA,GAAS,CAAA;AACvD,IAAA,MAAM,UAAU,MAAM,eAAA;AAAA,MACpB,QAAA;AAAA,MACA,cAAA;AAAA,MACA,MAAA;AAAA,MACA,IAAA;AAAA,MACA,MAAA;AAAA,MACA,CAAA;AAAA,MACA,YAAA;AAAA,MACA,MAAA,CAAO,gBAAA;AAAA,MACP;AAAA,KACF;AAEA,IAAA,IAAI,OAAA,CAAQ,SAAS,SAAA,EAAW;AAC9B,MAAA,aAAA,CAAc,MAAA,CAAO,KAAA,EAAO,QAAA,EAAU,OAAA,CAAQ,OAAO,CAAA;AACrD,MAAA,OAAO,OAAA,CAAQ,OAAA;AAAA,IACjB;AACA,IAAA,IAAI,OAAA,CAAQ,SAAS,eAAA,EAAiB;AACpC,MAAA,cAAA,GAAiB,OAAA,CAAQ,UAAA;AACzB,MAAA,aAAA,CAAc,MAAA,CAAO,KAAA,EAAO,QAAA,EAAU,OAAA,CAAQ,OAAO,CAAA;AACrD,MAAA,OAAO,OAAA,CAAQ,OAAA;AAAA,IACjB;AACA,IAAA,IAAI,OAAA,CAAQ,UAAA,KAAe,MAAA,EAAW,cAAA,GAAiB,OAAA,CAAQ,UAAA;AAAA,EACjE;AAEA,EAAA,OAAO,sBAAA,CAAuB,IAAA,EAAM,cAAA,EAAgB,QAAA,EAAU,MAAM,CAAA;AACtE;AAQA,SAAS,cAAgC,MAAA,EAAiC;AACxE,EAAA,OAAO;AAAA,IACL,gBAAA,EAAkB,MAAA,CAAO,MAAA,EAAQ,gBAAA,IAAoB,2BAAA;AAAA,IACrD,cAAA,EAAgB,MAAA,CAAO,MAAA,EAAQ,cAAA,IAAkB,wBAAA;AAAA,IACjD,QAAA,EAAU,MAAA,CAAO,MAAA,EAAQ,QAAA,IAAY,OAAO,SAAA,CAAU;AAAA,GACxD;AACF;AAEA,eAAe,eAAA,CACb,UACA,cAAA,EACA,MAAA,EACA,MACA,UAAA,EACA,KAAA,EACA,YAAA,EACA,gBAAA,EACA,cAAA,EAC4B;AAC5B,EAAA,MAAM,QAAA,GAAW,uBAAA,CAAwB,QAAA,EAAU,cAAA,EAAgB,MAAM,CAAA;AACzE,EAAA,MAAM,aAAA,GAAgB,WAAA,CAAY,OAAA,CAAQ,gBAAgB,CAAA;AAC1D,EAAA,MAAM,YAAA,GAAe,YAAA,CAAa,UAAA,EAAY,aAAa,CAAA;AAE3D,EAAA,IAAI,YAAA;AACJ,EAAA,IAAI;AACF,IAAA,YAAA,GAAe,MAAM,gBAAA;AAAA,MACnB,QAAA;AAAA,MACA,cAAA;AAAA,MACA,MAAA;AAAA,MACA,IAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF,SAAS,GAAA,EAAK;AACZ,IAAA,OAAO,uBAAA;AAAA,MACL,GAAA;AAAA,MACA,QAAA;AAAA,MACA,IAAA;AAAA,MACA,MAAA;AAAA,MACA,UAAA;AAAA,MACA,aAAA;AAAA,MACA,KAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAEA,EAAA,IAAI;AACF,IAAA,oBAAA,CAAqB,YAAA,EAAc,OAAO,KAAK,CAAA;AAAA,EACjD,SAAS,GAAA,EAAK;AACZ,IAAA,OAAO,sBAAsB,GAAA,EAAK,QAAA,EAAU,IAAA,EAAM,MAAA,EAAQ,OAAO,QAAQ,CAAA;AAAA,EAC3E;AAEA,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,UAAA,CAAW,KAAA,CAAM,YAAY,CAAA;AACvD,EAAA,MAAM,SAAS,eAAA,CAAgB,UAAA,EAAY,MAAA,CAAO,UAAA,EAAY,OAAO,KAAK,CAAA;AAE1E,EAAA,IAAI,MAAA,CAAO,SAAS,YAAA,EAAc;AAChC,IAAA,MAAM,OAAA,GAAyB;AAAA,MAC7B,IAAA,EAAM,YAAA;AAAA,MACN,OAAO,MAAA,CAAO,KAAA;AAAA,MACd,aAAa,MAAA,CAAO,WAAA;AAAA,MACpB,IAAA,EAAM,SAAA,CAAU,IAAA,EAAM,QAAQ;AAAA,KAChC;AACA,IAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,OAAA,EAAQ;AAAA,EACpC;AAEA,EAAA,IAAI,MAAA,CAAO,SAAS,qBAAA,EAAuB;AACzC,IAAA,MAAM,OAAA,GAAsB;AAAA,MAC1B,IAAA,EAAM,SAAA;AAAA,MACN,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM,qBAAA;AAAA,QACN,UAAU,MAAA,CAAO,QAAA;AAAA,QACjB,mBAAmB,MAAA,CAAO,iBAAA;AAAA,QAC1B,2BAA2B,MAAA,CAAO;AAAA,OACpC;AAAA,MACA,IAAA,EAAM,SAAA,CAAU,IAAA,EAAM,QAAQ;AAAA,KAChC;AACA,IAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,OAAA,EAAQ;AAAA,EACpC;AAGA,EAAA,IAAI,cAAA,EAAgB;AAClB,IAAA,MAAM,OAAA,GAAwB;AAAA,MAC5B,IAAA,EAAM,WAAA;AAAA,MACN,KAAK,MAAA,CAAO,GAAA;AAAA,MACZ,aAAa,MAAA,CAAO,WAAA;AAAA,MACpB,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,YAAA,EAAc,UAAA;AAAA,MACd,IAAA,EAAM,SAAA,CAAU,IAAA,EAAM,QAAQ;AAAA,KAChC;AACA,IAAA,OAAO,EAAE,IAAA,EAAM,eAAA,EAAiB,OAAA,EAAS,UAAA,EAAW;AAAA,EACtD;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,UAAA,EAAY,UAAA,EAAW;AACxC;AC5KA,IAAI,eAAA;AAMG,SAAS,eAAA,GAA6B;AAC3C,EAAA,IAAI,eAAA,KAAoB,QAAW,OAAO,eAAA;AAC1C,EAAA,MAAM,GAAA,GAAgB,aAAa,aAAa,CAAA;AAChD,EAAA,eAAA,GAAkB;AAAA,IAChB,EAAA,EAAI,oBAAA;AAAA,IACJ,OAAO,KAAA,EAAyB;AAI9B,MAAA,MAAM,mBAAmB,KAAA,CAAM,UAAA,CAAW,GAAG,CAAA,GAAI,KAAA,GAAQ,IAAI,KAAK,CAAA,CAAA;AAClE,MAAA,MAAM,GAAA,GAAM,GAAA,CAAI,MAAA,CAAO,gBAAgB,CAAA;AACvC,MAAA,OAAO,KAAA,CAAM,KAAK,GAAG,CAAA;AAAA,IACvB,CAAA;AAAA,IACA,aAAa,KAAA,EAAuB;AAClC,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA;AAC7B,MAAA,MAAM,KAAA,GAAQ,IAAI,CAAC,CAAA;AACnB,MAAA,IAAI,UAAU,MAAA,EAAW;AACvB,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,4CAAA,EAA+C,KAAK,SAAA,CAAU,KAAK,CAAC,CAAA,CAAE,CAAA;AAAA,MACxF;AACA,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,GACF;AACA,EAAA,OAAO,eAAA;AACT;AAeO,SAAS,uBAAA,CACd,WACA,KAAA,EACuD;AACvD,EAAA,MAAM,aAAA,uBAAoB,GAAA,EAAoB;AAC9C,EAAA,KAAA,MAAW,SAAS,KAAA,EAAO;AACzB,IAAA,MAAM,OAAA,GAAU,SAAA,CAAU,YAAA,CAAa,KAAK,CAAA;AAC5C,IAAA,MAAM,UAAA,GAAa,aAAA,CAAc,GAAA,CAAI,OAAO,CAAA;AAC5C,IAAA,IAAI,UAAA,KAAe,MAAA,IAAa,UAAA,KAAe,KAAA,EAAO;AACpD,MAAA,OAAO,EAAE,CAAA,EAAG,UAAA,EAAY,CAAA,EAAG,OAAO,OAAA,EAAQ;AAAA,IAC5C;AACA,IAAA,aAAA,CAAc,GAAA,CAAI,SAAS,KAAK,CAAA;AAAA,EAClC;AACA,EAAA,OAAO,MAAA;AACT;AAOO,SAAS,cAAA,CACd,SAAA,EACA,KAAA,EACA,IAAA,GAAO,GAAA,EACiB;AACxB,EAAA,OAAO,MAAA,CAAO,WAAA;AAAA,IACZ,KAAA,CAAM,GAAA,CAAI,CAAC,KAAA,KAAU,CAAC,MAAA,CAAO,SAAA,CAAU,YAAA,CAAa,KAAK,CAAC,CAAA,EAAG,IAAI,CAAU;AAAA,GAC7E;AACF;;;AC9EO,SAAS,0BAAA,CACd,KAAA,EACA,aAAA,EACA,UAAA,EACA,SAAA,EACiB;AACjB,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAe;AACnC,EAAA,IAAI,WAAA,GAAc,CAAA;AAElB,EAAA,KAAA,MAAW,SAAS,aAAA,EAAe;AACjC,IAAA,MAAM,GAAA,GAAM,SAAA,CAAU,MAAA,CAAO,KAAA,CAAM,KAAK,CAAA;AACxC,IAAA,MAAM,OAAA,GAAU,IAAI,CAAC,CAAA;AACrB,IAAA,IAAI,YAAY,MAAA,EAAW;AAC3B,IAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,GAAA,CAAI,OAAO,CAAA;AACpC,IAAA,IAAI,UAAU,MAAA,EAAW;AACzB,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,OAAO,CAAA;AACnC,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,IAAK,CAAA;AACvC,IAAA,IAAI,OAAO,QAAA,EAAU;AACnB,MAAA,OAAA,CAAQ,GAAA,CAAI,OAAO,IAAI,CAAA;AACvB,MAAA,WAAA,IAAe,IAAA,GAAO,QAAA;AAAA,IACxB;AAAA,EACF;AAEA,EAAA,OAAO,WAAA,CAAY,KAAA,EAAO,OAAA,EAAS,WAAW,CAAA;AAChD;AAEO,SAAS,8BAAA,CACd,OACA,aAAA,EACiB;AACjB,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAe;AACnC,EAAA,IAAI,WAAA,GAAc,CAAA;AAElB,EAAA,KAAA,MAAW,SAAS,KAAA,EAAO;AACzB,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,EAAK;AAC3B,IAAA,IAAI,QAAA,GAAW,CAAA;AACf,IAAA,KAAA,MAAW,SAAS,aAAA,EAAe;AACjC,MAAA,MAAM,GAAA,GAAM,KAAA,CAAM,KAAA,CAAM,IAAA,EAAK;AAE7B,MAAA,IAAI,QAAQ,OAAA,IAAY,GAAA,IAAO,OAAA,CAAQ,UAAA,CAAW,GAAG,CAAA,EAAI;AACvD,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,OAAO,CAAA;AACnC,QAAA,IAAI,IAAA,GAAO,UAAU,QAAA,GAAW,IAAA;AAAA,MAClC;AAAA,IACF;AACA,IAAA,IAAI,WAAW,CAAA,EAAG;AAChB,MAAA,OAAA,CAAQ,GAAA,CAAI,OAAO,QAAQ,CAAA;AAC3B,MAAA,WAAA,IAAe,QAAA;AAAA,IACjB;AAAA,EACF;AAEA,EAAA,OAAO,WAAA,CAAY,KAAA,EAAO,OAAA,EAAS,WAAW,CAAA;AAChD;AAEA,SAAS,WAAA,CACP,KAAA,EACA,OAAA,EACA,WAAA,EACiB;AACjB,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,WAAW,CAAA;AACxC,EAAA,MAAM,QAAgC,EAAC;AACvC,EAAA,KAAA,MAAW,SAAS,KAAA,EAAO;AACzB,IAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,IAAK,CAAA;AAClC,IAAA,KAAA,CAAM,KAAK,CAAA,GAAI,WAAA,GAAc,CAAA,GAAI,MAAM,WAAA,GAAc,CAAA;AAAA,EACvD;AACA,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA;AAAA,GACF;AACF;;;AC3EA,IAAM,gBAAA,GAAmB,GAAA;AAelB,SAAS,aAAa,IAAA,EAA6B;AAGxD,EAAA,MAAM,aAAA,uBAAoB,GAAA,EAAY;AACtC,EAAA,MAAM,YAAY,IAAA,CAAK,SAAA;AAIvB,EAAA,MAAM,aAAA,GACJ,SAAA,KAAc,MAAA,GACV,EAAC,GACD;AAAA,IACE,QAAA,EAAU,CAAC,KAAA,KAAmC;AAC5C,MAAA,kBAAA,CAAmB,SAAA,EAAW,OAAO,aAAa,CAAA;AAAA,IACpD;AAAA,GACF;AAEN,EAAA,OAAO;AAAA,IACL,IAAI,IAAA,CAAK,EAAA;AAAA,IACT,SAAS,IAAA,CAAK,OAAA;AAAA,IACd,aAAa,IAAA,CAAK,WAAA;AAAA,IAClB,cAAc,IAAA,CAAK,YAAA;AAAA,IACnB,GAAG,aAAA;AAAA,IAEH,MAAM,MAAA,CACJ,KAAA,EACA,KAAA,EACA,IAAA,EAC0B;AAE1B,MAAA,IAAI,SAAA;AACJ,MAAA,IAAI,oBAAA;AACJ,MAAA,IAAI,cAAc,MAAA,EAAW;AAC3B,QAAA,kBAAA,CAAmB,SAAA,EAAW,OAAO,aAAa,CAAA;AAClD,QAAA,SAAA,GAAY,cAAA,CAAe,SAAA,EAAW,KAAA,EAAO,gBAAgB,CAAA;AAC7D,QAAA,oBAAA,GAAuB,gBAAA,CAAiB,WAAW,KAAK,CAAA;AAAA,MAC1D;AAEA,MAAA,MAAM,WAAqD,EAAC;AAC5D,MAAA,MAAM,MAAA,GAAS,kBAAA,CAAmB,IAAA,CAAK,QAAA,EAAU,KAAK,CAAA;AACtD,MAAA,IAAI,WAAW,MAAA,EAAW;AACxB,QAAA,QAAA,CAAS,KAAK,EAAE,IAAA,EAAM,QAAA,EAAU,OAAA,EAAS,QAAQ,CAAA;AAAA,MACnD;AACA,MAAA,QAAA,CAAS,IAAA,CAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAS,gBAAA,CAAiB,IAAA,CAAK,QAAA,EAAU,KAAA,EAAO,KAAK,CAAA,EAAG,CAAA;AAEtF,MAAA,IAAI,QAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,GAA6D;AAAA,UACjE,OAAO,IAAA,CAAK,OAAA;AAAA,UACZ,QAAA;AAAA,UACA,aAAa,IAAA,CAAK,WAAA;AAAA,UAClB,QAAA,EAAU,IAAA;AAAA,UACV,YAAA,EAAc,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,YAAA,CAAa,cAAA,EAAgB,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG,CAAC,CAAC,CAAA;AAAA;AAAA,UAEtF,qBAAA,EAAuB;AAAA,SACzB;AACA,QAAA,IAAI,IAAA,CAAK,IAAA,KAAS,KAAA,CAAA,EAAW,MAAA,CAAO,OAAO,IAAA,CAAK,IAAA;AAChD,QAAA,IAAI,SAAA,KAAc,KAAA,CAAA,EAAW,MAAA,CAAO,UAAA,GAAa,SAAA;AAEjD,QAAA,MAAM,WAAA,GAA0D;AAAA,UAC9D,SAAS,IAAA,CAAK;AAAA,SAChB;AACA,QAAA,IAAI,IAAA,CAAK,MAAA,KAAW,KAAA,CAAA,EAAW,WAAA,CAAY,SAAS,IAAA,CAAK,MAAA;AACzD,QAAA,QAAA,GAAW,MAAM,IAAA,CAAK,MAAA,CAAO,KAAK,WAAA,CAAY,MAAA,CAAO,QAAQ,WAAW,CAAA;AAAA,MAC1E,SAAS,GAAA,EAAK;AACZ,QAAA,MAAM,0BAA0B,GAAG,CAAA;AAAA,MACrC;AAEA,MAAA,MAAM,MAAA,GAAS,QAAA,CAAS,OAAA,CAAQ,CAAC,CAAA;AACjC,MAAA,IAAI,WAAW,MAAA,EAAW;AACxB,QAAA,MAAM,IAAI,cAAc,iCAAA,EAAmC;AAAA,UACzD,IAAA,EAAM;AAAA,SACP,CAAA;AAAA,MACH;AACA,MAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,QAAA,EAAU,OAAA,GAAU,CAAC,CAAA,EAAG,YAAA;AACrD,MAAA,IAAI,aAAA,KAAkB,MAAA,IAAa,aAAA,CAAc,MAAA,KAAW,CAAA,EAAG;AAC7D,QAAA,MAAM,IAAI,cAAc,+CAAA,EAAiD;AAAA,UACvE,IAAA,EAAM;AAAA,SACP,CAAA;AAAA,MACH;AAEA,MAAA,OAAO,SAAA,KAAc,MAAA,IAAa,oBAAA,KAAyB,MAAA,GACvD,0BAAA,CAA2B,KAAA,EAAO,aAAA,EAAe,oBAAA,EAAsB,SAAS,CAAA,GAChF,8BAAA,CAA+B,KAAA,EAAO,aAAa,CAAA;AAAA,IACzD;AAAA,GACF;AACF;AAEA,SAAS,kBAAA,CACP,SAAA,EACA,KAAA,EACA,IAAA,EACM;AACN,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA;AACpC,EAAA,IAAI,IAAA,CAAK,GAAA,CAAI,OAAO,CAAA,EAAG;AACvB,EAAA,MAAM,SAAA,GAAY,uBAAA,CAAwB,SAAA,EAAW,KAAK,CAAA;AAC1D,EAAA,IAAI,cAAc,MAAA,EAAW;AAC3B,IAAA,MAAM,IAAI,WAAA;AAAA,MACR,CAAA,+CAAA,EAAkD,IAAA,CAAK,SAAA,CAAU,SAAA,CAAU,CAAC,CAAC,CAAA,KAAA,EAAQ,IAAA,CAAK,SAAA,CAAU,SAAA,CAAU,CAAC,CAAC,CAAA,yBAAA,EAA4B,UAAU,OAAO,CAAA,+EAAA,CAAA;AAAA,MAC7J,EAAE,MAAM,0BAAA;AAA2B,KACrC;AAAA,EACF;AACA,EAAA,IAAA,CAAK,IAAI,OAAO,CAAA;AAClB;AAEA,SAAS,gBAAA,CACP,WACA,KAAA,EACgB;AAChB,EAAA,MAAM,GAAA,uBAAU,GAAA,EAAe;AAC/B,EAAA,KAAA,MAAW,SAAS,KAAA,EAAO;AACzB,IAAA,GAAA,CAAI,GAAA,CAAI,SAAA,CAAU,YAAA,CAAa,KAAK,GAAG,KAAK,CAAA;AAAA,EAC9C;AACA,EAAA,OAAO,GAAA;AACT;;;AC3GA,IAAM,qBAAA,GAA8C;AAAA,EAClD,kBAAA,EAAoB,UAAA;AAAA,EACpB,mBAAA,EAAqB,OAAA;AAAA;AAAA,EAErB,cAAA,EAAgB;AAClB,CAAA;AAUO,SAAS,MAAA,CAAO,OAAoB,IAAA,EAAwC;AACjF,EAAA,MAAM,MAAA,GAAS,IAAI,MAAA,CAAO;AAAA,IACxB,MAAA,EAAwB,OAAA,CAAQ,GAAA,CAAI,cAAA;AAAA,IACpC,SAAS,IAAA,EAAM,OAAA;AAAA,IACf,SAAS,IAAA,EAAM;AAAA,GAChB,CAAA;AACD,EAAA,OAAO,YAAA,CAAa;AAAA,IAClB,EAAA,EAAI,UAAU,KAAK,CAAA,CAAA;AAAA,IACnB,OAAA,EAAS,KAAA;AAAA,IACT,WAAA,EAAa,oBAAA;AAAA,IACb,YAAA,EAAc,qBAAA;AAAA,IACd,MAAA;AAAA,IACA,WAAW,eAAA;AAAgB,GAC5B,CAAA;AACH;AAEA,IAAM,uBAAA,GAA0B,2BAAA;AAChC,IAAM,sBAAA,GAAyB,QAAA;AAcxB,SAAS,MAAA,CAAO,OAAe,IAAA,EAAwC;AAC5E,EAAA,MAAM,MAAA,GAAS,IAAI,MAAA,CAAO;AAAA,IACxB,MAAA,EAAwB,sBAAA;AAAA,IACxB,OAAA,EAA0B,uBAAA;AAAA,IAC1B,SAAS,IAAA,EAAM;AAAA,GAChB,CAAA;AACD,EAAA,OAAO,YAAA,CAAa;AAAA,IAClB,EAAA,EAAI,UAAU,KAAK,CAAA,CAAA;AAAA,IACnB,OAAA,EAAS,KAAA;AAAA;AAAA,IAET,WAAA,EAAa,UAAU,KAAK,CAAA,CAAA;AAAA,IAC5B,YAAA,EAAc,qBAAA;AAAA,IACd;AAAA;AAAA,GAED,CAAA;AACH;;;AC1EA,IAAM,iBAAA,GAA+C;AAAA,EACnD,MAAA,EAAQ,CAAC,KAAA,KAAkB,MAAA,CAAO,KAAK,CAAA;AAAA,EACvC,MAAA,EAAQ,CAAC,KAAA,KAAkB,MAAA,CAAO,KAAK;AACzC,CAAA;AAYO,SAAS,kBAAkB,GAAA,EAAiD;AACjF,EAAA,IAAI,GAAA,KAAQ,MAAA,EAAW,OAAO,EAAC;AAC/B,EAAA,MAAM,OAAA,GAAU,IAAI,IAAA,EAAK;AACzB,EAAA,IAAI,CAAC,OAAA,EAAS,OAAO,EAAC;AAEtB,EAAA,OAAO,OAAA,CACJ,KAAA,CAAM,GAAG,CAAA,CACT,IAAI,CAAC,IAAA,KAAS,IAAA,CAAK,IAAA,EAAM,CAAA,CACzB,MAAA,CAAO,OAAO,CAAA,CACd,IAAI,kBAAkB,CAAA;AAC3B;AAEA,SAAS,mBAAmB,KAAA,EAA4B;AACtD,EAAA,MAAM,UAAA,GAAa,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AACpC,EAAA,IAAI,aAAa,CAAA,EAAG;AAClB,IAAA,MAAM,IAAI,WAAA;AAAA,MACR,CAAA,mCAAA,EAAsC,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA,gCAAA,CAAA;AAAA,MAC3D,EAAE,MAAM,2BAAA;AAA4B,KACtC;AAAA,EACF;AACA,EAAA,MAAM,UAAU,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,UAAU,EAAE,IAAA,EAAK;AAChD,EAAA,MAAM,QAAQ,KAAA,CAAM,KAAA,CAAM,UAAA,GAAa,CAAC,EAAE,IAAA,EAAK;AAC/C,EAAA,IAAI,CAAC,OAAA,IAAW,CAAC,KAAA,EAAO;AACtB,IAAA,MAAM,IAAI,WAAA;AAAA,MACR,CAAA,mCAAA,EAAsC,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA,4BAAA,CAAA;AAAA,MAC3D,EAAE,MAAM,2BAAA;AAA4B,KACtC;AAAA,EACF;AACA,EAAA,OAAO,EAAE,SAAS,KAAA,EAAM;AAC1B;AAUO,SAAS,wBAAwB,GAAA,EAA8C;AACpF,EAAA,MAAM,OAAA,GAAU,kBAAkB,GAAG,CAAA;AACrC,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,MAAM,IAAI,WAAA;AAAA,MACR,0HAAA;AAAA,MAEA,EAAE,MAAM,yBAAA;AAA0B,KACpC;AAAA,EACF;AACA,EAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,KAAA,KAAU;AAC5B,IAAA,MAAM,OAAA,GAAU,iBAAA,CAAkB,KAAA,CAAM,OAAO,CAAA;AAC/C,IAAA,IAAI,YAAY,MAAA,EAAW;AACzB,MAAA,MAAM,IAAI,WAAA;AAAA,QACR,CAAA,mCAAA,EAAsC,IAAA,CAAK,SAAA,CAAU,KAAA,CAAM,OAAO,CAAC,CAAA,SAAA,EAAY,MAAA,CAAO,IAAA,CAAK,iBAAiB,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,+DAAA,CAAA;AAAA,QACxH,EAAE,MAAM,0BAAA;AAA2B,OACrC;AAAA,IACF;AACA,IAAA,OAAO,OAAA,CAAQ,MAAM,KAAK,CAAA;AAAA,EAC5B,CAAC,CAAA;AACH;AAUO,SAAS,wBAAwB,IAAA,EAAoC;AAC1E,EAAA,IAAI,SAAS,MAAA,EAAW;AACtB,IAAA,MAAM,QAAA,GAAW,CAAA,kBAAA,EAAqB,IAAA,CAAK,WAAA,EAAa,CAAA,CAAA;AACxD,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,GAAA,CAAI,QAAQ,CAAA;AACrC,IAAA,IAAI,QAAA,EAAU,MAAK,EAAG;AACpB,MAAA,OAAO,wBAAwB,QAAQ,CAAA;AAAA,IACzC;AAAA,EACF;AACA,EAAA,OAAO,uBAAA,CAAwB,OAAA,CAAQ,GAAA,CAAI,iBAAiB,CAAA;AAC9D;;;AClGA,IAAM,6BAA6B,EAAE,IAAA,EAAM,KAAK,GAAA,EAAK,GAAA,EAAK,aAAa,GAAA,EAAI;AAE3E,IAAM,YAAA,GAAe,CAAC,KAAA,EAAO,IAAI,CAAA;AAWjC,eAAsB,OAAA,CACpB,KAAA,EACA,QAAA,EACA,IAAA,EAC2B;AAC3B,EAAA,MAAM,SAAA,GACJ,IAAA,EAAM,SAAA,KAAc,MAAA,IAAa,IAAA,CAAK,UAAU,MAAA,GAAS,CAAA,GACrD,IAAA,CAAK,SAAA,GACL,uBAAA,EAAwB;AAE9B,EAAA,MAAM,UAAA,GAAa,MAAM,UAAA,IAAc,QAAA;AACvC,EAAA,MAAM,KAAA,GAAQ,IAAA,EAAM,KAAA,IAAS,WAAA,EAAY;AACzC,EAAA,MAAM,UAAA,GACJ,MAAM,UAAA,IAAc,0BAAA;AAEtB,EAAA,wBAAA,CAAyB;AAAA,IACvB,KAAA,EAAO,YAAA;AAAA,IACP,UAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,SAAS,YAAA,CAAoB;AAAA,IACjC,KAAA,EAAO,YAAA;AAAA,IACP,UAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA,EAAU,eAAA;AAAA,IACV,QAAA;AAAA,IACA,GAAI,MAAM,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAO,GAAI;AAAC,GAC7D,CAAA;AAED,EAAA,MAAM,UAAU,MAAM,MAAA,CAAO,KAAA,EAAO,MAAA,EAAQ,MAAM,MAAM,CAAA;AACxD,EAAA,OAAO,iBAAiB,OAAO,CAAA;AACjC;AAOA,SAAS,iBAAiB,CAAA,EAAqC;AAC7D,EAAA,QAAQ,EAAE,IAAA;AAAM,IACd,KAAK,YAAA;AACH,MAAA,OAAO,EAAE,GAAG,CAAA,EAAG,KAAA,EAAO,CAAA,CAAE,UAAU,KAAA,EAAM;AAAA,IAC1C,KAAK,WAAA;AACH,MAAA,OAAO;AAAA,QACL,GAAG,CAAA;AAAA,QACH,GAAA,EAAK,EAAE,GAAA,KAAQ,KAAA;AAAA,QACf,QAAA,EAAU,EAAE,QAAA,KAAa,KAAA;AAAA,QACzB,YAAA,EAAc,KAAA,CAAM,CAAA,CAAE,YAAY;AAAA,OACpC;AAAA,IACF,KAAK,SAAA;AACH,MAAA,OAAO,EAAE,GAAG,CAAA,EAAG,QAAQ,YAAA,CAAa,CAAA,CAAE,MAAM,CAAA,EAAE;AAAA;AAEpD;AAEA,SAAS,aAAa,KAAA,EAAiE;AACrF,EAAA,QAAQ,MAAM,IAAA;AAAM,IAClB,KAAK,qBAAA;AACH,MAAA,OAAO,EAAE,GAAG,KAAA,EAAO,iBAAA,EAAmB,KAAA,CAAM,sBAAsB,KAAA,EAAM;AAAA,IAC1E,KAAK,iBAAA;AACH,MAAA,OAAO,EAAE,GAAG,KAAA,EAAO,kBAAkB,KAAA,CAAM,KAAA,CAAM,gBAAgB,CAAA,EAAE;AAAA;AAAA;AAAA,IAGrE,KAAK,oBAAA;AAAA,IACL,KAAK,kBAAA;AAAA,IACL,KAAK,kBAAA;AAAA,IACL,KAAK,WAAA;AACH,MAAA,OAAO,KAAA;AAAA;AAEb;AAEA,SAAS,MAAM,CAAA,EAA+C;AAC5D,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,EAAE,IAAA,EAAM,CAAA,CAAE,MAAM,GAAA,EAAK,KAAA,EAAO,CAAA,CAAE,KAAA,CAAM,EAAA,EAAG;AAAA,IAC9C,UAAU,CAAA,CAAE;AAAA,GACd;AACF;;;AC/CA,IAAM,yBAAA,GAA4B,CAAA;AAE3B,SAAS,WACd,MAAA,EACkB;AAElB,EAAA,MAAM,SAAA,GACJ,MAAA,CAAO,SAAA,KAAc,MAAA,IAAa,MAAA,CAAO,SAAA,CAAU,MAAA,GAAS,CAAA,GACxD,MAAA,CAAO,SAAA,GACP,uBAAA,CAAwB,MAAA,CAAO,IAAI,CAAA;AAEzC,EAAA,MAAM,UAAA,GAAa,OAAO,UAAA,IAAc,QAAA;AACxC,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,IAAS,WAAA,EAAY;AAC1C,EAAA,MAAM,QAAA,GAAW,OAAO,QAAA,IAAY,eAAA;AAGpC,EAAA,wBAAA,CAAyB;AAAA,IACvB,GAAI,OAAO,IAAA,KAAS,MAAA,GAAY,EAAE,IAAA,EAAM,MAAA,CAAO,IAAA,EAAK,GAAI,EAAC;AAAA,IACzD,OAAO,MAAA,CAAO,KAAA;AAAA,IACd,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB,SAAA;AAAA,IACA;AAAA,GACD,CAAA;AAKD,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,MAAA,KAAW,CAAC,CAAA,KAAS,CAAA,CAAA;AAE3C,EAAA,MAAM,eAAe,YAAA,CAAgB;AAAA,IACnC,OAAO,MAAA,CAAO,KAAA;AAAA,IACd,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB,SAAA;AAAA,IACA,UAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,GAAI,OAAO,QAAA,KAAa,MAAA,GAAY,EAAE,QAAA,EAAU,MAAA,CAAO,QAAA,EAAS,GAAI,EAAC;AAAA,IACrE,GAAI,OAAO,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,EAAQ,MAAA,CAAO,MAAA,EAAO,GAAI,EAAC;AAAA,IAC/D,GAAI,OAAO,aAAA,KAAkB,MAAA,GAAY,EAAE,aAAA,EAAe,MAAA,CAAO,aAAA,EAAc,GAAI,EAAC;AAAA,IACpF,GAAI,OAAO,eAAA,KAAoB,MAAA,GAC3B,EAAE,eAAA,EAAiB,MAAA,CAAO,eAAA,EAAyB,GACnD,EAAC;AAAA,IACL,GAAI,OAAO,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,EAAO,MAAA,CAAO,KAAA,EAAM,GAAI;AAAC,GAC7D,CAAA;AAGD,EAAA,MAAM,MAAA,GAAS,OAAO,KAAA,EAAU,IAAA,KAAyD;AACvF,IAAA,MAAM,SAAA,GAAY,OAAO,KAAK,CAAA;AAC9B,IAAA,OAAO,MAAA,CAAO,SAAA,EAAW,YAAA,EAAc,IAAA,EAAM,MAAM,CAAA;AAAA,EACrD,CAAA;AAGA,EAAA,MAAM,KAAA,GAAQ,OACZ,KAAA,EACA,IAAA,KAC0B;AAC1B,IAAA,MAAM,WAAA,GAAc,MAAM,WAAA,IAAe,yBAAA;AACzC,IAAA,MAAM,OAAA,GAAwB,IAAI,KAAA,CAAM,KAAA,CAAM,MAAM,CAAA;AACpD,IAAA,IAAI,IAAA,GAAO,CAAA;AAEX,IAAA,eAAe,MAAA,GAAwB;AACrC,MAAA,OAAO,IAAA,EAAM;AACX,QAAA,MAAM,GAAA,GAAM,IAAA,EAAA;AACZ,QAAA,IAAI,GAAA,IAAO,MAAM,MAAA,EAAQ;AACzB,QAAA,MAAM,IAAA,GAAO,MAAM,GAAG,CAAA;AAGtB,QAAA,OAAA,CAAQ,GAAG,IAAI,MAAM,MAAA;AAAA,UACnB,IAAA;AAAA,UACA,IAAA,EAAM,WAAW,MAAA,GAAY,EAAE,QAAQ,IAAA,CAAK,MAAA,KAAW;AAAC,SAC1D;AAAA,MACF;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,GAAU,KAAA,CAAM,IAAA,CAAK,EAAE,QAAQ,IAAA,CAAK,GAAA,CAAI,WAAA,EAAa,KAAA,CAAM,MAAM,CAAA,EAAE,EAAG,MAAM,QAAQ,CAAA;AAC1F,IAAA,MAAM,OAAA,CAAQ,IAAI,OAAO,CAAA;AACzB,IAAA,OAAO,OAAA;AAAA,EACT,CAAA;AAGA,EAAA,MAAM,QAAA,GAAW,MAAA;AACjB,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,QAAA,EAAU,EAAE,OAAO,CAAA;AAC1C;;;AClIA,IAAM,2BAAA,GAA8B,EAAE,IAAA,EAAM,GAAA,EAAK,aAAa,GAAA,EAAI;AAYlE,eAAsB,QAAA,CACpB,KAAA,EACA,KAAA,EACA,IAAA,EACqB;AACrB,EAAA,MAAM,SAAA,GACJ,IAAA,EAAM,SAAA,KAAc,MAAA,IAAa,IAAA,CAAK,UAAU,MAAA,GAAS,CAAA,GACrD,IAAA,CAAK,SAAA,GACL,uBAAA,EAAwB;AAE9B,EAAA,MAAM,UAAA,GAAa,MAAM,UAAA,IAAc,QAAA;AACvC,EAAA,MAAM,KAAA,GAAQ,IAAA,EAAM,KAAA,IAAS,WAAA,EAAY;AACzC,EAAA,MAAM,UAAA,GAAc,MAAM,UAAA,IAAc,2BAAA;AAKxC,EAAA,wBAAA,CAAyB;AAAA,IACvB,KAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,SAAS,YAAA,CAAgB;AAAA,IAC7B,KAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA,EAAU,eAAA;AAAA,IACV,GAAI,MAAM,QAAA,KAAa,MAAA,GAAY,EAAE,QAAA,EAAU,IAAA,CAAK,QAAA,EAAS,GAAI,EAAC;AAAA,IAClE,GAAI,MAAM,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAO,GAAI;AAAC,GAC7D,CAAA;AAED,EAAA,OAAO,MAAA,CAAO,KAAA,EAAO,MAAA,EAAQ,IAAA,EAAM,MAAM,CAAA;AAC3C;;;AC1DO,SAAS,aAA8B,CAAA,EAAmC;AAC/E,EAAA,OAAO,EAAE,IAAA,KAAS,YAAA;AACpB;AAEO,SAAS,YAA6B,CAAA,EAAkC;AAC7E,EAAA,OAAO,EAAE,IAAA,KAAS,WAAA;AACpB;AAEO,SAAS,UAA2B,CAAA,EAAgC;AACzE,EAAA,OAAO,EAAE,IAAA,KAAS,SAAA;AACpB;AAaO,SAAS,KAAA,CACd,GACA,QAAA,EAKG;AACH,EAAA,QAAQ,EAAE,IAAA;AAAM,IACd,KAAK,YAAA;AACH,MAAA,OAAO,QAAA,CAAS,WAAW,CAAC,CAAA;AAAA,IAC9B,KAAK,WAAA;AACH,MAAA,OAAO,QAAA,CAAS,UAAU,CAAC,CAAA;AAAA,IAC7B,KAAK,SAAA;AACH,MAAA,OAAO,QAAA,CAAS,QAAQ,CAAC,CAAA;AAAA;AAE/B;AAaO,SAAS,OAAwB,IAAA,EAAqC;AAC3E,EAAA,OAAO,CAAC,CAAA,KAA8B;AACpC,IAAA,IAAI,CAAA,CAAE,IAAA,KAAS,SAAA,EAAW,OAAO,CAAA;AACjC,IAAA,IAAI,IAAA,CAAK,CAAC,CAAA,EAAG,OAAO,CAAA;AACpB,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,SAAA;AAAA,MACN,QAAQ,EAAE,IAAA,EAAM,oBAAA,EAAsB,YAAA,EAAc,EAAE,IAAA,EAAK;AAAA,MAC3D,MAAM,CAAA,CAAE;AAAA,KACV;AAAA,EACF,CAAA;AACF;;;ACnBO,IAAM,OAAA,GAAU;AAAA,EACrB,QAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF","file":"index.js","sourcesContent":["/**\n * Stable canonical hashing for cache keys.\n *\n * - SHA-256 from `node:crypto` (stdlib only; cross-process stable so future\n * persistent backends can share keys).\n * - Canonical JSON serialization with lexicographically sorted object keys.\n * - NFC normalization + trim for input string hashing.\n */\n\nimport { createHash } from \"node:crypto\";\n\n/** SHA-256 hex digest of the given string. */\nexport function sha256(s: string): string {\n return createHash(\"sha256\").update(s).digest(\"hex\");\n}\n\n/**\n * Canonicalize a JSON-serializable value into a deterministic string:\n * - Object keys sorted lexicographically.\n * - Arrays preserve order — decision-space ordering in cache keys honors\n * the user-given order (re-ordering changes the prompt and the model's\n * first-token distribution, so it must change the cache key).\n * - undefined values are omitted (matches JSON.stringify semantics for object values).\n *\n * Throws on non-JSON-serializable inputs (functions, symbols, circular refs).\n */\nexport function canonicalJSON(value: unknown): string {\n return JSON.stringify(canonicalize(value));\n}\n\nfunction canonicalize(value: unknown): unknown {\n if (value === null) return null;\n if (Array.isArray(value)) return value.map(canonicalize);\n if (typeof value !== \"object\") return value;\n const record = value as Record<string, unknown>;\n return Object.fromEntries(\n Object.keys(record)\n .sort()\n .filter((key) => record[key] !== undefined)\n .map((key) => [key, canonicalize(record[key])] as const),\n );\n}\n\n/**\n * Normalize an input string for hashing: NFC normalization + trim.\n * Used to compute `input_hash` in the cache key composition.\n */\nexport function normalizeInput(input: string): string {\n return input.normalize(\"NFC\").trim();\n}\n","/**\n * Cache primitives.\n *\n * The public `Cache` interface is async, opaque-string-valued, and requires\n * `delete`. The engine owns serialization; backends (Redis, KV, SQLite,\n * in-memory) just round-trip strings.\n *\n * `InFlight` is the engine-side dedup table — concurrent calls with the same\n * key share one Promise. Distinct from the `Cache` interface so external\n * backends never see in-flight state.\n */\n\nimport { canonicalJSON, normalizeInput, sha256 } from \"./hash.js\";\nimport type { Distribution } from \"./types.js\";\n\n/**\n * Bump manually only when a change would make existing cache entries\n * semantically wrong (cache key composition, stored value shape, provider\n * distribution computation). Library-version bumps alone do not bump this.\n */\nexport const CACHE_SCHEMA_VERSION = 1;\n\ntype CacheKeyInputs = {\n readonly providerId: string;\n readonly modelId: string;\n readonly tokenizerId: string;\n readonly templateHash: string;\n /**\n * Decision space in user-given order. Re-ordering changes the prompt — and\n * therefore the model output — so it must change the cache key.\n */\n readonly decisionSpace: readonly string[];\n readonly temperature: number;\n /**\n * Stable hash of provider options that affect Distribution shape (e.g.\n * `multiSampleN`). Empty string for providers without such options.\n */\n readonly providerConfigHash: string;\n /** Output of `classifier({ format })`, not the raw input. */\n readonly formattedInput: string;\n};\n\n/**\n * SHA-256 hex digest over canonical-JSON of all inputs. Stable across\n * processes — safe for persistent backends.\n */\nexport function computeCacheKey(inputs: CacheKeyInputs): string {\n return sha256(\n canonicalJSON({\n cache_schema_version: CACHE_SCHEMA_VERSION,\n provider_id: inputs.providerId,\n model_id: inputs.modelId,\n tokenizer_id: inputs.tokenizerId,\n template_hash: inputs.templateHash,\n decision_space: inputs.decisionSpace,\n temperature: inputs.temperature,\n provider_config_hash: inputs.providerConfigHash,\n input_hash: sha256(normalizeInput(inputs.formattedInput)),\n }),\n );\n}\n\ntype CachedValue = {\n readonly schemaVersion: number;\n readonly distribution: Distribution<string>;\n readonly storedAt: number;\n};\n\nexport function serializeCachedValue<T extends string>(d: Distribution<T>): string {\n const value: CachedValue = {\n schemaVersion: CACHE_SCHEMA_VERSION,\n distribution: d,\n storedAt: Date.now(),\n };\n return JSON.stringify(value);\n}\n\n/**\n * Returns `undefined` on a stored-schema-version mismatch; the engine treats\n * that as a miss and re-samples from the provider.\n */\nexport function deserializeCachedValue<T extends string>(raw: string): Distribution<T> | undefined {\n try {\n const parsed = JSON.parse(raw) as CachedValue;\n if (parsed.schemaVersion !== CACHE_SCHEMA_VERSION) return undefined;\n return parsed.distribution as Distribution<T>;\n } catch {\n return undefined;\n }\n}\n\n/**\n * @example\n * const redisCache: Cache = {\n * async get(key) { return await redis.get(key); },\n * async set(key, value, ttlMs) {\n * if (ttlMs !== undefined) await redis.set(key, value, \"PX\", ttlMs);\n * else await redis.set(key, value);\n * },\n * async delete(key) { await redis.del(key); },\n * };\n */\nexport interface Cache {\n get(key: string): Promise<string | undefined>;\n set(key: string, value: string, ttlMs?: number): Promise<void>;\n delete(key: string): Promise<void>;\n}\n\nexport type CacheStats = {\n readonly size: number;\n readonly hits: number;\n readonly misses: number;\n readonly evictions: number;\n};\n\n/**\n * Optional extension over `Cache`. The built-in `memoryCache` implements it;\n * external backends may opt in.\n */\nexport interface CacheWithStats extends Cache {\n stats(): CacheStats;\n}\n\ntype Entry = {\n value: string;\n expiresAt: number | undefined;\n};\n\n/**\n * Count-bounded in-memory LRU cache. Used as the per-classifier default when\n * `cache` isn't supplied. Eviction runs after every successful `set`; the\n * cache may briefly hold `maxEntries + concurrent-in-flight` entries during\n * concurrent writes, then drops back to bound.\n *\n * @param options.maxEntries Default 10_000.\n * @param options.defaultTtlMs Optional fallback TTL when `set` omits it.\n */\nexport function memoryCache(options?: {\n maxEntries?: number;\n defaultTtlMs?: number;\n}): CacheWithStats {\n const maxEntries = options?.maxEntries ?? 10_000;\n const defaultTtlMs = options?.defaultTtlMs;\n\n // Map preserves insertion order; re-inserting a key on access bumps it to MRU.\n const store = new Map<string, Entry>();\n let hits = 0;\n let misses = 0;\n let evictions = 0;\n\n function isExpired(entry: Entry): boolean {\n return entry.expiresAt !== undefined && entry.expiresAt <= Date.now();\n }\n\n return {\n async get(key: string): Promise<string | undefined> {\n const entry = store.get(key);\n if (entry === undefined) {\n misses++;\n return undefined;\n }\n if (isExpired(entry)) {\n store.delete(key);\n misses++;\n return undefined;\n }\n store.delete(key);\n store.set(key, entry);\n hits++;\n return entry.value;\n },\n\n async set(key: string, value: string, ttlMs?: number): Promise<void> {\n const ttl = ttlMs ?? defaultTtlMs;\n const expiresAt = ttl !== undefined ? Date.now() + ttl : undefined;\n if (store.has(key)) store.delete(key);\n store.set(key, { value, expiresAt });\n while (store.size > maxEntries) {\n const oldest = store.keys().next().value;\n if (oldest === undefined) break;\n store.delete(oldest);\n evictions++;\n }\n },\n\n async delete(key: string): Promise<void> {\n store.delete(key);\n },\n\n stats(): CacheStats {\n return {\n size: store.size,\n hits,\n misses,\n evictions,\n };\n },\n };\n}\n\n/**\n * Engine-side dedup table. Two callers hitting the same key concurrently\n * share a single Promise; on settle the slot is cleared.\n */\nexport class InFlight<V> {\n private readonly map = new Map<string, Promise<V>>();\n\n async run(key: string, factory: () => Promise<V>): Promise<V> {\n const existing = this.map.get(key);\n if (existing !== undefined) return existing;\n const promise = factory().finally(() => {\n this.map.delete(key);\n });\n this.map.set(key, promise);\n return promise;\n }\n\n /** Drop the in-flight slot for `key`, allowing the next caller to retry. */\n forget(key: string): void {\n this.map.delete(key);\n }\n}\n","/**\n * Error taxonomy for domovoi.\n *\n * Four classes (`DomovoiError` base + `ProviderError`, `ConfigError`,\n * `BudgetExhaustedError`) with a stable `code` field for fine-grained\n * discrimination. All accept `{ cause }` for ES2022 chaining.\n *\n * The engine canonicalizes anything thrown from `Provider.sample` that isn't\n * already a `DomovoiError` into `ProviderError({ cause })`, so callers always\n * see a known error type. Under the default `onErrorPolicy: \"fallback\"`,\n * runtime errors become `Unknown` Verdict variants rather than throw;\n * `ConfigError` always throws.\n */\n\n/**\n * Stable error codes carried in `error.code`. Discriminate on these rather\n * than on `instanceof` of removed-historical subclasses.\n */\nexport type ErrorCode =\n // ConfigError — construction-time\n | \"decision_space_collision\"\n | \"decision_space_too_large\"\n | \"missing_provider_config\"\n | \"malformed_provider_config\"\n | \"unknown_provider_factory\"\n | \"missing_credential\"\n | \"incompatible_calibrator\"\n | \"invalid_classifier_name\"\n | \"invalid_thresholds\"\n | \"invalid_space\"\n | \"empty_providers\"\n // ProviderError — runtime\n | \"provider_network\"\n | \"provider_rate_limit\"\n | \"provider_timeout\"\n | \"provider_unauthorized\"\n | \"provider_server_error\"\n | \"provider_malformed_response\"\n | \"invalid_distribution\"\n // BudgetExhaustedError — runtime\n | \"per_call_timeout\"\n | \"chain_timeout\"\n | \"max_calls\";\n\nexport class DomovoiError extends Error {\n readonly code: string;\n\n constructor(message: string, options?: { code?: string; cause?: unknown }) {\n super(message, options?.cause !== undefined ? { cause: options.cause } : undefined);\n this.name = \"DomovoiError\";\n this.code = options?.code ?? \"unspecified\";\n }\n}\n\nexport class ProviderError extends DomovoiError {\n constructor(message: string, options?: { code?: string; cause?: unknown }) {\n super(message, options);\n this.name = \"ProviderError\";\n }\n}\n\nexport class ConfigError extends DomovoiError {\n constructor(message: string, options?: { code?: string; cause?: unknown }) {\n super(message, options);\n this.name = \"ConfigError\";\n }\n}\n\nexport class BudgetExhaustedError extends DomovoiError {\n readonly attemptedProviders: readonly string[];\n readonly elapsedMs: number;\n readonly scope: \"per_call_timeout\" | \"chain_timeout\" | \"max_calls\";\n\n constructor(\n message: string,\n options: {\n scope: \"per_call_timeout\" | \"chain_timeout\" | \"max_calls\";\n attemptedProviders: readonly string[];\n elapsedMs: number;\n cause?: unknown;\n },\n ) {\n super(message, { code: options.scope, cause: options.cause });\n this.name = \"BudgetExhaustedError\";\n this.scope = options.scope;\n this.attemptedProviders = options.attemptedProviders;\n this.elapsedMs = options.elapsedMs;\n }\n}\n\n/**\n * Wraps any non-DomovoiError thrown value in `ProviderError({ cause })`.\n * `DomovoiError` subtypes — including `ProviderError` subclasses defined by\n * external Provider implementations — pass through unchanged.\n */\nexport function canonicalizeProviderThrow(thrown: unknown): DomovoiError {\n if (thrown instanceof DomovoiError) return thrown;\n if (thrown instanceof Error) {\n return new ProviderError(thrown.message || \"Provider call failed\", {\n code: \"provider_network\",\n cause: thrown,\n });\n }\n return new ProviderError(String(thrown), {\n code: \"provider_network\",\n cause: thrown,\n });\n}\n\n/**\n * Convert an Error to the JSON-safe shape stored in\n * `Verdict.meta.providerErrors`. Cause chains are preserved recursively.\n */\nexport function serializeError(err: unknown): {\n readonly name: string;\n readonly message: string;\n readonly code?: string;\n readonly cause?: ReturnType<typeof serializeError>;\n readonly stack?: string;\n} {\n if (!(err instanceof Error)) {\n return { name: \"Error\", message: String(err) };\n }\n const code = err instanceof DomovoiError ? err.code : undefined;\n const cause = err.cause !== undefined ? serializeError(err.cause) : undefined;\n return {\n name: err.name,\n message: err.message,\n ...(code !== undefined ? { code } : {}),\n ...(cause !== undefined ? { cause } : {}),\n ...(err.stack !== undefined ? { stack: err.stack } : {}),\n };\n}\n","/**\n * Built-in calibrator factories.\n *\n * - `identity` — pass-through; the default.\n * - `temperatureScaling(T)` — `p^(1/T) / Σ p_j^(1/T)`; equivalent to\n * scaling logits before softmax.\n * - `plattScaling({ a, b })` — sigmoid scaling; binary spaces only.\n *\n * `Calibrator.apply` must be pure and stateless. The engine runs it\n * per-caller after the Distribution is loaded from the cache, so impurity\n * would leak across callers sharing a cache row.\n */\n\nimport { ConfigError } from \"../errors.js\";\nimport type { Distribution } from \"../types.js\";\n\nexport interface Calibrator {\n /** Identifier; `\"identity\"` is reserved and recognized by the engine. */\n readonly kind: string;\n apply<T extends string>(d: Distribution<T>): Distribution<T>;\n}\n\nexport const identity: Calibrator = {\n kind: \"identity\",\n apply<T extends string>(d: Distribution<T>): Distribution<T> {\n return d;\n },\n};\n\n/**\n * - `T = 1` → identity.\n * - `T > 1` → softens (less peaked).\n * - `T < 1` → sharpens (more peaked).\n *\n * Operates on probabilities (not logits) and leaves `coverage` unchanged.\n * Throws `ConfigError` on `T <= 0`.\n *\n * @example\n * calibrator: temperatureScaling(0.85) // user-fit on held-out eval set\n */\nexport function temperatureScaling(T: number): Calibrator {\n if (Number.isNaN(T) || T <= 0) {\n throw new ConfigError(`temperatureScaling(T): T must be > 0; got ${T}.`, {\n code: \"incompatible_calibrator\",\n });\n }\n const inverseT = 1 / T;\n return {\n kind: \"temperature\",\n apply<U extends string>(d: Distribution<U>): Distribution<U> {\n const scaledEntries = (Object.entries(d.probs) as [string, number][]).map(\n ([label, prob]) => [label, prob === 0 ? 0 : prob ** inverseT] as const,\n );\n const partitionFn = scaledEntries.reduce(\n (running, [, scaledProb]) => running + scaledProb,\n 0,\n );\n // Degenerate input (every prob is 0) — return as-is rather than divide by 0.\n if (partitionFn === 0) return d;\n const normalizedProbs = Object.fromEntries(\n scaledEntries.map(([label, scaledProb]) => [label, scaledProb / partitionFn] as const),\n );\n return {\n probs: normalizedProbs as Distribution<U>[\"probs\"],\n coverage: d.coverage,\n };\n },\n };\n}\n\n/**\n * Platt scaling: `sigmoid(a*z + b)` where `z = logit(p_pos)`.\n *\n * Binary-only — the second label in the distribution (in user-given order)\n * is treated as the positive class. Construction-time space-size validation\n * happens in the classifier; `apply()` re-checks at runtime as a defensive\n * guard against direct misuse.\n */\nexport function plattScaling(params: { a: number; b: number }): Calibrator {\n if (\n Number.isNaN(params.a) ||\n Number.isNaN(params.b) ||\n !Number.isFinite(params.a) ||\n !Number.isFinite(params.b)\n ) {\n throw new ConfigError(\n `plattScaling({ a, b }): a and b must be finite numbers; got a=${params.a}, b=${params.b}.`,\n { code: \"incompatible_calibrator\" },\n );\n }\n return {\n kind: \"platt\",\n apply<U extends string>(d: Distribution<U>): Distribution<U> {\n const labels = Object.keys(d.probs);\n if (labels.length !== 2) {\n throw new ConfigError(\n `plattScaling is binary-only; got distribution with ${labels.length} labels.`,\n { code: \"incompatible_calibrator\" },\n );\n }\n const [neg, pos] = labels as [string, string];\n const probs = d.probs as Record<string, number>;\n const pPos = probs[pos] ?? 0;\n // Clamp away from {0, 1} so `Math.log(p / (1 - p))` is finite.\n const eps = 1e-9;\n const clamped = Math.min(1 - eps, Math.max(eps, pPos));\n const logit = Math.log(clamped / (1 - clamped));\n const calibratedPos = sigmoid(params.a * logit + params.b);\n return {\n probs: {\n [neg]: 1 - calibratedPos,\n [pos]: calibratedPos,\n } as Distribution<U>[\"probs\"],\n coverage: d.coverage,\n };\n },\n };\n}\n\nfunction sigmoid(x: number): number {\n return 1 / (1 + Math.exp(-x));\n}\n\nexport function isIdentityCalibrator(c: Calibrator): boolean {\n return c.kind === \"identity\";\n}\n","/**\n * Default classifier prompt template and rendering helpers.\n *\n * Labels render in user-given order (never sorted) so prompt-position bias\n * is the caller's choice. Custom templates must supply their own\n * `templateHash` so cache keys stay correct.\n */\n\nimport type { PromptTemplate } from \"./types.js\";\n\nconst DEFAULT_TEMPLATE_HASH = \"domovoi/v0-default\";\n\nexport const defaultTemplate: PromptTemplate = {\n systemPrompt: \"You are a careful classifier. Output exactly one of: {labels_csv}. No other text.\",\n userTemplate: (input: string, _space: readonly string[], question?: string): string =>\n question === undefined ? input : `${question}\\n${input}`,\n templateHash: DEFAULT_TEMPLATE_HASH,\n};\n\n/** Substitute `{labels_csv}` in the system prompt; `undefined` if there isn't one. */\nexport function renderSystemPrompt(\n template: PromptTemplate,\n space: readonly string[],\n): string | undefined {\n if (template.systemPrompt === undefined) return undefined;\n return template.systemPrompt.replace(\"{labels_csv}\", space.join(\", \"));\n}\n\n/** Render the user message via the template's `userTemplate` callback. */\nexport function renderUserPrompt(\n template: PromptTemplate,\n input: string,\n space: readonly string[],\n question?: string,\n): string {\n return template.userTemplate(input, space, question);\n}\n","/**\n * Construction-time validators throw `ConfigError`; the runtime\n * `validateDistribution` (called by the engine after `Provider.sample` returns)\n * throws `ProviderError`.\n */\n\nimport { ConfigError, ProviderError } from \"./errors.js\";\nimport type { Distribution, ProviderCapabilities, Thresholds } from \"./types.js\";\n\n/**\n * Throws if the decision space contains: empty labels (post-NFC + trim),\n * duplicates (post-NFC), whitespace-padded labels, or fewer than 2 entries.\n *\n * The empty-array case is also rejected at the type level via the\n * `readonly [T, ...T[]]` shape on classifier configs.\n */\nexport function validateSpace(space: readonly string[]): void {\n if (space.length < 2) {\n throw new ConfigError(`Decision space must have at least 2 labels; got ${space.length}.`, {\n code: \"invalid_space\",\n });\n }\n const seen = new Set<string>();\n for (let i = 0; i < space.length; i++) {\n const label = space[i] as string;\n if (label !== label.trim()) {\n throw new ConfigError(\n `Decision space label at index ${i} has leading/trailing whitespace: ${JSON.stringify(label)}.`,\n { code: \"invalid_space\" },\n );\n }\n const normalized = label.normalize(\"NFC\");\n if (!normalized) {\n throw new ConfigError(`Decision space label at index ${i} is empty.`, {\n code: \"invalid_space\",\n });\n }\n if (seen.has(normalized)) {\n throw new ConfigError(`Decision space contains duplicate label: ${JSON.stringify(label)}.`, {\n code: \"invalid_space\",\n });\n }\n seen.add(normalized);\n }\n}\n\n/**\n * Validate threshold values at construction. Inclusive [0, 1] range; binary\n * requires `high > low` strict; `margin >= 0` if present.\n */\nexport function validateThresholds<S extends readonly string[]>(\n thresholds: Thresholds<S>,\n spaceLength: number,\n): void {\n const t = thresholds as {\n high: number;\n low?: number;\n margin?: number;\n coverageMin?: number;\n };\n\n inRange01(\"high\", t.high);\n if (t.coverageMin !== undefined) inRange01(\"coverageMin\", t.coverageMin);\n\n if (spaceLength === 2) {\n if (t.low === undefined) {\n throw new ConfigError(\"Binary classifier requires `thresholds.low`.\", {\n code: \"invalid_thresholds\",\n });\n }\n inRange01(\"low\", t.low);\n if (!(t.high > t.low)) {\n throw new ConfigError(\n `Binary deadband requires high > low strict; got high=${t.high}, low=${t.low}.`,\n { code: \"invalid_thresholds\" },\n );\n }\n } else {\n if (t.margin !== undefined) {\n if (t.margin < 0 || t.margin > 1 || Number.isNaN(t.margin)) {\n throw new ConfigError(`thresholds.margin must be in [0, 1]; got ${t.margin}.`, {\n code: \"invalid_thresholds\",\n });\n }\n }\n }\n}\n\nfunction inRange01(name: string, value: number): void {\n if (Number.isNaN(value) || value < 0 || value > 1) {\n throw new ConfigError(`thresholds.${name} must be in [0, 1] inclusive; got ${value}.`, {\n code: \"invalid_thresholds\",\n });\n }\n}\n\nconst CLASSIFIER_NAME_REGEX = /^[a-z][a-z0-9_]*$/;\n\nexport function validateClassifierName(name: string): void {\n if (!CLASSIFIER_NAME_REGEX.test(name)) {\n throw new ConfigError(\n `Classifier name must match /^[a-z][a-z0-9_]*$/; got ${JSON.stringify(name)}.`,\n { code: \"invalid_classifier_name\" },\n );\n }\n}\n\n/**\n * Validates the provider chain. Throws if the array is empty, or if the\n * decision space exceeds the smallest `maxTopLogprobs` across all\n * `distributionSource: \"logprobs\"` providers in the chain (multi-sample\n * providers have no top-K constraint and are exempt).\n */\nexport function validateProviderChain(\n providers: ReadonlyArray<{ readonly id: string; readonly capabilities: ProviderCapabilities }>,\n spaceLength: number,\n): void {\n if (providers.length === 0) {\n throw new ConfigError(\"Provider chain is empty; supply at least one provider.\", {\n code: \"empty_providers\",\n });\n }\n\n const logprobsCaps = providers\n .filter((p) => p.capabilities.distributionSource === \"logprobs\")\n .map((p) => ({ id: p.id, cap: p.capabilities.maxTopLogprobs }));\n\n if (logprobsCaps.length === 0) return; // all multi_sample; no top-K cap applies\n\n const min = logprobsCaps.reduce(\n (acc, p) => (p.cap < acc.cap ? p : acc),\n logprobsCaps[0] as { id: string; cap: number },\n );\n\n if (spaceLength > min.cap) {\n throw new ConfigError(\n `Decision space size (${spaceLength}) exceeds provider ${min.id}'s top-K cap (${min.cap}). Reduce space size or replace the provider.`,\n { code: \"decision_space_too_large\" },\n );\n }\n}\n\n/**\n * Validate calibrator vs provider chain capabilities at construction.\n * Multi-sample providers reject non-identity calibrators.\n */\nexport function validateCalibratorCompatibility(\n calibratorIsIdentity: boolean,\n providers: ReadonlyArray<{ readonly id: string; readonly capabilities: ProviderCapabilities }>,\n): void {\n if (calibratorIsIdentity) return;\n const multiSample = providers.find((p) => p.capabilities.distributionSource === \"multi_sample\");\n if (multiSample) {\n throw new ConfigError(\n `Provider ${multiSample.id} uses distributionSource: \"multi_sample\"; non-identity calibrators are not supported on multi-sample providers in v0. Use 'identity' calibrator or remove the multi-sample provider from the chain.`,\n { code: \"incompatible_calibrator\" },\n );\n }\n}\n\nconst SUM_TOLERANCE = 0.001;\n\n/**\n * Engine-side check on every Distribution returned by `Provider.sample`,\n * before calibration. Verifies coverage and per-prob range, fills missing\n * in-space labels with `0` (mutates `probs`), and asserts sum-to-one within\n * a fixed tolerance. Throws `ProviderError` on violation — surfaces buggy\n * custom Provider implementations.\n */\nexport function validateDistribution<T extends string>(\n d: Distribution<T>,\n space: readonly T[],\n): void {\n if (Number.isNaN(d.coverage) || d.coverage < 0 || d.coverage > 1) {\n throw new ProviderError(`Invalid Distribution.coverage: ${d.coverage} (must be in [0, 1]).`, {\n code: \"invalid_distribution\",\n });\n }\n\n const probs = d.probs as Record<string, number | undefined>;\n for (const [label, prob] of Object.entries(probs)) {\n if (prob === undefined) continue;\n if (Number.isNaN(prob) || prob < 0 || prob > 1) {\n throw new ProviderError(\n `Invalid probability for label ${JSON.stringify(label)}: ${prob} (must be in [0, 1]).`,\n { code: \"invalid_distribution\" },\n );\n }\n }\n\n // Missing in-space labels (first-token outside provider top-K) get 0.\n for (const label of space) {\n if (!(label in probs)) {\n probs[label] = 0;\n }\n }\n\n let sum = 0;\n for (const label of space) {\n sum += probs[label] ?? 0;\n }\n if (Math.abs(sum - 1) > SUM_TOLERANCE) {\n throw new ProviderError(\n `Distribution probs sum to ${sum.toFixed(6)}; expected 1 ± ${SUM_TOLERANCE}.`,\n { code: \"invalid_distribution\" },\n );\n }\n}\n","/**\n * Engine configuration: `DecideConfig`, defaults, validation, and the\n * `withDefaults` builder used by verbs and one-shots.\n *\n * `DecideConfig` is the engine's internal contract — verbs (boolean,\n * classify, classifier) translate user-facing options into this shape.\n */\n\nimport { type Cache, memoryCache } from \"../cache.js\";\nimport type { Calibrator } from \"../calibration/index.js\";\nimport { identity, isIdentityCalibrator } from \"../calibration/index.js\";\nimport type { ProviderError } from \"../errors.js\";\nimport { defaultTemplate } from \"../prompt.js\";\nimport type { Provider } from \"../providers/provider.js\";\nimport type { Budget, PromptTemplate, Thresholds } from \"../types.js\";\nimport {\n validateCalibratorCompatibility,\n validateClassifierName,\n validateProviderChain,\n validateSpace,\n validateThresholds,\n} from \"../validate.js\";\n\nexport const DEFAULT_PER_CALL_TIMEOUT_MS = 10_000;\nexport const DEFAULT_CHAIN_TIMEOUT_MS = 30_000;\n\ntype OnProviderErrorHook = (\n err: ProviderError,\n ctx: { providerId: string; attempt: number },\n) => void | Promise<void>;\n\ntype EngineHooks = {\n onCall?: (...args: unknown[]) => void | Promise<void>;\n onResult?: (...args: unknown[]) => void | Promise<void>;\n};\n\nexport type DecideConfig<T extends string> = {\n readonly space: readonly T[];\n readonly thresholds: Thresholds<readonly T[]>;\n readonly providers: readonly Provider[];\n readonly calibrator: Calibrator;\n readonly cache: Cache;\n readonly template: PromptTemplate;\n readonly question?: string;\n readonly budget?: Budget;\n readonly onErrorPolicy: \"fallback\" | \"throw\";\n readonly onProviderError?: OnProviderErrorHook;\n readonly hooks?: EngineHooks;\n /**\n * Stable hash of provider-specific options that affect Distribution shape\n * (e.g. `multiSampleN`). Mixed into the cache key so changing those opts is\n * a cache miss. Empty string when the provider has no such options.\n */\n readonly providerConfigHash: string;\n readonly temperature: number;\n};\n\ntype DecideConfigInput<T extends string> = {\n readonly space: readonly T[];\n readonly thresholds: Thresholds<readonly T[]>;\n readonly providers: readonly Provider[];\n readonly calibrator?: Calibrator;\n readonly cache?: Cache;\n readonly template?: PromptTemplate;\n readonly question?: string;\n readonly budget?: Budget;\n readonly onErrorPolicy?: \"fallback\" | \"throw\";\n readonly onProviderError?: OnProviderErrorHook;\n readonly hooks?: EngineHooks;\n readonly providerConfigHash?: string;\n};\n\n/**\n * Materialize a fully-defaulted `DecideConfig` from a partial input. Used by\n * verbs to translate caller-facing options into the engine's internal shape.\n */\nexport function withDefaults<T extends string>(input: DecideConfigInput<T>): DecideConfig<T> {\n return {\n space: input.space,\n thresholds: input.thresholds,\n providers: input.providers,\n calibrator: input.calibrator ?? identity,\n cache: input.cache ?? memoryCache(),\n template: input.template ?? defaultTemplate,\n ...(input.question !== undefined ? { question: input.question } : {}),\n ...(input.budget !== undefined ? { budget: input.budget } : {}),\n onErrorPolicy: input.onErrorPolicy ?? \"fallback\",\n ...(input.onProviderError !== undefined ? { onProviderError: input.onProviderError } : {}),\n ...(input.hooks !== undefined ? { hooks: input.hooks } : {}),\n providerConfigHash: input.providerConfigHash ?? \"\",\n temperature: 0,\n };\n}\n\ntype ValidateClassifierConfigInput<T extends string> = {\n readonly name?: string;\n readonly space: readonly T[];\n readonly thresholds: Thresholds<readonly T[]>;\n readonly providers: readonly Provider[];\n readonly calibrator: Calibrator;\n};\n\n/**\n * Validate a classifier configuration at construction. Throws `ConfigError`\n * with the relevant `code` on first failure; never partially configures.\n *\n * Each registered provider's optional `validate(space)` hook fires last —\n * giving tokenizer-aware adapters (e.g. OpenAI) a chance to surface\n * first-token collisions eagerly, before any network I/O.\n */\nexport function validateClassifierConfig<T extends string>(\n input: ValidateClassifierConfigInput<T>,\n): void {\n if (input.name !== undefined) validateClassifierName(input.name);\n validateSpace(input.space);\n validateProviderChain(input.providers, input.space.length);\n validateThresholds(input.thresholds, input.space.length);\n validateCalibratorCompatibility(isIdentityCalibrator(input.calibrator), input.providers);\n for (const provider of input.providers) {\n provider.validate?.(input.space);\n }\n}\n","/**\n * `VerdictMeta` builder — accumulates state across the engine's chain\n * (providers attempted, errors swallowed, latency, cache hits) and produces\n * the final `meta` object on every Verdict variant.\n */\n\nimport type { Provider } from \"../providers/provider.js\";\nimport type { SerializableError, VerdictMeta } from \"../types.js\";\n\ntype ProviderErrorRecord = {\n readonly providerId: string;\n readonly error: SerializableError;\n};\n\n/**\n * Mutable accumulator used by `decide()`. Only the helpers in this file should\n * mutate it; callers append to `providersAttempted` / `providerErrors` and\n * flip `cacheHit` directly.\n */\nexport type MetaBuilder = {\n readonly providersAttempted: string[];\n readonly providerErrors: ProviderErrorRecord[];\n readonly startedAtMs: number;\n cacheHit: boolean;\n};\n\nexport function makeMetaBuilder(): MetaBuilder {\n return {\n providersAttempted: [],\n providerErrors: [],\n startedAtMs: Date.now(),\n cacheHit: false,\n };\n}\n\n/**\n * Build the final `VerdictMeta` for a Classified or Uncertain Verdict produced\n * by a specific (successful) provider.\n */\nexport function buildMeta(builder: MetaBuilder, provider: Provider): VerdictMeta {\n return {\n providerUsed: provider.id,\n providersAttempted: [...builder.providersAttempted],\n providerErrors: [...builder.providerErrors],\n latencyMs: Date.now() - builder.startedAtMs,\n cacheHit: builder.cacheHit,\n coverageQuality: provider.capabilities.coverageMeasurement,\n distributionSource: provider.capabilities.distributionSource,\n };\n}\n\n/**\n * Build `VerdictMeta` for failure-mode Verdicts (provider_failure,\n * chain_exhausted, cancelled, budget_exhausted) where there's no clear\n * \"successful provider\" to attribute. Falls back to the last-attempted\n * provider for `providerUsed`, or the empty string when none was attempted.\n */\nexport function buildMetaForFailure(\n builder: MetaBuilder,\n fallbackProvider?: Provider,\n): VerdictMeta {\n const providerUsed = fallbackProvider?.id ?? builder.providersAttempted.at(-1) ?? \"\";\n return {\n providerUsed,\n providersAttempted: [...builder.providersAttempted],\n providerErrors: [...builder.providerErrors],\n latencyMs: Date.now() - builder.startedAtMs,\n cacheHit: builder.cacheHit,\n coverageQuality: fallbackProvider?.capabilities.coverageMeasurement ?? \"none\",\n distributionSource: fallbackProvider?.capabilities.distributionSource ?? \"logprobs\",\n };\n}\n","/**\n * Abort and budget utilities.\n *\n * Engine signal merging: user signal + per-call timeout merge into a single\n * `AbortSignal.any` that's passed to the provider. When the merged signal\n * aborts, we discriminate on the abort reason to decide whether the\n * resulting Verdict is `Unknown { cancelled }` (user-initiated) or\n * `Unknown { budget_exhausted, scope: \"per_call_timeout\" }` (timeout-initiated).\n *\n * AggregateError construction: under `onErrorPolicy: \"throw\"` and full-chain\n * provider failure, we throw `AggregateError` containing rehydrated `Error`\n * instances. `deserializeForAggregate` walks the SerializableError shape back\n * into Error instances with `cause` chaining preserved.\n */\n\nimport type { Provider } from \"../providers/provider.js\";\nimport type { SerializableError, Unknown } from \"../types.js\";\nimport type { MetaBuilder } from \"./meta.js\";\nimport { buildMetaForFailure } from \"./meta.js\";\n\n/**\n * Returns a human-readable string describing why a signal aborted, or\n * `undefined` if the signal isn't aborted (or wasn't supplied).\n */\nexport function abortReason(signal: AbortSignal | undefined): string | undefined {\n if (signal === undefined || !signal.aborted) return undefined;\n const reason = signal.reason;\n if (typeof reason === \"string\") return reason;\n if (reason instanceof Error) return reason.message;\n if (reason !== undefined) return String(reason);\n return \"aborted\";\n}\n\n/**\n * Detects whether a merged signal's abort came from `AbortSignal.timeout(...)`.\n * The timeout path produces a DOMException with `name === \"TimeoutError\"`.\n */\nexport function isTimeoutAbort(signal: AbortSignal): boolean {\n const reason = signal.reason;\n return reason instanceof Error && reason.name === \"TimeoutError\";\n}\n\nexport function buildCancelledVerdict<T extends string>(\n meta: MetaBuilder,\n reason: string,\n provider: Provider,\n): Unknown<T> {\n return {\n kind: \"unknown\",\n reason: { type: \"cancelled\", reason },\n meta: buildMetaForFailure(meta, provider),\n };\n}\n\ntype BudgetScope = \"per_call_timeout\" | \"chain_timeout\" | \"max_calls\";\n\n/**\n * Build `Unknown { budget_exhausted, scope }` for `onErrorPolicy: \"fallback\"`.\n * Returns `undefined` under `\"throw\"` policy — the engine throws\n * `BudgetExhaustedError` instead.\n */\nexport function buildBudgetExhaustedVerdict<T extends string>(\n meta: MetaBuilder,\n scope: BudgetScope,\n policy: \"fallback\" | \"throw\",\n provider?: Provider,\n): Unknown<T> | undefined {\n if (policy === \"throw\") return undefined;\n return {\n kind: \"unknown\",\n reason: { type: \"budget_exhausted\", scope },\n meta: buildMetaForFailure(meta, provider),\n };\n}\n\n/**\n * Rehydrate a `SerializableError` (the JSON-safe shape stored in\n * `meta.providerErrors`) back into an `Error` instance suitable for\n * `AggregateError`. Cause chains are reconstructed recursively.\n */\nexport function deserializeForAggregate(serialized: SerializableError): Error {\n const err = new Error(serialized.message);\n err.name = serialized.name;\n if (serialized.stack !== undefined) err.stack = serialized.stack;\n if (serialized.cause !== undefined) {\n Object.defineProperty(err, \"cause\", {\n value: deserializeForAggregate(serialized.cause),\n enumerable: false,\n writable: true,\n });\n }\n return err;\n}\n","/**\n * Cache lookup, in-flight dedup, and per-attempt cache-key composition.\n * The provider call itself happens inside `loadDistribution`; the engine\n * orchestrator never invokes `Provider.sample` directly.\n */\n\nimport {\n computeCacheKey,\n deserializeCachedValue,\n InFlight,\n serializeCachedValue,\n} from \"../cache.js\";\nimport type { Provider } from \"../providers/provider.js\";\nimport type { Distribution } from \"../types.js\";\nimport { DEFAULT_PER_CALL_TIMEOUT_MS, type DecideConfig } from \"./config.js\";\nimport type { MetaBuilder } from \"./meta.js\";\n\n/**\n * Process-wide in-flight dedup. Concurrent calls with the same cache key\n * share a single Promise; the *raw* Distribution is shared, while each caller\n * still applies its own calibrator and thresholds.\n */\nconst globalInFlight = new InFlight<Distribution<string>>();\n\nexport function computeProviderCacheKey<T extends string>(\n provider: Provider,\n formattedInput: string,\n config: DecideConfig<T>,\n): string {\n return computeCacheKey({\n providerId: provider.id,\n modelId: provider.modelId,\n tokenizerId: provider.tokenizerId,\n templateHash: config.template.templateHash,\n decisionSpace: config.space,\n temperature: config.temperature,\n providerConfigHash: config.providerConfigHash,\n formattedInput,\n });\n}\n\nexport function mergeSignals(\n userSignal: AbortSignal | undefined,\n timeoutSignal: AbortSignal,\n): AbortSignal {\n const signals: AbortSignal[] = [timeoutSignal];\n if (userSignal !== undefined) signals.push(userSignal);\n return AbortSignal.any(signals);\n}\n\nexport async function loadDistribution<T extends string>(\n provider: Provider,\n formattedInput: string,\n config: DecideConfig<T>,\n meta: MetaBuilder,\n signal: AbortSignal,\n cacheKey: string,\n): Promise<Distribution<T>> {\n const cached = await config.cache.get(cacheKey);\n if (cached !== undefined) {\n const parsed = deserializeCachedValue<T>(cached);\n if (parsed !== undefined) {\n meta.cacheHit = true;\n return parsed;\n }\n // Schema mismatch → fresh sample.\n }\n const fresh = await fetchFresh(provider, formattedInput, config, signal, cacheKey);\n await config.cache.set(cacheKey, serializeCachedValue(fresh));\n return fresh;\n}\n\nasync function fetchFresh<T extends string>(\n provider: Provider,\n formattedInput: string,\n config: DecideConfig<T>,\n signal: AbortSignal,\n cacheKey: string,\n): Promise<Distribution<T>> {\n return globalInFlight.run(cacheKey, () =>\n provider.sample<T>(formattedInput, config.space, {\n template: config.template,\n temperature: config.temperature,\n timeoutMs: config.budget?.perCallTimeoutMs ?? DEFAULT_PER_CALL_TIMEOUT_MS,\n signal,\n }),\n ) as Promise<Distribution<T>>;\n}\n\n/**\n * Drop the in-flight slot for a key after a failed sample so a concurrent\n * caller in another classifier doesn't keep getting served the failed Promise.\n */\nexport function forgetInFlight(cacheKey: string): void {\n globalInFlight.forget(cacheKey);\n}\n","/**\n * Hook invocation helper.\n *\n * All observability hooks (`onCall`, `onResult`, `onProviderError`) are\n * fire-and-forget: the engine never awaits them, and sync or async errors\n * inside the hook are swallowed. A slow logger doesn't slow fallback; an\n * unhandled rejection inside a hook can't crash the engine.\n */\n\ntype FireAndForgetFn = ((...args: never[]) => void | Promise<void>) | undefined;\n\nexport function fireAndForget(fn: FireAndForgetFn, ...args: unknown[]): void {\n if (fn === undefined) return;\n try {\n const result = (fn as (...a: unknown[]) => void | Promise<void>)(...args);\n if (result instanceof Promise) {\n result.catch(() => {});\n }\n } catch {\n // Sync errors swallowed.\n }\n}\n","/**\n * Error-handling helpers for `decide()`'s attempt loop. Translates raw\n * exceptions thrown from the provider/cache/validation path into either\n * a terminal `Verdict` (for cancellation, budget exhaustion) or a\n * \"continue chain\" signal (for swallowable `ProviderError`).\n *\n * Distinguishes between three error sources: per-call timeout, user\n * cancellation, and provider-side failure. Each produces a different\n * `AttemptOutcome` shape that the orchestrator dispatches on.\n */\n\nimport {\n BudgetExhaustedError,\n canonicalizeProviderThrow,\n ProviderError,\n serializeError,\n} from \"../errors.js\";\nimport type { Provider } from \"../providers/provider.js\";\nimport type { Distribution, Uncertain, Verdict } from \"../types.js\";\nimport {\n abortReason,\n buildBudgetExhaustedVerdict,\n buildCancelledVerdict,\n isTimeoutAbort,\n} from \"./abort.js\";\nimport type { DecideConfig } from \"./config.js\";\nimport { forgetInFlight } from \"./distribution.js\";\nimport { fireAndForget } from \"./hooks.js\";\nimport type { MetaBuilder } from \"./meta.js\";\n\n/**\n * Outcome of a single provider attempt within `decide()`. The orchestrator\n * dispatches on this:\n * - `verdict`: terminal — return immediately.\n * - `lastUncertain`: terminal-if-last-provider — return Uncertain Verdict.\n * - `continue`: try the next provider (after recording any error in meta).\n */\nexport type AttemptOutcome<T extends string> =\n | { kind: \"verdict\"; verdict: Verdict<T> }\n | { kind: \"lastUncertain\"; verdict: Uncertain<T>; calibrated: Distribution<T> }\n | { kind: \"continue\"; calibrated?: Distribution<T> };\n\nexport function handleDistributionError<T extends string>(\n err: unknown,\n provider: Provider,\n meta: MetaBuilder,\n config: DecideConfig<T>,\n userSignal: AbortSignal | undefined,\n timeoutSignal: AbortSignal,\n index: number,\n chainStartMs: number,\n cacheKey: string,\n): AttemptOutcome<T> {\n if (timeoutSignal.aborted && isTimeoutAbort(timeoutSignal)) {\n const verdict = buildBudgetExhaustedVerdict<T>(\n meta,\n \"per_call_timeout\",\n config.onErrorPolicy,\n provider,\n );\n if (verdict !== undefined) return { kind: \"verdict\", verdict };\n throw new BudgetExhaustedError(\"per_call_timeout exceeded\", {\n scope: \"per_call_timeout\",\n attemptedProviders: meta.providersAttempted,\n elapsedMs: Date.now() - chainStartMs,\n cause: err,\n });\n }\n\n const userAbort = abortReason(userSignal);\n if (userAbort !== undefined) {\n const verdict = buildCancelledVerdict<T>(meta, userAbort, provider);\n return { kind: \"verdict\", verdict };\n }\n\n return recordProviderError(err, provider, meta, config, index, cacheKey);\n}\n\nfunction recordProviderError<T extends string>(\n err: unknown,\n provider: Provider,\n meta: MetaBuilder,\n config: DecideConfig<T>,\n index: number,\n cacheKey: string,\n): AttemptOutcome<T> {\n const wrapped = canonicalizeProviderThrow(err);\n if (!(wrapped instanceof ProviderError)) {\n // Non-Provider DomovoiError or unknown — propagate.\n throw wrapped;\n }\n meta.providerErrors.push({ providerId: provider.id, error: serializeError(wrapped) });\n fireAndForget(config.onProviderError, wrapped, {\n providerId: provider.id,\n attempt: index + 1,\n });\n forgetInFlight(cacheKey);\n return { kind: \"continue\" };\n}\n\nexport function recordValidationError<T extends string>(\n err: unknown,\n provider: Provider,\n meta: MetaBuilder,\n config: DecideConfig<T>,\n index: number,\n cacheKey: string,\n): AttemptOutcome<T> {\n const wrapped = canonicalizeProviderThrow(err);\n if (!(wrapped instanceof ProviderError)) throw wrapped;\n meta.providerErrors.push({ providerId: provider.id, error: serializeError(wrapped) });\n fireAndForget(config.onProviderError, wrapped, {\n providerId: provider.id,\n attempt: index + 1,\n });\n forgetInFlight(cacheKey);\n return { kind: \"continue\" };\n}\n","/**\n * Terminal-Verdict construction for `decide()`'s exit paths:\n * chain-budget exhaustion, pre/mid-loop cancellation, and chain-exhausted\n * (every-provider-errored vs last-provider-uncertain).\n */\n\nimport { BudgetExhaustedError } from \"../errors.js\";\nimport type { Distribution, Unknown, Verdict } from \"../types.js\";\nimport { buildBudgetExhaustedVerdict, deserializeForAggregate } from \"./abort.js\";\nimport type { DecideConfig } from \"./config.js\";\nimport { fireAndForget } from \"./hooks.js\";\nimport { buildMetaForFailure, type MetaBuilder } from \"./meta.js\";\n\nexport function checkChainBudget<T extends string>(\n meta: MetaBuilder,\n chainStartMs: number,\n chainTimeoutMs: number,\n config: DecideConfig<T>,\n): Unknown<T> | undefined {\n const elapsed = Date.now() - chainStartMs;\n if (elapsed < chainTimeoutMs) return undefined;\n const verdict = buildBudgetExhaustedVerdict<T>(meta, \"chain_timeout\", config.onErrorPolicy);\n if (verdict !== undefined) return verdict;\n throw new BudgetExhaustedError(\"chain_timeout exceeded\", {\n scope: \"chain_timeout\",\n attemptedProviders: meta.providersAttempted,\n elapsedMs: elapsed,\n });\n}\n\nexport function makeCancelledFromMeta<T extends string>(\n meta: MetaBuilder,\n reason: string,\n): Unknown<T> {\n return {\n kind: \"unknown\",\n reason: { type: \"cancelled\", reason },\n meta: buildMetaForFailure(meta),\n };\n}\n\nexport function finalizeChainExhausted<T extends string>(\n meta: MetaBuilder,\n lastCalibrated: Distribution<T> | undefined,\n attempts: number,\n config: DecideConfig<T>,\n): Verdict<T> {\n // Every provider erroring is distinct from \"chain exhausted with Uncertain\".\n const allErrored =\n lastCalibrated === undefined &&\n meta.providerErrors.length > 0 &&\n meta.providerErrors.length === meta.providersAttempted.length;\n\n if (allErrored) {\n if (config.onErrorPolicy === \"throw\") {\n const errors = meta.providerErrors.map((e) => deserializeForAggregate(e.error));\n throw new AggregateError(errors, \"All providers failed.\");\n }\n const verdict: Unknown<T> = {\n kind: \"unknown\",\n reason: {\n type: \"provider_failure\",\n errors: meta.providerErrors.map((e) => e.error),\n },\n meta: buildMetaForFailure(meta),\n };\n fireAndForget(config.hooks?.onResult, verdict);\n return verdict;\n }\n\n // Reachable only in degenerate cases (e.g. `maxCalls: 0`); the in-loop\n // `lastUncertain` path otherwise returns first.\n const verdict: Unknown<T> = {\n kind: \"unknown\",\n reason: {\n type: \"chain_exhausted\",\n lastDistribution: lastCalibrated ?? { probs: {} as Distribution<T>[\"probs\"], coverage: 0 },\n providersAttempted: attempts,\n },\n meta: buildMetaForFailure(meta),\n };\n fireAndForget(config.hooks?.onResult, verdict);\n return verdict;\n}\n","/**\n * Threshold application — turn a calibrated Distribution into a per-variant\n * decision. All comparisons are inclusive (`>=`, `<=`).\n *\n * - **Coverage gate first.** If `coverage < coverageMin`, return\n * `out_of_distribution` (engine wraps this into Unknown).\n * - **Binary (N=2):** classic deadband. `top.prob >= high` → top wins;\n * `top.prob <= low` → other wins; else Uncertain.\n * - **Multi-class (N>2):** top-confidence rule. `top.prob >= high` → top wins;\n * else Uncertain. Optional margin rule: requires *both*\n * `top.prob >= high` AND `top.prob - second.prob >= margin`.\n */\n\nimport type { Distribution, Thresholds } from \"../types.js\";\n\ntype ThresholdResult<T extends string> =\n | { kind: \"classified\"; value: T; probability: number }\n | { kind: \"uncertain\"; top: T; probability: number; runnerUp: T }\n | {\n kind: \"out_of_distribution\";\n coverage: number;\n topIfRenormalized: T;\n probabilityIfRenormalized: number;\n };\n\nconst DEFAULT_COVERAGE_MIN = 0.5;\n\ntype ThresholdValues = {\n high: number;\n low?: number;\n margin?: number;\n coverageMin?: number;\n};\n\nexport function applyThresholds<T extends string>(\n d: Distribution<T>,\n thresholds: Thresholds<readonly T[]>,\n space: readonly T[],\n): ThresholdResult<T> {\n const t = thresholds as ThresholdValues;\n const sorted = sortBySpaceProbability(d, space);\n const top = sorted[0] as { label: T; prob: number };\n const second = sorted[1] as { label: T; prob: number };\n\n const coverageMin = t.coverageMin ?? DEFAULT_COVERAGE_MIN;\n if (d.coverage < coverageMin) {\n return {\n kind: \"out_of_distribution\",\n coverage: d.coverage,\n topIfRenormalized: top.label,\n probabilityIfRenormalized: top.prob,\n };\n }\n\n if (space.length === 2 && t.low !== undefined) {\n return applyBinaryDeadband(top, second, t);\n }\n\n return applyMultiClassRule(top, second, t);\n}\n\nfunction sortBySpaceProbability<T extends string>(\n d: Distribution<T>,\n space: readonly T[],\n): { label: T; prob: number }[] {\n // T extends string here, so Distribution<T>.probs resolves to the keyed-by-T\n // branch of the conditional. The cast tells TS the conditional collapsed.\n const probs = d.probs as { readonly [K in T]: number };\n const items: { label: T; prob: number }[] = space.map((label) => ({\n label,\n prob: probs[label],\n }));\n items.sort((a, b) => b.prob - a.prob);\n return items;\n}\n\nfunction applyBinaryDeadband<T extends string>(\n top: { label: T; prob: number },\n second: { label: T; prob: number },\n t: ThresholdValues,\n): ThresholdResult<T> {\n if (top.prob >= t.high) {\n return { kind: \"classified\", value: top.label, probability: top.prob };\n }\n if (t.low !== undefined && top.prob <= t.low) {\n return { kind: \"classified\", value: second.label, probability: second.prob };\n }\n return { kind: \"uncertain\", top: top.label, probability: top.prob, runnerUp: second.label };\n}\n\nfunction applyMultiClassRule<T extends string>(\n top: { label: T; prob: number },\n second: { label: T; prob: number },\n t: ThresholdValues,\n): ThresholdResult<T> {\n if (top.prob < t.high) {\n return { kind: \"uncertain\", top: top.label, probability: top.prob, runnerUp: second.label };\n }\n if (t.margin !== undefined && top.prob - second.prob < t.margin) {\n return { kind: \"uncertain\", top: top.label, probability: top.prob, runnerUp: second.label };\n }\n return { kind: \"classified\", value: top.label, probability: top.prob };\n}\n","/**\n * `decide()` — the engine orchestrator. Walks the provider chain, dispatching\n * each attempt's outcome (`Verdict` / `lastUncertain` / `continue`) into the\n * right terminal path.\n *\n * Single-responsibility helpers handle the heavy lifting:\n * - cache + provider call → `engine/distribution.ts`\n * - error → outcome translation → `engine/error-recording.ts`\n * - terminal Verdict construction → `engine/finalize.ts`\n *\n * Errors during the chain become `Unknown` Verdicts under the default\n * `onErrorPolicy: \"fallback\"`; under `\"throw\"` they propagate as\n * `BudgetExhaustedError` / `AbortError` / `AggregateError`.\n */\n\nimport type { Provider } from \"../providers/provider.js\";\nimport type { Classified, Distribution, Uncertain, Unknown, Verdict } from \"../types.js\";\nimport { validateDistribution } from \"../validate.js\";\nimport { abortReason, buildCancelledVerdict } from \"./abort.js\";\nimport {\n DEFAULT_CHAIN_TIMEOUT_MS,\n DEFAULT_PER_CALL_TIMEOUT_MS,\n type DecideConfig,\n} from \"./config.js\";\nimport { computeProviderCacheKey, loadDistribution, mergeSignals } from \"./distribution.js\";\nimport {\n type AttemptOutcome,\n handleDistributionError,\n recordValidationError,\n} from \"./error-recording.js\";\nimport { checkChainBudget, finalizeChainExhausted, makeCancelledFromMeta } from \"./finalize.js\";\nimport { fireAndForget } from \"./hooks.js\";\nimport { buildMeta, type MetaBuilder, makeMetaBuilder } from \"./meta.js\";\nimport { applyThresholds } from \"./threshold.js\";\n\nexport async function decide<T extends string>(\n formattedInput: string,\n config: DecideConfig<T>,\n signal?: AbortSignal,\n): Promise<Verdict<T>> {\n const meta = makeMetaBuilder();\n\n const preAbort = abortReason(signal);\n if (preAbort !== undefined) {\n return makeCancelledFromMeta(meta, preAbort);\n }\n\n fireAndForget(config.hooks?.onCall, formattedInput, {\n providers: config.providers.map((p) => p.id),\n });\n\n const limits = computeLimits(config);\n const chainStartMs = Date.now();\n let lastCalibrated: Distribution<T> | undefined;\n let attempts = 0;\n\n for (let i = 0; i < config.providers.length; i++) {\n const provider = config.providers[i] as Provider;\n if (attempts >= limits.maxCalls) break;\n attempts++;\n meta.providersAttempted.push(provider.id);\n\n const chainBudgetVerdict = checkChainBudget(meta, chainStartMs, limits.chainTimeoutMs, config);\n if (chainBudgetVerdict !== undefined) {\n fireAndForget(config.hooks?.onResult, chainBudgetVerdict);\n return chainBudgetVerdict;\n }\n\n const midAbort = abortReason(signal);\n if (midAbort !== undefined) {\n const verdict = buildCancelledVerdict<T>(meta, midAbort, provider);\n fireAndForget(config.hooks?.onResult, verdict);\n return verdict;\n }\n\n const isLastProvider = i === config.providers.length - 1;\n const outcome = await attemptProvider(\n provider,\n formattedInput,\n config,\n meta,\n signal,\n i,\n chainStartMs,\n limits.perCallTimeoutMs,\n isLastProvider,\n );\n\n if (outcome.kind === \"verdict\") {\n fireAndForget(config.hooks?.onResult, outcome.verdict);\n return outcome.verdict;\n }\n if (outcome.kind === \"lastUncertain\") {\n lastCalibrated = outcome.calibrated;\n fireAndForget(config.hooks?.onResult, outcome.verdict);\n return outcome.verdict;\n }\n if (outcome.calibrated !== undefined) lastCalibrated = outcome.calibrated;\n }\n\n return finalizeChainExhausted(meta, lastCalibrated, attempts, config);\n}\n\ntype Limits = {\n perCallTimeoutMs: number;\n chainTimeoutMs: number;\n maxCalls: number;\n};\n\nfunction computeLimits<T extends string>(config: DecideConfig<T>): Limits {\n return {\n perCallTimeoutMs: config.budget?.perCallTimeoutMs ?? DEFAULT_PER_CALL_TIMEOUT_MS,\n chainTimeoutMs: config.budget?.chainTimeoutMs ?? DEFAULT_CHAIN_TIMEOUT_MS,\n maxCalls: config.budget?.maxCalls ?? config.providers.length,\n };\n}\n\nasync function attemptProvider<T extends string>(\n provider: Provider,\n formattedInput: string,\n config: DecideConfig<T>,\n meta: MetaBuilder,\n userSignal: AbortSignal | undefined,\n index: number,\n chainStartMs: number,\n perCallTimeoutMs: number,\n isLastProvider: boolean,\n): Promise<AttemptOutcome<T>> {\n const cacheKey = computeProviderCacheKey(provider, formattedInput, config);\n const timeoutSignal = AbortSignal.timeout(perCallTimeoutMs);\n const mergedSignal = mergeSignals(userSignal, timeoutSignal);\n\n let distribution: Distribution<T>;\n try {\n distribution = await loadDistribution(\n provider,\n formattedInput,\n config,\n meta,\n mergedSignal,\n cacheKey,\n );\n } catch (err) {\n return handleDistributionError(\n err,\n provider,\n meta,\n config,\n userSignal,\n timeoutSignal,\n index,\n chainStartMs,\n cacheKey,\n );\n }\n\n try {\n validateDistribution(distribution, config.space);\n } catch (err) {\n return recordValidationError(err, provider, meta, config, index, cacheKey);\n }\n\n const calibrated = config.calibrator.apply(distribution);\n const result = applyThresholds(calibrated, config.thresholds, config.space);\n\n if (result.kind === \"classified\") {\n const verdict: Classified<T> = {\n kind: \"classified\",\n value: result.value,\n probability: result.probability,\n meta: buildMeta(meta, provider),\n };\n return { kind: \"verdict\", verdict };\n }\n\n if (result.kind === \"out_of_distribution\") {\n const verdict: Unknown<T> = {\n kind: \"unknown\",\n reason: {\n type: \"out_of_distribution\",\n coverage: result.coverage,\n topIfRenormalized: result.topIfRenormalized,\n probabilityIfRenormalized: result.probabilityIfRenormalized,\n },\n meta: buildMeta(meta, provider),\n };\n return { kind: \"verdict\", verdict };\n }\n\n // Uncertain: last provider in the chain returns it; otherwise fall through.\n if (isLastProvider) {\n const verdict: Uncertain<T> = {\n kind: \"uncertain\",\n top: result.top,\n probability: result.probability,\n runnerUp: result.runnerUp,\n distribution: calibrated,\n meta: buildMeta(meta, provider),\n };\n return { kind: \"lastUncertain\", verdict, calibrated };\n }\n return { kind: \"continue\", calibrated };\n}\n","/**\n * Tokenizer abstraction (internal — not exported from the public surface).\n *\n * Supports first-token-id resolution for decision-space collision detection\n * and logit_bias construction. Backed by tiktoken (`cl100k_base` for OpenAI\n * models). Adapters that need different tokenizers can build their own\n * implementation of the same internal interface.\n *\n * Contract:\n * - `encode(label)` returns the token ids for the leading whitespace + label\n * (matches OpenAI's tokenization of an emitted output token).\n * - `firstTokenId(label)` returns the first token id of the encoded label.\n *\n * Note: OpenAI's tokenizer often prepends a leading space to emitted tokens\n * (`\" yes\"` vs `\"yes\"`). We detect first-token id with the leading-space\n * variant since that's what the model emits at the first content position.\n */\n\nimport { get_encoding, type Tiktoken } from \"tiktoken\";\n\ntype TokenizerId = \"openai/cl100k_base\";\n\nexport interface Tokenizer {\n readonly id: TokenizerId;\n /** Token ids for `label` as it would appear at a generation boundary. */\n encode(label: string): number[];\n /** First token id of `label` at a generation boundary. */\n firstTokenId(label: string): number;\n}\n\nlet cl100kSingleton: Tokenizer | undefined;\n\n/**\n * cl100k_base tokenizer, used by GPT-4o family + most OpenAI Chat models.\n * Lazy-initialized; the underlying tiktoken native module is heavy.\n */\nexport function cl100kTokenizer(): Tokenizer {\n if (cl100kSingleton !== undefined) return cl100kSingleton;\n const enc: Tiktoken = get_encoding(\"cl100k_base\");\n cl100kSingleton = {\n id: \"openai/cl100k_base\",\n encode(label: string): number[] {\n // Models typically emit labels with a leading space at the first content\n // position (e.g., the model writes \" yes\" not \"yes\"). Encode with that\n // convention so first-token detection matches what we'd see in logprobs.\n const withLeadingSpace = label.startsWith(\" \") ? label : ` ${label}`;\n const ids = enc.encode(withLeadingSpace);\n return Array.from(ids);\n },\n firstTokenId(label: string): number {\n const ids = this.encode(label);\n const first = ids[0];\n if (first === undefined) {\n throw new Error(`Tokenizer produced empty encoding for label ${JSON.stringify(label)}`);\n }\n return first;\n },\n };\n return cl100kSingleton;\n}\n\n/**\n * Detect first-token-id collisions across a decision space. Returns the\n * conflicting label pair if any two labels resolve to the same first token,\n * or `undefined` if the space is collision-free.\n *\n * Used by the OpenAI adapter (and other tokenizer-aware adapters) at\n * construction time to throw `ConfigError({ code: \"decision_space_collision\" })`\n * before any network I/O.\n *\n * Imperative form (rather than `reduce`) chosen for readability: the early\n * return on first collision short-circuits naturally without the bookkeeping\n * that a `reduce` accumulator would require.\n */\nexport function findFirstTokenCollision(\n tokenizer: Tokenizer,\n space: readonly string[],\n): { a: string; b: string; tokenId: number } | undefined {\n const seenByTokenId = new Map<number, string>();\n for (const label of space) {\n const tokenId = tokenizer.firstTokenId(label);\n const priorLabel = seenByTokenId.get(tokenId);\n if (priorLabel !== undefined && priorLabel !== label) {\n return { a: priorLabel, b: label, tokenId };\n }\n seenByTokenId.set(tokenId, label);\n }\n return undefined;\n}\n\n/**\n * Build a logit_bias map for OpenAI Chat Completions: positive bias on each\n * in-space first-token id. Negative biases are deliberately avoided so the\n * coverage signal stays honest — positive bias nudges, doesn't force.\n */\nexport function buildLogitBias(\n tokenizer: Tokenizer,\n space: readonly string[],\n bias = 100,\n): Record<string, number> {\n return Object.fromEntries(\n space.map((label) => [String(tokenizer.firstTokenId(label)), bias] as const),\n );\n}\n","/**\n * Two paths from OpenAI's `top_logprobs` array to a `Distribution<T>` over\n * the in-space labels:\n *\n * - `buildDistributionByTokenId` — preferred path when a tokenizer is\n * wired up (hosted OpenAI's cl100k_base, or `openaiCompat` with\n * `useCl100kTokenizer: true`). Each top-K entry's surface-form string\n * is re-encoded to its first token id, then matched against the\n * in-space first-token id map. Reliable across SDK versions and\n * handles whitespace-padded variants.\n * - `buildDistributionByStringMatch` — fallback when no tokenizer is\n * available (Ollama with arbitrary models). Matches by trimmed string\n * equality or label-prefix.\n *\n * Both end with `renormalize` over the in-space mass to produce a proper\n * probability distribution; the pre-renormalization in-space mass is\n * preserved as `coverage`.\n */\n\nimport type OpenAI from \"openai\";\nimport type { Tokenizer } from \"../../tokenizer.js\";\nimport type { Distribution } from \"../../types.js\";\n\ntype TopLogprobEntry = OpenAI.Chat.Completions.ChatCompletionTokenLogprob.TopLogprob;\n\nexport function buildDistributionByTokenId<T extends string>(\n space: readonly T[],\n tokenLogprobs: readonly TopLogprobEntry[],\n inSpaceIds: Map<number, T>,\n tokenizer: Tokenizer,\n): Distribution<T> {\n const inSpace = new Map<T, number>();\n let inSpaceMass = 0;\n\n for (const entry of tokenLogprobs) {\n const ids = tokenizer.encode(entry.token);\n const firstId = ids[0];\n if (firstId === undefined) continue;\n const label = inSpaceIds.get(firstId);\n if (label === undefined) continue;\n const prob = Math.exp(entry.logprob);\n const previous = inSpace.get(label) ?? 0;\n if (prob > previous) {\n inSpace.set(label, prob);\n inSpaceMass += prob - previous;\n }\n }\n\n return renormalize(space, inSpace, inSpaceMass);\n}\n\nexport function buildDistributionByStringMatch<T extends string>(\n space: readonly T[],\n tokenLogprobs: readonly TopLogprobEntry[],\n): Distribution<T> {\n const inSpace = new Map<T, number>();\n let inSpaceMass = 0;\n\n for (const label of space) {\n const trimmed = label.trim();\n let bestProb = 0;\n for (const entry of tokenLogprobs) {\n const tok = entry.token.trim();\n // `startsWith(\"\")` is trivially true; require a non-empty token first.\n if (tok === trimmed || (tok && trimmed.startsWith(tok))) {\n const prob = Math.exp(entry.logprob);\n if (prob > bestProb) bestProb = prob;\n }\n }\n if (bestProb > 0) {\n inSpace.set(label, bestProb);\n inSpaceMass += bestProb;\n }\n }\n\n return renormalize(space, inSpace, inSpaceMass);\n}\n\nfunction renormalize<T extends string>(\n space: readonly T[],\n inSpace: Map<T, number>,\n inSpaceMass: number,\n): Distribution<T> {\n const coverage = Math.min(1, inSpaceMass);\n const probs: Record<string, number> = {};\n for (const label of space) {\n const raw = inSpace.get(label) ?? 0;\n probs[label] = inSpaceMass > 0 ? raw / inSpaceMass : 0;\n }\n return {\n probs: probs as Distribution<T>[\"probs\"],\n coverage,\n };\n}\n","/**\n * The internal `buildAdapter` that all three openai-flavored factories\n * (`openai`, `ollama`, `openaiCompat`) share. Wires up the OpenAI Chat\n * Completions request, translates its top-K logprobs into a `Distribution<T>`,\n * and exposes the eager `validate(space)` hook when a tokenizer is available\n * for first-token collision detection.\n */\n\nimport type OpenAI from \"openai\";\nimport { ConfigError, canonicalizeProviderThrow, ProviderError } from \"../../errors.js\";\nimport { renderSystemPrompt, renderUserPrompt } from \"../../prompt.js\";\nimport { buildLogitBias, findFirstTokenCollision, type Tokenizer } from \"../../tokenizer.js\";\nimport type { Distribution, ProviderCapabilities } from \"../../types.js\";\nimport type { Provider, SampleOptions } from \"../provider.js\";\nimport { buildDistributionByStringMatch, buildDistributionByTokenId } from \"./distribution.js\";\n\n// Positive bias on in-space first-tokens only. Nudges the model toward\n// in-space output without forcing — keeps the coverage signal honest.\nconst LOGIT_BIAS_VALUE = 100;\n\nexport type AdapterArgs = {\n readonly id: string;\n readonly modelId: string;\n readonly tokenizerId: string;\n readonly capabilities: ProviderCapabilities;\n readonly client: OpenAI;\n /**\n * Tokenizer for first-token-id resolution and logit_bias construction.\n * When omitted, the adapter falls back to string-based logprob matching.\n */\n readonly tokenizer?: Tokenizer;\n};\n\nexport function buildAdapter(args: AdapterArgs): Provider {\n // Memo of spaces already checked, shared by the eager validate hook and\n // the per-call defense-in-depth check, so repeat passes are zero-cost.\n const collisionMemo = new Set<string>();\n const tokenizer = args.tokenizer;\n\n // The eager `validate` hook is exposed only when a tokenizer is available;\n // backends without tokenizer info (e.g. default Ollama) skip it.\n const eagerValidate =\n tokenizer === undefined\n ? {}\n : {\n validate: (space: readonly string[]): void => {\n ensureNoCollisions(tokenizer, space, collisionMemo);\n },\n };\n\n return {\n id: args.id,\n modelId: args.modelId,\n tokenizerId: args.tokenizerId,\n capabilities: args.capabilities,\n ...eagerValidate,\n\n async sample<T extends string>(\n input: string,\n space: readonly T[],\n opts: SampleOptions,\n ): Promise<Distribution<T>> {\n // Defense-in-depth: catches callers that bypassed `validateClassifierConfig`.\n let logitBias: Record<string, number> | undefined;\n let inSpaceFirstTokenIds: Map<number, T> | undefined;\n if (tokenizer !== undefined) {\n ensureNoCollisions(tokenizer, space, collisionMemo);\n logitBias = buildLogitBias(tokenizer, space, LOGIT_BIAS_VALUE);\n inSpaceFirstTokenIds = mapFirstTokenIds(tokenizer, space);\n }\n\n const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [];\n const system = renderSystemPrompt(opts.template, space);\n if (system !== undefined) {\n messages.push({ role: \"system\", content: system });\n }\n messages.push({ role: \"user\", content: renderUserPrompt(opts.template, input, space) });\n\n let response: OpenAI.Chat.ChatCompletion;\n try {\n const params: OpenAI.Chat.ChatCompletionCreateParamsNonStreaming = {\n model: args.modelId,\n messages,\n temperature: opts.temperature,\n logprobs: true,\n top_logprobs: Math.min(args.capabilities.maxTopLogprobs, Math.max(space.length * 2, 5)),\n // One label is one short word; 16 tokens is enough headroom.\n max_completion_tokens: 16,\n };\n if (opts.seed !== undefined) params.seed = opts.seed;\n if (logitBias !== undefined) params.logit_bias = logitBias;\n\n const requestOpts: { signal?: AbortSignal; timeout?: number } = {\n timeout: opts.timeoutMs,\n };\n if (opts.signal !== undefined) requestOpts.signal = opts.signal;\n response = await args.client.chat.completions.create(params, requestOpts);\n } catch (err) {\n throw canonicalizeProviderThrow(err);\n }\n\n const choice = response.choices[0];\n if (choice === undefined) {\n throw new ProviderError(\"OpenAI response had no choices.\", {\n code: \"provider_malformed_response\",\n });\n }\n const tokenLogprobs = choice.logprobs?.content?.[0]?.top_logprobs;\n if (tokenLogprobs === undefined || tokenLogprobs.length === 0) {\n throw new ProviderError(\"OpenAI response missing first-token logprobs.\", {\n code: \"provider_malformed_response\",\n });\n }\n\n return tokenizer !== undefined && inSpaceFirstTokenIds !== undefined\n ? buildDistributionByTokenId(space, tokenLogprobs, inSpaceFirstTokenIds, tokenizer)\n : buildDistributionByStringMatch(space, tokenLogprobs);\n },\n };\n}\n\nfunction ensureNoCollisions<T extends string>(\n tokenizer: Tokenizer,\n space: readonly T[],\n memo: Set<string>,\n): void {\n const memoKey = JSON.stringify(space);\n if (memo.has(memoKey)) return;\n const collision = findFirstTokenCollision(tokenizer, space);\n if (collision !== undefined) {\n throw new ConfigError(\n `Decision space contains first-token collision: ${JSON.stringify(collision.a)} and ${JSON.stringify(collision.b)} both encode to token id ${collision.tokenId}. Prefix-disambiguate the labels (e.g., 'A_yes' / 'A_no') or pick alternatives.`,\n { code: \"decision_space_collision\" },\n );\n }\n memo.add(memoKey);\n}\n\nfunction mapFirstTokenIds<T extends string>(\n tokenizer: Tokenizer,\n space: readonly T[],\n): Map<number, T> {\n const map = new Map<number, T>();\n for (const label of space) {\n map.set(tokenizer.firstTokenId(label), label);\n }\n return map;\n}\n","/**\n * Three factories for OpenAI Chat Completions backends — hosted, local\n * Ollama, and generic OpenAI-compatible (vLLM, LM Studio, Together,\n * Fireworks, OpenRouter, …). All share the internal adapter; they differ\n * only in default base URL, default API key, and whether a tokenizer is\n * wired up for first-token collision detection and logit_bias construction.\n */\n\nimport OpenAI from \"openai\";\nimport { cl100kTokenizer } from \"../../tokenizer.js\";\nimport type { ProviderCapabilities } from \"../../types.js\";\nimport type { Provider } from \"../provider.js\";\nimport { type AdapterArgs, buildAdapter } from \"./adapter.js\";\n\n/**\n * The known-models list provides autocomplete; the `(string & {})` member is\n * an escape hatch so new models work without a library release.\n */\nexport type OpenAIModel =\n | \"gpt-4o\"\n | \"gpt-4o-mini\"\n | \"gpt-4-turbo\"\n | \"o1\"\n | \"o1-mini\"\n | \"o1-preview\"\n | \"gpt-3.5-turbo\"\n | (string & {});\n\nexport type OpenAIProviderOptions = {\n /** Default: `\"https://api.openai.com/v1\"`. */\n readonly baseURL?: string;\n /**\n * Default: `process.env.OPENAI_API_KEY`. For Ollama / LM Studio /\n * compat backends, pass any non-empty string the SDK will accept.\n */\n readonly apiKey?: string;\n /** SDK-level request timeout. Independent of the engine's own budget. */\n readonly timeout?: number;\n};\n\nconst LOGPROBS_CAPABILITIES: ProviderCapabilities = {\n distributionSource: \"logprobs\",\n coverageMeasurement: \"exact\",\n // OpenAI hosted caps top_logprobs at 20; most OpenAI-compat backends match.\n maxTopLogprobs: 20,\n};\n\n/**\n * Hosted OpenAI provider. Defaults to `process.env.OPENAI_API_KEY` and\n * `https://api.openai.com/v1`. Uses the cl100k_base tokenizer for exact\n * first-token-id resolution + logit_bias on the request.\n *\n * @example\n * const cloud = openai(\"gpt-4o-mini\");\n */\nexport function openai(model: OpenAIModel, opts?: OpenAIProviderOptions): Provider {\n const client = new OpenAI({\n apiKey: opts?.apiKey ?? process.env.OPENAI_API_KEY,\n baseURL: opts?.baseURL,\n timeout: opts?.timeout,\n });\n return buildAdapter({\n id: `openai/${model}`,\n modelId: model,\n tokenizerId: \"openai/cl100k_base\",\n capabilities: LOGPROBS_CAPABILITIES,\n client,\n tokenizer: cl100kTokenizer(),\n });\n}\n\nconst OLLAMA_DEFAULT_BASE_URL = \"http://localhost:11434/v1\";\nconst OLLAMA_DEFAULT_API_KEY = \"ollama\";\n\n/**\n * Local Ollama provider via OpenAI-compatible endpoint.\n * Defaults to `http://localhost:11434/v1` with apiKey `\"ollama\"`.\n *\n * Ollama backends run various tokenizers depending on the model; the\n * adapter falls back to string-based logprob matching by default. Users\n * who need exact collision detection can supply a custom Provider\n * implementing the public Provider interface.\n *\n * @example\n * const local = ollama(\"llama-3.1-70b\");\n */\nexport function ollama(model: string, opts?: OpenAIProviderOptions): Provider {\n const client = new OpenAI({\n apiKey: opts?.apiKey ?? OLLAMA_DEFAULT_API_KEY,\n baseURL: opts?.baseURL ?? OLLAMA_DEFAULT_BASE_URL,\n timeout: opts?.timeout,\n });\n return buildAdapter({\n id: `ollama/${model}`,\n modelId: model,\n // Tokenizer id for cache-key composition; treated opaquely.\n tokenizerId: `ollama/${model}`,\n capabilities: LOGPROBS_CAPABILITIES,\n client,\n // No tokenizer — string-based fallback matches Ollama's varied tokenizers.\n });\n}\n\nexport type OpenAICompatOptions = OpenAIProviderOptions & {\n /** Required for openaiCompat — caller must specify the endpoint. */\n readonly baseURL: string;\n /** Optional override of the tokenizer identifier (used in cache keys). */\n readonly tokenizerId?: string;\n /** Optional override of the provider id (used in cache keys + meta.providerUsed). */\n readonly providerId?: string;\n /** Override capabilities (e.g., higher maxTopLogprobs than 20 if backend supports). */\n readonly capabilities?: Partial<ProviderCapabilities>;\n /**\n * Opt into cl100k_base tokenizer (use only when backend's tokenizer matches\n * OpenAI's cl100k_base — e.g., vLLM running an OpenAI-compatible model).\n * Default: false (string-based fallback).\n */\n readonly useCl100kTokenizer?: boolean;\n};\n\n/**\n * Generic OpenAI-compatible provider. Use for vLLM, LM Studio, Together,\n * Fireworks, OpenRouter, or any backend that speaks the OpenAI Chat\n * Completions wire format.\n *\n * @example\n * const fireworks = openaiCompat(\"accounts/fireworks/models/llama-3\", {\n * baseURL: \"https://api.fireworks.ai/inference/v1\",\n * apiKey: process.env.FIREWORKS_API_KEY,\n * });\n */\nexport function openaiCompat(model: string, opts: OpenAICompatOptions): Provider {\n const client = new OpenAI({\n apiKey: opts.apiKey,\n baseURL: opts.baseURL,\n timeout: opts.timeout,\n });\n const capabilities: ProviderCapabilities = {\n ...LOGPROBS_CAPABILITIES,\n ...opts.capabilities,\n };\n // Derive an id from baseURL host if not explicitly overridden.\n const inferredId =\n opts.providerId ??\n (() => {\n try {\n const host = new URL(opts.baseURL).host;\n return `${host}/${model}`;\n } catch {\n return `compat/${model}`;\n }\n })();\n const args: AdapterArgs = {\n id: inferredId,\n modelId: model,\n tokenizerId: opts.tokenizerId ?? `compat/${model}`,\n capabilities,\n client,\n };\n if (opts.useCl100kTokenizer === true) {\n return buildAdapter({ ...args, tokenizer: cl100kTokenizer() });\n }\n return buildAdapter(args);\n}\n","/**\n * Environment-driven provider chain resolution.\n *\n * DOMOVOI_PROVIDERS=openai/gpt-4o-mini,openai/gpt-4o,ollama/llama-3.1-70b\n * DOMOVOI_PROVIDERS_ARTICLES=... (override for `classifier({ name: \"articles\" })`)\n *\n * Format: `factory/model[,factory/model…]`. The first `/` separates factory\n * from model; later slashes belong to the model name (e.g.\n * `openrouter/meta-llama/llama-3.1-70b`). Whitespace is trimmed; empty\n * entries are skipped; an empty / whitespace-only value counts as unset.\n *\n * Per-provider parametric options (`multiSampleN`, custom timeouts) cannot\n * be expressed in env — drop to an explicit `providers: [...]` array for\n * those.\n */\n\nimport { ConfigError } from \"./errors.js\";\nimport { ollama, openai } from \"./providers/openai/index.js\";\nimport type { Provider } from \"./providers/provider.js\";\n\ntype FactoryFn = (model: string) => Provider;\n\n/**\n * Env-resolvable factories. `openaiCompat` is omitted — it requires a\n * `baseURL` which is not expressible in the env format; callers needing\n * OpenAI-compat backends pass `providers: [...]` explicitly.\n */\nconst BUILTIN_FACTORIES: Record<string, FactoryFn> = {\n openai: (model: string) => openai(model),\n ollama: (model: string) => ollama(model),\n};\n\ntype ParsedEntry = {\n readonly factory: string;\n readonly model: string;\n};\n\n/**\n * Parses a DOMOVOI_PROVIDERS-style string into typed entries. Throws\n * `ConfigError` with `code: \"malformed_provider_config\"` on a bad entry.\n * Returns `[]` for empty / whitespace-only input — callers treat that as unset.\n */\nexport function parseProvidersEnv(raw: string | undefined): readonly ParsedEntry[] {\n if (raw === undefined) return [];\n const trimmed = raw.trim();\n if (!trimmed) return [];\n\n return trimmed\n .split(\",\")\n .map((part) => part.trim())\n .filter(Boolean)\n .map(parseProviderEntry);\n}\n\nfunction parseProviderEntry(entry: string): ParsedEntry {\n const slashIndex = entry.indexOf(\"/\");\n if (slashIndex < 0) {\n throw new ConfigError(\n `DOMOVOI_PROVIDERS: malformed entry ${JSON.stringify(entry)}; expected factory/model format.`,\n { code: \"malformed_provider_config\" },\n );\n }\n const factory = entry.slice(0, slashIndex).trim();\n const model = entry.slice(slashIndex + 1).trim();\n if (!factory || !model) {\n throw new ConfigError(\n `DOMOVOI_PROVIDERS: malformed entry ${JSON.stringify(entry)}; factory or model is empty.`,\n { code: \"malformed_provider_config\" },\n );\n }\n return { factory, model };\n}\n\n/**\n * Resolves a DOMOVOI_PROVIDERS-style env value into Provider instances.\n *\n * Throws `ConfigError` with `code` ∈ { `missing_provider_config`,\n * `malformed_provider_config`, `unknown_provider_factory` }. Credential\n * presence is not checked here — the underlying SDK surfaces that on first\n * call.\n */\nexport function resolveProvidersFromEnv(raw: string | undefined): readonly Provider[] {\n const entries = parseProvidersEnv(raw);\n if (entries.length === 0) {\n throw new ConfigError(\n \"Cannot resolve provider chain: DOMOVOI_PROVIDERS is unset or empty. \" +\n \"Set the env variable or pass `providers` explicitly.\",\n { code: \"missing_provider_config\" },\n );\n }\n return entries.map((entry) => {\n const factory = BUILTIN_FACTORIES[entry.factory];\n if (factory === undefined) {\n throw new ConfigError(\n `DOMOVOI_PROVIDERS: unknown factory ${JSON.stringify(entry.factory)}. Known: ${Object.keys(BUILTIN_FACTORIES).join(\", \")}. For other providers, supply { providers } explicitly in code.`,\n { code: \"unknown_provider_factory\" },\n );\n }\n return factory(entry.model);\n });\n}\n\n/**\n * Resolves the chain for a classifier with optional `name`. Tries\n * `DOMOVOI_PROVIDERS_<NAME>` first (uppercased), then `DOMOVOI_PROVIDERS`.\n * Throws `ConfigError({ code: \"missing_provider_config\" })` if both are unset.\n *\n * Tests must stub env *before* the first domovoi call — env is read lazily,\n * but only once per classifier resolution.\n */\nexport function resolveDefaultProviders(name?: string): readonly Provider[] {\n if (name !== undefined) {\n const namedKey = `DOMOVOI_PROVIDERS_${name.toUpperCase()}`;\n const namedRaw = process.env[namedKey];\n if (namedRaw?.trim()) {\n return resolveProvidersFromEnv(namedRaw);\n }\n }\n return resolveProvidersFromEnv(process.env.DOMOVOI_PROVIDERS);\n}\n","/**\n * Binary one-shot classifier — returns `Verdict<boolean>`.\n *\n * The engine internally classifies over the string space `[\"yes\", \"no\"]` to\n * match LLM first-token tokenization cleanly; a small transform at the verb\n * boundary maps the result to `boolean` so the public surface is idiomatic.\n *\n * Default deadband `{ high: 0.7, low: 0.3, coverageMin: 0.3 }` is\n * illustrative — tune for your workload.\n */\n\nimport { type Cache, memoryCache } from \"../cache.js\";\nimport { type Calibrator, identity } from \"../calibration/index.js\";\nimport { decide, validateClassifierConfig, withDefaults } from \"../engine/index.js\";\nimport { resolveDefaultProviders } from \"../env.js\";\nimport { defaultTemplate } from \"../prompt.js\";\nimport type { Provider } from \"../providers/provider.js\";\nimport type { Budget, Distribution, Thresholds, UnknownVerdictCause, Verdict } from \"../types.js\";\n\ntype YesNo = \"yes\" | \"no\";\n\nconst ONE_SHOT_BINARY_THRESHOLDS = { high: 0.7, low: 0.3, coverageMin: 0.3 } as const;\n\nconst YES_NO_SPACE = [\"yes\", \"no\"] as const satisfies readonly [YesNo, YesNo];\n\nexport type BooleanOptions = {\n readonly providers?: readonly Provider[];\n readonly calibrator?: Calibrator;\n readonly cache?: Cache;\n readonly budget?: Budget;\n readonly thresholds?: Thresholds<typeof YES_NO_SPACE>;\n readonly signal?: AbortSignal;\n};\n\nexport async function boolean(\n input: string,\n question: string,\n opts?: BooleanOptions,\n): Promise<Verdict<boolean>> {\n const providers =\n opts?.providers !== undefined && opts.providers.length > 0\n ? opts.providers\n : resolveDefaultProviders();\n\n const calibrator = opts?.calibrator ?? identity;\n const cache = opts?.cache ?? memoryCache();\n const thresholds: Thresholds<typeof YES_NO_SPACE> =\n opts?.thresholds ?? ONE_SHOT_BINARY_THRESHOLDS;\n\n validateClassifierConfig({\n space: YES_NO_SPACE,\n thresholds,\n providers,\n calibrator,\n });\n\n const config = withDefaults<YesNo>({\n space: YES_NO_SPACE,\n thresholds,\n providers,\n calibrator,\n cache,\n template: defaultTemplate,\n question,\n ...(opts?.budget !== undefined ? { budget: opts.budget } : {}),\n });\n\n const verdict = await decide(input, config, opts?.signal);\n return toBooleanVerdict(verdict);\n}\n\n/**\n * Map `Verdict<\"yes\" | \"no\">` → `Verdict<boolean>`. The engine works on string\n * labels; this transform is the verb-boundary adapter so the public type is a\n * plain `boolean`. Distribution keys go from `{ yes, no }` → `{ true, false }`.\n */\nfunction toBooleanVerdict(v: Verdict<YesNo>): Verdict<boolean> {\n switch (v.kind) {\n case \"classified\":\n return { ...v, value: v.value === \"yes\" };\n case \"uncertain\":\n return {\n ...v,\n top: v.top === \"yes\",\n runnerUp: v.runnerUp === \"yes\",\n distribution: rekey(v.distribution),\n };\n case \"unknown\":\n return { ...v, reason: convertCause(v.reason) };\n }\n}\n\nfunction convertCause(cause: UnknownVerdictCause<YesNo>): UnknownVerdictCause<boolean> {\n switch (cause.type) {\n case \"out_of_distribution\":\n return { ...cause, topIfRenormalized: cause.topIfRenormalized === \"yes\" };\n case \"chain_exhausted\":\n return { ...cause, lastDistribution: rekey(cause.lastDistribution) };\n // Remaining variants don't reference T — payload is structurally identical\n // between UnknownVerdictCause<YesNo> and UnknownVerdictCause<boolean>.\n case \"predicate_rejected\":\n case \"provider_failure\":\n case \"budget_exhausted\":\n case \"cancelled\":\n return cause;\n }\n}\n\nfunction rekey(d: Distribution<YesNo>): Distribution<boolean> {\n return {\n probs: { true: d.probs.yes, false: d.probs.no },\n coverage: d.coverage,\n };\n}\n","/**\n * domovoi.classifier({...}) — reusable configured classifier factory.\n *\n * Returns a `Classifier<T, I>`: a callable that takes an input, returns\n * `Promise<Verdict<T>>`. Also exposes `.batch(items, opts?)` and `.classify`\n * alias for discoverability.\n *\n * Validates configuration at construction time (validate.ts) and resolves\n * env-driven providers if `providers` is omitted (env.ts).\n *\n * Note: full callable+method shape requires assigning methods to a function\n * object. We use `Object.assign` to achieve this with type safety.\n */\n\nimport { type Cache, memoryCache } from \"../cache.js\";\nimport { type Calibrator, identity } from \"../calibration/index.js\";\nimport { decide, validateClassifierConfig, withDefaults } from \"../engine/index.js\";\nimport { resolveDefaultProviders } from \"../env.js\";\nimport { defaultTemplate } from \"../prompt.js\";\nimport type { Provider } from \"../providers/provider.js\";\nimport type { Budget, PromptTemplate, Thresholds, Verdict } from \"../types.js\";\n\n/**\n * Configuration accepted by `domovoi.classifier({...})`.\n *\n * `format` is required when `I` is not assignable to `string`. When `I = string`\n * (default), `format` is optional and defaults to identity.\n */\nexport type ClassifierConfig<T extends string, I> = {\n /** /^[a-z][a-z0-9_]*$/; uppercased for env-binding lookup. */\n readonly name?: string;\n readonly space: readonly [T, ...T[]];\n readonly question?: string;\n readonly format?: (x: I) => string;\n readonly thresholds: Thresholds<readonly [T, ...T[]]>;\n readonly providers?: readonly Provider[];\n readonly calibrator?: Calibrator;\n readonly cache?: Cache;\n readonly budget?: Budget;\n readonly template?: PromptTemplate;\n readonly hooks?: {\n onCall?: (...args: unknown[]) => void | Promise<void>;\n onResult?: (...args: unknown[]) => void | Promise<void>;\n };\n readonly onProviderError?: (\n err: Error,\n ctx: { providerId: string; attempt: number },\n ) => void | Promise<void>;\n readonly onErrorPolicy?: \"fallback\" | \"throw\";\n};\n\n/**\n * The configured runtime instance. Callable with an input; returns\n * `Promise<Verdict<T>>`.\n *\n * Methods:\n * - `.batch(items, opts?)`: per-item Verdicts in input order.\n */\nexport interface Classifier<T extends string, I> {\n (input: I, opts?: { signal?: AbortSignal }): Promise<Verdict<T>>;\n batch(\n items: readonly I[],\n opts?: { concurrency?: number; signal?: AbortSignal },\n ): Promise<Verdict<T>[]>;\n}\n\nconst DEFAULT_BATCH_CONCURRENCY = 5;\n\nexport function classifier<const T extends string, I = string>(\n config: ClassifierConfig<T, I>,\n): Classifier<T, I> {\n // Resolve providers: explicit overrides env.\n const providers =\n config.providers !== undefined && config.providers.length > 0\n ? config.providers\n : resolveDefaultProviders(config.name);\n\n const calibrator = config.calibrator ?? identity;\n const cache = config.cache ?? memoryCache();\n const template = config.template ?? defaultTemplate;\n\n // Validate at construction.\n validateClassifierConfig({\n ...(config.name !== undefined ? { name: config.name } : {}),\n space: config.space,\n thresholds: config.thresholds,\n providers,\n calibrator,\n });\n\n // Default `format` to identity if I is string-typed (caller didn't supply).\n // We can't enforce I = string at the type level here (it's a generic param),\n // so we accept the slight runtime cost: if no format, treat input as string.\n const format = config.format ?? ((x: I) => x as unknown as string);\n\n const decideConfig = withDefaults<T>({\n space: config.space,\n thresholds: config.thresholds,\n providers,\n calibrator,\n cache,\n template,\n ...(config.question !== undefined ? { question: config.question } : {}),\n ...(config.budget !== undefined ? { budget: config.budget } : {}),\n ...(config.onErrorPolicy !== undefined ? { onErrorPolicy: config.onErrorPolicy } : {}),\n ...(config.onProviderError !== undefined\n ? { onProviderError: config.onProviderError as never }\n : {}),\n ...(config.hooks !== undefined ? { hooks: config.hooks } : {}),\n });\n\n // Single-item callable.\n const single = async (input: I, opts?: { signal?: AbortSignal }): Promise<Verdict<T>> => {\n const formatted = format(input);\n return decide(formatted, decideConfig, opts?.signal);\n };\n\n // Batch callable.\n const batch = async (\n items: readonly I[],\n opts?: { concurrency?: number; signal?: AbortSignal },\n ): Promise<Verdict<T>[]> => {\n const concurrency = opts?.concurrency ?? DEFAULT_BATCH_CONCURRENCY;\n const results: Verdict<T>[] = new Array(items.length);\n let next = 0;\n\n async function worker(): Promise<void> {\n while (true) {\n const idx = next++;\n if (idx >= items.length) return;\n const item = items[idx] as I;\n // signal-already-aborted produces Unknown { cancelled }; abort\n // discrimination is handled inside single().\n results[idx] = await single(\n item,\n opts?.signal !== undefined ? { signal: opts.signal } : {},\n );\n }\n }\n\n const workers = Array.from({ length: Math.min(concurrency, items.length) }, () => worker());\n await Promise.all(workers);\n return results;\n };\n\n // Callable function with a `.batch` method attached.\n const callable = single as Classifier<T, I>;\n return Object.assign(callable, { batch });\n}\n","/**\n * Multi-class one-shot classifier — returns `Verdict<T>` where `T` is the\n * literal union of labels in `space`.\n *\n * Reads providers from `DOMOVOI_PROVIDERS` env unless the caller supplies\n * `{ providers }`. Default thresholds `{ high: 0.5, coverageMin: 0.3 }` are\n * illustrative — production code should construct `classifier({ ... })`\n * with thresholds tuned to the workload.\n */\n\nimport { type Cache, memoryCache } from \"../cache.js\";\nimport { type Calibrator, identity } from \"../calibration/index.js\";\nimport { decide, validateClassifierConfig, withDefaults } from \"../engine/index.js\";\nimport { resolveDefaultProviders } from \"../env.js\";\nimport { defaultTemplate } from \"../prompt.js\";\nimport type { Provider } from \"../providers/provider.js\";\nimport type { Budget, Thresholds, Verdict } from \"../types.js\";\n\nconst ONE_SHOT_DEFAULT_THRESHOLDS = { high: 0.5, coverageMin: 0.3 } as const;\n\nexport type ClassifyOptions<T extends string> = {\n readonly question?: string;\n readonly providers?: readonly Provider[];\n readonly calibrator?: Calibrator;\n readonly cache?: Cache;\n readonly budget?: Budget;\n readonly thresholds?: Thresholds<readonly [T, ...T[]]>;\n readonly signal?: AbortSignal;\n};\n\nexport async function classify<const T extends string>(\n input: string,\n space: readonly [T, ...T[]],\n opts?: ClassifyOptions<T>,\n): Promise<Verdict<T>> {\n const providers =\n opts?.providers !== undefined && opts.providers.length > 0\n ? opts.providers\n : resolveDefaultProviders();\n\n const calibrator = opts?.calibrator ?? identity;\n const cache = opts?.cache ?? memoryCache();\n const thresholds = (opts?.thresholds ?? ONE_SHOT_DEFAULT_THRESHOLDS) as Thresholds<\n readonly [T, ...T[]]\n >;\n\n // Validate at first-call (one-shots validate lazily).\n validateClassifierConfig({\n space,\n thresholds,\n providers,\n calibrator,\n });\n\n const config = withDefaults<T>({\n space,\n thresholds,\n providers,\n calibrator,\n cache,\n template: defaultTemplate,\n ...(opts?.question !== undefined ? { question: opts.question } : {}),\n ...(opts?.budget !== undefined ? { budget: opts.budget } : {}),\n });\n\n return decide(input, config, opts?.signal);\n}\n","/**\n * Verdict combinators and type guards. The library ships only `match`,\n * `filter`, and the three type guards; richer combinators (tap, getOrElse,\n * etc.) compose cleanly in userspace.\n */\n\nimport type { Classified, Filterable, Label, Uncertain, Unknown, Verdict } from \"./types.js\";\n\nexport function isClassified<T extends Label>(v: Verdict<T>): v is Classified<T> {\n return v.kind === \"classified\";\n}\n\nexport function isUncertain<T extends Label>(v: Verdict<T>): v is Uncertain<T> {\n return v.kind === \"uncertain\";\n}\n\nexport function isUnknown<T extends Label>(v: Verdict<T>): v is Unknown<T> {\n return v.kind === \"unknown\";\n}\n\n/**\n * Pattern-match against a Verdict. All three branches are required;\n * omitting one is a compile-time error.\n *\n * @example\n * const result = match(verdict, {\n * classified: ({ value }) => save(value),\n * uncertain: ({ top, runnerUp }) => queue.review(top, runnerUp),\n * unknown: ({ reason }) => routeUnknown(reason),\n * });\n */\nexport function match<T extends Label, R>(\n v: Verdict<T>,\n handlers: {\n classified: (v: Classified<T>) => R;\n uncertain: (v: Uncertain<T>) => R;\n unknown: (v: Unknown<T>) => R;\n },\n): R {\n switch (v.kind) {\n case \"classified\":\n return handlers.classified(v);\n case \"uncertain\":\n return handlers.uncertain(v);\n case \"unknown\":\n return handlers.unknown(v);\n }\n}\n\n/**\n * Domain-validity filter. The predicate sees `Filterable<T>` — Classified or\n * Uncertain only. When it returns `false`, the Verdict becomes\n * `Unknown { predicate_rejected }`. Unknown inputs pass through unchanged.\n *\n * @example\n * const safe = filter<MyLabels>((v) => {\n * const pick = v.kind === \"classified\" ? v.value : v.top;\n * return !DEPRECATED.has(pick);\n * })(verdict);\n */\nexport function filter<T extends Label>(pred: (v: Filterable<T>) => boolean) {\n return (v: Verdict<T>): Verdict<T> => {\n if (v.kind === \"unknown\") return v;\n if (pred(v)) return v;\n return {\n kind: \"unknown\",\n reason: { type: \"predicate_rejected\", previousKind: v.kind },\n meta: v.meta,\n };\n };\n}\n","/**\n * domovoi — typed-uncertainty classification for TypeScript.\n *\n * Public API entry point. Subpaths:\n * - `@hourslabs/domovoi/providers` — Provider factories and interface (openai, ollama, openaiCompat).\n * - `@hourslabs/domovoi/calibration` — Calibrator factories (identity, temperatureScaling, plattScaling).\n * - `@hourslabs/domovoi/testing` — mockProvider for unit tests.\n */\n\nimport { memoryCache as memoryCacheFactory } from \"./cache.js\";\nimport { boolean as booleanVerb } from \"./verbs/boolean.js\";\nimport { classifier as classifierFactory } from \"./verbs/classifier.js\";\nimport { classify as classifyVerb } from \"./verbs/classify.js\";\n\nexport type { Cache, CacheStats, CacheWithStats } from \"./cache.js\";\nexport {\n BudgetExhaustedError,\n ConfigError,\n DomovoiError,\n type ErrorCode,\n ProviderError,\n} from \"./errors.js\";\nexport type {\n Budget,\n Classified,\n Distribution,\n Filterable,\n Label,\n PromptTemplate,\n ProviderCapabilities,\n SerializableError,\n Thresholds,\n Uncertain,\n Unknown,\n UnknownVerdictCause,\n Verdict,\n VerdictMeta,\n} from \"./types.js\";\nexport type { BooleanOptions } from \"./verbs/boolean.js\";\nexport type { Classifier, ClassifierConfig } from \"./verbs/classifier.js\";\nexport type { ClassifyOptions } from \"./verbs/classify.js\";\nexport { filter, isClassified, isUncertain, isUnknown, match } from \"./verdict.js\";\n\n/**\n * Top-level API surface — what users primarily import.\n *\n * @example\n * import { domovoi, isClassified } from \"@hourslabs/domovoi\";\n * const v = await domovoi.classify(input, [\"a\",\"b\",\"c\"] as const);\n * if (isClassified(v)) console.log(v.value);\n */\nexport const domovoi = {\n classify: classifyVerb,\n boolean: booleanVerb,\n classifier: classifierFactory,\n memoryCache: memoryCacheFactory,\n} as const;\n"]}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Default classifier prompt template and rendering helpers.
3
+ *
4
+ * Labels render in user-given order (never sorted) so prompt-position bias
5
+ * is the caller's choice. Custom templates must supply their own
6
+ * `templateHash` so cache keys stay correct.
7
+ */
8
+ import type { PromptTemplate } from "./types.js";
9
+ export declare const defaultTemplate: PromptTemplate;
10
+ /** Substitute `{labels_csv}` in the system prompt; `undefined` if there isn't one. */
11
+ export declare function renderSystemPrompt(template: PromptTemplate, space: readonly string[]): string | undefined;
12
+ /** Render the user message via the template's `userTemplate` callback. */
13
+ export declare function renderUserPrompt(template: PromptTemplate, input: string, space: readonly string[], question?: string): string;
14
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAIjD,eAAO,MAAM,eAAe,EAAE,cAK7B,CAAC;AAEF,sFAAsF;AACtF,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,MAAM,GAAG,SAAS,CAGpB;AAED,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAER"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Public exports from `@hourslabs/domovoi/providers` subpath.
3
+ */
4
+ export { type OpenAICompatOptions, type OpenAIModel, type OpenAIProviderOptions, ollama, openai, openaiCompat, } from "./openai/index.js";
5
+ export type { Provider, SampleOptions } from "./provider.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,KAAK,qBAAqB,EAC1B,MAAM,EACN,MAAM,EACN,YAAY,GACb,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}