oracular 0.15.0 → 0.17.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.
- package/CHANGELOG.md +12 -0
- package/README.md +8 -10
- package/dist/index.cjs +14 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +42 -7
- package/dist/index.d.ts +42 -7
- package/dist/index.js +14 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/schema/config.schema.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/math.ts","../src/util.ts","../src/learning.ts","../src/attribution.ts","../src/intent.ts","../src/config.ts","../src/episode.ts","../src/version.ts","../src/state.ts","../src/assess.ts","../src/evaluate.ts","../src/evidence.ts","../src/explain.ts","../src/observe.ts","../src/predict.ts","../src/recorder.ts","../src/migrate.ts","../src/serialize.ts","../src/units.ts","../src/validate.ts"],"names":["record","explain","typeError"],"mappings":";AAGO,SAAS,WAAA,CAAY,SAAiB,QAAA,EAA0B;AACrE,EAAA,IAAI,EAAE,OAAA,GAAU,CAAA,CAAA,EAAI,OAAO,CAAA;AAC3B,EAAA,OAAO,CAAA,KAAM,CAAC,OAAA,GAAU,QAAA,CAAA;AAC1B;AAEO,SAAS,QAAA,CAAS,OAAe,IAAA,EAAsB;AAC5D,EAAA,OAAO,SAAS,KAAA,GAAQ,IAAA,CAAA;AAC1B;AAEO,SAAS,YAAA,CAAa,OAAe,IAAA,EAAsB;AAChE,EAAA,MAAM,IAAI,KAAA,GAAQ,IAAA;AAClB,EAAA,OAAQ,KAAA,GAAQ,IAAA,IAAS,CAAA,GAAI,CAAA,IAAK,CAAA,GAAI,CAAA,CAAA,CAAA;AACxC;AAEO,SAAS,MAAA,CAAO,OAAe,IAAA,EAAsB;AAC1D,EAAA,OAAO,IAAA,CAAK,IAAA,CAAK,YAAA,CAAa,KAAA,EAAO,IAAI,CAAC,CAAA;AAC5C;AAEO,SAAS,QAAQ,CAAA,EAAmB;AACzC,EAAA,IAAI,CAAA,GAAI,GAAG,OAAO,CAAA;AAClB,EAAA,IAAI,CAAA,GAAI,GAAG,OAAO,CAAA;AAClB,EAAA,OAAO,CAAA;AACT;AAMO,SAAS,WAAW,CAAA,EAAmB;AAC5C,EAAA,MAAM,CAAA,GAAI,IAAI,IAAA,CAAK,KAAA;AACnB,EAAA,MAAM,CAAA,GAAI,CAAA,IAAK,CAAA,GAAI,SAAA,GAAY,CAAA,CAAA;AAC/B,EAAA,MAAM,IAAA,GACJ,KACC,WAAA,GAAc,CAAA,IAAK,eAAe,CAAA,IAAK,WAAA,GAAc,CAAA,IAAK,YAAA,GAAe,CAAA,GAAI,WAAA,CAAA,CAAA,CAAA,CAAA;AAChF,EAAA,OAAO,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,CAAC,IAAI,CAAC,CAAA;AACrC;AAGO,SAAS,OAAO,CAAA,EAAmB;AACxC,EAAA,IAAI,GAAA,GAAM,CAAA;AACV,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,OAAO,IAAI,CAAA,EAAG;AACZ,IAAA,GAAA,IAAO,IAAA,CAAK,IAAI,CAAC,CAAA;AACjB,IAAA,CAAA,IAAK,CAAA;AAAA,EACP;AACA,EAAA,MAAM,IAAI,CAAA,GAAI,CAAA;AACd,EAAA,MAAM,KAAK,CAAA,GAAI,CAAA;AACf,EAAA,OACE,OACC,CAAA,GAAI,GAAA,IAAO,KAAK,GAAA,CAAI,CAAC,IACtB,CAAA,GACA,kBAAA,GACA,CAAA,IAAK,CAAA,GAAI,KAAK,EAAA,IAAM,CAAA,GAAI,MAAM,EAAA,IAAM,CAAA,GAAI,OAAO,EAAA,GAAK,IAAA,CAAA,CAAA,CAAA;AAExD;AAQA,SAAS,MAAA,CAAO,CAAA,EAAW,CAAA,EAAW,CAAA,EAAmB;AACvD,EAAA,MAAM,IAAA,GAAO,MAAA;AACb,EAAA,MAAM,KAAA,GAAQ,CAAC,CAAA,KAAuB,IAAA,CAAK,IAAI,CAAC,CAAA,GAAI,OAAO,IAAA,GAAO,CAAA;AAClE,EAAA,IAAI,IAAI,CAAA,GAAI,IAAA;AACZ,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,EAAQ,CAAA,EAAA,EAAK;AAC/B,IAAA,MAAM,IAAI,CAAA,IAAK,CAAA;AACf,IAAA,MAAM,MAAO,CAAA,GAAI,CAAA,GAAI,EAAE,CAAA,GAAI,MAAM,CAAA,GAAI,CAAA,GAAI,CAAA,CAAA,GAAK,CAAA,IAAK,IAAI,CAAA,CAAA,IAAM,CAAA,IAAA,CAAO,CAAA,GAAI,CAAA,GAAI,MAAM,CAAA,GAAI,CAAA,CAAA,CAAA;AACtF,IAAA,CAAA,GAAI,CAAA,GAAI,KAAA,CAAM,CAAA,GAAI,EAAA,GAAK,CAAC,CAAA;AACxB,IAAA,CAAA,GAAI,KAAA,CAAM,CAAA,GAAI,EAAA,GAAK,CAAC,CAAA;AACpB,IAAA,MAAM,MAAM,CAAA,GAAI,CAAA;AAChB,IAAA,CAAA,IAAK,GAAA;AACL,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,GAAA,GAAM,CAAC,IAAI,KAAA,EAAO;AAAA,EACjC;AACA,EAAA,OAAO,CAAA;AACT;AAGO,SAAS,cAAA,CAAe,CAAA,EAAW,CAAA,EAAW,CAAA,EAAmB;AACtE,EAAA,IAAI,CAAA,IAAK,GAAG,OAAO,CAAA;AACnB,EAAA,IAAI,CAAA,IAAK,GAAG,OAAO,CAAA;AACnB,EAAA,MAAM,QAAQ,IAAA,CAAK,GAAA;AAAA,IACjB,OAAO,CAAA,GAAI,CAAC,IAAI,MAAA,CAAO,CAAC,IAAI,MAAA,CAAO,CAAC,IAAI,CAAA,GAAI,IAAA,CAAK,IAAI,CAAC,CAAA,GAAI,IAAI,IAAA,CAAK,GAAA,CAAI,IAAI,CAAC;AAAA,GAC9E;AAEA,EAAA,OAAO,CAAA,GAAA,CAAK,IAAI,CAAA,KAAM,CAAA,GAAI,IAAI,CAAA,CAAA,GACzB,KAAA,GAAQ,OAAO,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,GAAK,CAAA,GAC5B,IAAK,KAAA,GAAQ,MAAA,CAAO,IAAI,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA,GAAK,CAAA;AAC1C;AAMO,SAAS,YAAA,CAAa,CAAA,EAAW,CAAA,EAAW,CAAA,EAAmB;AACpE,EAAA,IAAI,EAAA,GAAK,CAAA;AACT,EAAA,IAAI,EAAA,GAAK,CAAA;AACT,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,MAAM,EAAA,GAAK,EAAA,GAAK,MAAM,CAAA,EAAA,EAAK;AAC7C,IAAA,MAAM,GAAA,GAAA,CAAO,KAAK,EAAA,IAAM,CAAA;AACxB,IAAA,IAAI,eAAe,GAAA,EAAK,CAAA,EAAG,CAAC,CAAA,GAAI,GAAG,EAAA,GAAK,GAAA;AAAA,SACnC,EAAA,GAAK,GAAA;AAAA,EACZ;AACA,EAAA,OAAA,CAAQ,KAAK,EAAA,IAAM,CAAA;AACrB;AAMO,SAAS,UAAA,CACd,KAAA,EACA,IAAA,EACA,CAAA,EACA,KAAA,EACQ;AACR,EAAA,IAAI,KAAA,KAAU,SAAS,OAAO,YAAA,CAAa,WAAW,CAAC,CAAA,EAAG,OAAO,IAAI,CAAA;AACrE,EAAA,OAAO,OAAA,CAAQ,SAAS,KAAA,EAAO,IAAI,IAAI,CAAA,GAAI,MAAA,CAAO,KAAA,EAAO,IAAI,CAAC,CAAA;AAChE;AAOO,SAAS,aAAa,CAAA,EAAmB;AAC9C,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,CAAA,GAAI,CAAC,IAAI,IAAA,CAAK,GAAA;AAClC;AAaO,SAAS,UAAA,CAAW,SAAA,EAAmB,KAAA,EAAe,IAAA,EAAsB;AACjF,EAAA,OAAA,CAAQ,SAAA,GAAY,CAAA,GAAI,IAAA,KAAS,KAAA,GAAQ,CAAA,CAAA;AAC3C;AAWO,SAAS,IAAA,CAAK,CAAA,EAAW,CAAA,EAAW,IAAA,GAAiB,uBAAA,EAAiC;AAC3F,EAAA,IAAI,IAAA,KAAS,qBAAA,EAAuB,OAAO,CAAA,GAAI,CAAA;AAC/C,EAAA,IAAI,SAAS,uBAAA,EAAyB;AACpC,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,OAAA,EAAS,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,MAAA,CAAO,OAAA,EAAS,CAAC,CAAC,CAAA;AACrE,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,OAAA,EAAS,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,MAAA,CAAO,OAAA,EAAS,CAAC,CAAC,CAAA;AACrE,IAAA,QAAQ,IAAA;AAAM,MACZ,KAAK,eAAA;AACH,QAAA,OAAA,CAAQ,OAAO,IAAA,IAAQ,IAAA;AAAA,MACzB,KAAK,UAAA;AACH,QAAA,OAAO,IAAA,CAAK,GAAA,CAAI,IAAA,GAAO,IAAI,CAAA;AAAA,MAC7B,KAAK,YAAA;AACH,QAAA,OAAO,IAAA,IAAQ,CAAA,GAAI,IAAA,CAAA,IAAS,IAAA,IAAQ,CAAA,GAAI,IAAA,CAAA,CAAA;AAAA,MAC1C,KAAK,YAAA;AAAA,MACL,KAAK,kBAAA;AACH,QAAA,OAAO,IAAA,GAAO,IAAA;AAAA;AAClB,EACF;AACA,EAAA,IAAI,CAAA,IAAK,GAAG,OAAO,CAAA,IAAK,IAAI,CAAA,GAAA,CAAK,CAAA,GAAI,MAAM,CAAA,GAAI,CAAA,CAAA;AAC/C,EAAA,OAAO,CAAA,IAAK,CAAA,GAAI,CAAA,GAAA,CAAK,CAAA,GAAI,CAAA,IAAK,CAAA;AAChC;AAOO,SAAS,aAAA,CAAc,KAAA,EAAe,IAAA,GAAiB,uBAAA,EAAiC;AAC7F,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,YAAA;AAAA,IACL,KAAK,YAAA;AAAA,IACL,KAAK,kBAAA;AACH,MAAA,OAAA,CAAQ,KAAA,GAAQ,MAAM,KAAA,GAAQ,CAAA,CAAA;AAAA,IAChC,KAAK,eAAA;AAAA,IACL,KAAK,UAAA;AACH,MAAA,OAAO,KAAA,IAAS,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA,CAAA;AAAA,IACpC;AACE,MAAA,OAAO,KAAA;AAAA;AAEb;;;ACpMO,SAAS,SAAS,KAAA,EAAkD;AACzE,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC5E;AAGO,SAAS,MAAA,CAAOA,SAAgB,GAAA,EAAsB;AAE3D,EAAA,OAAO,MAAA,CAAO,SAAA,CAAU,cAAA,CAAe,IAAA,CAAKA,SAAQ,GAAG,CAAA;AACzD;AAEO,SAAS,MAAA,CAAUA,SAA2B,GAAA,EAA4B;AAC/E,EAAA,OAAO,OAAOA,OAAAA,EAAQ,GAAG,CAAA,GAAIA,OAAAA,CAAO,GAAG,CAAA,GAAI,MAAA;AAC7C;AAEO,SAAS,SAAA,CACdA,SACA,EAAA,EACmB;AACnB,EAAA,MAAM,MAAyB,EAAC;AAChC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQA,OAAM,CAAA,EAAG;AACjD,IAAA,GAAA,CAAI,GAAG,CAAA,GAAI,EAAA,CAAG,KAAA,EAAO,GAAG,CAAA;AAAA,EAC1B;AACA,EAAA,OAAO,GAAA;AACT;;;AClBA,IAAM,IAAA,GAAqB,EAAE,IAAA,EAAM,CAAA,EAAG,QAAQ,CAAA,EAAE;AAMzC,SAAS,YAAA,CACd,KAAA,EACA,QAAA,EACA,EAAA,EACa;AACb,EAAA,IAAI,KAAA,CAAM,cAAc,IAAA,EAAM,OAAO,EAAE,GAAG,KAAA,EAAO,WAAW,EAAA,EAAG;AAC/D,EAAA,IAAI,EAAE,EAAA,GAAK,KAAA,CAAM,SAAA,CAAA,EAAY,OAAO,KAAA;AACpC,EAAA,MAAM,CAAA,GAAI,QAAA,CAAS,QAAA,KAAa,IAAA,GAAO,CAAA,GAAI,YAAY,EAAA,GAAK,KAAA,CAAM,SAAA,EAAW,QAAA,CAAS,QAAQ,CAAA;AAC9F,EAAA,IAAI,MAAM,CAAA,EAAG,OAAO,EAAE,GAAG,KAAA,EAAO,WAAW,EAAA,EAAG;AAC9C,EAAA,OAAO;AAAA,IACL,GAAG,KAAA;AAAA,IACH,SAAA,EAAW,EAAA;AAAA,IACX,OAAA,EAAS,SAAA,CAAU,KAAA,CAAM,OAAA,EAAS,CAAC,CAAA,MAAO,EAAE,IAAA,EAAM,CAAA,CAAE,OAAO,CAAA,EAAG,MAAA,EAAQ,CAAA,CAAE,MAAA,GAAS,GAAE,CAAE,CAAA;AAAA,IACrF,QAAA,EAAU,EAAE,IAAA,EAAM,KAAA,CAAM,QAAA,CAAS,IAAA,GAAO,CAAA,EAAG,MAAA,EAAQ,KAAA,CAAM,QAAA,CAAS,MAAA,GAAS,CAAA;AAAE,GAC/E;AACF;AAuBO,SAAS,aAAA,CACd,KAAA,EACA,MAAA,EACA,QAAA,EACA,MAAA,EACe;AACf,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,MAAM,CAAA;AAC7C,EAAA,IAAI,YAAY,MAAA,EAAW;AACzB,IAAA,MAAM,IAAI,UAAA,CAAW,CAAA,UAAA,EAAa,KAAK,SAAA,CAAU,MAAM,CAAC,CAAA,+BAAA,CAAiC,CAAA;AAAA,EAC3F;AACA,EAAA,MAAMA,OAAAA,GAAS,MAAA,CAAO,KAAA,CAAM,OAAA,EAAS,MAAM,CAAA,IAAK,IAAA;AAChD,EAAA,MAAM,KAAA,GAAQA,OAAAA,CAAO,IAAA,GAAOA,OAAAA,CAAO,MAAA;AAGnC,EAAA,MAAM,aAAA,GAAgB,KAAA,CAAM,QAAA,CAAS,IAAA,GAAO,MAAM,QAAA,CAAS,MAAA;AAC3D,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,gBAAgB,KAAK,CAAA;AAClD,EAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,GAAA,CAAI,QAAA,EAAU,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAA,CAAM,QAAA,CAAS,IAAA,GAAOA,OAAAA,CAAO,IAAI,CAAC,CAAA;AAGzF,EAAA,MAAM,OAAO,aAAA,KAAkB,CAAA,GAAI,CAAA,GAAI,KAAA,CAAM,SAAS,IAAA,GAAO,aAAA;AAC7D,EAAA,MAAM,KAAA,GAAQ,UAAA,CAAWA,OAAAA,CAAO,IAAA,EAAM,OAAO,IAAI,CAAA;AACjD,EAAA,MAAM,QAAA,GAAW,UAAA,CAAW,eAAA,EAAiB,QAAA,EAAU,IAAI,CAAA;AAG3D,EAAA,MAAM,QAAA,GACJ,QAAA,CAAS,IAAA,KAAS,kBAAA,GACd,UAAA,CAAWA,OAAAA,CAAO,IAAA,GAAO,eAAA,EAAiB,KAAA,GAAQ,QAAA,EAAU,IAAI,CAAA,GAChE,QAAA;AACN,EAAA,MAAM,KAAA,GAAQ,cAAc,IAAA,CAAK,KAAA,EAAO,UAAU,QAAA,CAAS,IAAI,CAAA,EAAG,QAAA,CAAS,IAAI,CAAA;AAC/E,EAAA,MAAM,OAAA,GAAU,UAAU,CAAA,GAAI,CAAA,GAAI,SAAS,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,OAAO,CAAA,GAAI,KAAA;AAEtE,EAAA,MAAM,OAAO,KAAA,GAAQ,QAAA,KAAa,IAAI,CAAA,GAAK,KAAA,GAAQ,YAAa,KAAA,GAAQ,QAAA,CAAA;AACxE,EAAA,MAAM,IAAI,QAAA,CAAS,aAAA;AACnB,EAAA,MAAM,SAAA,GAAA,CAAa,CAAA,GAAI,OAAA,GAAU,IAAA,GAAO,YAAY,CAAA,GAAI,IAAA,CAAA;AACxD,EAAA,OAAO,EAAE,SAAS,OAAA,EAAS,SAAA,EAAW,MAAMA,OAAAA,CAAO,IAAA,EAAM,MAAA,EAAQA,OAAAA,CAAO,MAAA,EAAO;AACjF;AAQO,SAAS,aAAA,CACd,KAAA,EACA,OAAA,EACA,MAAA,EACa;AACb,EAAA,MAAM,OAAO,CAAA,GAAI,MAAA;AACjB,EAAA,MAAM,OAAA,GAAU,EAAE,GAAG,KAAA,CAAM,OAAA,EAAQ;AACnC,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,MAAM,CAAA,GAAI,MAAA,CAAO,OAAA,EAAS,MAAM,CAAA,IAAK,IAAA;AACrC,IAAA,OAAA,CAAQ,MAAM,CAAA,GAAI,EAAE,IAAA,EAAM,CAAA,CAAE,OAAO,MAAA,EAAQ,MAAA,EAAQ,CAAA,CAAE,MAAA,GAAS,IAAA,EAAK;AAAA,EACrE;AACA,EAAA,MAAM,QAAA,GAAW,EAAE,IAAA,EAAM,KAAA,CAAM,QAAA,CAAS,IAAA,GAAO,MAAA,EAAQ,MAAA,EAAQ,KAAA,CAAM,QAAA,CAAS,MAAA,GAAS,IAAA,EAAK;AAC5F,EAAA,OAAO,EAAE,GAAG,KAAA,EAAO,OAAA,EAAS,QAAA,EAAS;AACvC;;;ACnGO,IAAM,WAAA,GAAc,EAAA;AAM3B,SAAS,MAAA,CAAO,SAAyB,MAAA,EAA8B;AACrE,EAAA,OAAO,OAAA,CAAQ,OAAA,IAAW,MAAA,CAAO,WAAA,IAAe,CAAA,CAAA;AAClD;AAQO,SAAS,aAAA,CACd,KAAA,EACA,MAAA,EACA,QAAA,EACA,EAAA,EACa;AACb,EAAA,IAAI,EAAA,GAAK,KAAA;AACT,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,KAAA,MAAW,OAAA,IAAW,MAAM,OAAA,EAAS;AACnC,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,OAAA,EAAS,MAAM,CAAA;AAClC,IAAA,IAAI,EAAE,MAAM,EAAA,CAAA,EAAK;AACjB,IAAA,EAAA,GAAK,aAAA,CAAc,aAAa,EAAA,EAAI,QAAA,EAAU,GAAG,CAAA,EAAG,OAAA,CAAQ,MAAM,CAAC,CAAA;AACnE,IAAA,OAAA,EAAA;AAAA,EACF;AACA,EAAA,IAAI,OAAA,GAAU,CAAA,EAAG,EAAA,GAAK,EAAE,GAAG,EAAA,EAAI,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,KAAA,CAAM,OAAO,CAAA,EAAE;AACrE,EAAA,OAAO,YAAA,CAAa,EAAA,EAAI,QAAA,EAAU,EAAE,CAAA;AACtC;AAOO,SAAS,YAAA,CACd,KAAA,EACA,IAAA,EACA,OAAA,EACa;AACb,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,KAAA,CAAM,OAAA,EAAS,EAAE,OAAA,EAAS,IAAA,EAAM,CAAC,GAAG,IAAI,CAAA,EAAG,CAAA;AAClE,EAAA,IAAI,QAAQ,MAAA,IAAU,WAAA,SAAoB,EAAE,GAAG,OAAO,OAAA,EAAQ;AAC9D,EAAA,MAAM,CAAC,MAAA,EAAQ,GAAG,IAAI,CAAA,GAAI,OAAA;AAC1B,EAAA,OAAO,EAAE,GAAG,aAAA,CAAc,KAAA,EAAQ,OAA0B,IAAA,EAAM,CAAC,CAAA,EAAG,OAAA,EAAS,IAAA,EAAK;AACtF;AAGA,SAAS,MAAA,CAAO,SAAoC,OAAA,EAA2C;AAC7F,EAAA,IAAI,IAAI,OAAA,CAAQ,MAAA;AAChB,EAAA,OAAO,CAAA,GAAI,KAAM,OAAA,CAAQ,CAAA,GAAI,CAAC,CAAA,CAAqB,OAAA,GAAU,QAAQ,OAAA,EAAS,CAAA,EAAA;AAC9E,EAAA,OAAO,CAAC,GAAG,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,EAAG,OAAA,EAAS,GAAG,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAC,CAAA;AAC9D;AAOO,SAAS,aAAA,CAAc,KAAA,EAAoB,MAAA,EAAsB,EAAA,EAAyB;AAC/F,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,KAAA;AACvC,EAAA,IAAI,EAAA,GAAK,KAAA;AACT,EAAA,KAAA,MAAW,OAAA,IAAW,MAAM,OAAA,EAAS;AACnC,IAAA,EAAA,GAAK,aAAA,CAAc,EAAA,EAAI,OAAA,CAAQ,IAAA,EAAM,WAAA,CAAY,KAAK,OAAA,CAAQ,OAAA,EAAS,MAAA,CAAO,QAAQ,CAAC,CAAA;AAAA,EACzF;AACA,EAAA,OAAO,EAAE,GAAG,EAAA,EAAI,OAAA,EAAS,EAAC,EAAE;AAC9B;;;ACvEO,SAAS,YAAY,MAAA,EAAyD;AACnF,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,MAAA,CAAO,KAAA,GAAQ,MAAA,CAAO,aAAA;AAAA,IAC9B,KAAA,EAAA,CAAQ,CAAA,GAAI,MAAA,CAAO,KAAA,IAAS,MAAA,CAAO;AAAA,GACrC;AACF;AAEO,SAAS,WAAW,MAAA,EAAmC;AAC5D,EAAA,MAAM,EAAE,MAAA,EAAQ,KAAA,EAAM,GAAI,YAAY,MAAM,CAAA;AAC5C,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,MAAA;AAAA,IACP,IAAA,EAAM,KAAA;AAAA,IACN,SAAA,EAAW,IAAA;AAAA,IACX,eAAe,EAAC;AAAA,IAChB,SAAS,EAAC;AAAA,IACV,QAAA,EAAU,EAAE,IAAA,EAAM,CAAA,EAAG,QAAQ,CAAA,EAAE;AAAA,IAC/B,SAAS,EAAC;AAAA,IACV,SAAA,EAAW,IAAA;AAAA,IACX,cAAA,EAAgB,IAAA;AAAA,IAChB,aAAA,EAAe,IAAA;AAAA,IACf,WAAA,EAAa;AAAA,GACf;AACF;AAMO,SAAS,iBAAA,CACd,KAAA,EACA,MAAA,EACA,aAAA,EACa;AACb,EAAA,MAAM,EAAE,MAAA,EAAQ,KAAA,EAAM,GAAI,YAAY,MAAM,CAAA;AAC5C,EAAA,IAAI,KAAA,GAAQ,MAAA;AACZ,EAAA,IAAI,IAAA,GAAO,KAAA;AACX,EAAA,KAAA,MAAW,CAAA,IAAK,MAAA,CAAO,MAAA,CAAO,aAAa,CAAA,EAAG;AAC5C,IAAA,KAAA,IAAS,CAAA,CAAE,KAAA;AACX,IAAA,IAAA,IAAQ,CAAA,CAAE,IAAA;AAAA,EACZ;AACA,EAAA,OAAO,EAAE,GAAG,KAAA,EAAO,KAAA,EAAO,MAAM,aAAA,EAAc;AAChD;AAQO,SAAS,WAAA,CAAY,KAAA,EAAoB,MAAA,EAAsB,EAAA,EAAyB;AAC7F,EAAA,IAAI,KAAA,CAAM,cAAc,IAAA,EAAM,OAAO,EAAE,GAAG,KAAA,EAAO,WAAW,EAAA,EAAG;AAC/D,EAAA,IAAI,EAAE,EAAA,GAAK,KAAA,CAAM,SAAA,CAAA,EAAY,OAAO,KAAA;AACpC,EAAA,MAAM,IAAI,WAAA,CAAY,EAAA,GAAK,KAAA,CAAM,SAAA,EAAW,OAAO,QAAQ,CAAA;AAC3D,EAAA,IAAI,MAAM,CAAA,EAAG,OAAO,EAAE,GAAG,KAAA,EAAO,WAAW,EAAA,EAAG;AAC9C,EAAA,MAAM,aAAA,GAAgB,SAAA,CAAU,KAAA,CAAM,aAAA,EAAe,CAAC,CAAA,MAAO;AAAA,IAC3D,KAAA,EAAO,EAAE,KAAA,GAAQ,CAAA;AAAA,IACjB,IAAA,EAAM,EAAE,IAAA,GAAO;AAAA,GACjB,CAAE,CAAA;AACF,EAAA,OAAO,iBAAA,CAAkB,EAAE,GAAG,KAAA,EAAO,WAAW,EAAA,EAAG,EAAG,QAAQ,aAAa,CAAA;AAC7E;AAGO,SAAS,WAAA,CACd,KAAA,EACA,MAAA,EACA,MAAA,EACA,MAAA,EACa;AACb,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,KAAA,CAAM,aAAA,EAAe,MAAM,KAAK,EAAE,KAAA,EAAO,CAAA,EAAG,IAAA,EAAM,CAAA,EAAE;AACxE,EAAA,MAAM,OACJ,MAAA,IAAU,CAAA,GACN,EAAE,KAAA,EAAO,IAAA,CAAK,QAAQ,MAAA,EAAQ,IAAA,EAAM,KAAK,IAAA,EAAK,GAC9C,EAAE,KAAA,EAAO,IAAA,CAAK,OAAO,IAAA,EAAM,IAAA,CAAK,OAAO,MAAA,EAAO;AACpD,EAAA,OAAO,iBAAA,CAAkB,KAAA,EAAO,MAAA,EAAQ,EAAE,GAAG,KAAA,CAAM,aAAA,EAAe,CAAC,MAAM,GAAG,IAAA,EAAM,CAAA;AACpF;AAGO,SAAS,YAAA,CAAa,OAAoB,MAAA,EAAmC;AAClF,EAAA,OAAO,iBAAA,CAAkB,KAAA,EAAO,MAAA,EAAQ,EAAE,CAAA;AAC5C;;;ACxEO,IAAM,iBAAA,GAAoB,GAAA;AAC1B,IAAM,SAAA,GAAY,IAAA;AAClB,IAAM,YAAA,GAAe,CAAA;AACrB,IAAM,sBAAA,GAAyB,EAAA;AAM/B,IAAM,aAAA,GAAgB,GAAA;AAEtB,IAAM,KAAA,GAAQ,EAAA;AAGd,IAAM,WAAA,GAAc,CAAC,SAAA,EAAW,gBAAA,EAAkB,YAAY,QAAQ,CAAA;AACtE,IAAM,WAAA,GAAc;AAAA,EACzB,OAAA;AAAA,EACA,eAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,gBAAA;AAAA,EACA,UAAA;AAAA,EACA,mBAAA;AAAA,EACA,aAAA;AAAA,EACA;AACF,CAAA;AACO,IAAM,cAAc,CAAC,WAAA,EAAa,GAAA,EAAK,UAAA,EAAY,mBAAmB,OAAO,CAAA;AAC7E,IAAM,aAAA,GAAgB,CAAC,UAAA,EAAY,MAAA,EAAQ,iBAAiB,MAAM,CAAA;AAClE,IAAM,UAAA,GAAkC;AAAA,EAC7C,qBAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA,EACA,uBAAA;AAAA,EACA;AACF,CAAA;AACA,IAAM,YAAA,GAAe,CAAC,SAAA,EAAW,OAAO,CAAA;AAExC,SAAS,SAAA,CAAU,MAAc,OAAA,EAAwB;AACvD,EAAA,MAAM,IAAI,SAAA,CAAU,CAAA,UAAA,EAAa,IAAI,CAAA,CAAA,EAAI,OAAO,CAAA,CAAE,CAAA;AACpD;AAEA,SAAS,UAAA,CAAW,MAAc,OAAA,EAAwB;AACxD,EAAA,MAAM,IAAI,UAAA,CAAW,CAAA,UAAA,EAAa,IAAI,CAAA,CAAA,EAAI,OAAO,CAAA,CAAE,CAAA;AACrD;AAEA,SAAS,YAAA,CAAa,OAAgB,IAAA,EAAuC;AAC3E,EAAA,IAAI,CAAC,QAAA,CAAS,KAAK,CAAA,EAAG,SAAA,CAAU,MAAM,wBAAwB,CAAA;AAC9D,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,UAAA,CACPA,OAAAA,EACA,OAAA,EACA,IAAA,EACM;AACN,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAKA,OAAM,CAAA,EAAG;AACrC,IAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAAG;AAC1B,MAAA,SAAA;AAAA,QACE,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA;AAAA,QACd,CAAA,6CAAA,EAAgD,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA;AAAA,OACpE;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,YAAA,CAAa,OAAgB,IAAA,EAAsB;AAC1D,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,MAAA,CAAO,SAAS,KAAK,CAAA;AACrD,IAAA,SAAA,CAAU,MAAM,yBAAyB,CAAA;AAC3C,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,cAAA,CAAe,OAAgB,IAAA,EAAsB;AAC5D,EAAA,MAAM,CAAA,GAAI,YAAA,CAAa,KAAA,EAAO,IAAI,CAAA;AAClC,EAAA,IAAI,CAAA,IAAK,CAAA,EAAG,UAAA,CAAW,IAAA,EAAM,wBAAwB,CAAA;AACrD,EAAA,OAAO,CAAA;AACT;AAGA,SAAS,qBAAA,CAAsB,OAAgB,IAAA,EAAsB;AACnE,EAAA,MAAM,CAAA,GAAI,cAAA,CAAe,KAAA,EAAO,IAAI,CAAA;AACpC,EAAA,IAAI,IAAI,aAAA,EAAe,UAAA,CAAW,IAAA,EAAM,CAAA,gBAAA,EAAmB,aAAa,CAAA,CAAE,CAAA;AAC1E,EAAA,OAAO,CAAA;AACT;AAEA,SAAS,iBAAA,CAAkB,OAAgB,IAAA,EAAsB;AAC/D,EAAA,MAAM,CAAA,GAAI,YAAA,CAAa,KAAA,EAAO,IAAI,CAAA;AAClC,EAAA,IAAI,CAAA,GAAI,CAAA,EAAG,UAAA,CAAW,IAAA,EAAM,sBAAsB,CAAA;AAClD,EAAA,OAAO,CAAA;AACT;AAEA,SAAS,cAAA,CAAe,OAAgB,IAAA,EAAsB;AAC5D,EAAA,MAAM,CAAA,GAAI,YAAA,CAAa,KAAA,EAAO,IAAI,CAAA;AAClC,EAAA,IAAI,KAAK,CAAA,IAAK,CAAA,IAAK,CAAA,EAAG,UAAA,CAAW,MAAM,kCAAkC,CAAA;AACzE,EAAA,OAAO,CAAA;AACT;AAEA,SAAS,gBAAA,CAAiB,OAAgB,IAAA,EAAsB;AAC9D,EAAA,MAAM,CAAA,GAAI,YAAA,CAAa,KAAA,EAAO,IAAI,CAAA;AAClC,EAAA,IAAI,IAAI,CAAA,IAAK,CAAA,GAAI,CAAA,EAAG,UAAA,CAAW,MAAM,yBAAyB,CAAA;AAC9D,EAAA,OAAO,CAAA;AACT;AAEO,SAAS,UAAA,CAAW,OAAgB,IAAA,EAAsB;AAC/D,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,CAAM,MAAA,KAAW,CAAA;AAChD,IAAA,SAAA,CAAU,MAAM,4BAA4B,CAAA;AAC9C,EAAA,OAAO,KAAA;AACT;AAGA,SAAS,aAAA,CAAc,MAAc,IAAA,EAAsB;AACzD,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,SAAA,CAAU,MAAM,iCAAiC,CAAA;AACxE,EAAA,IAAI,IAAA,KAAS,WAAA,EAAa,SAAA,CAAU,IAAA,EAAM,4CAA4C,CAAA;AACtF,EAAA,OAAO,IAAA;AACT;AAOO,SAAS,sBAAA,CAAuB,KAAA,EAAgB,IAAA,EAAc,MAAA,GAAS,IAAA,EAAqB;AACjG,EAAA,MAAMA,OAAAA,GAAS,YAAA,CAAa,KAAA,EAAO,IAAI,CAAA;AACvC,EAAA,UAAA,CAAWA,OAAAA,EAAQ,aAAa,IAAI,CAAA;AACpC,EAAA,MAAM,MAAqB,EAAC;AAC5B,EAAA,IAAIA,OAAAA,CAAO,cAAc,MAAA,EAAW;AAClC,IAAA,GAAA,CAAI,SAAA,GAAY,MAAA,GACZ,cAAA,CAAeA,OAAAA,CAAO,WAAW,CAAA,EAAG,IAAI,CAAA,UAAA,CAAY,CAAA,GACpD,gBAAA,CAAiBA,OAAAA,CAAO,SAAA,EAAW,CAAA,EAAG,IAAI,CAAA,UAAA,CAAY,CAAA;AAAA,EAC5D;AACA,EAAA,IAAIA,OAAAA,CAAO,MAAM,MAAA,EAAW;AAC1B,IAAA,GAAA,CAAI,IAAI,iBAAA,CAAkBA,OAAAA,CAAO,CAAA,EAAG,CAAA,EAAG,IAAI,CAAA,EAAA,CAAI,CAAA;AAC/C,IAAA,IAAI,MAAA,IAAU,GAAA,CAAI,CAAA,GAAI,KAAA,EAAO,UAAA,CAAW,GAAG,IAAI,CAAA,EAAA,CAAA,EAAM,CAAA,gBAAA,EAAmB,KAAK,CAAA,CAAE,CAAA;AAAA,EACjF;AACA,EAAA,IAAIA,OAAAA,CAAO,aAAa,MAAA,EAAW;AACjC,IAAA,GAAA,CAAI,WAAW,iBAAA,CAAkBA,OAAAA,CAAO,QAAA,EAAU,CAAA,EAAG,IAAI,CAAA,SAAA,CAAW,CAAA;AAAA,EACtE;AACA,EAAA,IAAIA,OAAAA,CAAO,oBAAoB,MAAA,EAAW;AACxC,IAAA,GAAA,CAAI,kBAAkB,iBAAA,CAAkBA,OAAAA,CAAO,eAAA,EAAiB,CAAA,EAAG,IAAI,CAAA,gBAAA,CAAkB,CAAA;AAAA,EAC3F;AACA,EAAA,IAAIA,OAAAA,CAAO,UAAU,MAAA,EAAW;AAC9B,IAAA,IAAIA,OAAAA,CAAO,KAAA,KAAU,QAAA,IAAYA,OAAAA,CAAO,UAAU,OAAA,EAAS;AACzD,MAAA,SAAA,CAAU,CAAA,EAAG,IAAI,CAAA,MAAA,CAAA,EAAU,6BAA6B,CAAA;AAAA,IAC1D;AACA,IAAA,GAAA,CAAI,QAAQA,OAAAA,CAAO,KAAA;AAAA,EACrB;AACA,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,iBAAA,CAAkB,OAAgB,IAAA,EAA8B;AACvE,EAAA,MAAMA,OAAAA,GAAS,YAAA,CAAa,KAAA,EAAO,IAAI,CAAA;AACvC,EAAA,UAAA,CAAWA,OAAAA,EAAQ,eAAe,IAAI,CAAA;AACtC,EAAA,MAAM,MAAsB,EAAC;AAC7B,EAAA,IAAIA,OAAAA,CAAO,SAAS,MAAA,EAAW;AAC7B,IAAA,IAAI,CAAC,UAAA,CAAW,QAAA,CAASA,OAAAA,CAAO,IAAgB,CAAA,EAAG;AACjD,MAAA,SAAA,CAAU,CAAA,EAAG,IAAI,CAAA,KAAA,CAAA,EAAS,CAAA,gBAAA,EAAmB,WAAW,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,IACtE;AACA,IAAA,GAAA,CAAI,OAAOA,OAAAA,CAAO,IAAA;AAAA,EACpB;AACA,EAAA,IAAIA,QAAO,QAAA,KAAa,MAAA;AACtB,IAAA,GAAA,CAAI,WAAW,cAAA,CAAeA,OAAAA,CAAO,QAAA,EAAU,CAAA,EAAG,IAAI,CAAA,SAAA,CAAW,CAAA;AACnE,EAAA,IAAIA,OAAAA,CAAO,IAAA,KAAS,MAAA,EAAW,GAAA,CAAI,IAAA,GAAO,sBAAsBA,OAAAA,CAAO,IAAA,EAAM,CAAA,EAAG,IAAI,CAAA,KAAA,CAAO,CAAA;AAC3F,EAAA,IAAIA,OAAAA,CAAO,kBAAkB,MAAA,EAAW;AACtC,IAAA,GAAA,CAAI,gBAAgB,qBAAA,CAAsBA,OAAAA,CAAO,aAAA,EAAe,CAAA,EAAG,IAAI,CAAA,cAAA,CAAgB,CAAA;AAAA,EACzF;AACA,EAAA,OAAO,GAAA;AACT;AAOO,SAAS,qBAAA,CAAsB,KAAA,EAAgB,IAAA,EAAc,MAAA,GAAS,IAAA,EAAoB;AAC/F,EAAA,MAAMA,OAAAA,GAAS,YAAA,CAAa,KAAA,EAAO,IAAI,CAAA;AACvC,EAAA,UAAA,CAAWA,OAAAA,EAAQ,aAAa,IAAI,CAAA;AACpC,EAAA,MAAM,gBAAgB,YAAA,CAAaA,OAAAA,CAAO,OAAA,EAAS,CAAA,EAAG,IAAI,CAAA,QAAA,CAAU,CAAA;AACpE,EAAA,MAAM,UAAkC,EAAC;AACzC,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,MAAM,KAAK,MAAA,CAAO,OAAA,CAAQ,aAAa,CAAA,EAAG;AAC1D,IAAA,aAAA,CAAc,IAAA,EAAM,CAAA,EAAG,IAAI,CAAA,QAAA,CAAU,CAAA;AACrC,IAAA,MAAM,CAAA,GAAI,YAAA,CAAa,MAAA,EAAQ,CAAA,EAAG,IAAI,YAAY,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA,CAAA,CAAG,CAAA;AACzE,IAAA,IAAI,MAAM,CAAA,EAAG;AACX,MAAA,UAAA;AAAA,QACE,GAAG,IAAI,CAAA,SAAA,EAAY,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA,CAAA,CAAA;AAAA,QACvC;AAAA,OACF;AAAA,IACF;AACA,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,GAAI,aAAA,EAAe;AAC/B,MAAA,UAAA;AAAA,QACE,GAAG,IAAI,CAAA,SAAA,EAAY,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA,CAAA,CAAA;AAAA,QACvC,CAAA,iBAAA,EAAoB,aAAa,CAAA,KAAA,EAAQ,aAAa,CAAA;AAAA,OACxD;AAAA,IACF;AACA,IAAA,OAAA,CAAQ,IAAI,CAAA,GAAI,CAAA;AAAA,EAClB;AACA,EAAA,MAAM,GAAA,GAAoB;AAAA,IACxB,OAAO,cAAA,CAAeA,OAAAA,CAAO,KAAA,EAAO,CAAA,EAAG,IAAI,CAAA,MAAA,CAAQ,CAAA;AAAA,IACnD,eAAe,qBAAA,CAAsBA,OAAAA,CAAO,aAAA,EAAe,CAAA,EAAG,IAAI,CAAA,cAAA,CAAgB,CAAA;AAAA,IAClF,UAAU,cAAA,CAAeA,OAAAA,CAAO,QAAA,EAAU,CAAA,EAAG,IAAI,CAAA,SAAA,CAAW,CAAA;AAAA,IAC5D;AAAA,GACF;AACA,EAAA,IAAIA,OAAAA,CAAO,OAAA,KAAY,MAAA,EAAW,GAAA,CAAI,OAAA,GAAU,WAAWA,OAAAA,CAAO,OAAA,EAAS,CAAA,EAAG,IAAI,CAAA,QAAA,CAAU,CAAA;AAC5F,EAAA,IAAIA,OAAAA,CAAO,mBAAmB,MAAA,EAAW;AACvC,IAAA,IAAI,OAAOA,OAAAA,CAAO,cAAA,KAAmB,SAAA,EAAW;AAC9C,MAAA,SAAA,CAAU,CAAA,EAAG,IAAI,CAAA,eAAA,CAAA,EAAmB,mBAAmB,CAAA;AAAA,IACzD;AACA,IAAA,GAAA,CAAI,iBAAiBA,OAAAA,CAAO,cAAA;AAAA,EAC9B;AACA,EAAA,IAAIA,OAAAA,CAAO,aAAa,MAAA,EAAW;AACjC,IAAA,IAAI,OAAOA,QAAO,QAAA,KAAa,SAAA,YAAqB,CAAA,EAAG,IAAI,aAAa,mBAAmB,CAAA;AAC3F,IAAA,GAAA,CAAI,WAAWA,OAAAA,CAAO,QAAA;AAAA,EACxB;AACA,EAAA,IAAIA,OAAAA,CAAO,sBAAsB,MAAA,EAAW;AAC1C,IAAA,IAAI,OAAOA,OAAAA,CAAO,iBAAA,KAAsB,SAAA,EAAW;AACjD,MAAA,SAAA,CAAU,CAAA,EAAG,IAAI,CAAA,kBAAA,CAAA,EAAsB,mBAAmB,CAAA;AAAA,IAC5D;AACA,IAAA,GAAA,CAAI,oBAAoBA,OAAAA,CAAO,iBAAA;AAAA,EACjC;AACA,EAAA,IAAIA,OAAAA,CAAO,gBAAgB,MAAA,EAAW;AACpC,IAAA,GAAA,CAAI,cAAc,cAAA,CAAeA,OAAAA,CAAO,WAAA,EAAa,CAAA,EAAG,IAAI,CAAA,YAAA,CAAc,CAAA;AAAA,EAC5E;AACA,EAAA,IAAIA,OAAAA,CAAO,WAAW,MAAA,EAAW;AAC/B,IAAA,GAAA,CAAI,SAAS,sBAAA,CAAuBA,OAAAA,CAAO,QAAQ,CAAA,EAAG,IAAI,WAAW,MAAM,CAAA;AAAA,EAC7E;AACA,EAAA,IACE,MAAA,IACA,GAAA,CAAI,OAAA,KAAY,MAAA,IAChB,MAAA,CAAO,OAAA,EAAS,GAAA,CAAI,OAAO,CAAA,IAC3B,GAAA,CAAI,cAAA,KAAmB,KAAA,EACvB;AACA,IAAA,SAAA;AAAA,MACE,GAAG,IAAI,CAAA,QAAA,CAAA;AAAA,MACP;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAO,GAAA;AACT;AAOO,SAAS,eAAA,CAAgB,KAAA,EAAgB,MAAA,GAAS,IAAA,EAAoB;AAC3E,EAAA,MAAMA,OAAAA,GAAS,YAAA,CAAa,KAAA,EAAO,QAAQ,CAAA;AAC3C,EAAA,UAAA,CAAWA,OAAAA,EAAQ,aAAa,QAAQ,CAAA;AACxC,EAAA,MAAM,aAAA,GAAgB,YAAA,CAAaA,OAAAA,CAAO,OAAA,EAAS,gBAAgB,CAAA;AACnE,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,aAAa,CAAA;AACvC,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,SAAA,CAAU,kBAAkB,kCAAkC,CAAA;AACtF,EAAA,MAAM,UAAwC,EAAC;AAC/C,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,aAAA,CAAc,MAAM,gBAAgB,CAAA;AACpC,IAAA,OAAA,CAAQ,IAAI,CAAA,GAAI,qBAAA;AAAA,MACd,cAAc,IAAI,CAAA;AAAA,MAClB,CAAA,eAAA,EAAkB,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA,CAAA,CAAA;AAAA,MACtC;AAAA,KACF;AAAA,EACF;AACA,EAAA,MAAM,GAAA,GAAoB,EAAE,OAAA,EAAQ;AACpC,EAAA,IAAIA,OAAAA,CAAO,mBAAmB,MAAA,EAAW;AACvC,IAAA,GAAA,CAAI,cAAA,GAAiB,cAAA,CAAeA,OAAAA,CAAO,cAAA,EAAgB,uBAAuB,CAAA;AAAA,EACpF;AACA,EAAA,IAAIA,QAAO,QAAA,KAAa,MAAA;AACtB,IAAA,GAAA,CAAI,QAAA,GAAW,iBAAA,CAAkBA,OAAAA,CAAO,QAAA,EAAU,iBAAiB,CAAA;AACrE,EAAA,IAAIA,OAAAA,CAAO,WAAW,MAAA,EAAW;AAC/B,IAAA,GAAA,CAAI,MAAA,GAAS,sBAAA,CAAuBA,OAAAA,CAAO,MAAA,EAAQ,iBAAiB,MAAM,CAAA;AAAA,EAC5E;AACA,EAAA,OAAO,GAAA;AACT;AAGO,SAAS,uBAAA,CAAwB,OAAgB,IAAA,EAA8B;AACpF,EAAA,MAAMA,OAAAA,GAAS,YAAA,CAAa,KAAA,EAAO,IAAI,CAAA;AACvC,EAAA,UAAA,CAAWA,OAAAA,EAAQ,cAAc,IAAI,CAAA;AACrC,EAAA,MAAM,MAAsB,EAAC;AAC7B,EAAA,IAAIA,OAAAA,CAAO,YAAY,MAAA,EAAW;AAChC,IAAA,IAAI,OAAOA,QAAO,OAAA,KAAY,SAAA,YAAqB,CAAA,EAAG,IAAI,YAAY,mBAAmB,CAAA;AACzF,IAAA,GAAA,CAAI,UAAUA,OAAAA,CAAO,OAAA;AAAA,EACvB;AACA,EAAA,IAAIA,OAAAA,CAAO,UAAU,MAAA,EAAW;AAC9B,IAAA,MAAM,IAAI,YAAA,CAAaA,OAAAA,CAAO,KAAA,EAAO,CAAA,EAAG,IAAI,CAAA,MAAA,CAAQ,CAAA;AACpD,IAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,CAAC,KAAK,CAAA,GAAI,CAAA;AAC9B,MAAA,UAAA,CAAW,CAAA,EAAG,IAAI,CAAA,MAAA,CAAA,EAAU,gCAAgC,CAAA;AAC9D,IAAA,GAAA,CAAI,KAAA,GAAQ,CAAA;AAAA,EACd;AACA,EAAA,OAAO,GAAA;AACT;AAGO,SAAS,oBAAA,CACd,OACA,IAAA,EACoD;AACpD,EAAA,IAAI,KAAA,KAAU,QAAW,OAAO,EAAE,QAAQ,EAAC,EAAG,OAAA,EAAS,EAAC,EAAE;AAC1D,EAAA,MAAMA,OAAAA,GAAS,YAAA,CAAa,KAAA,EAAO,IAAI,CAAA;AACvC,EAAA,UAAA,CAAWA,SAAQ,CAAC,GAAG,aAAa,GAAG,YAAY,GAAG,IAAI,CAAA;AAC1D,EAAA,MAAM,SAAkC,EAAC;AACzC,EAAA,MAAMC,WAAmC,EAAC;AAC1C,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,CAAC,KAAK,MAAA,CAAO,OAAA,CAAQD,OAAM,CAAA,EAAG;AAC7C,IAAA,IAAK,YAAkC,QAAA,CAAS,GAAG,CAAA,EAAG,MAAA,CAAO,GAAG,CAAA,GAAI,CAAA;AAAA,SAC/DC,QAAAA,CAAQ,GAAG,CAAA,GAAI,CAAA;AAAA,EACtB;AACA,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,sBAAA,CAAuB,MAAA,EAAQ,IAAA,EAAM,KAAK,CAAA;AAAA,IAClD,OAAA,EAAS,uBAAA,CAAwBA,QAAAA,EAAS,IAAI;AAAA,GAChD;AACF;AAWO,SAAS,aAAA,CACd,MAAA,EACA,MAAA,EACA,IAAA,EACA,aAAa,KAAA,EACG;AAGhB,EAAA,MAAM,CAAA,GACJ,IAAA,KAAS,MAAA,GAAY,EAAC,GAAI,aAAa,IAAA,GAAO,sBAAA,CAAuB,IAAA,EAAM,SAAA,EAAW,KAAK,CAAA;AAC7F,EAAA,MAAM,QAAA,GACJ,EAAE,QAAA,IAAY,MAAA,CAAO,QAAQ,QAAA,IAAY,MAAA,EAAQ,MAAA,EAAQ,QAAA,IAAY,MAAA,CAAO,QAAA;AAC9E,EAAA,OAAO;AAAA,IACL,SAAA,EACE,EAAE,SAAA,IAAa,MAAA,CAAO,QAAQ,SAAA,IAAa,MAAA,EAAQ,QAAQ,SAAA,IAAa,iBAAA;AAAA,IAC1E,CAAA,EAAG,EAAE,CAAA,IAAK,MAAA,CAAO,QAAQ,CAAA,IAAK,MAAA,EAAQ,QAAQ,CAAA,IAAK,SAAA;AAAA,IACnD,QAAA;AAAA,IACA,eAAA,EACE,EAAE,eAAA,IACF,MAAA,CAAO,QAAQ,eAAA,IACf,MAAA,EAAQ,QAAQ,eAAA,IAChB,QAAA;AAAA,IACF,KAAA,EAAO,EAAE,KAAA,IAAS,MAAA,CAAO,QAAQ,KAAA,IAAS,MAAA,EAAQ,QAAQ,KAAA,IAAS;AAAA,GACrE;AACF;AAUO,SAAS,gBAAgB,MAAA,EAAwC;AACtE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,MAAA,CAAO,QAAA,EAAU,IAAA,IAAQ,uBAAA;AAAA,IAC/B,QAAA,EAAU,MAAA,CAAO,QAAA,EAAU,QAAA,IAAY,IAAA;AAAA,IACvC,IAAA,EAAM,MAAA,CAAO,QAAA,EAAU,IAAA,IAAQ,YAAA;AAAA,IAC/B,aAAA,EAAe,MAAA,CAAO,QAAA,EAAU,aAAA,IAAiB;AAAA,GACnD;AACF;AAEO,SAAS,eAAA,CAAgB,OAAgB,IAAA,EAAsB;AACpE,EAAA,OAAO,YAAA,CAAa,OAAO,IAAI,CAAA;AACjC;AAEO,SAAS,cAAc,KAAA,EAA8C;AAC1E,EAAA,IAAI,CAAC,QAAA,CAAS,KAAK,CAAA,EAAG,SAAA,CAAU,SAAS,qCAAqC,CAAA;AAC9E,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,KAAA,CAAM,IAAA,EAAM,YAAY,CAAA;AAChD,EAAA,MAAM,EAAA,GAAK,eAAA,CAAgB,KAAA,CAAM,EAAA,EAAI,UAAU,CAAA;AAC/C,EAAA,IAAI,MAAM,KAAA,KAAU,MAAA,IAAa,CAAC,QAAA,CAAS,KAAA,CAAM,KAAK,CAAA,EAAG;AACvD,IAAA,SAAA,CAAU,eAAe,qCAAqC,CAAA;AAAA,EAChE;AACA,EAAA,OAAO,EAAE,MAAM,EAAA,EAAG;AACpB;;;AC9XO,SAAS,YAAA,GAA6B;AAC3C,EAAA,OAAO,EAAE,SAAA,EAAW,IAAA,EAAM,aAAa,IAAA,EAAM,OAAA,EAAS,EAAC,EAAE;AAC3D;AAGO,SAAS,UAAA,CACd,OAAA,EACA,OAAA,EACA,EAAA,EACe;AACf,EAAA,IAAI,OAAA,KAAY,MAAA,IAAa,OAAA,CAAQ,WAAA,KAAgB,MAAM,OAAO,IAAA;AAClE,EAAA,OAAO,KAAK,OAAA,CAAQ,WAAA,GAAc,OAAA,GAAU,OAAA,CAAQ,cAAc,OAAA,GAAU,IAAA;AAC9E;AAGO,SAAS,aAAA,CAAc,SAAuB,EAAA,EAA0B;AAC7E,EAAA,OAAO,EAAE,WAAW,OAAA,CAAQ,SAAA,IAAa,IAAI,WAAA,EAAa,EAAA,EAAI,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAQ;AACzF;AAEO,SAAS,aAAA,CAAc,SAAuB,MAAA,EAAqC;AACxF,EAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,OAAA,EAAS,MAAM,CAAA,IAAK,EAAE,IAAA,EAAM,EAAC,EAAG,MAAA,EAAQ,EAAC,EAAG,UAAU,KAAA,EAAM;AACpF;AAGO,SAAS,WAAA,CAAY,OAAA,EAAuB,MAAA,EAAgB,MAAA,EAAwB;AACzF,EAAA,OAAO,OAAO,aAAA,CAAc,OAAA,EAAS,MAAM,CAAA,CAAE,MAAA,EAAQ,MAAM,CAAA,IAAK,CAAA;AAClE;AAGO,SAAS,QAAA,CAAS,OAAA,EAAuB,MAAA,EAAgB,MAAA,EAA8B;AAC5F,EAAA,MAAMD,OAAAA,GAAS,aAAA,CAAc,OAAA,EAAS,MAAM,CAAA;AAC5C,EAAA,MAAM,IAAA,GAAOA,OAAAA,CAAO,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,GAAIA,OAAAA,CAAO,IAAA,GAAO,CAAC,GAAGA,OAAAA,CAAO,IAAA,EAAM,MAAM,CAAA;AACjF,EAAA,MAAM,MAAA,GAAS,EAAE,GAAGA,OAAAA,CAAO,QAAQ,CAAC,MAAM,GAAA,CAAI,MAAA,CAAOA,OAAAA,CAAO,MAAA,EAAQ,MAAM,CAAA,IAAK,KAAK,CAAA,EAAE;AACtF,EAAA,OAAO,EAAE,GAAG,OAAA,EAAS,OAAA,EAAS,EAAE,GAAG,OAAA,CAAQ,OAAA,EAAS,CAAC,MAAM,GAAG,EAAE,GAAGA,SAAQ,IAAA,EAAM,MAAA,IAAS,EAAE;AAC9F;AAEO,SAAS,YAAA,CAAa,SAAuB,MAAA,EAA8B;AAChF,EAAA,OAAO;AAAA,IACL,GAAG,OAAA;AAAA,IACH,SAAS,EAAE,GAAG,OAAA,CAAQ,OAAA,EAAS,CAAC,MAAM,GAAG,EAAE,IAAA,EAAM,EAAC,EAAG,MAAA,EAAQ,EAAC,EAAG,QAAA,EAAU,MAAK;AAAE,GACpF;AACF;;;ACrBO,IAAM,aAAA,GAAgB;AAgBtB,IAAM,cAAA,GAAiB;;;ACAvB,SAAS,YAAY,MAAA,EAAmC;AAC7D,EAAA,MAAM,UAAA,GAAa,gBAAgB,MAAM,CAAA;AACzC,EAAA,MAAM,UAAuC,EAAC;AAC9C,EAAA,KAAA,MAAW,CAAC,MAAM,MAAM,CAAA,IAAK,OAAO,OAAA,CAAQ,UAAA,CAAW,OAAO,CAAA,EAAG;AAC/D,IAAA,OAAA,CAAQ,IAAI,CAAA,GAAI,UAAA,CAAW,MAAM,CAAA;AAAA,EACnC;AACA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,aAAA;AAAA,IACT,MAAA,EAAQ,UAAA;AAAA,IACR,OAAA;AAAA,IACA,SAAS,YAAA,EAAa;AAAA,IACtB,KAAA,EAAO,EAAE,EAAA,EAAI,IAAA,EAAM,UAAU,IAAA;AAAK,GACpC;AACF;AAEO,SAAS,aAAa,KAAA,EAA6B;AACxD,EAAA,IACE,CAAC,QAAA,CAAS,KAAK,CAAA,IACf,KAAA,CAAM,OAAA,KAAY,aAAA,IAClB,CAAC,QAAA,CAAS,KAAA,CAAM,MAAM,CAAA,IACtB,CAAC,SAAS,KAAA,CAAM,OAAO,CAAA,IACvB,CAAC,QAAA,CAAS,KAAA,CAAM,OAAO,CAAA,IACvB,CAAC,QAAA,CAAS,KAAA,CAAM,KAAK,CAAA,EACrB;AACA,IAAA,MAAM,IAAI,UAAU,wEAAwE,CAAA;AAAA,EAC9F;AACA,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,mBAAA,CAAoB,OAAoB,IAAA,EAA4B;AAClF,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,SAAS,IAAI,CAAA;AAChD,EAAA,IAAI,WAAW,MAAA,EAAW;AACxB,IAAA,MAAM,IAAI,UAAA,CAAW,CAAA,yBAAA,EAA4B,KAAK,SAAA,CAAU,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,EACzE;AACA,EAAA,OAAO,MAAA;AACT;AAGO,SAAS,cAAA,CACd,KAAA,EACA,IAAA,EACA,MAAA,EACa;AACb,EAAA,OAAO,OAAO,KAAA,CAAM,OAAA,EAAS,IAAI,CAAA,IAAK,WAAW,MAAM,CAAA;AACzD;;;AC/DO,SAAS,YAAA,CACd,KAAA,EACA,IAAA,EACA,MAAA,EACA,UACA,EAAA,EACa;AACb,EAAA,MAAM,EAAA,GAAK,YAAY,cAAA,CAAe,KAAA,EAAO,MAAM,MAAM,CAAA,EAAG,QAAQ,EAAE,CAAA;AACtE,EAAA,OAAO,aAAA,CAAc,EAAA,EAAI,MAAA,EAAQ,QAAA,EAAU,EAAE,CAAA;AAC/C;AAQA,SAAS,WAAA,CAAY,KAAA,EAAsB,QAAA,EAAkB,EAAA,EAA2B;AACtF,EAAA,IAAI,KAAA,KAAU,MAAM,OAAO,IAAA;AAC3B,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,EAAE,CAAA,GAAI,QAAA;AAClC,EAAA,OAAO,EAAA,GAAK,MAAM,GAAA,GAAM,IAAA;AAC1B;AAEO,SAAS,eAAA,CACd,EAAA,EACA,IAAA,EACA,MAAA,EACA,EAAA,EACY;AACZ,EAAA,MAAM,CAAA,GAAI,QAAA,CAAS,EAAA,CAAG,KAAA,EAAO,GAAG,IAAI,CAAA;AACpC,EAAA,MAAM,EAAA,GAAK,MAAA,CAAO,EAAA,CAAG,KAAA,EAAO,GAAG,IAAI,CAAA;AACnC,EAAA,MAAM,YAAY,WAAA,CAAY,EAAA,CAAG,cAAA,EAAgB,MAAA,CAAO,UAAU,EAAE,CAAA;AACpE,EAAA,MAAM,aAAa,WAAA,CAAY,EAAA,CAAG,aAAA,EAAe,MAAA,CAAO,iBAAiB,EAAE,CAAA;AAC3E,EAAA,MAAM,eAAA,GACJ,SAAA,KAAc,IAAA,GACV,UAAA,GACA,UAAA,KAAe,OACb,SAAA,GACA,IAAA,CAAK,GAAA,CAAI,SAAA,EAAW,UAAU,CAAA;AACtC,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,IAAA;AAAA,IACR,CAAA;AAAA,IACA,EAAA;AAAA,IACA,KAAA,EAAO,WAAW,EAAA,CAAG,KAAA,EAAO,GAAG,IAAA,EAAM,MAAA,CAAO,CAAA,EAAG,MAAA,CAAO,KAAK,CAAA;AAAA,IAC3D,UAAA,EAAY,OAAA,CAAQ,CAAA,GAAI,CAAA,GAAI,EAAE,CAAA;AAAA,IAC9B,QAAA,EAAU,EAAA,CAAG,KAAA,GAAQ,EAAA,CAAG,IAAA;AAAA,IACxB,UAAU,SAAA,KAAc,IAAA;AAAA,IACxB,YAAY,EAAA,CAAG,cAAA;AAAA,IACf;AAAA,GACF;AACF;AAEO,SAAS,YAAA,CAAa,YAAwB,MAAA,EAAiC;AACpF,EAAA,OACE,UAAA,CAAW,oBAAoB,IAAA,IAC/B,UAAA,CAAW,KAAK,MAAA,CAAO,SAAA,IACvB,UAAA,CAAW,KAAA,IAAS,MAAA,CAAO,SAAA;AAE/B;AAEO,SAAS,gBAAA,CACd,EAAA,EACA,MAAA,EACA,QAAA,EACA,IAAA,EACqB;AACrB,EAAA,MAAM,CAAA,GAAI,QAAA,CAAS,EAAA,CAAG,KAAA,EAAO,GAAG,IAAI,CAAA;AACpC,EAAA,MAAM,MAA2B,EAAC;AAClC,EAAA,KAAA,MAAW,MAAA,IAAU,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,EAAG;AAChD,IAAA,MAAM,CAAA,GAAI,MAAA,CAAO,EAAA,CAAG,aAAA,EAAe,MAAM,KAAK,EAAE,KAAA,EAAO,CAAA,EAAG,IAAA,EAAM,CAAA,EAAE;AAClE,IAAA,MAAM,CAAA,GAAI,aAAA,CAAc,EAAA,EAAI,MAAA,EAAQ,UAAU,MAAM,CAAA;AACpD,IAAA,MAAM,OAAA,GAAU,SAAS,EAAA,CAAG,KAAA,GAAQ,EAAE,KAAA,EAAO,EAAA,CAAG,IAAA,GAAO,CAAA,CAAE,IAAI,CAAA;AAC7D,IAAA,GAAA,CAAI,IAAA,CAAK;AAAA,MACP,MAAA;AAAA,MACA,YAAA,EAAc,CAAA,CAAE,KAAA,GAAQ,CAAA,CAAE,IAAA;AAAA,MAC1B,QAAQ,CAAA,GAAI,OAAA;AAAA,MACZ,eAAe,CAAA,CAAE,OAAA;AAAA,MACjB,eAAe,CAAA,CAAE,OAAA;AAAA,MACjB,iBAAiB,CAAA,CAAE,SAAA;AAAA,MACnB,MAAM,CAAA,CAAE,IAAA;AAAA,MACR,QAAQ,CAAA,CAAE;AAAA,KACX,CAAA;AAAA,EACH;AACA,EAAA,GAAA,CAAI,KAAK,CAAC,CAAA,EAAG,MAAM,IAAA,CAAK,GAAA,CAAI,EAAE,MAAM,CAAA,GAAI,KAAK,GAAA,CAAI,CAAA,CAAE,MAAM,CAAA,IAAK,OAAA,CAAQ,EAAE,MAAA,EAAQ,CAAA,CAAE,MAAM,CAAC,CAAA;AACzF,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,OAAA,GAAU,GAAA,CAAI,MAAA,CAAO,CAAC,GAAA,KAAQ,GAAA,CAAI,YAAA,KAAiB,CAAC,CAAA,GAAI,GAAA;AAC9E,EAAA,OAAO,IAAA,CAAK,UAAU,MAAA,GAAY,QAAA,GAAW,SAAS,KAAA,CAAM,CAAA,EAAG,KAAK,KAAK,CAAA;AAC3E;AAEA,SAAS,OAAA,CAAQ,GAAW,CAAA,EAAmB;AAC7C,EAAA,IAAI,CAAA,GAAI,GAAG,OAAO,EAAA;AAClB,EAAA,IAAI,CAAA,GAAI,GAAG,OAAO,CAAA;AAClB,EAAA,OAAO,CAAA;AACT;;;AC/EO,SAAS,QAAA,CACd,KAAA,EACA,MAAA,EACA,EAAA,EACA,IAAA,EACY;AACZ,EAAA,MAAM,CAAA,GAAI,aAAa,KAAK,CAAA;AAC5B,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,MAAA,EAAQ,QAAQ,CAAA;AACxC,EAAA,MAAM,CAAA,GAAI,eAAA,CAAgB,EAAA,EAAI,IAAI,CAAA;AAClC,EAAA,MAAM,MAAA,GAAS,mBAAA,CAAoB,CAAA,EAAG,IAAI,CAAA;AAC1C,EAAA,MAAM,KAAA,GAAQ,oBAAA,CAAqB,IAAA,EAAM,SAAS,CAAA;AAClD,EAAA,MAAM,SAAS,aAAA,CAAc,CAAA,CAAE,QAAQ,MAAA,EAAQ,KAAA,CAAM,QAAQ,IAAI,CAAA;AACjE,EAAA,MAAM,QAAA,GAAW,eAAA,CAAgB,CAAA,CAAE,MAAM,CAAA;AACzC,EAAA,MAAM,KAAK,YAAA,CAAa,CAAA,EAAG,IAAA,EAAM,MAAA,EAAQ,UAAU,CAAC,CAAA;AACpD,EAAA,MAAM,UAAA,GAAa,eAAA,CAAgB,EAAA,EAAI,IAAA,EAAM,QAAQ,CAAC,CAAA;AACtD,EAAA,OAAO;AAAA,IACL,UAAA;AAAA,IACA,MAAA,EAAQ,YAAA,CAAa,UAAA,EAAY,MAAM,CAAA;AAAA,IACvC,aAAa,gBAAA,CAAiB,EAAA,EAAI,MAAA,EAAQ,QAAA,EAAU,MAAM,OAAO;AAAA,GACnE;AACF;AAoBO,SAAS,OAAA,CAAQ,KAAA,EAAoB,EAAA,EAAY,IAAA,EAAkC;AACxF,EAAA,MAAM,CAAA,GAAI,aAAa,KAAK,CAAA;AAC5B,EAAA,MAAM,OAAA,GAAU,OAAO,IAAA,CAAK,CAAA,CAAE,OAAO,OAAO,CAAA,CAAE,GAAA,CAAI,CAAC,MAAA,MAAY;AAAA,IAC7D,MAAA;AAAA,IACA,GAAG,QAAA,CAAS,CAAA,EAAG,MAAA,EAAQ,IAAI,IAAI;AAAA,GACjC,CAAE,CAAA;AACF,EAAA,OAAO,EAAE,IAAI,OAAA,EAAQ;AACvB;;;ACpDO,SAAS,gBAAA,CAAiB,QAAsB,IAAA,EAA8B;AACnF,EAAA,MAAM,MAAA,GAAS,qBAAA,CAAsB,MAAA,EAAQ,QAAQ,CAAA;AACrD,EAAA,MAAM,EAAE,WAAW,CAAA,EAAG,KAAA,KAAU,aAAA,CAAc,MAAA,EAAW,QAAQ,IAAI,CAAA;AACrE,EAAA,MAAM,EAAE,MAAA,EAAQ,KAAA,EAAM,GAAI,YAAY,MAAM,CAAA;AAE5C,EAAA,MAAM,IAAA,GAAO,CAAC,CAAA,KACZ,QAAA,CAAS,SAAS,CAAA,EAAG,KAAK,CAAA,IAAK,SAAA,IAC/B,WAAW,MAAA,GAAS,CAAA,EAAG,KAAA,EAAO,CAAA,EAAG,KAAK,CAAA,IAAK,SAAA;AAE7C,EAAA,IAAI,SAAA,IAAa,CAAA,EAAG,OAAO,MAAA,CAAO,iBAAA;AAClC,EAAA,IAAI,IAAA,CAAK,CAAC,CAAA,EAAG,OAAO,CAAA;AAIpB,EAAA,IAAI,EAAA,GAAK,CAAA;AACT,EAAA,IAAI,EAAA,GAAK,CAAA;AACT,EAAA,OAAO,CAAC,IAAA,CAAK,EAAE,CAAA,EAAG;AAChB,IAAA,EAAA,GAAK,EAAA;AACL,IAAA,EAAA,IAAM,CAAA;AACN,IAAA,IAAI,EAAA,GAAK,IAAA,EAAM,OAAO,MAAA,CAAO,iBAAA;AAAA,EAC/B;AACA,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,OAAO,EAAA,GAAK,EAAA,GAAK,MAAM,CAAA,EAAA,EAAK;AAC9C,IAAA,MAAM,GAAA,GAAA,CAAO,KAAK,EAAA,IAAM,CAAA;AACxB,IAAA,IAAI,IAAA,CAAK,GAAG,CAAA,EAAG,EAAA,GAAK,GAAA;AAAA,SACf,EAAA,GAAK,GAAA;AAAA,EACZ;AACA,EAAA,OAAO,EAAA;AACT;;;AC1BO,SAAS,OAAA,CACd,KAAA,EACA,MAAA,EACA,EAAA,EACA,IAAA,EACqB;AACrB,EAAA,MAAM,CAAA,GAAI,aAAa,KAAK,CAAA;AAC5B,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,MAAA,EAAQ,QAAQ,CAAA;AACxC,EAAA,MAAM,CAAA,GAAI,eAAA,CAAgB,EAAA,EAAI,IAAI,CAAA;AAClC,EAAA,MAAM,MAAA,GAAS,mBAAA,CAAoB,CAAA,EAAG,IAAI,CAAA;AAC1C,EAAA,MAAM,UAAU,IAAA,KAAS,MAAA,GAAY,EAAC,GAAI,uBAAA,CAAwB,MAAM,SAAS,CAAA;AACjF,EAAA,MAAM,QAAA,GAAW,eAAA,CAAgB,CAAA,CAAE,MAAM,CAAA;AACzC,EAAA,OAAO,gBAAA,CAAiB,YAAA,CAAa,CAAA,EAAG,IAAA,EAAM,MAAA,EAAQ,UAAU,CAAC,CAAA,EAAG,MAAA,EAAQ,QAAA,EAAU,OAAO,CAAA;AAC/F;;;ACkBO,SAAS,OAAA,CAAQ,OAAoB,KAAA,EAAiC;AAC3E,EAAA,MAAM,EAAE,IAAA,EAAM,EAAA,EAAI,KAAA,EAAM,GAAI,cAAc,KAAK,CAAA;AAC/C,EAAA,MAAM,MAAA,GAAS,SAAA,CAAU,YAAA,CAAa,KAAK,GAAG,KAAK,CAAA;AACnD,EAAA,IAAI,IAAI,MAAA,CAAO,KAAA;AACf,EAAA,MAAM,KAAK,MAAA,CAAO,EAAA;AAElB,EAAA,MAAM,UAAU,UAAA,CAAW,CAAA,CAAE,SAAS,CAAA,CAAE,MAAA,CAAO,gBAAgB,EAAE,CAAA;AACjE,EAAA,IAAI,OAAA,KAAY,IAAA,EAAM,CAAA,GAAI,YAAA,CAAa,GAAG,OAAO,CAAA;AAEjD,EAAA,MAAM,QAAA,GAAW,eAAA,CAAgB,CAAA,CAAE,MAAM,CAAA;AACzC,EAAA,MAAM,OAAA,GAAuC,EAAE,GAAG,CAAA,CAAE,OAAA,EAAQ;AAC5D,EAAA,IAAI,OAAA,GAAU,aAAA,CAAc,CAAA,CAAE,OAAA,EAAS,EAAE,CAAA;AAEzC,EAAA,KAAA,MAAW,CAAC,YAAY,MAAM,CAAA,IAAK,OAAO,OAAA,CAAQ,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,EAAG;AACnE,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,IAAI,CAAA;AAC5C,IAAA,MAAM,SAAA,GAAY,OAAO,OAAA,KAAY,IAAA;AACrC,IAAA,IAAI,CAAC,QAAA,IAAY,CAAC,SAAA,EAAW;AAE7B,IAAA,IAAI,EAAA,GAAK,cAAA,CAAe,CAAA,EAAG,UAAA,EAAY,MAAM,CAAA;AAC7C,IAAA,EAAA,GAAK,WAAA,CAAY,EAAA,EAAI,MAAA,EAAQ,EAAE,CAAA;AAC/B,IAAA,EAAA,GAAK,aAAA,CAAc,EAAA,EAAI,MAAA,EAAQ,QAAA,EAAU,EAAE,CAAA;AAE3C,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,MAAM,EAAE,SAAA,EAAU,GAAI,cAAc,EAAA,EAAI,MAAA,EAAQ,UAAU,IAAI,CAAA;AAC9D,MAAA,MAAM,CAAA,GAAI,WAAA,CAAY,OAAA,EAAS,UAAA,EAAY,IAAI,CAAA,GAAI,CAAA;AACnD,MAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,IAAY,CAAA,CAAE,OAAO,cAAA,KAAmB,MAAA;AAChE,MAAA,MAAM,MAAA,GAAS,QAAA,GAAW,YAAA,CAAa,CAAC,CAAA,GAAI,CAAA;AAC5C,MAAA,EAAA,GAAK,WAAA,CAAY,EAAA,EAAI,MAAA,EAAQ,IAAA,EAAM,YAAY,MAAM,CAAA;AAErD,MAAA,IAAI,CAAC,SAAA,EAAW,OAAA,GAAU,QAAA,CAAS,OAAA,EAAS,YAAY,IAAI,CAAA;AAAA,IAC9D;AAEA,IAAA,IAAI,SAAA,EAAW;AAKb,MAAA,MAAMA,OAAAA,GAAS,aAAA,CAAc,OAAA,EAAS,UAAU,CAAA;AAChD,MAAA,IAAI,CAACA,QAAO,QAAA,IAAYA,OAAAA,CAAO,KAAK,MAAA,GAAS,CAAA,IAAK,MAAA,CAAO,iBAAA,KAAsB,IAAA,EAAM;AACnF,QAAA,EAAA,GAAK,aAAA,CAAc,EAAA,EAAIA,OAAAA,CAAO,IAAA,EAAM,CAAC,CAAA;AAAA,MACvC;AACA,MAAA,EAAA,GAAK,aAAA,CAAc,EAAA,EAAI,MAAA,EAAQ,EAAE,CAAA;AACjC,MAAA,OAAA,GAAU,YAAA,CAAa,SAAS,UAAU,CAAA;AAC1C,MAAA,EAAA,GAAK,EAAE,GAAG,EAAA,EAAI,aAAA,EAAe,EAAA,EAAG;AAChC,MAAA,IAAI,OAAO,cAAA,IAAkB,IAAA,EAAM,EAAA,GAAK,YAAA,CAAa,IAAI,MAAM,CAAA;AAAA,IACjE;AAEA,IAAA,OAAA,CAAQ,UAAU,CAAA,GAAI,EAAA;AAAA,EACxB;AAEA,EAAA,OAAO,EAAE,GAAG,CAAA,EAAG,OAAA,EAAS,OAAA,EAAQ;AAClC;AAUA,SAAS,SAAA,CAAU,OAAoB,KAAA,EAAmD;AACxF,EAAA,MAAM,EAAE,EAAA,EAAI,QAAA,EAAS,GAAI,KAAA,CAAM,KAAA;AAC/B,EAAA,IAAI,EAAA,KAAO,IAAA,IAAQ,KAAA,IAAS,EAAA,EAAI,OAAO,EAAE,KAAA,EAAO,KAAA,CAAM,KAAA,EAAO,KAAK,CAAA,EAAG,EAAA,EAAI,KAAA,EAAM;AAC/E,EAAA,IAAI,QAAA,KAAa,MAAM,OAAO,SAAA,CAAU,MAAM,KAAA,EAAO,QAAQ,GAAG,KAAK,CAAA;AACrE,EAAA,OAAO,EAAE,KAAA,EAAO,EAAE,GAAG,KAAA,EAAO,KAAA,EAAO,EAAE,EAAA,EAAI,QAAA,EAAU,KAAA,EAAM,EAAE,EAAG,EAAA,EAAG;AACnE;AAEA,IAAM,cAAA,GAAiB,CAAC,WAAA,EAAa,WAAA,EAAa,kBAAkB,eAAe,CAAA;AACnF,IAAM,eAAA,GAAkB,CAAC,WAAA,EAAa,aAAa,CAAA;AAGnD,SAAS,KAAA,CAAM,OAAoB,CAAA,EAAwB;AACzD,EAAA,IAAI,UAAU,KAAA,CAAM,OAAA;AACpB,EAAA,KAAA,MAAW,CAAC,MAAM,EAAE,CAAA,IAAK,OAAO,OAAA,CAAQ,KAAA,CAAM,OAAO,CAAA,EAAG;AACtD,IAAA,IAAI,MAAA,GAAS,OAAA,CAAQ,EAAA,EAAI,cAAA,EAAgB,CAAC,CAAA;AAC1C,IAAA,IAAI,EAAA,CAAG,QAAQ,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,OAAA,GAAU,CAAC,CAAA,EAAG;AACzC,MAAA,MAAA,GAAS;AAAA,QACP,GAAG,MAAA;AAAA,QACH,OAAA,EAAS,EAAA,CAAG,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAO,CAAA,CAAE,OAAA,GAAU,CAAA,GAAI,EAAE,GAAG,CAAA,EAAG,OAAA,EAAS,CAAA,KAAM,CAAE;AAAA,OAC3E;AAAA,IACF;AACA,IAAA,IAAI,MAAA,KAAW,IAAI,OAAA,GAAU,EAAE,GAAG,OAAA,EAAS,CAAC,IAAI,GAAG,MAAA,EAAO;AAAA,EAC5D;AACA,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,KAAA,CAAM,OAAA,EAAS,iBAAiB,CAAC,CAAA;AACzD,EAAA,OAAO,EAAE,GAAG,KAAA,EAAO,OAAA,EAAS,OAAA,EAAS,KAAA,EAAO,EAAE,EAAA,EAAI,CAAA,EAAG,QAAA,EAAU,IAAA,EAAK,EAAE;AACxE;AAGA,SAAS,OAAA,CAA0B,GAAA,EAAQ,IAAA,EAA4B,CAAA,EAAc;AACnF,EAAA,IAAI,GAAA,GAAM,GAAA;AACV,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,MAAM,KAAA,GAAiB,IAAI,GAAG,CAAA;AAC9B,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,GAAQ,CAAA,EAAG,GAAA,GAAM,EAAE,GAAG,GAAA,EAAK,CAAC,GAAG,GAAG,CAAA,EAAE;AAAA,EACvE;AACA,EAAA,OAAO,GAAA;AACT;AAsBO,SAAS,UAAA,CAAW,OAAoB,EAAA,EAAyB;AACtE,EAAA,MAAM,CAAA,GAAI,aAAa,KAAK,CAAA;AAC5B,EAAA,MAAM,CAAA,GAAI,eAAA,CAAgB,EAAA,EAAI,IAAI,CAAA;AAClC,EAAA,IAAI,CAAA,CAAE,OAAA,CAAQ,SAAA,KAAc,IAAA,EAAM,OAAO,CAAA;AACzC,EAAA,MAAM,UAAU,UAAA,CAAW,CAAA,CAAE,SAAS,CAAA,CAAE,MAAA,CAAO,gBAAgB,CAAC,CAAA;AAChE,EAAA,OAAO,YAAA,CAAa,CAAA,EAAG,OAAA,IAAW,CAAC,CAAA;AACrC;AAEA,SAAS,YAAA,CAAa,OAAoB,EAAA,EAAyB;AACjE,EAAA,MAAM,QAAA,GAAW,eAAA,CAAgB,KAAA,CAAM,MAAM,CAAA;AAC7C,EAAA,MAAM,OAAA,GAAuC,EAAE,GAAG,KAAA,CAAM,OAAA,EAAQ;AAChE,EAAA,KAAA,MAAW,CAAC,YAAY,MAAM,CAAA,IAAK,OAAO,OAAA,CAAQ,KAAA,CAAM,MAAA,CAAO,OAAO,CAAA,EAAG;AACvE,IAAA,MAAMA,OAAAA,GAAS,aAAA,CAAc,KAAA,CAAM,OAAA,EAAS,UAAU,CAAA;AAItD,IAAA,IAAIA,QAAO,QAAA,KAAa,MAAA,CAAO,sBAAsB,IAAA,IAAQA,OAAAA,CAAO,KAAK,MAAA,KAAW,CAAA,CAAA;AAClF,MAAA;AACF,IAAA,IAAI,EAAA,GAAK,cAAA,CAAe,KAAA,EAAO,UAAA,EAAY,MAAM,CAAA;AACjD,IAAA,EAAA,GAAK,aAAA,CAAc,EAAA,EAAI,MAAA,EAAQ,QAAA,EAAU,EAAE,CAAA;AAC3C,IAAA,EAAA,GACE,MAAA,CAAO,WAAA,KAAgB,MAAA,GACnB,aAAA,CAAc,EAAA,EAAIA,OAAAA,CAAO,IAAA,EAAM,CAAC,CAAA,GAChC,YAAA,CAAa,EAAA,EAAIA,OAAAA,CAAO,MAAM,EAAE,CAAA;AACtC,IAAA,OAAA,CAAQ,UAAU,CAAA,GAAI,EAAA;AAAA,EACxB;AACA,EAAA,OAAO,EAAE,GAAG,KAAA,EAAO,OAAA,EAAS,OAAA,EAAS,cAAa,EAAE;AACtD;AAoBO,SAAS,aAAA,CAAc,MAAmB,IAAA,EAA4B;AAC3E,EAAA,MAAM,CAAA,GAAI,aAAa,IAAI,CAAA;AAC3B,EAAA,MAAM,CAAA,GAAI,aAAa,IAAI,CAAA;AAC3B,EAAA,OAAO,CAAA,CAAE,QAAQ,SAAA,KAAc,IAAA,IAAQ,EAAE,OAAA,CAAQ,SAAA,KAAc,EAAE,OAAA,CAAQ,SAAA;AAC3E;;;ACxMO,SAAS,OAAA,CACd,KAAA,EACA,MAAA,EACA,EAAA,EACA,IAAA,EACY;AACZ,EAAA,MAAM,CAAA,GAAI,aAAa,KAAK,CAAA;AAC5B,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,MAAA,EAAQ,QAAQ,CAAA;AACxC,EAAA,MAAM,CAAA,GAAI,eAAA,CAAgB,EAAA,EAAI,IAAI,CAAA;AAClC,EAAA,MAAM,MAAA,GAAS,mBAAA,CAAoB,CAAA,EAAG,IAAI,CAAA;AAC1C,EAAA,MAAM,MAAA,GAAS,aAAA,CAAc,CAAA,CAAE,MAAA,EAAQ,QAAQ,IAAI,CAAA;AACnD,EAAA,MAAM,EAAA,GAAK,YAAY,cAAA,CAAe,CAAA,EAAG,MAAM,MAAM,CAAA,EAAG,QAAQ,CAAC,CAAA;AACjE,EAAA,OAAO,eAAA,CAAgB,EAAA,EAAI,IAAA,EAAM,MAAA,EAAQ,CAAC,CAAA;AAC5C;AA0BO,SAAS,YAAA,CACd,KAAA,EACA,MAAA,EACA,EAAA,EACA,IAAA,EACS;AACT,EAAA,MAAM,CAAA,GAAI,aAAa,KAAK,CAAA;AAC5B,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,MAAA,EAAQ,QAAQ,CAAA;AACxC,EAAA,MAAM,MAAA,GAAS,mBAAA,CAAoB,CAAA,EAAG,IAAI,CAAA;AAC1C,EAAA,MAAM,MAAA,GAAS,aAAA,CAAc,CAAA,CAAE,MAAA,EAAQ,QAAQ,IAAI,CAAA;AACnD,EAAA,OAAO,aAAa,OAAA,CAAQ,CAAA,EAAG,MAAM,EAAA,EAAI,IAAI,GAAG,MAAM,CAAA;AACxD;AAmBO,SAAS,YAAA,CAAa,KAAA,EAAoB,MAAA,EAAgB,EAAA,EAAyB;AACxF,EAAA,MAAM,CAAA,GAAI,aAAa,KAAK,CAAA;AAC5B,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,MAAA,EAAQ,QAAQ,CAAA;AACxC,EAAA,MAAM,CAAA,GAAI,eAAA,CAAgB,EAAA,EAAI,IAAI,CAAA;AAClC,EAAA,MAAM,MAAA,GAAS,mBAAA,CAAoB,CAAA,EAAG,IAAI,CAAA;AAC1C,EAAA,MAAM,EAAA,GAAK,cAAA,CAAe,CAAA,EAAG,IAAA,EAAM,MAAM,CAAA;AACzC,EAAA,OAAO;AAAA,IACL,GAAG,CAAA;AAAA,IACH,OAAA,EAAS;AAAA,MACP,GAAG,CAAA,CAAE,OAAA;AAAA,MACL,CAAC,IAAI,GAAG,EAAE,GAAG,EAAA,EAAI,cAAA,EAAgB,CAAA,EAAG,WAAA,EAAa,EAAA,CAAG,WAAA,GAAc,CAAA;AAAE;AACtE,GACF;AACF;;;AC1FA,IAAM,WAAA,GAAc,CAAC,WAAA,EAAa,MAAA,EAAQ,KAAK,CAAA;AAC/C,IAAM,WAAA,GAAc,CAAA;AAEpB,SAAS,uBAAuB,KAAA,EAAyC;AACvE,EAAA,IAAI,CAAC,QAAA,CAAS,KAAK,CAAA,EAAG;AACpB,IAAA,MAAM,IAAI,UAAU,8DAA8D,CAAA;AAAA,EACpF;AACA,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,EAAG;AACpC,IAAA,IAAI,CAAC,WAAA,CAAY,QAAA,CAAS,GAAG,CAAA,EAAG;AAC9B,MAAA,MAAM,IAAI,SAAA;AAAA,QACR,qBAAqB,GAAG,CAAA,8CAAA,EAAiD,WAAA,CAAY,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA;AAAA,OACjG;AAAA,IACF;AAAA,EACF;AACA,EAAA,MAAM,SAAA,GAAY,UAAA,CAAW,KAAA,CAAM,SAAA,EAAW,mBAAmB,CAAA;AACjE,EAAA,MAAM,OAAO,KAAA,CAAM,IAAA;AACnB,EAAA,IAAI,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,MAAA,EAAQ;AACxC,IAAA,MAAM,IAAI,UAAU,mDAAmD,CAAA;AAAA,EACzE;AACA,EAAA,IAAI,GAAA,GAAM,WAAA;AACV,EAAA,IAAI,KAAA,CAAM,QAAQ,MAAA,EAAW;AAC3B,IAAA,IAAI,OAAO,MAAM,GAAA,KAAQ,QAAA,IAAY,CAAC,MAAA,CAAO,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA,EAAG;AAChE,MAAA,MAAM,IAAI,UAAU,+CAA+C,CAAA;AAAA,IACrE;AACA,IAAA,IAAI,CAAC,OAAO,SAAA,CAAU,KAAA,CAAM,GAAG,CAAA,IAAK,KAAA,CAAM,MAAM,CAAA,EAAG;AACjD,MAAA,MAAM,IAAI,WAAW,sDAAsD,CAAA;AAAA,IAC7E;AACA,IAAA,GAAA,GAAM,KAAA,CAAM,GAAA;AAAA,EACd;AACA,EAAA,OAAO,EAAE,SAAA,EAAW,IAAA,EAA0B,GAAA,EAAI;AACpD;AA+BO,SAAS,YAAA,CACd,KAAA,EACA,KAAA,EACA,IAAA,EACa;AACb,EAAA,MAAM,CAAA,GAAI,aAAa,KAAK,CAAA;AAC5B,EAAA,MAAM,EAAE,IAAA,EAAM,EAAA,EAAG,GAAI,cAAc,KAAK,CAAA;AACxC,EAAA,MAAM,EAAE,SAAA,EAAW,IAAA,EAAM,GAAA,EAAI,GAAI,uBAAuB,IAAI,CAAA;AAC5D,EAAA,MAAM,QAAA,GAAW,eAAA,CAAgB,CAAA,CAAE,MAAM,CAAA;AACzC,EAAA,MAAM,YAA8C,EAAC;AACrD,EAAA,KAAA,MAAW,CAAC,YAAY,MAAM,CAAA,IAAK,OAAO,OAAA,CAAQ,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,EAAG;AACnE,IAAA,MAAM,MAAA,GAAS,aAAA,CAAc,CAAA,CAAE,MAAA,EAAQ,QAAQ,MAAS,CAAA;AACxD,IAAA,MAAM,KAAK,YAAA,CAAa,CAAA,EAAG,UAAA,EAAY,MAAA,EAAQ,UAAU,EAAE,CAAA;AAC3D,IAAA,MAAM,UAAA,GAAa,eAAA,CAAgB,EAAA,EAAI,UAAA,EAAY,QAAQ,EAAE,CAAA;AAC7D,IAAA,MAAM,OAAO,gBAAA,CAAiB,EAAA,EAAI,MAAA,EAAQ,QAAA,EAAU,EAAE,CAAA;AACtD,IAAA,MAAM,UAAkC,EAAC;AACzC,IAAA,KAAA,MAAW,MAAA,IAAU,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,EAAG;AAChD,MAAA,OAAA,CAAQ,MAAM,IACZ,IAAA,CAAK,IAAA,CAAK,CAAC,GAAA,KAAQ,GAAA,CAAI,MAAA,KAAW,MAAM,CAAA,CACxC,eAAA;AAAA,IACJ;AACA,IAAA,SAAA,CAAU,UAAU,CAAA,GAAI;AAAA,MACtB,GAAG,UAAA,CAAW,CAAA;AAAA,MACd,OAAO,UAAA,CAAW,KAAA;AAAA,MAClB,YAAA,EAAc,YAAA,CAAa,UAAA,EAAY,MAAM,CAAA;AAAA,MAC7C,iBAAiB,UAAA,CAAW,eAAA;AAAA,MAC5B,GAAA,EAAK,KACF,MAAA,CAAO,CAAC,QAAQ,GAAA,CAAI,YAAA,KAAiB,CAAC,CAAA,CACtC,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA,CACZ,GAAA,CAAI,CAAC,GAAA,MAAS,EAAE,MAAA,EAAQ,IAAI,MAAA,EAAQ,MAAA,EAAQ,GAAA,CAAI,MAAA,EAAO,CAAE,CAAA;AAAA,MAC5D;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAO,EAAE,CAAA,EAAG,cAAA,EAAgB,IAAA,EAAM,OAAA,EAAS,SAAA,EAAW,IAAA,EAAM,KAAA,EAAO,EAAE,IAAA,EAAM,EAAA,EAAG,EAAG,SAAA,EAAU;AAC7F;AAoBO,SAAS,eAAA,CAAgB,IAAY,IAAA,EAAgC;AAC1E,EAAA,MAAM,CAAA,GAAI,eAAA,CAAgB,EAAA,EAAI,IAAI,CAAA;AAClC,EAAA,MAAM,EAAE,SAAA,EAAW,IAAA,EAAK,GAAI,uBAAuB,IAAI,CAAA;AACvD,EAAA,OAAO,EAAE,GAAG,cAAA,EAAgB,IAAA,EAAM,OAAO,SAAA,EAAW,IAAA,EAAM,IAAI,CAAA,EAAE;AAClE;;;AClIA,IAAM,UAAA,GAAyD;AAAA,EAC7D,CAAA,EAAG,MAAA;AAAA,EACH,CAAA,EAAG,MAAA;AAAA,EACH,CAAA,EAAG;AACL,CAAA;AAGO,SAAS,WAAW,OAAA,EAA0B;AACnD,EAAA,OAAO,MAAA,CAAO,UAAA,EAAY,MAAA,CAAO,OAAO,CAAC,CAAA;AAC3C;AAGO,SAAS,cAAc,MAAA,EAAwB;AACpD,EAAA,IAAI,OAAA,GAAU,MAAA;AACd,EAAA,OAAO,OAAO,OAAA,CAAQ,OAAA,KAAY,YAAY,UAAA,CAAW,OAAA,CAAQ,OAAO,CAAA,EAAG;AACzE,IAAA,OAAA,GAAW,UAAA,CAAW,OAAA,CAAQ,OAAO,CAAA,CAAiC,OAAO,CAAA;AAAA,EAC/E;AACA,EAAA,OAAO,OAAA;AACT;AAQA,SAAS,OAAO,MAAA,EAAwB;AACtC,EAAA,MAAM,UAAU,MAAA,CAAO,OAAA;AACvB,EAAA,IAAI,CAAC,QAAA,CAAS,OAAO,CAAA,IAAK,CAAC,QAAA,CAAS,OAAA,CAAQ,OAAO,CAAA,EAAG,OAAO,EAAE,GAAG,MAAA,EAAQ,SAAS,CAAA,EAAE;AACrF,EAAA,MAAM,UAAkB,EAAC;AACzB,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,OAAA,CAAQ,OAAO,CAAA,EAAG;AAC9C,IAAA,IAAI,QAAQ,WAAA,EAAa;AACzB,IAAA,MAAMA,OAAAA,GAAS,OAAA,CAAQ,OAAA,CAAQ,GAAG,CAAA;AAClC,IAAA,IAAI,SAASA,OAAM,CAAA,IAAK,MAAM,OAAA,CAAQA,OAAAA,CAAO,IAAI,CAAA,EAAG;AAClD,MAAA,MAAM,SAAiC,EAAC;AACxC,MAAA,KAAA,MAAW,MAAA,IAAUA,QAAO,IAAA,EAAM;AAChC,QAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,WAAW,WAAA,EAAa,MAAA,CAAO,MAAM,CAAA,GAAI,CAAA;AAAA,MAC7E;AACA,MAAA,OAAA,CAAQ,GAAG,CAAA,GAAI,EAAE,GAAGA,SAAQ,MAAA,EAAO;AAAA,IACrC,CAAA,MAAO;AACL,MAAA,OAAA,CAAQ,GAAG,CAAA,GAAIA,OAAAA;AAAA,IACjB;AAAA,EACF;AACA,EAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAG,SAAS,EAAE,GAAG,OAAA,EAAS,OAAA,EAAQ,EAAE;AACnE;AAQA,SAAS,OAAO,MAAA,EAAwB;AACtC,EAAA,IAAI,CAAC,QAAA,CAAS,MAAA,CAAO,OAAO,CAAA,SAAU,EAAE,GAAG,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAC9D,EAAA,MAAM,UAAkB,EAAC;AACzB,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,EAAG;AAC7C,IAAA,IAAI,QAAQ,WAAA,EAAa;AACzB,IAAA,MAAM,MAAA,GAAS,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA;AACjC,IAAA,OAAA,CAAQ,GAAG,CAAA,GAAI,QAAA,CAAS,MAAM,CAAA,GAAI,EAAE,GAAG,MAAA,EAAQ,OAAA,EAAS,EAAC,EAAE,GAAI,MAAA;AAAA,EACjE;AACA,EAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,OAAA,EAAS,GAAG,OAAA,EAAQ;AAC1C;AASA,SAAS,OAAO,MAAA,EAAwB;AACtC,EAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAG,KAAA,EAAO,EAAE,EAAA,EAAI,IAAA,EAAM,QAAA,EAAU,IAAA,EAAK,EAAE;AACtE;;;ACjDO,SAAS,UAAU,KAAA,EAA4B;AACpD,EAAA,OAAO,IAAA,CAAK,SAAA,CAAU,YAAA,CAAa,KAAK,CAAC,CAAA;AAC3C;AAqCO,SAAS,WAAA,CAAY,IAAA,EAAc,IAAA,GAA2B,EAAC,EAAgB;AACpF,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,EAAU,MAAM,IAAI,UAAU,6CAA6C,CAAA;AAC/F,EAAA,IAAI,CAAC,QAAA,CAAS,IAAI,GAAG,MAAM,IAAI,UAAU,0CAA0C,CAAA;AACnF,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,EAAG;AACnC,IAAA,IAAI,GAAA,KAAQ,QAAA,IAAY,GAAA,KAAQ,SAAA,EAAW;AACzC,MAAA,MAAM,IAAI,SAAA;AAAA,QACR,qBAAqB,GAAG,CAAA,8DAAA;AAAA,OAC1B;AAAA,IACF;AAAA,EACF;AACA,EAAA,IAAI,KAAK,OAAA,KAAY,MAAA,IAAa,OAAO,IAAA,CAAK,YAAY,UAAA,EAAY;AACpE,IAAA,MAAM,IAAI,UAAU,8CAA8C,CAAA;AAAA,EACpE;AAEA,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,EAC1B,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,IAAI,WAAA,CAAY,CAAA,0CAAA,EAA8C,KAAA,CAAgB,OAAO,CAAA,CAAA,CAAG,CAAA;AAAA,EAChG;AACA,EAAA,IAAI,CAAC,QAAA,CAAS,MAAM,KAAK,OAAO,MAAA,CAAO,YAAY,QAAA,EAAU;AAC3D,IAAA,MAAM,IAAI,UAAU,qDAAqD,CAAA;AAAA,EAC3E;AAEA,EAAA,IAAI,MAAA,GAAkB,MAAA;AACtB,EAAA,IAAI,MAAA,CAAO,YAAY,aAAA,EAAe;AACpC,IAAA,IAAI,UAAA,CAAW,MAAA,CAAO,OAAO,CAAA,EAAG;AAC9B,MAAA,MAAA,GAAS,cAAc,MAAM,CAAA;AAAA,IAC/B,CAAA,MAAA,IAAW,MAAA,CAAO,OAAA,KAAY,aAAA,GAAgB,CAAA,EAAG;AAI/C,MAAA,MAAA,GAAS,EAAE,GAAG,MAAA,EAAQ,OAAA,EAAS,aAAA,EAAc;AAAA,IAC/C,CAAA,MAAA,IAAW,IAAA,CAAK,OAAA,KAAY,MAAA,EAAW;AACrC,MAAA,MAAM,IAAI,UAAA;AAAA,QACR,CAAA,kCAAA,EAAqC,MAAA,CAAO,OAAO,CAAA,sCAAA,EAAyC,gBAAgB,CAAC,CAAA,yBAAA;AAAA,OAC/G;AAAA,IACF,CAAA,MAAO;AACL,MAAA,MAAA,GAAS,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,MAAA,CAAO,OAAO,CAAA;AAAA,IAC9C;AAAA,EACF;AAEA,EAAA,MAAM,SAAS,IAAA,CAAK,MAAA,KAAW,SAAY,MAAA,GAAY,eAAA,CAAgB,KAAK,MAAM,CAAA;AAClF,EAAA,MAAM,GAAA,GAAM,UAAA,CAAW,MAAA,EAAQ,MAAM,CAAA;AACrC,EAAA,OAAO,iBAAA,CAAkB,SAAA,CAAU,GAAA,EAAK,GAAA,CAAI,MAAM,CAAC,CAAA;AACrD;AAIA,SAASE,UAAAA,CAAU,MAAc,OAAA,EAAwB;AACvD,EAAA,MAAM,IAAI,SAAA,CAAU,CAAA,UAAA,EAAa,IAAI,CAAA,CAAA,EAAI,OAAO,CAAA,CAAE,CAAA;AACpD;AAEA,SAAS,MAAA,CAAO,OAAgB,IAAA,EAAuC;AACrE,EAAA,IAAI,CAAC,QAAA,CAAS,KAAK,GAAGA,UAAAA,CAAU,MAAM,wBAAwB,CAAA;AAC9D,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,MAAA,CAAO,OAAgB,IAAA,EAAsB;AACpD,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,MAAA,CAAO,SAAS,KAAK,CAAA;AACrD,IAAAA,UAAAA,CAAU,MAAM,yBAAyB,CAAA;AAC3C,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,WAAA,CAAY,OAAgB,IAAA,EAAsB;AACzD,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,KAAA,EAAO,IAAI,CAAA;AAC5B,EAAA,IAAI,IAAI,CAAA,EAAG,MAAM,IAAI,UAAA,CAAW,CAAA,UAAA,EAAa,IAAI,CAAA,qBAAA,CAAuB,CAAA;AACxE,EAAA,OAAO,CAAA;AACT;AAEA,SAAS,YAAA,CAAa,OAAgB,IAAA,EAA6B;AACjE,EAAA,OAAO,KAAA,KAAU,IAAA,GAAO,IAAA,GAAO,MAAA,CAAO,OAAO,IAAI,CAAA;AACnD;AAEA,SAAS,YAAA,CAAa,OAAgB,IAAA,EAA4B;AAChE,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,KAAA,EAAO,IAAI,CAAA;AAC5B,EAAA,OAAO;AAAA,IACL,MAAM,WAAA,CAAY,CAAA,CAAE,IAAA,EAAM,CAAA,EAAG,IAAI,CAAA,KAAA,CAAO,CAAA;AAAA,IACxC,QAAQ,WAAA,CAAY,CAAA,CAAE,MAAA,EAAQ,CAAA,EAAG,IAAI,CAAA,OAAA,CAAS;AAAA,GAChD;AACF;AAEA,SAAS,YAAA,CAAa,OAAgB,IAAA,EAAkC;AACtE,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,KAAA,EAAO,IAAI,CAAA;AAC5B,EAAA,OAAO;AAAA,IACL,OAAO,WAAA,CAAY,CAAA,CAAE,KAAA,EAAO,CAAA,EAAG,IAAI,CAAA,MAAA,CAAQ,CAAA;AAAA,IAC3C,MAAM,WAAA,CAAY,CAAA,CAAE,IAAA,EAAM,CAAA,EAAG,IAAI,CAAA,KAAA,CAAO;AAAA,GAC1C;AACF;AAEA,SAAS,MAAA,CACP,KAAA,EACA,IAAA,EACA,EAAA,EACmB;AACnB,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,KAAA,EAAO,IAAI,CAAA;AAC5B,EAAA,MAAM,MAAyB,EAAC;AAChC,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,EAAG;AAChC,IAAA,IAAI,QAAQ,WAAA,EAAa;AACzB,IAAA,GAAA,CAAI,GAAG,CAAA,GAAI,EAAA,CAAG,CAAA,CAAE,GAAG,CAAA,EAAG,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,IAAA,CAAK,SAAA,CAAU,GAAG,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,EACzD;AACA,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,eAAA,CAAgB,OAAgB,IAAA,EAAgC;AACvE,EAAA,IAAI,CAAC,MAAM,OAAA,CAAQ,KAAK,GAAGA,UAAAA,CAAU,MAAM,kBAAkB,CAAA;AAC7D,EAAA,IAAI,KAAA,CAAM,SAAS,WAAA,EAAa;AAC9B,IAAA,MAAM,IAAI,UAAA,CAAW,CAAA,UAAA,EAAa,IAAI,CAAA,mBAAA,EAAsB,WAAW,CAAA,SAAA,CAAW,CAAA;AAAA,EACpF;AACA,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,EAAM,CAAA,KAAM;AAC5B,IAAA,MAAM,IAAI,MAAA,CAAO,IAAA,EAAM,GAAG,IAAI,CAAA,CAAA,EAAI,CAAC,CAAA,CAAA,CAAG,CAAA;AACtC,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,IAAI,CAAA,IAAK,CAAC,CAAA,CAAE,IAAA,CAAK,MAAM,CAAC,CAAA,KAAM,OAAO,CAAA,KAAM,QAAQ,CAAA,EAAG;AACzE,MAAAA,WAAU,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,CAAC,UAAU,6BAA6B,CAAA;AAAA,IAC/D;AACA,IAAA,OAAO,EAAE,OAAA,EAAS,MAAA,CAAO,CAAA,CAAE,OAAA,EAAS,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,CAAC,CAAA,SAAA,CAAW,CAAA,EAAG,IAAA,EAAM,EAAE,IAAA,EAAiB;AAAA,EACzF,CAAC,CAAA;AACH;AAEA,SAAS,WAAA,CAAY,OAAgB,IAAA,EAA2B;AAC9D,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,KAAA,EAAO,IAAI,CAAA;AAC5B,EAAA,MAAM,cAAc,MAAA,CAAO,CAAA,CAAE,WAAA,EAAa,CAAA,EAAG,IAAI,CAAA,YAAA,CAAc,CAAA;AAC/D,EAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,WAAW,CAAA,IAAK,cAAc,CAAA,EAAG;AACrD,IAAA,MAAM,IAAI,UAAA,CAAW,CAAA,UAAA,EAAa,IAAI,CAAA,2CAAA,CAA6C,CAAA;AAAA,EACrF;AACA,EAAA,OAAO;AAAA,IACL,OAAO,MAAA,CAAO,CAAA,CAAE,KAAA,EAAO,CAAA,EAAG,IAAI,CAAA,MAAA,CAAQ,CAAA;AAAA,IACtC,MAAM,MAAA,CAAO,CAAA,CAAE,IAAA,EAAM,CAAA,EAAG,IAAI,CAAA,KAAA,CAAO,CAAA;AAAA,IACnC,WAAW,YAAA,CAAa,CAAA,CAAE,SAAA,EAAW,CAAA,EAAG,IAAI,CAAA,UAAA,CAAY,CAAA;AAAA,IACxD,eAAe,MAAA,CAAO,CAAA,CAAE,eAAe,CAAA,EAAG,IAAI,kBAAkB,YAAY,CAAA;AAAA,IAC5E,SAAS,MAAA,CAAO,CAAA,CAAE,SAAS,CAAA,EAAG,IAAI,YAAY,YAAY,CAAA;AAAA,IAC1D,UAAU,YAAA,CAAa,CAAA,CAAE,QAAA,EAAU,CAAA,EAAG,IAAI,CAAA,SAAA,CAAW,CAAA;AAAA,IACrD,SAAS,eAAA,CAAgB,CAAA,CAAE,OAAA,EAAS,CAAA,EAAG,IAAI,CAAA,QAAA,CAAU,CAAA;AAAA,IACrD,WAAW,YAAA,CAAa,CAAA,CAAE,SAAA,EAAW,CAAA,EAAG,IAAI,CAAA,UAAA,CAAY,CAAA;AAAA,IACxD,gBAAgB,YAAA,CAAa,CAAA,CAAE,cAAA,EAAgB,CAAA,EAAG,IAAI,CAAA,eAAA,CAAiB,CAAA;AAAA,IACvE,eAAe,YAAA,CAAa,CAAA,CAAE,aAAA,EAAe,CAAA,EAAG,IAAI,CAAA,cAAA,CAAgB,CAAA;AAAA,IACpE;AAAA,GACF;AACF;AAEA,SAAS,eAAA,CAAgB,OAAgB,IAAA,EAAsB;AAC7D,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,KAAA,EAAO,IAAI,CAAA;AAC5B,EAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,CAAC,CAAA,IAAK,IAAI,CAAA,EAAG;AACjC,IAAA,MAAM,IAAI,UAAA,CAAW,CAAA,UAAA,EAAa,IAAI,CAAA,2BAAA,CAA6B,CAAA;AAAA,EACrE;AACA,EAAA,OAAO,CAAA;AACT;AAEA,SAAS,aAAA,CAAc,OAAgB,IAAA,EAAmC;AACxE,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,KAAA,EAAO,IAAI,CAAA;AAC5B,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,IAAI,CAAA,IAAK,CAAC,CAAA,CAAE,IAAA,CAAK,MAAM,CAAC,CAAA,KAAM,OAAO,CAAA,KAAM,QAAQ,CAAA,EAAG;AACzE,IAAAA,UAAAA,CAAU,CAAA,EAAG,IAAI,CAAA,KAAA,CAAA,EAAS,6BAA6B,CAAA;AAAA,EACzD;AACA,EAAA,MAAM,SAAS,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAA,EAAG,IAAI,WAAW,eAAe,CAAA;AACjE,EAAA,IAAI,OAAO,EAAE,QAAA,KAAa,SAAA,EAAWA,UAAAA,CAAU,CAAA,EAAG,IAAI,CAAA,SAAA,CAAA,EAAa,mBAAmB,CAAA;AACtF,EAAA,OAAO,EAAE,IAAA,EAAM,CAAA,CAAE,MAAkB,MAAA,EAAQ,QAAA,EAAU,EAAE,QAAA,EAAS;AAClE;AAEA,SAAS,YAAA,CAAa,OAAgB,IAAA,EAA4B;AAChE,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,KAAA,EAAO,IAAI,CAAA;AAC5B,EAAA,OAAO;AAAA,IACL,WAAW,YAAA,CAAa,CAAA,CAAE,SAAA,EAAW,CAAA,EAAG,IAAI,CAAA,UAAA,CAAY,CAAA;AAAA,IACxD,aAAa,YAAA,CAAa,CAAA,CAAE,WAAA,EAAa,CAAA,EAAG,IAAI,CAAA,YAAA,CAAc,CAAA;AAAA,IAC9D,SAAS,MAAA,CAAO,CAAA,CAAE,SAAS,CAAA,EAAG,IAAI,YAAY,aAAa;AAAA,GAC7D;AACF;AAEA,SAAS,UAAA,CAAW,OAAgB,IAAA,EAA0B;AAC5D,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,KAAA,EAAO,IAAI,CAAA;AAC5B,EAAA,OAAO;AAAA,IACL,IAAI,YAAA,CAAa,CAAA,CAAE,EAAA,EAAI,CAAA,EAAG,IAAI,CAAA,GAAA,CAAK,CAAA;AAAA,IACnC,UAAU,YAAA,CAAa,CAAA,CAAE,QAAA,EAAU,CAAA,EAAG,IAAI,CAAA,SAAA,CAAW;AAAA,GACvD;AACF;AASA,SAAS,UAAA,CAAW,OAAgB,MAAA,EAA+C;AACjF,EAAA,MAAM,CAAA,GAAI,MAAA,CAAO,KAAA,EAAO,OAAO,CAAA;AAC/B,EAAA,IAAI,CAAA,CAAE,YAAY,aAAA,EAAe;AAC/B,IAAA,MAAM,IAAI,UAAA,CAAW,CAAA,gCAAA,EAAmC,aAAa,CAAA,gBAAA,CAAkB,CAAA;AAAA,EACzF;AACA,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,CAAA,CAAE,MAAA,EAAQ,cAAc,CAAA;AAChD,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,aAAA;AAAA,IACT,MAAA,EAAQ,MAAA,IAAU,eAAA,CAAgB,QAAA,EAAU,KAAK,CAAA;AAAA,IACjD,OAAA,EAAS,MAAA,CAAO,CAAA,CAAE,OAAA,EAAS,iBAAiB,WAAW,CAAA;AAAA,IACvD,OAAA,EAAS,YAAA,CAAa,CAAA,CAAE,OAAA,EAAS,eAAe,CAAA;AAAA,IAChD,KAAA,EAAO,UAAA,CAAW,CAAA,CAAE,KAAA,EAAO,aAAa;AAAA,GAC1C;AACF;AASA,SAAS,kBAAkB,KAAA,EAAiC;AAC1D,EAAA,MAAM,QAAA,GAAW,eAAA,CAAgB,KAAA,CAAM,MAAM,CAAA;AAC7C,EAAA,KAAA,MAAW,CAAC,MAAM,MAAM,CAAA,IAAK,OAAO,OAAA,CAAQ,KAAA,CAAM,MAAA,CAAO,OAAO,CAAA,EAAG;AACjE,IAAA,MAAM,EAAA,GAAK,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA;AAC7B,IAAA,MAAM,IAAA,GAAO,CAAA,cAAA,EAAiB,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA,CAAA,CAAA;AAClD,IAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,EAAA,CAAG,QAAQ,EAAA,CAAG,IAAI,CAAA,IAAK,CAAC,OAAO,QAAA,CAAS,EAAA,CAAG,KAAA,GAAQ,EAAA,CAAG,IAAI,CAAA,EAAG;AAChF,MAAA,MAAM,IAAI,UAAA,CAAW,CAAA,UAAA,EAAa,IAAI,CAAA,8CAAA,CAAgD,CAAA;AAAA,IACxF;AACA,IAAA,KAAA,MAAW,MAAA,IAAU,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,EAAG;AAChD,MAAA,MAAM,CAAA,GAAI,aAAA,CAAc,EAAA,EAAI,MAAA,EAAQ,UAAU,MAAM,CAAA;AACpD,MAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,CAAA,CAAE,OAAO,CAAA,IAAK,CAAC,MAAA,CAAO,QAAA,CAAS,CAAA,CAAE,SAAS,CAAA,EAAG;AAChE,QAAA,MAAM,IAAI,UAAA;AAAA,UACR,aAAa,IAAI,CAAA,0BAAA,EAA6B,IAAA,CAAK,SAAA,CAAU,MAAM,CAAC,CAAA,0BAAA;AAAA,SACtE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,KAAA;AACT;AAIA,SAAS,IAAA,CAAQ,QAA2B,QAAA,EAAsD;AAChG,EAAA,MAAM,MAAyB,EAAC;AAChC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACjD,IAAA,IAAI,OAAO,QAAA,EAAU,GAAG,CAAA,EAAG,GAAA,CAAI,GAAG,CAAA,GAAI,KAAA;AAAA,EACxC;AACA,EAAA,OAAO,GAAA;AACT;AAGA,SAAS,WAAA,CACP,SACA,OAAA,EACkB;AAClB,EAAA,OAAO,OAAA,CACJ,GAAA,CAAI,CAAC,OAAA,MAAa;AAAA,IACjB,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,MAAM,OAAA,CAAQ,IAAA,CAAK,MAAA,CAAO,CAAC,GAAG,CAAA,KAAM,MAAA,CAAO,OAAA,EAAS,CAAC,KAAK,OAAA,CAAQ,IAAA,CAAK,OAAA,CAAQ,CAAC,MAAM,CAAC;AAAA,GACzF,CAAE,EACD,IAAA,CAAK,CAAC,GAAG,CAAA,KAAM,CAAA,CAAE,OAAA,GAAU,CAAA,CAAE,OAAO,CAAA;AACzC;AAMA,SAAS,SAAA,CAAU,KAAkB,MAAA,EAAmC;AACtE,EAAA,MAAM,UAAuC,EAAC;AAC9C,EAAA,MAAM,iBAAsD,EAAC;AAE7D,EAAA,KAAA,MAAW,CAAC,MAAM,MAAM,CAAA,IAAK,OAAO,OAAA,CAAQ,MAAA,CAAO,OAAO,CAAA,EAAG;AAC3D,IAAA,MAAM,MAAA,GAAS,MAAA,CAAO,GAAA,CAAI,OAAA,EAAS,IAAI,CAAA;AACvC,IAAA,IAAI,WAAW,MAAA,EAAW;AACxB,MAAA,OAAA,CAAQ,IAAI,CAAA,GAAI,UAAA,CAAW,MAAM,CAAA;AAAA,IACnC,CAAA,MAAO;AACL,MAAA,OAAA,CAAQ,IAAI,CAAA,GAAI,iBAAA;AAAA,QACd;AAAA,UACE,GAAG,MAAA;AAAA,UACH,OAAA,EAAS,IAAA,CAAK,MAAA,CAAO,OAAA,EAAS,OAAO,OAAO,CAAA;AAAA,UAC5C,OAAA,EAAS,WAAA,CAAY,MAAA,CAAO,OAAA,EAAS,OAAO,OAAO;AAAA,SACrD;AAAA,QACA,MAAA;AAAA,QACA,IAAA,CAAK,MAAA,CAAO,aAAA,EAAe,MAAA,CAAO,OAAO;AAAA,OAC3C;AAAA,IACF;AAAA,EACF;AAIA,EAAA,IAAI,GAAA,CAAI,OAAA,CAAQ,SAAA,KAAc,IAAA,EAAM;AAClC,IAAA,KAAA,MAAW,CAAC,MAAM,OAAO,CAAA,IAAK,OAAO,OAAA,CAAQ,GAAA,CAAI,OAAA,CAAQ,OAAO,CAAA,EAAG;AACjE,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,IAAI,CAAA;AAC1C,MAAA,IAAI,WAAW,MAAA,EAAW;AAC1B,MAAA,MAAM,IAAA,GAAO,QAAQ,IAAA,CAAK,MAAA;AAAA,QACxB,CAAC,CAAA,EAAG,CAAA,KAAM,MAAA,CAAO,MAAA,CAAO,OAAA,EAAS,CAAC,CAAA,IAAK,OAAA,CAAQ,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAA,KAAM;AAAA,OACrE;AAEA,MAAA,MAAM,SAAiC,EAAC;AACxC,MAAA,KAAA,MAAW,CAAA,IAAK,MAAM,MAAA,CAAO,CAAC,IAAI,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,CAAC,CAAA,IAAK,CAAA;AAC/D,MAAA,cAAA,CAAe,IAAI,CAAA,GAAI,EAAE,MAAM,MAAA,EAAQ,QAAA,EAAU,QAAQ,QAAA,EAAS;AAAA,IACpE;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,aAAA;AAAA,IACT,MAAA;AAAA,IACA,OAAA;AAAA,IACA,OAAA,EAAS;AAAA,MACP,SAAA,EAAW,IAAI,OAAA,CAAQ,SAAA;AAAA,MACvB,aAAa,GAAA,CAAI,OAAA,CAAQ,cAAc,IAAA,GAAO,IAAA,GAAO,IAAI,OAAA,CAAQ,WAAA;AAAA,MACjE,OAAA,EAAS;AAAA,KACX;AAAA,IACA,OAAO,YAAA,CAAa,GAAA,CAAI,KAAA,EAAO,OAAA,EAAS,IAAI,OAAO;AAAA,GACrD;AACF;AAQA,SAAS,YAAA,CACP,KAAA,EACA,OAAA,EACA,OAAA,EACY;AACZ,EAAA,IAAI,KAAK,KAAA,CAAM,EAAA;AACf,EAAA,MAAM,GAAA,GAAM,CAAC,KAAA,KAA+B;AAC1C,IAAA,IAAI,UAAU,IAAA,KAAS,EAAA,KAAO,IAAA,IAAQ,KAAA,GAAQ,KAAK,EAAA,GAAK,KAAA;AAAA,EAC1D,CAAA;AACA,EAAA,GAAA,CAAI,QAAQ,SAAS,CAAA;AACrB,EAAA,GAAA,CAAI,QAAQ,WAAW,CAAA;AACvB,EAAA,KAAA,MAAW,EAAA,IAAM,MAAA,CAAO,MAAA,CAAO,OAAO,CAAA,EAAG;AACvC,IAAA,GAAA,CAAI,GAAG,SAAS,CAAA;AAChB,IAAA,GAAA,CAAI,GAAG,aAAa,CAAA;AAAA,EACtB;AACA,EAAA,MAAM,QAAA,GACJ,KAAA,CAAM,QAAA,KAAa,IAAA,IAAQ,EAAA,KAAO,QAAQ,KAAA,CAAM,QAAA,GAAW,EAAA,GAAK,KAAA,CAAM,QAAA,GAAW,IAAA;AACnF,EAAA,OAAO,EAAA,KAAO,MAAM,EAAA,IAAM,QAAA,KAAa,MAAM,QAAA,GAAW,KAAA,GAAQ,EAAE,EAAA,EAAI,QAAA,EAAS;AACjF;;;ACxWO,IAAM,EAAA,GAAY;AAAA,EACvB,OAAA,EAAS,CAAC,CAAA,KAAM,CAAA,GAAI,GAAA;AAAA,EACpB,OAAA,EAAS,CAAC,CAAA,KAAM,CAAA,GAAI,GAAA;AAAA,EACpB,KAAA,EAAO,CAAC,CAAA,KAAM,CAAA,GAAI,IAAA;AAAA,EAClB,IAAA,EAAM,CAAC,CAAA,KAAM,CAAA,GAAI,KAAA;AAAA,EACjB,KAAA,EAAO,CAAC,CAAA,KAAM,CAAA,GAAI;AACpB;;;ACjBO,SAAS,eAAe,MAAA,EAA+B;AAC5D,EAAA,OAAO,gBAAgB,MAAM,CAAA;AAC/B","file":"index.js","sourcesContent":["import type { LiftType } from './types';\n\n/** 2^(−elapsed / halfLife): 1 for zero, negative or NaN elapsed time, 0 for an infinite one. */\nexport function decayFactor(elapsed: number, halfLife: number): number {\n if (!(elapsed > 0)) return 1;\n return 2 ** (-elapsed / halfLife);\n}\n\nexport function betaMean(alpha: number, beta: number): number {\n return alpha / (alpha + beta);\n}\n\nexport function betaVariance(alpha: number, beta: number): number {\n const n = alpha + beta;\n return (alpha * beta) / (n * n * (n + 1));\n}\n\nexport function betaSd(alpha: number, beta: number): number {\n return Math.sqrt(betaVariance(alpha, beta));\n}\n\nexport function clamp01(x: number): number {\n if (x < 0) return 0;\n if (x > 1) return 1;\n return x;\n}\n\n/**\n * Φ(−z) for z ≥ 0: the one-sided tail of the standard normal, so that `z` names the same level\n * under both bounds. Abramowitz–Stegun 7.1.26, |error| below 1.5e-7.\n */\nexport function normalTail(z: number): number {\n const x = z / Math.SQRT2;\n const t = 1 / (1 + 0.3275911 * x);\n const poly =\n t *\n (0.254829592 + t * (-0.284496736 + t * (1.421413741 + t * (-1.453152027 + t * 1.061405429))));\n return 0.5 * poly * Math.exp(-x * x);\n}\n\n/** ln Γ(x) for x > 0: Stirling's series once x is shifted up to 8 or more (about 1e-11 relative). */\nexport function lgamma(x: number): number {\n let acc = 0;\n let v = x;\n while (v < 8) {\n acc -= Math.log(v);\n v += 1;\n }\n const r = 1 / v;\n const r2 = r * r;\n return (\n acc +\n (v - 0.5) * Math.log(v) -\n v +\n 0.9189385332046728 +\n r * (1 / 12 - r2 * (1 / 360 - r2 * (1 / 1260 - r2 / 1680)))\n );\n}\n\n/**\n * The continued fraction of the incomplete Beta function, by the modified Lentz method. Both\n * halves of each step share the denominator (a + i − 1)(a + i), so one loop over i covers them,\n * and i = 1 is the usual initialisation. Converges in about √max(a, b) steps; the cap covers the\n * largest counts a config allows.\n */\nfunction betacf(x: number, a: number, b: number): number {\n const tiny = 1e-300;\n const guard = (v: number): number => (Math.abs(v) < tiny ? tiny : v);\n let c = 1 / tiny;\n let d = 1;\n let h = 1;\n for (let i = 1; i < 20_000; i++) {\n const m = i >> 1;\n const aa = ((i & 1 ? -(a + m) * (a + b + m) : m * (b - m)) * x) / ((a + i - 1) * (a + i));\n d = 1 / guard(1 + aa * d);\n c = guard(1 + aa / c);\n const del = c * d;\n h *= del;\n if (Math.abs(del - 1) < 1e-12) break;\n }\n return h;\n}\n\n/** The regularized incomplete Beta function I_x(a, b): P(X ≤ x) for X ~ Beta(a, b). */\nexport function incompleteBeta(x: number, a: number, b: number): number {\n if (x <= 0) return 0;\n if (x >= 1) return 1;\n const front = Math.exp(\n lgamma(a + b) - lgamma(a) - lgamma(b) + a * Math.log(x) + b * Math.log(1 - x),\n );\n // The fraction converges fast on the near side of the mean; symmetry covers the far side.\n return x < (a + 1) / (a + b + 2)\n ? (front * betacf(x, a, b)) / a\n : 1 - (front * betacf(1 - x, b, a)) / b;\n}\n\n/**\n * The q-quantile of Beta(a, b), by bisection to a width of 1e-9. The answer is the middle of the\n * last bracket, so it is always strictly inside (0, 1), however small a or b.\n */\nexport function betaQuantile(q: number, a: number, b: number): number {\n let lo = 0;\n let hi = 1;\n for (let i = 0; i < 40 && hi - lo > 1e-9; i++) {\n const mid = (lo + hi) / 2;\n if (incompleteBeta(mid, a, b) < q) lo = mid;\n else hi = mid;\n }\n return (lo + hi) / 2;\n}\n\n/**\n * The lower bound `shouldReveal` compares to the threshold: p − z·sd clamped to [0, 1], or\n * with `'exact'` the Beta quantile at the same one-sided level, Φ(−z).\n */\nexport function lowerBound(\n alpha: number,\n beta: number,\n z: number,\n bound: 'normal' | 'exact',\n): number {\n if (bound === 'exact') return betaQuantile(normalTail(z), alpha, beta);\n return clamp01(betaMean(alpha, beta) - z * betaSd(alpha, beta));\n}\n\n/**\n * What the n-th occurrence of a signal within one episode adds, as a fraction of its weight:\n * log2(1 + 1/n), so that n occurrences add log2(1 + n) weights in total. 1 for the first\n * occurrence, 0.585 for the second, 0.415 for the third; every doubling adds one more weight.\n */\nexport function repeatFactor(n: number): number {\n return Math.log1p(1 / n) / Math.LN2;\n}\n\n/** Laplace-smoothed rate: (successes + 1) / (total + 2). Strictly inside (0, 1) in exact arithmetic. */\nexport function laplace(successes: number, total: number): number {\n return (successes + 1) / (total + 2);\n}\n\n/**\n * A rate shrunk toward `rate` by two pseudo-episodes: (successes + 2·rate) / (total + 2). With a\n * `rate` of 0.5 this is Laplace smoothing; with the intent's own base rate, two groups whose\n * observed rates both equal it agree exactly whatever their sizes, and with no outcome yet every\n * rate is 0.\n */\nexport function smoothRate(successes: number, total: number, rate: number): number {\n return (successes + 2 * rate) / (total + 2);\n}\n\n/**\n * The raw association measure comparing rate `q` with baseline `b`. Convert it with\n * `learningScore` before using it as signed evidence; raw ratios have a neutral value of 1.\n * For association-rule lift, `b` must be the overall outcome rate rather than the rate without\n * the signal: P(outcome | signal) / P(outcome) = P(signal, outcome) / (P(signal) P(outcome)).\n * Ratio/log inputs are bounded away from 0 and 1: tune's Wilson interval endpoints can be\n * exactly 0 or 1, and large smoothed counts can round there too. This keeps raw metrics and\n * their evidence scores finite. The default retains its original arithmetic.\n */\nexport function lift(q: number, b: number, type: LiftType = 'normalized-difference'): number {\n if (type === 'absolute-difference') return q - b;\n if (type !== 'normalized-difference') {\n const rate = Math.max(Number.EPSILON, Math.min(1 - Number.EPSILON, q));\n const base = Math.max(Number.EPSILON, Math.min(1 - Number.EPSILON, b));\n switch (type) {\n case 'relative-lift':\n return (rate - base) / base;\n case 'log-lift':\n return Math.log(rate / base);\n case 'odds-ratio':\n return rate / (1 - rate) / (base / (1 - base));\n case 'risk-ratio':\n case 'association-rule':\n return rate / base;\n }\n }\n if (q >= b) return b >= 1 ? 0 : (q - b) / (1 - b);\n return b <= 0 ? 0 : (q - b) / b;\n}\n\n/**\n * Converts raw lift to signed evidence in [−1, 1], with independence at 0. Bounded differences\n * keep their original scale. Ratios use (R − 1)/(R + 1); unbounded differences and log lift use\n * x/(1 + |x|). Both transforms are monotone, so direction and interval ordering are preserved.\n */\nexport function learningScore(value: number, type: LiftType = 'normalized-difference'): number {\n switch (type) {\n case 'risk-ratio':\n case 'odds-ratio':\n case 'association-rule':\n return (value - 1) / (value + 1);\n case 'relative-lift':\n case 'log-lift':\n return value / (1 + Math.abs(value));\n default:\n return value;\n }\n}\n","export function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** Own-property check, so event names like \"constructor\" never hit Object.prototype. */\nexport function hasOwn(record: object, key: string): boolean {\n // biome-ignore lint/suspicious/noPrototypeBuiltins: Object.hasOwn is ES2022; this library targets ES2020 runtimes.\n return Object.prototype.hasOwnProperty.call(record, key);\n}\n\nexport function getOwn<T>(record: Record<string, T>, key: string): T | undefined {\n return hasOwn(record, key) ? record[key] : undefined;\n}\n\nexport function mapRecord<T, U>(\n record: Record<string, T>,\n fn: (value: T, key: string) => U,\n): Record<string, U> {\n const out: Record<string, U> = {};\n for (const [key, value] of Object.entries(record)) {\n out[key] = fn(value, key);\n }\n return out;\n}\n","import type { ResolvedLearning } from './config';\nimport { decayFactor, learningScore, lift, smoothRate } from './math';\nimport type { IntentConfig, IntentState, SignalRecord } from './types';\nimport { getOwn, mapRecord } from './util';\n\nconst NONE: SignalRecord = { hits: 0, misses: 0 };\n\n/**\n * Decays learned counts toward 0 by 2^(−Δt / learning.halfLife) and moves the anchor to `at`; an\n * `at` before the anchor holds the counts and leaves the anchor, as `decayIntent` does.\n */\nexport function decayLearned(\n state: IntentState,\n learning: ResolvedLearning,\n at: number,\n): IntentState {\n if (state.learnedAt === null) return { ...state, learnedAt: at };\n if (!(at > state.learnedAt)) return state;\n const d = learning.halfLife === null ? 1 : decayFactor(at - state.learnedAt, learning.halfLife);\n if (d === 1) return { ...state, learnedAt: at };\n return {\n ...state,\n learnedAt: at,\n learned: mapRecord(state.learned, (r) => ({ hits: r.hits * d, misses: r.misses * d })),\n episodes: { hits: state.episodes.hits * d, misses: state.episodes.misses * d },\n };\n}\n\nexport interface SignalWeights {\n initial: number;\n learned: number;\n effective: number;\n hits: number;\n misses: number;\n}\n\n/**\n * initial: the developer's weight w0.\n * learned: gain · |w0| · the signed, bounded score of the configured lift. qWith is the outcome\n * rate where the signal was seen (hits / (hits + misses)) and qWithout the outcome rate\n * of the intent's other episodes, both shrunk toward the intent's own base rate by two\n * pseudo-episodes, so that a signal whose rate equals the base rate learns nothing\n * whatever the sample sizes, and nothing moves before the first outcome. 0 until the\n * signal has completed an episode.\n * effective: (k · w0 + nEff · learned) / (k + nEff), with k = learning.priorEpisodes and\n * nEff = (nWith · nWithout) / (nWith + nWithout): the comparison is only trusted once\n * the signal has been both present and absent. A signal that has never been absent\n * (or never present) has no counterfactual, nEff is 0, and the developer's weight stands.\n */\nexport function signalWeights(\n state: IntentState,\n intent: IntentConfig,\n learning: ResolvedLearning,\n signal: string,\n): SignalWeights {\n const initial = getOwn(intent.signals, signal);\n if (initial === undefined) {\n throw new RangeError(`oracular: ${JSON.stringify(signal)} is not a signal of this intent`);\n }\n const record = getOwn(state.learned, signal) ?? NONE;\n const nWith = record.hits + record.misses;\n // The contrast: episodes of this intent in which the signal was not seen. hits + misses counts\n // the episodes it was seen in (one record per episode), so the rest is the complement.\n const totalEpisodes = state.episodes.hits + state.episodes.misses;\n const nWithout = Math.max(0, totalEpisodes - nWith);\n const outcomesWithout = Math.min(nWithout, Math.max(0, state.episodes.hits - record.hits));\n // Both rates are shrunk toward the intent's own base rate, not toward 0.5: two groups that\n // differ only in size then agree, and before the first outcome every rate is 0.\n const base = totalEpisodes === 0 ? 0 : state.episodes.hits / totalEpisodes;\n const qWith = smoothRate(record.hits, nWith, base);\n const qWithout = smoothRate(outcomesWithout, nWithout, base);\n // Nothing has been learned about a signal until it has been seen in a completed episode. The\n // association-rule baseline is the pooled rate, shrunk the same way (so, the base rate itself).\n const baseline =\n learning.lift === 'association-rule'\n ? smoothRate(record.hits + outcomesWithout, nWith + nWithout, base)\n : qWithout;\n const score = learningScore(lift(qWith, baseline, learning.lift), learning.lift);\n const learned = nWith === 0 ? 0 : learning.gain * Math.abs(initial) * score;\n // Learning needs contrast: weight the comparison by how much of both sides has been seen.\n const nEff = nWith + nWithout === 0 ? 0 : (nWith * nWithout) / (nWith + nWithout);\n const k = learning.priorEpisodes;\n const effective = (k * initial + nEff * learned) / (k + nEff);\n return { initial, learned, effective, hits: record.hits, misses: record.misses };\n}\n\n/**\n * Counts one episode for the listed signals and for the base rate: `credit` of a hit and\n * `1 − credit` of a miss. 1 when the outcome arrived in the episode, 0 when it ended without it,\n * and in between for an episode a later outcome credits under `attribution` (see attribution.ts).\n * Whatever the credit, the episode counts exactly once.\n */\nexport function recordEpisode(\n state: IntentState,\n signals: readonly string[],\n credit: number,\n): IntentState {\n const miss = 1 - credit;\n const learned = { ...state.learned };\n for (const signal of signals) {\n const r = getOwn(learned, signal) ?? NONE;\n learned[signal] = { hits: r.hits + credit, misses: r.misses + miss };\n }\n const episodes = { hits: state.episodes.hits + credit, misses: state.episodes.misses + miss };\n return { ...state, learned, episodes };\n}\n","import type { ResolvedLearning } from './config';\nimport { decayLearned, recordEpisode } from './learning';\nimport { decayFactor } from './math';\nimport type { IntentConfig, IntentState, PendingEpisode } from './types';\n\n/** Most closed episodes one intent keeps waiting for its outcome. Past it the oldest is a miss at once. */\nexport const MAX_PENDING = 32;\n\n/**\n * When a waiting episode's window ends: its close plus the intent's `attribution`. 0 when the\n * intent no longer sets one, so an episode held under an earlier config settles on the next touch.\n */\nfunction expiry(episode: PendingEpisode, intent: IntentConfig): number {\n return episode.endedAt + (intent.attribution ?? 0);\n}\n\n/**\n * Brings the learned counts up to `at`. Every waiting episode whose window has ended by then is a\n * miss, recorded at the moment its window ended (the counts are decayed to that moment first, as\n * for an episode that closes by timing out), and the counts are then decayed to `at`. Every path\n * that reads or writes learned counts goes through here, so no verdict lands out of order.\n */\nexport function settlePending(\n state: IntentState,\n intent: IntentConfig,\n learning: ResolvedLearning,\n at: number,\n): IntentState {\n let is = state;\n let settled = 0;\n for (const episode of state.pending) {\n const end = expiry(episode, intent);\n if (!(end < at)) break;\n is = recordEpisode(decayLearned(is, learning, end), episode.seen, 0);\n settled++;\n }\n if (settled > 0) is = { ...is, pending: state.pending.slice(settled) };\n return decayLearned(is, learning, at);\n}\n\n/**\n * Holds a closed episode for the intent's outcome instead of counting it, in order of close. Past\n * {@link MAX_PENDING} the oldest is a miss at once, so the stored state stays bounded whatever the\n * session cadence.\n */\nexport function deferEpisode(\n state: IntentState,\n seen: readonly string[],\n endedAt: number,\n): IntentState {\n const pending = insert(state.pending, { endedAt, seen: [...seen] });\n if (pending.length <= MAX_PENDING) return { ...state, pending };\n const [oldest, ...rest] = pending;\n return { ...recordEpisode(state, (oldest as PendingEpisode).seen, 0), pending: rest };\n}\n\n/** Keeps the list in order of close; a clock that went backwards inserts before later closes. */\nfunction insert(pending: readonly PendingEpisode[], episode: PendingEpisode): PendingEpisode[] {\n let i = pending.length;\n while (i > 0 && (pending[i - 1] as PendingEpisode).endedAt > episode.endedAt) i--;\n return [...pending.slice(0, i), episode, ...pending.slice(i)];\n}\n\n/**\n * The outcome arrived at `at`: every waiting episode gets the share `2^(−age / halfLife)` of a hit\n * that its evidence would still hold now, and the rest of a miss, so each episode still counts\n * exactly once. The list is then empty.\n */\nexport function creditPending(state: IntentState, intent: IntentConfig, at: number): IntentState {\n if (state.pending.length === 0) return state;\n let is = state;\n for (const episode of state.pending) {\n is = recordEpisode(is, episode.seen, decayFactor(at - episode.endedAt, intent.halfLife));\n }\n return { ...is, pending: [] };\n}\n","import { decayFactor } from './math';\nimport type { IntentConfig, IntentState, SignalContribution } from './types';\nimport { getOwn, mapRecord } from './util';\n\nexport function priorCounts(intent: IntentConfig): { alpha0: number; beta0: number } {\n return {\n alpha0: intent.prior * intent.priorStrength,\n beta0: (1 - intent.prior) * intent.priorStrength,\n };\n}\n\nexport function initIntent(intent: IntentConfig): IntentState {\n const { alpha0, beta0 } = priorCounts(intent);\n return {\n alpha: alpha0,\n beta: beta0,\n updatedAt: null,\n contributions: {},\n learned: {},\n episodes: { hits: 0, misses: 0 },\n pending: [],\n learnedAt: null,\n lastRevealedAt: null,\n lastOutcomeAt: null,\n revealCount: 0,\n };\n}\n\n/**\n * The one place α and β are written: always the prior plus the sum of contributions,\n * so the invariant α = α0 + Σ contributions.alpha (and β likewise) holds by construction.\n */\nexport function withContributions(\n state: IntentState,\n intent: IntentConfig,\n contributions: Record<string, SignalContribution>,\n): IntentState {\n const { alpha0, beta0 } = priorCounts(intent);\n let alpha = alpha0;\n let beta = beta0;\n for (const c of Object.values(contributions)) {\n alpha += c.alpha;\n beta += c.beta;\n }\n return { ...state, alpha, beta, contributions };\n}\n\n/**\n * Decays evidence toward the prior by 2^(−Δt / halfLife) and moves the anchor to `at`. An `at`\n * before the anchor holds the evidence and leaves the anchor where it is: `observe` resolves the\n * clock before it writes (see `syncClock` there), and a read before the anchor sees what the\n * anchor sees.\n */\nexport function decayIntent(state: IntentState, intent: IntentConfig, at: number): IntentState {\n if (state.updatedAt === null) return { ...state, updatedAt: at };\n if (!(at > state.updatedAt)) return state;\n const d = decayFactor(at - state.updatedAt, intent.halfLife);\n if (d === 1) return { ...state, updatedAt: at };\n const contributions = mapRecord(state.contributions, (c) => ({\n alpha: c.alpha * d,\n beta: c.beta * d,\n }));\n return withContributions({ ...state, updatedAt: at }, intent, contributions);\n}\n\n/** Adds `weight` pseudo-counts for the intent (positive → α) or against it (negative → β). */\nexport function applySignal(\n state: IntentState,\n intent: IntentConfig,\n signal: string,\n weight: number,\n): IntentState {\n const prev = getOwn(state.contributions, signal) ?? { alpha: 0, beta: 0 };\n const next: SignalContribution =\n weight >= 0\n ? { alpha: prev.alpha + weight, beta: prev.beta }\n : { alpha: prev.alpha, beta: prev.beta - weight };\n return withContributions(state, intent, { ...state.contributions, [signal]: next });\n}\n\n/** Drops all evidence; α and β return to the prior. Learned data is untouched. */\nexport function resetToPrior(state: IntentState, intent: IntentConfig): IntentState {\n return withContributions(state, intent, {});\n}\n","import type {\n EngineConfig,\n EvaluateOptions,\n ExplainOptions,\n IntentConfig,\n LearningConfig,\n LiftType,\n RevealOptions,\n} from './types';\nimport { hasOwn, isRecord } from './util';\n\nexport const DEFAULT_THRESHOLD = 0.5;\nexport const DEFAULT_Z = 1.28;\nexport const DEFAULT_GAIN = 2;\nexport const DEFAULT_PRIOR_EPISODES = 10;\n/**\n * Largest accepted magnitude for weights, `priorStrength`, `learning.gain` and\n * `learning.priorEpisodes`: far beyond any real config, and small enough that the Beta and\n * learning arithmetic can never overflow to Infinity or NaN.\n */\nexport const MAX_MAGNITUDE = 1e6;\n/** Largest accepted `z`: 3.09 is already a one-sided 99.9% bound, and 128 is a misplaced 1.28. */\nexport const MAX_Z = 10;\n\n// Exported for tests/schema.test.ts, which pins schema/config.schema.json to these lists.\nexport const CONFIG_KEYS = ['intents', 'episodeTimeout', 'learning', 'reveal'] as const;\nexport const INTENT_KEYS = [\n 'prior',\n 'priorStrength',\n 'halfLife',\n 'signals',\n 'outcome',\n 'resetOnOutcome',\n 'saturate',\n 'episodePerOutcome',\n 'attribution',\n 'reveal',\n] as const;\nexport const REVEAL_KEYS = ['threshold', 'z', 'cooldown', 'outcomeCooldown', 'bound'] as const;\nexport const LEARNING_KEYS = ['halfLife', 'gain', 'priorEpisodes', 'lift'] as const;\nexport const LIFT_TYPES: readonly LiftType[] = [\n 'absolute-difference',\n 'relative-lift',\n 'risk-ratio',\n 'log-lift',\n 'odds-ratio',\n 'normalized-difference',\n 'association-rule',\n];\nconst EXPLAIN_KEYS = ['nonZero', 'limit'] as const;\n\nfunction typeError(path: string, message: string): never {\n throw new TypeError(`oracular: ${path} ${message}`);\n}\n\nfunction rangeError(path: string, message: string): never {\n throw new RangeError(`oracular: ${path} ${message}`);\n}\n\nfunction expectRecord(value: unknown, path: string): Record<string, unknown> {\n if (!isRecord(value)) typeError(path, 'must be a plain object');\n return value;\n}\n\nfunction expectKeys(\n record: Record<string, unknown>,\n allowed: readonly string[],\n path: string,\n): void {\n for (const key of Object.keys(record)) {\n if (!allowed.includes(key)) {\n typeError(\n `${path}.${key}`,\n `is not a recognised option (expected one of: ${allowed.join(', ')})`,\n );\n }\n }\n}\n\nfunction expectNumber(value: unknown, path: string): number {\n if (typeof value !== 'number' || !Number.isFinite(value))\n typeError(path, 'must be a finite number');\n return value;\n}\n\nfunction expectPositive(value: unknown, path: string): number {\n const n = expectNumber(value, path);\n if (n <= 0) rangeError(path, 'must be greater than 0');\n return n;\n}\n\n/** A positive number no larger than {@link MAX_MAGNITUDE}. */\nfunction expectBoundedPositive(value: unknown, path: string): number {\n const n = expectPositive(value, path);\n if (n > MAX_MAGNITUDE) rangeError(path, `must be at most ${MAX_MAGNITUDE}`);\n return n;\n}\n\nfunction expectNonNegative(value: unknown, path: string): number {\n const n = expectNumber(value, path);\n if (n < 0) rangeError(path, 'must be 0 or greater');\n return n;\n}\n\nfunction expectOpenUnit(value: unknown, path: string): number {\n const n = expectNumber(value, path);\n if (n <= 0 || n >= 1) rangeError(path, 'must be strictly between 0 and 1');\n return n;\n}\n\nfunction expectClosedUnit(value: unknown, path: string): number {\n const n = expectNumber(value, path);\n if (n < 0 || n > 1) rangeError(path, 'must be between 0 and 1');\n return n;\n}\n\nexport function expectName(value: unknown, path: string): string {\n if (typeof value !== 'string' || value.length === 0)\n typeError(path, 'must be a non-empty string');\n return value;\n}\n\n/** Keys of user-named records must be usable as own properties of a plain object. */\nfunction expectKeyName(name: string, path: string): string {\n if (name.length === 0) typeError(path, 'names must be non-empty strings');\n if (name === '__proto__') typeError(path, 'must not use the reserved name \"__proto__\"');\n return name;\n}\n\n/**\n * Validates reveal options and returns a copy with only the defined keys. `strict` adds the checks\n * that catch a config that cannot work (a threshold of 0 or 1, a `z` past {@link MAX_Z}); a\n * stored config is read without them, so a state saved before those checks existed still loads.\n */\nexport function normalizeRevealOptions(value: unknown, path: string, strict = true): RevealOptions {\n const record = expectRecord(value, path);\n expectKeys(record, REVEAL_KEYS, path);\n const out: RevealOptions = {};\n if (record.threshold !== undefined) {\n out.threshold = strict\n ? expectOpenUnit(record.threshold, `${path}.threshold`)\n : expectClosedUnit(record.threshold, `${path}.threshold`);\n }\n if (record.z !== undefined) {\n out.z = expectNonNegative(record.z, `${path}.z`);\n if (strict && out.z > MAX_Z) rangeError(`${path}.z`, `must be at most ${MAX_Z}`);\n }\n if (record.cooldown !== undefined) {\n out.cooldown = expectNonNegative(record.cooldown, `${path}.cooldown`);\n }\n if (record.outcomeCooldown !== undefined) {\n out.outcomeCooldown = expectNonNegative(record.outcomeCooldown, `${path}.outcomeCooldown`);\n }\n if (record.bound !== undefined) {\n if (record.bound !== 'normal' && record.bound !== 'exact') {\n typeError(`${path}.bound`, 'must be \"normal\" or \"exact\"');\n }\n out.bound = record.bound;\n }\n return out;\n}\n\nfunction normalizeLearning(value: unknown, path: string): LearningConfig {\n const record = expectRecord(value, path);\n expectKeys(record, LEARNING_KEYS, path);\n const out: LearningConfig = {};\n if (record.lift !== undefined) {\n if (!LIFT_TYPES.includes(record.lift as LiftType)) {\n typeError(`${path}.lift`, `must be one of: ${LIFT_TYPES.join(', ')}`);\n }\n out.lift = record.lift as LiftType;\n }\n if (record.halfLife !== undefined)\n out.halfLife = expectPositive(record.halfLife, `${path}.halfLife`);\n if (record.gain !== undefined) out.gain = expectBoundedPositive(record.gain, `${path}.gain`);\n if (record.priorEpisodes !== undefined) {\n out.priorEpisodes = expectBoundedPositive(record.priorEpisodes, `${path}.priorEpisodes`);\n }\n return out;\n}\n\n/**\n * Validates one intent's config and returns a copy with only the defined, recognised keys. See\n * {@link normalizeRevealOptions} for `strict`: here it also rejects an outcome that is one of the\n * intent's own signals while `resetOnOutcome` is on.\n */\nexport function normalizeIntentConfig(value: unknown, path: string, strict = true): IntentConfig {\n const record = expectRecord(value, path);\n expectKeys(record, INTENT_KEYS, path);\n const signalsRecord = expectRecord(record.signals, `${path}.signals`);\n const signals: Record<string, number> = {};\n for (const [name, weight] of Object.entries(signalsRecord)) {\n expectKeyName(name, `${path}.signals`);\n const w = expectNumber(weight, `${path}.signals[${JSON.stringify(name)}]`);\n if (w === 0) {\n rangeError(\n `${path}.signals[${JSON.stringify(name)}]`,\n 'must be non-zero (positive is evidence for the intent, negative is evidence against)',\n );\n }\n if (Math.abs(w) > MAX_MAGNITUDE) {\n rangeError(\n `${path}.signals[${JSON.stringify(name)}]`,\n `must be between -${MAX_MAGNITUDE} and ${MAX_MAGNITUDE}`,\n );\n }\n signals[name] = w;\n }\n const out: IntentConfig = {\n prior: expectOpenUnit(record.prior, `${path}.prior`),\n priorStrength: expectBoundedPositive(record.priorStrength, `${path}.priorStrength`),\n halfLife: expectPositive(record.halfLife, `${path}.halfLife`),\n signals,\n };\n if (record.outcome !== undefined) out.outcome = expectName(record.outcome, `${path}.outcome`);\n if (record.resetOnOutcome !== undefined) {\n if (typeof record.resetOnOutcome !== 'boolean') {\n typeError(`${path}.resetOnOutcome`, 'must be a boolean');\n }\n out.resetOnOutcome = record.resetOnOutcome;\n }\n if (record.saturate !== undefined) {\n if (typeof record.saturate !== 'boolean') typeError(`${path}.saturate`, 'must be a boolean');\n out.saturate = record.saturate;\n }\n if (record.episodePerOutcome !== undefined) {\n if (typeof record.episodePerOutcome !== 'boolean') {\n typeError(`${path}.episodePerOutcome`, 'must be a boolean');\n }\n out.episodePerOutcome = record.episodePerOutcome;\n }\n if (record.attribution !== undefined) {\n out.attribution = expectPositive(record.attribution, `${path}.attribution`);\n }\n if (record.reveal !== undefined) {\n out.reveal = normalizeRevealOptions(record.reveal, `${path}.reveal`, strict);\n }\n if (\n strict &&\n out.outcome !== undefined &&\n hasOwn(signals, out.outcome) &&\n out.resetOnOutcome !== false\n ) {\n typeError(\n `${path}.outcome`,\n 'is also one of its signals: the reset on outcome would wipe what it adds; set resetOnOutcome: false to keep it',\n );\n }\n return out;\n}\n\n/**\n * Validates a config and returns a fresh copy holding only the defined, recognised keys,\n * so that it survives a JSON round trip unchanged. `strict` (the default) adds the checks that\n * catch a config that cannot work; `deserialize` reads a stored config without them.\n */\nexport function normalizeConfig(value: unknown, strict = true): EngineConfig {\n const record = expectRecord(value, 'config');\n expectKeys(record, CONFIG_KEYS, 'config');\n const intentsRecord = expectRecord(record.intents, 'config.intents');\n const names = Object.keys(intentsRecord);\n if (names.length === 0) typeError('config.intents', 'must declare at least one intent');\n const intents: Record<string, IntentConfig> = {};\n for (const name of names) {\n expectKeyName(name, 'config.intents');\n intents[name] = normalizeIntentConfig(\n intentsRecord[name],\n `config.intents[${JSON.stringify(name)}]`,\n strict,\n );\n }\n const out: EngineConfig = { intents };\n if (record.episodeTimeout !== undefined) {\n out.episodeTimeout = expectPositive(record.episodeTimeout, 'config.episodeTimeout');\n }\n if (record.learning !== undefined)\n out.learning = normalizeLearning(record.learning, 'config.learning');\n if (record.reveal !== undefined) {\n out.reveal = normalizeRevealOptions(record.reveal, 'config.reveal', strict);\n }\n return out;\n}\n\n/** Validates explain filters and returns a copy with only the defined keys. */\nexport function normalizeExplainOptions(value: unknown, path: string): ExplainOptions {\n const record = expectRecord(value, path);\n expectKeys(record, EXPLAIN_KEYS, path);\n const out: ExplainOptions = {};\n if (record.nonZero !== undefined) {\n if (typeof record.nonZero !== 'boolean') typeError(`${path}.nonZero`, 'must be a boolean');\n out.nonZero = record.nonZero;\n }\n if (record.limit !== undefined) {\n const n = expectNumber(record.limit, `${path}.limit`);\n if (!Number.isInteger(n) || n < 0)\n rangeError(`${path}.limit`, 'must be a non-negative integer');\n out.limit = n;\n }\n return out;\n}\n\n/** Splits `evaluate` options into reveal overrides and explain filters, rejecting unknown keys. */\nexport function splitEvaluateOptions(\n value: EvaluateOptions | undefined,\n path: string,\n): { reveal: RevealOptions; explain: ExplainOptions } {\n if (value === undefined) return { reveal: {}, explain: {} };\n const record = expectRecord(value, path);\n expectKeys(record, [...REVEAL_KEYS, ...EXPLAIN_KEYS], path);\n const reveal: Record<string, unknown> = {};\n const explain: Record<string, unknown> = {};\n for (const [key, v] of Object.entries(record)) {\n if ((REVEAL_KEYS as readonly string[]).includes(key)) reveal[key] = v;\n else explain[key] = v;\n }\n return {\n reveal: normalizeRevealOptions(reveal, path, false),\n explain: normalizeExplainOptions(explain, path),\n };\n}\n\nexport interface ResolvedReveal {\n threshold: number;\n z: number;\n cooldown: number;\n /** The pause after the outcome event; the resolved `cooldown` unless set. */\n outcomeCooldown: number;\n bound: 'normal' | 'exact';\n}\n\nexport function resolveReveal(\n config: EngineConfig | undefined,\n intent: IntentConfig,\n opts: RevealOptions | undefined,\n normalized = false,\n): ResolvedReveal {\n // Per-call options are read without the strict checks: a probe at threshold 0 or 1 is a\n // legitimate question (evidenceToReveal asks it); a config that commits to one is not.\n const o =\n opts === undefined ? {} : normalized ? opts : normalizeRevealOptions(opts, 'options', false);\n const cooldown =\n o.cooldown ?? intent.reveal?.cooldown ?? config?.reveal?.cooldown ?? intent.halfLife;\n return {\n threshold:\n o.threshold ?? intent.reveal?.threshold ?? config?.reveal?.threshold ?? DEFAULT_THRESHOLD,\n z: o.z ?? intent.reveal?.z ?? config?.reveal?.z ?? DEFAULT_Z,\n cooldown,\n outcomeCooldown:\n o.outcomeCooldown ??\n intent.reveal?.outcomeCooldown ??\n config?.reveal?.outcomeCooldown ??\n cooldown,\n bound: o.bound ?? intent.reveal?.bound ?? config?.reveal?.bound ?? 'normal',\n };\n}\n\nexport interface ResolvedLearning {\n lift: LiftType;\n /** null means learned counts never decay. */\n halfLife: number | null;\n gain: number;\n priorEpisodes: number;\n}\n\nexport function resolveLearning(config: EngineConfig): ResolvedLearning {\n return {\n lift: config.learning?.lift ?? 'normalized-difference',\n halfLife: config.learning?.halfLife ?? null,\n gain: config.learning?.gain ?? DEFAULT_GAIN,\n priorEpisodes: config.learning?.priorEpisodes ?? DEFAULT_PRIOR_EPISODES,\n };\n}\n\nexport function expectTimestamp(value: unknown, path: string): number {\n return expectNumber(value, path);\n}\n\nexport function validateEvent(event: unknown): { name: string; at: number } {\n if (!isRecord(event)) typeError('event', 'must be an object like { name, at }');\n const name = expectName(event.name, 'event.name');\n const at = expectTimestamp(event.at, 'event.at');\n if (event.props !== undefined && !isRecord(event.props)) {\n typeError('event.props', 'must be a plain object when present');\n }\n return { name, at };\n}\n","import type { EpisodeIntentRecord, EpisodeState } from './types';\nimport { getOwn } from './util';\n\nexport function emptyEpisode(): EpisodeState {\n return { startedAt: null, lastEventAt: null, intents: {} };\n}\n\n/** If the episode has been idle longer than `timeout` by `at`, the moment it timed out; otherwise null. */\nexport function timedOutAt(\n episode: EpisodeState,\n timeout: number | undefined,\n at: number,\n): number | null {\n if (timeout === undefined || episode.lastEventAt === null) return null;\n return at - episode.lastEventAt > timeout ? episode.lastEventAt + timeout : null;\n}\n\n/** Opens the episode if needed and records activity at `at` (never behind the last activity: `observe` resolves the clock first). */\nexport function extendEpisode(episode: EpisodeState, at: number): EpisodeState {\n return { startedAt: episode.startedAt ?? at, lastEventAt: at, intents: episode.intents };\n}\n\nexport function episodeRecord(episode: EpisodeState, intent: string): EpisodeIntentRecord {\n return getOwn(episode.intents, intent) ?? { seen: [], counts: {}, resolved: false };\n}\n\n/** How many times `signal` has occurred for `intent` in this episode (since its last outcome). */\nexport function occurrences(episode: EpisodeState, intent: string, signal: string): number {\n return getOwn(episodeRecord(episode, intent).counts, signal) ?? 0;\n}\n\n/** Remembers one more occurrence of `signal`: added to `seen` the first time, counted every time. */\nexport function markSeen(episode: EpisodeState, intent: string, signal: string): EpisodeState {\n const record = episodeRecord(episode, intent);\n const seen = record.seen.includes(signal) ? record.seen : [...record.seen, signal];\n const counts = { ...record.counts, [signal]: (getOwn(record.counts, signal) ?? 0) + 1 };\n return { ...episode, intents: { ...episode.intents, [intent]: { ...record, seen, counts } } };\n}\n\nexport function markResolved(episode: EpisodeState, intent: string): EpisodeState {\n return {\n ...episode,\n intents: { ...episode.intents, [intent]: { seen: [], counts: {}, resolved: true } },\n };\n}\n","/**\n * Version of the serialized state shape, stored in every state as `state.version`. Bumped only\n * when `EngineState` changes shape, and every bump ships its migration: {@link deserialize}\n * upgrades states saved by earlier versions of this library on its own (version 1, written by\n * oracular 0.1.0 to 0.2.x, version 2, written by 0.3.0 to 0.5.x, and version 3, written by 0.6.0\n * to 0.11.x, become version 4), reads a state one version newer than its own as its own (a\n * version bump only adds fields, so a rollback by one release keeps the user's history), and\n * calls your `migrate` function only for a version it does not know.\n *\n * @example\n * ```ts\n * import { STATE_VERSION, deserialize } from 'oracular';\n *\n * const state = deserialize(saved, {\n * config,\n * // Only reached for versions this library cannot migrate itself, such as a state written by a\n * // newer oracular before a rollback.\n * migrate: (stored, version) => {\n * throw new Error(`cannot read oracular state version ${version} (this build reads ${STATE_VERSION})`);\n * },\n * });\n * ```\n */\nexport const STATE_VERSION = 4 as const;\n\n/**\n * Version of the recorder format: the `v` field of every record that {@link createRecord} and\n * {@link createEndRecord} produce. A new optional field does not change it; readers ignore fields\n * they do not know and skip records of a `kind` they do not know. Anything a reader written for\n * this version could misread bumps it.\n *\n * @example\n * ```ts\n * import { RECORD_VERSION } from 'oracular';\n *\n * const record = JSON.parse(line);\n * if (record.v !== RECORD_VERSION) throw new Error(`unsupported recorder format ${record.v}`);\n * ```\n */\nexport const RECORD_VERSION = 1 as const;\n","import { normalizeConfig } from './config';\nimport { emptyEpisode } from './episode';\nimport { initIntent } from './intent';\nimport type { EngineConfig, EngineState, IntentConfig, IntentState } from './types';\nimport { getOwn, isRecord } from './util';\nimport { STATE_VERSION } from './version';\n\n/**\n * Builds a fresh engine state from a config. Every intent starts at its prior and no episode is\n * open. The config is validated and a normalized copy is stored inside the state, so a persisted\n * state remembers the weights it was built with; pass your current config to {@link deserialize}\n * when loading. `config.learning.lift` selects the lift formula; omitting it preserves the\n * normalized difference used by existing configs and states.\n *\n * @param config - Intents with their priors and signals, plus engine-wide options. Validated\n * strictly: unknown keys, non-finite numbers and out-of-range values throw.\n * @returns A new, JSON-serializable state. `config` is not mutated.\n * @throws `TypeError` when a value has the wrong type, a key is not recognised, or an intent's\n * `outcome` is also one of its signals while `resetOnOutcome` is on (the reset would wipe what\n * the signal just added).\n * @throws `RangeError` when a number is out of range, for example a `prior` outside (0, 1), a\n * signal weight of 0, a reveal `threshold` of 0 or 1, a `z` above 10, or a weight,\n * `priorStrength`, `learning.gain` or `learning.priorEpisodes` beyond 1e6 (larger values could\n * overflow the arithmetic).\n * @example\n * ```ts\n * const state = createState({\n * intents: {\n * upgrade: {\n * prior: 0.05,\n * priorStrength: 10,\n * halfLife: 7 * 24 * 60 * 60 * 1000,\n * signals: { 'pricing.viewed': 3, 'limit.hit': 2, 'plan.downgraded': -4 },\n * outcome: 'upgrade.completed',\n * },\n * },\n * });\n * ```\n */\nexport function createState(config: EngineConfig): EngineState {\n const normalized = normalizeConfig(config);\n const intents: Record<string, IntentState> = {};\n for (const [name, intent] of Object.entries(normalized.intents)) {\n intents[name] = initIntent(intent);\n }\n return {\n version: STATE_VERSION,\n config: normalized,\n intents,\n episode: emptyEpisode(),\n clock: { at: null, behindAt: null },\n };\n}\n\nexport function requireState(state: unknown): EngineState {\n if (\n !isRecord(state) ||\n state.version !== STATE_VERSION ||\n !isRecord(state.config) ||\n !isRecord(state.intents) ||\n !isRecord(state.episode) ||\n !isRecord(state.clock)\n ) {\n throw new TypeError('oracular: state must be an EngineState from createState or deserialize');\n }\n return state as unknown as EngineState;\n}\n\nexport function requireIntentConfig(state: EngineState, name: string): IntentConfig {\n const intent = getOwn(state.config.intents, name);\n if (intent === undefined) {\n throw new RangeError(`oracular: unknown intent ${JSON.stringify(name)}`);\n }\n return intent;\n}\n\n/** The stored intent state, or a fresh prior if the intent was added to the config after the state was created. */\nexport function getIntentState(\n state: EngineState,\n name: string,\n intent: IntentConfig,\n): IntentState {\n return getOwn(state.intents, name) ?? initIntent(intent);\n}\n","import { settlePending } from './attribution';\nimport type { ResolvedLearning, ResolvedReveal } from './config';\nimport { decayIntent } from './intent';\nimport { signalWeights } from './learning';\nimport { betaMean, betaSd, clamp01, lowerBound } from './math';\nimport { getIntentState } from './state';\nimport type {\n EngineState,\n ExplainOptions,\n IntentConfig,\n IntentState,\n Prediction,\n SignalExplanation,\n} from './types';\nimport { getOwn } from './util';\n\n/**\n * The intent brought up to `at` without storing anything: evidence decayed, waiting episodes whose\n * window has passed settled as misses, learned counts decayed.\n */\nexport function assessIntent(\n state: EngineState,\n name: string,\n intent: IntentConfig,\n learning: ResolvedLearning,\n at: number,\n): IntentState {\n const is = decayIntent(getIntentState(state, name, intent), intent, at);\n return settlePending(is, intent, learning, at);\n}\n\n/**\n * The end of a cooldown that started at `since`, if it is still running at `at`. A start ahead of\n * `at` (stamped by a clock that was ahead) counts as having happened now, so the cooldown ends\n * one `cooldown` from `at` rather than from a date that may never come; the next event pins the\n * stored time to `at` (see `observe`).\n */\nfunction cooldownEnd(since: number | null, cooldown: number, at: number): number | null {\n if (since === null) return null;\n const end = Math.min(since, at) + cooldown;\n return at < end ? end : null;\n}\n\nexport function buildPrediction(\n is: IntentState,\n name: string,\n reveal: ResolvedReveal,\n at: number,\n): Prediction {\n const p = betaMean(is.alpha, is.beta);\n const sd = betaSd(is.alpha, is.beta);\n const revealEnd = cooldownEnd(is.lastRevealedAt, reveal.cooldown, at);\n const outcomeEnd = cooldownEnd(is.lastOutcomeAt, reveal.outcomeCooldown, at);\n const suppressedUntil =\n revealEnd === null\n ? outcomeEnd\n : outcomeEnd === null\n ? revealEnd\n : Math.max(revealEnd, outcomeEnd);\n return {\n intent: name,\n p,\n sd,\n lower: lowerBound(is.alpha, is.beta, reveal.z, reveal.bound),\n confidence: clamp01(1 - 2 * sd),\n evidence: is.alpha + is.beta,\n revealed: revealEnd !== null,\n revealedAt: is.lastRevealedAt,\n suppressedUntil,\n };\n}\n\nexport function decideReveal(prediction: Prediction, reveal: ResolvedReveal): boolean {\n return (\n prediction.suppressedUntil === null &&\n prediction.p >= reveal.threshold &&\n prediction.lower >= reveal.threshold\n );\n}\n\nexport function buildExplanation(\n is: IntentState,\n intent: IntentConfig,\n learning: ResolvedLearning,\n opts: ExplainOptions,\n): SignalExplanation[] {\n const p = betaMean(is.alpha, is.beta);\n const out: SignalExplanation[] = [];\n for (const signal of Object.keys(intent.signals)) {\n const c = getOwn(is.contributions, signal) ?? { alpha: 0, beta: 0 };\n const w = signalWeights(is, intent, learning, signal);\n const without = betaMean(is.alpha - c.alpha, is.beta - c.beta);\n out.push({\n signal,\n contribution: c.alpha - c.beta,\n impact: p - without,\n initialWeight: w.initial,\n learnedWeight: w.learned,\n effectiveWeight: w.effective,\n hits: w.hits,\n misses: w.misses,\n });\n }\n out.sort((a, b) => Math.abs(b.impact) - Math.abs(a.impact) || compare(a.signal, b.signal));\n const filtered = opts.nonZero ? out.filter((row) => row.contribution !== 0) : out;\n return opts.limit === undefined ? filtered : filtered.slice(0, opts.limit);\n}\n\nfunction compare(a: string, b: string): number {\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n}\n","import { assessIntent, buildExplanation, buildPrediction, decideReveal } from './assess';\nimport {\n expectName,\n expectTimestamp,\n resolveLearning,\n resolveReveal,\n splitEvaluateOptions,\n} from './config';\nimport { requireIntentConfig, requireState } from './state';\nimport type { EngineState, EvaluateOptions, Evaluation, Snapshot } from './types';\n\n/**\n * {@link predict}, {@link shouldReveal} and {@link explain} in one call, from a single decay\n * pass over the intent. The three results are identical to what the separate functions return\n * for the same inputs; this is the one to call on every event when you need all of them.\n * Read-only.\n *\n * @param state - The current state. Not mutated.\n * @param intent - Name of an intent declared in the config.\n * @param at - The time to evaluate at.\n * @param opts - Reveal overrides (`threshold`, `z`, `cooldown`, `bound`) and explain filters\n * (`nonZero`, `limit`) in one object.\n * @returns `prediction` (as `predict`), `reveal` (as `shouldReveal`) and `explanation` (as\n * `explain` with the same filters).\n * @throws `RangeError` when `intent` is not declared in the config.\n * @throws `TypeError` when `state` is not an engine state, `at` is not finite, or `opts` is\n * malformed.\n * @example\n * ```ts\n * const { prediction, reveal, explanation } = evaluate(state, 'upgrade', Date.now(), { limit: 3 });\n * if (reveal) showOffer(explanation[0]?.signal);\n * ```\n */\nexport function evaluate(\n state: EngineState,\n intent: string,\n at: number,\n opts?: EvaluateOptions,\n): Evaluation {\n const s = requireState(state);\n const name = expectName(intent, 'intent');\n const t = expectTimestamp(at, 'at');\n const config = requireIntentConfig(s, name);\n const split = splitEvaluateOptions(opts, 'options');\n const reveal = resolveReveal(s.config, config, split.reveal, true);\n const learning = resolveLearning(s.config);\n const is = assessIntent(s, name, config, learning, t);\n const prediction = buildPrediction(is, name, reveal, t);\n return {\n prediction,\n reveal: decideReveal(prediction, reveal),\n explanation: buildExplanation(is, config, learning, split.explain),\n };\n}\n\n/**\n * {@link evaluate} for every declared intent at once, in config order: the whole engine's view at\n * one moment, as plain data. This is what to log, assert on, or hand to `renderInspector` from\n * `oracular/inspect` for a live panel. Read-only.\n *\n * @param state - The current state. Not mutated.\n * @param at - The time to evaluate at.\n * @param opts - Reveal overrides and explain filters, applied to every intent.\n * @returns `at` and one {@link IntentSnapshot} per intent.\n * @throws `TypeError` when `state` is not an engine state, `at` is not finite, or `opts` is\n * malformed.\n * @example\n * ```ts\n * for (const { intent, prediction, reveal } of inspect(state, Date.now()).intents) {\n * console.log(intent, prediction.p.toFixed(3), reveal ? 'reveal' : '');\n * }\n * ```\n */\nexport function inspect(state: EngineState, at: number, opts?: EvaluateOptions): Snapshot {\n const s = requireState(state);\n const intents = Object.keys(s.config.intents).map((intent) => ({\n intent,\n ...evaluate(s, intent, at, opts),\n }));\n return { at, intents };\n}\n","import { normalizeIntentConfig, resolveReveal } from './config';\nimport { priorCounts } from './intent';\nimport { betaMean, lowerBound } from './math';\nimport type { IntentConfig, RevealOptions } from './types';\n\n/**\n * How much positive evidence an intent needs before {@link shouldReveal} first becomes true:\n * the smallest pseudo-count `w` such that Beta(α₀ + w, β₀) clears both `p ≥ threshold` and\n * `lower ≥ threshold`, with `lower` as `bound` defines it (p − z·sd, or the exact Beta quantile).\n * Divide by a signal's weight and round up for the number of full-weight\n * occurrences that open the gate: distinct signals, or one occurrence per episode. Repeats within\n * one episode add less (n of them add `w × log2(1 + n)`, see {@link IntentConfig.saturate}).\n * Solved numerically to 1e-9.\n *\n * Cooldowns and decay are not part of the answer: this is the evidence needed at one instant.\n *\n * @param intent - One intent's config, validated as `createState` would.\n * @param opts - `threshold`, `z` and `bound` overrides, resolved as call → intent → defaults\n * (there is no engine config here). `cooldown` is accepted and ignored.\n * @returns The pseudo-count sum; 0 when the prior alone already clears the gate; `Infinity`\n * when no finite amount of evidence can (threshold 1).\n * @throws `TypeError` or `RangeError` when `intent` or `opts` is invalid.\n * @example\n * ```ts\n * const needed = evidenceToReveal(config.intents.upgrade); // ≈ 15.1 for the quickstart config\n * Math.ceil(needed / 3); // 6 full-weight signals of weight 3\n * ```\n */\nexport function evidenceToReveal(intent: IntentConfig, opts?: RevealOptions): number {\n const config = normalizeIntentConfig(intent, 'intent');\n const { threshold, z, bound } = resolveReveal(undefined, config, opts);\n const { alpha0, beta0 } = priorCounts(config);\n\n const open = (w: number): boolean =>\n betaMean(alpha0 + w, beta0) >= threshold &&\n lowerBound(alpha0 + w, beta0, z, bound) >= threshold;\n\n if (threshold >= 1) return Number.POSITIVE_INFINITY;\n if (open(0)) return 0;\n\n // Bracket the first crossing geometrically, then bisect. Both p and the lower bound keep\n // rising with evidence past the first crossing, so the first opening is the answer.\n let lo = 0;\n let hi = 1;\n while (!open(hi)) {\n lo = hi;\n hi *= 2;\n if (hi > 1e15) return Number.POSITIVE_INFINITY;\n }\n for (let i = 0; i < 200 && hi - lo > 1e-9; i++) {\n const mid = (lo + hi) / 2;\n if (open(mid)) hi = mid;\n else lo = mid;\n }\n return hi;\n}\n","import { assessIntent, buildExplanation } from './assess';\nimport { expectName, expectTimestamp, normalizeExplainOptions, resolveLearning } from './config';\nimport { requireIntentConfig, requireState } from './state';\nimport type { EngineState, ExplainOptions, SignalExplanation } from './types';\n\n/**\n * Why the intent's p is what it is at time `at`: one entry per declared signal, the ones that\n * matter most first. `contribution` is the signed pseudo-count the signal currently holds after\n * decay, `impact` is how much p would change if that contribution were removed, and the three\n * weights show what the developer said, what this user's history says, and what the next\n * occurrence will actually add. Read-only.\n *\n * @param state - The current state. Not mutated.\n * @param intent - Name of an intent declared in the config.\n * @param at - The time to evaluate at; contributions and learned counts are decayed to it.\n * @param opts - Optional filters: `nonZero` keeps only signals that currently hold evidence,\n * `limit` caps the number of rows. Default: every declared signal.\n * @returns One {@link SignalExplanation} per declared signal, sorted by |impact| descending,\n * then by name, then filtered by `opts`. Empty for an intent that declares no signals.\n * @throws `RangeError` when `intent` is not declared in the config.\n * @throws `TypeError` when `state` is not an engine state, `at` is not finite, or `opts` is\n * malformed.\n * @example\n * ```ts\n * for (const row of explain(state, 'upgrade', Date.now(), { nonZero: true })) {\n * console.log(row.signal, row.impact.toFixed(2), row.effectiveWeight.toFixed(2));\n * }\n * ```\n */\nexport function explain(\n state: EngineState,\n intent: string,\n at: number,\n opts?: ExplainOptions,\n): SignalExplanation[] {\n const s = requireState(state);\n const name = expectName(intent, 'intent');\n const t = expectTimestamp(at, 'at');\n const config = requireIntentConfig(s, name);\n const filters = opts === undefined ? {} : normalizeExplainOptions(opts, 'options');\n const learning = resolveLearning(s.config);\n return buildExplanation(assessIntent(s, name, config, learning, t), config, learning, filters);\n}\n","import { creditPending, deferEpisode, settlePending } from './attribution';\nimport { expectTimestamp, resolveLearning, validateEvent } from './config';\nimport {\n emptyEpisode,\n episodeRecord,\n extendEpisode,\n markResolved,\n markSeen,\n occurrences,\n timedOutAt,\n} from './episode';\nimport { applySignal, decayIntent, resetToPrior } from './intent';\nimport { recordEpisode, signalWeights } from './learning';\nimport { repeatFactor } from './math';\nimport { getIntentState, requireState } from './state';\nimport type { EngineState, IntentEvent, IntentState } from './types';\nimport { hasOwn } from './util';\n\n/**\n * Feeds one event to the engine.\n *\n * For every intent the event is a signal of: decay its evidence to `event.at`, then add the\n * signal's effective weight to α (positive) or β (negative) and remember the signal for this\n * episode. Repeats within an episode saturate: the n-th occurrence of a signal adds\n * `w × log2(1 + 1/n)`, counted since the episode started or the intent's outcome last arrived.\n * That is the default when `config.episodeTimeout` is set, and `IntentConfig.saturate` overrides\n * it either way; otherwise every occurrence adds all of `w`. For every intent the event is the\n * outcome of: give the signals remembered since the episode started or the outcome last arrived a\n * hit and count the episode toward the base rate (a repeated outcome with nothing seen since\n * counts nothing, unless `IntentConfig.episodePerOutcome` makes every outcome an episode of its\n * own for the intent), credit\n * the closed episodes still waiting under `IntentConfig.attribution` by `2^(−age / halfLife)`\n * each, record `lastOutcomeAt`, and (by default) reset the evidence to the prior. Any event opens\n * or extends the current episode; an idle gap longer than `config.episodeTimeout` closes the\n * previous episode first.\n *\n * The clock. An event at or after the latest event time moves the engine's clock there, and\n * anything stamped ahead of it (a reveal stamped by a clock that was ahead) is pinned to it. An\n * event stamped *behind* the clock counts now, at the clock's time, and its stamp is held: if the\n * next event is also behind the clock, the clock was corrected, and every anchor ahead of the\n * held stamp moves back to it so decay and cooldowns resume from the corrected time; if the next\n * event is at or after the clock, the held stamp was one glitch and nothing moved. So one event\n * stamped years ahead cannot hold an intent past the two events that follow it, and one stamped\n * years behind cannot wipe the evidence or close the session.\n *\n * @param state - The current state. Not mutated.\n * @param event - `name` is matched against every intent's signals and outcome; `at` is the\n * event's timestamp, in the same unit as your durations; `props` are accepted and ignored,\n * and never stored.\n * @returns The next state. Intents the event does not touch keep their stored numbers; their\n * decay is applied when they are next read or updated.\n * @throws `TypeError` when `state` is not an engine state, or the event has no non-empty\n * `name`, no finite `at`, or a `props` that is not a plain object.\n * @example\n * ```ts\n * let state = createState(config);\n * state = observe(state, { name: 'pricing.viewed', at: Date.now() });\n * state = observe(state, { name: 'upgrade.completed', at: Date.now() }); // outcome\n * ```\n */\nexport function observe(state: EngineState, event: IntentEvent): EngineState {\n const { name, at: stamp } = validateEvent(event);\n const synced = syncClock(requireState(state), stamp);\n let s = synced.state;\n const at = synced.at;\n\n const closeAt = timedOutAt(s.episode, s.config.episodeTimeout, at);\n if (closeAt !== null) s = closeEpisode(s, closeAt);\n\n const learning = resolveLearning(s.config);\n const intents: Record<string, IntentState> = { ...s.intents };\n let episode = extendEpisode(s.episode, at);\n\n for (const [intentName, intent] of Object.entries(s.config.intents)) {\n const isSignal = hasOwn(intent.signals, name);\n const isOutcome = intent.outcome === name;\n if (!isSignal && !isOutcome) continue;\n\n let is = getIntentState(s, intentName, intent);\n is = decayIntent(is, intent, at);\n is = settlePending(is, intent, learning, at);\n\n if (isSignal) {\n const { effective } = signalWeights(is, intent, learning, name);\n const n = occurrences(episode, intentName, name) + 1;\n const saturate = intent.saturate ?? s.config.episodeTimeout !== undefined;\n const factor = saturate ? repeatFactor(n) : 1;\n is = applySignal(is, intent, name, effective * factor);\n // An event that is also the intent's outcome must not learn from itself.\n if (!isOutcome) episode = markSeen(episode, intentName, name);\n }\n\n if (isOutcome) {\n // The signals seen since the episode started, or since the intent's outcome last arrived,\n // get the hit. A repeated outcome with no signal seen since is a duplicate, not another\n // episode, so it does not count toward the base rate; with episodePerOutcome every outcome\n // is an episode of its own, and it counts.\n const record = episodeRecord(episode, intentName);\n if (!record.resolved || record.seen.length > 0 || intent.episodePerOutcome === true) {\n is = recordEpisode(is, record.seen, 1);\n }\n is = creditPending(is, intent, at);\n episode = markResolved(episode, intentName);\n is = { ...is, lastOutcomeAt: at };\n if (intent.resetOnOutcome ?? true) is = resetToPrior(is, intent);\n }\n\n intents[intentName] = is;\n }\n\n return { ...s, intents, episode };\n}\n\n/**\n * Resolves an event's stamp against the clock and says when the event counts. At or after the\n * clock (or the first event): the clock moves to the stamp and every anchor ahead of it is pinned\n * to it. Behind the clock with nothing held: the event counts now, at the clock's time, and the\n * stamp is held. Behind the clock with a stamp already held: two in a row confirm a correction,\n * so everything ahead of the held stamp moves back to it and the event is resolved again from\n * there. At or after the clock with a stamp held: the held one was a glitch, forgotten.\n */\nfunction syncClock(state: EngineState, stamp: number): { state: EngineState; at: number } {\n const { at, behindAt } = state.clock;\n if (at === null || stamp >= at) return { state: pinTo(state, stamp), at: stamp };\n if (behindAt !== null) return syncClock(pinTo(state, behindAt), stamp);\n return { state: { ...state, clock: { at, behindAt: stamp } }, at };\n}\n\nconst INTENT_ANCHORS = ['updatedAt', 'learnedAt', 'lastRevealedAt', 'lastOutcomeAt'] as const;\nconst EPISODE_ANCHORS = ['startedAt', 'lastEventAt'] as const;\n\n/** Moves every anchor ahead of `t` back to `t` and sets the clock there; intents nothing moves in keep their objects. */\nfunction pinTo(state: EngineState, t: number): EngineState {\n let intents = state.intents;\n for (const [name, is] of Object.entries(state.intents)) {\n let pinned = pinKeys(is, INTENT_ANCHORS, t);\n if (is.pending.some((p) => p.endedAt > t)) {\n pinned = {\n ...pinned,\n pending: is.pending.map((p) => (p.endedAt > t ? { ...p, endedAt: t } : p)),\n };\n }\n if (pinned !== is) intents = { ...intents, [name]: pinned };\n }\n const episode = pinKeys(state.episode, EPISODE_ANCHORS, t);\n return { ...state, intents, episode, clock: { at: t, behindAt: null } };\n}\n\n/** `obj` with every listed key that holds a number above `t` set to `t`; the same object when none does. */\nfunction pinKeys<T extends object>(obj: T, keys: readonly (keyof T)[], t: number): T {\n let out = obj;\n for (const key of keys) {\n const value: unknown = obj[key];\n if (typeof value === 'number' && value > t) out = { ...out, [key]: t };\n }\n return out;\n}\n\n/**\n * Ends the current episode at `at`. Every intent whose outcome did not arrive gives a miss to\n * each signal seen this episode and counts the episode toward its base rate, or, with\n * `IntentConfig.attribution` set, holds the episode for the outcome instead. Call it when a\n * session ends: tab closed, app backgrounded, user signed out.\n *\n * @param state - The current state. Not mutated.\n * @param at - When the episode ended. If it had already timed out under\n * `config.episodeTimeout`, it is closed at the moment it timed out instead.\n * @returns The next state with no open episode, or the very same state object when no episode\n * was open.\n * @throws `TypeError` when `state` is not an engine state or `at` is not a finite number.\n * @example\n * ```ts\n * window.addEventListener('pagehide', () => {\n * state = endEpisode(state, Date.now());\n * localStorage.setItem('oracular', serialize(state));\n * });\n * ```\n */\nexport function endEpisode(state: EngineState, at: number): EngineState {\n const s = requireState(state);\n const t = expectTimestamp(at, 'at');\n if (s.episode.startedAt === null) return s;\n const closeAt = timedOutAt(s.episode, s.config.episodeTimeout, t);\n return closeEpisode(s, closeAt ?? t);\n}\n\nfunction closeEpisode(state: EngineState, at: number): EngineState {\n const learning = resolveLearning(state.config);\n const intents: Record<string, IntentState> = { ...state.intents };\n for (const [intentName, intent] of Object.entries(state.config.intents)) {\n const record = episodeRecord(state.episode, intentName);\n // Resolved: the outcome arrived. Signals seen after it stay neutral at the close; they are\n // judged only if another outcome follows them in the same episode. With episodePerOutcome\n // they are a new attempt, judged at the close like a first one; nothing seen is nothing.\n if (record.resolved && (intent.episodePerOutcome !== true || record.seen.length === 0))\n continue;\n let is = getIntentState(state, intentName, intent);\n is = settlePending(is, intent, learning, at);\n is =\n intent.attribution === undefined\n ? recordEpisode(is, record.seen, 0)\n : deferEpisode(is, record.seen, at);\n intents[intentName] = is;\n }\n return { ...state, intents, episode: emptyEpisode() };\n}\n\n/**\n * Whether an episode closed between two states: `prev` had an open episode and `next` either\n * has none or has a different one. Useful after `observe` or `endEpisode` to react to a\n * session ending, for example to persist, or to read the misses it produced as\n * `next.intents[x].episodes.misses - prev.intents[x].episodes.misses` (0 for an intent with\n * `attribution` set, whose verdict waits).\n *\n * @param prev - The state before the operation.\n * @param next - The state after it.\n * @returns True when `prev.episode.startedAt` is not null and differs from\n * `next.episode.startedAt`.\n * @throws `TypeError` when either argument is not an engine state.\n * @example\n * ```ts\n * const next = observe(state, event);\n * if (episodeClosed(state, next)) persist(next);\n * ```\n */\nexport function episodeClosed(prev: EngineState, next: EngineState): boolean {\n const a = requireState(prev);\n const b = requireState(next);\n return a.episode.startedAt !== null && b.episode.startedAt !== a.episode.startedAt;\n}\n","import { buildPrediction, decideReveal } from './assess';\nimport { expectName, expectTimestamp, resolveReveal } from './config';\nimport { decayIntent } from './intent';\nimport { getIntentState, requireIntentConfig, requireState } from './state';\nimport type { EngineState, Prediction, RevealOptions } from './types';\n\n/**\n * The intent's current estimate at time `at`: the Beta mean p, its standard deviation, the\n * lower confidence bound that {@link shouldReveal} tests, and the cooldown status. Read-only:\n * the stored state is decayed to `at` for the reading but not changed.\n *\n * @param state - The current state. Not mutated.\n * @param intent - Name of an intent declared in the config.\n * @param at - The time to evaluate at, in the same unit as your durations.\n * @param opts - Overrides for `threshold`, `z`, `cooldown`, `outcomeCooldown` and `bound`,\n * resolved as call → intent → engine → defaults. `z` and `bound` set `lower`; `cooldown` sets\n * `revealed` and, with `outcomeCooldown` (default: `cooldown`), `suppressedUntil`;\n * `threshold` only matters to {@link shouldReveal}.\n * @returns The prediction. `p`, `sd`, `lower` and `confidence` are in [0, 1]; `evidence` is\n * α + β.\n * @throws `RangeError` when `intent` is not declared in the config.\n * @throws `TypeError` when `state` is not an engine state, `at` is not finite, or `opts` is\n * malformed.\n * @example\n * ```ts\n * const { p, lower, suppressedUntil } = predict(state, 'upgrade', Date.now());\n * if (suppressedUntil !== null) scheduleNextCheck(suppressedUntil);\n * ```\n */\nexport function predict(\n state: EngineState,\n intent: string,\n at: number,\n opts?: RevealOptions,\n): Prediction {\n const s = requireState(state);\n const name = expectName(intent, 'intent');\n const t = expectTimestamp(at, 'at');\n const config = requireIntentConfig(s, name);\n const reveal = resolveReveal(s.config, config, opts);\n const is = decayIntent(getIntentState(s, name, config), config, t);\n return buildPrediction(is, name, reveal, t);\n}\n\n/**\n * Whether to act on the intent now. True when p ≥ `threshold`, the lower confidence bound\n * (p − z·sd, or the exact Beta quantile with `bound: 'exact'`) also clears `threshold`, and no\n * cooldown is running: neither the one started by\n * {@link markRevealed} nor the one started by the intent's outcome event.\n *\n * @param state - The current state. Not mutated.\n * @param intent - Name of an intent declared in the config.\n * @param at - The time to evaluate at.\n * @param opts - Overrides for `threshold` (default 0.5), `z` (default 1.28, a one-sided 90%\n * bound), `cooldown` (default: the intent's `halfLife`) and `outcomeCooldown` (default:\n * `cooldown`; 0 lets the outcome pause nothing).\n * @returns True when the app should show, offer or reveal whatever this intent gates.\n * @throws `RangeError` when `intent` is not declared in the config.\n * @throws `TypeError` when `state` is not an engine state, `at` is not finite, or `opts` is\n * malformed.\n * @example\n * ```ts\n * if (shouldReveal(state, 'upgrade', Date.now())) {\n * showUpgradeOffer();\n * state = markRevealed(state, 'upgrade', Date.now());\n * }\n * ```\n */\nexport function shouldReveal(\n state: EngineState,\n intent: string,\n at: number,\n opts?: RevealOptions,\n): boolean {\n const s = requireState(state);\n const name = expectName(intent, 'intent');\n const config = requireIntentConfig(s, name);\n const reveal = resolveReveal(s.config, config, opts);\n return decideReveal(predict(s, name, at, opts), reveal);\n}\n\n/**\n * Records that the app acted on the intent at `at`. Starts the reveal cooldown, during which\n * `predict().revealed` is true and {@link shouldReveal} is false, and increments\n * `revealCount`. Evidence and learned data are untouched.\n *\n * @param state - The current state. Not mutated.\n * @param intent - Name of an intent declared in the config.\n * @param at - When the reveal happened.\n * @returns The next state.\n * @throws `RangeError` when `intent` is not declared in the config.\n * @throws `TypeError` when `state` is not an engine state or `at` is not finite.\n * @example\n * ```ts\n * state = markRevealed(state, 'upgrade', Date.now());\n * predict(state, 'upgrade', Date.now()).revealed; // true until the cooldown ends\n * ```\n */\nexport function markRevealed(state: EngineState, intent: string, at: number): EngineState {\n const s = requireState(state);\n const name = expectName(intent, 'intent');\n const t = expectTimestamp(at, 'at');\n const config = requireIntentConfig(s, name);\n const is = getIntentState(s, name, config);\n return {\n ...s,\n intents: {\n ...s.intents,\n [name]: { ...is, lastRevealedAt: t, revealCount: is.revealCount + 1 },\n },\n };\n}\n","import { assessIntent, buildExplanation, buildPrediction, decideReveal } from './assess';\nimport {\n expectName,\n expectTimestamp,\n resolveLearning,\n resolveReveal,\n validateEvent,\n} from './config';\nimport { requireState } from './state';\nimport type {\n EndRecord,\n EngineState,\n EventRecord,\n IntentEvent,\n RecordedDecision,\n RecordMode,\n RecordOptions,\n} from './types';\nimport { isRecord } from './util';\nimport { RECORD_VERSION } from './version';\n\nconst RECORD_KEYS = ['installId', 'mode', 'top'];\nconst DEFAULT_TOP = 3;\n\nfunction normalizeRecordOptions(value: unknown): Required<RecordOptions> {\n if (!isRecord(value)) {\n throw new TypeError('oracular: options must be an object like { installId, mode }');\n }\n for (const key of Object.keys(value)) {\n if (!RECORD_KEYS.includes(key)) {\n throw new TypeError(\n `oracular: options.${key} is not a recognised option (expected one of: ${RECORD_KEYS.join(', ')})`,\n );\n }\n }\n const installId = expectName(value.installId, 'options.installId');\n const mode = value.mode;\n if (mode !== 'shadow' && mode !== 'live') {\n throw new TypeError('oracular: options.mode must be \"shadow\" or \"live\"');\n }\n let top = DEFAULT_TOP;\n if (value.top !== undefined) {\n if (typeof value.top !== 'number' || !Number.isFinite(value.top)) {\n throw new TypeError('oracular: options.top must be a finite number');\n }\n if (!Number.isInteger(value.top) || value.top < 0) {\n throw new RangeError('oracular: options.top must be a non-negative integer');\n }\n top = value.top;\n }\n return { installId, mode: mode as RecordMode, top };\n}\n\n/**\n * A recorder record for an event: the event itself and, for every intent, what the engine decides\n * right after it. Call it with the state `observe` returned for that event, then append\n * `JSON.stringify(record)` as one line of the log (NDJSON). The record holds the event's `name` and\n * `at`, never its `props`.\n *\n * Each decision is what {@link evaluate} reports at `event.at` with the state's own reveal\n * options: `p`, `lower`, `shouldReveal`, `suppressedUntil`, the signals with the largest impact,\n * and the effective weight of every signal. Pure: the install id comes from the app, never from\n * here. See the Shadow mode guide for the whole workflow.\n *\n * @param state - The state after `observe(state, event)`. Not mutated.\n * @param event - The event just observed. Only `name` and `at` are recorded.\n * @param opts - `installId` (generated and stored by the app), `mode` (`'shadow'` while\n * reveals are computed but not shown, `'live'` once they are), and `top` (default 3).\n * @returns A plain, JSON-serializable {@link EventRecord}.\n * @throws `TypeError` when `state` is not an engine state, the event is malformed, `opts` is\n * not an object, has an unknown key, an empty `installId` or a `mode` other than\n * `'shadow'` or `'live'`.\n * @throws `RangeError` when `opts.top` is negative or fractional.\n * @example\n * ```ts\n * const recording = { installId: localStorage.getItem('oracular.install')!, mode: 'shadow' } as const;\n *\n * const event = { name: 'pricing.viewed', at: Date.now() };\n * state = observe(state, event);\n * appendLine(JSON.stringify(createRecord(state, event, recording)));\n * ```\n */\nexport function createRecord(\n state: EngineState,\n event: IntentEvent,\n opts: RecordOptions,\n): EventRecord {\n const s = requireState(state);\n const { name, at } = validateEvent(event);\n const { installId, mode, top } = normalizeRecordOptions(opts);\n const learning = resolveLearning(s.config);\n const decisions: Record<string, RecordedDecision> = {};\n for (const [intentName, intent] of Object.entries(s.config.intents)) {\n const reveal = resolveReveal(s.config, intent, undefined);\n const is = assessIntent(s, intentName, intent, learning, at);\n const prediction = buildPrediction(is, intentName, reveal, at);\n const rows = buildExplanation(is, intent, learning, {});\n const weights: Record<string, number> = {};\n for (const signal of Object.keys(intent.signals)) {\n weights[signal] = (\n rows.find((row) => row.signal === signal) as { effectiveWeight: number }\n ).effectiveWeight;\n }\n decisions[intentName] = {\n p: prediction.p,\n lower: prediction.lower,\n shouldReveal: decideReveal(prediction, reveal),\n suppressedUntil: prediction.suppressedUntil,\n top: rows\n .filter((row) => row.contribution !== 0)\n .slice(0, top)\n .map((row) => ({ signal: row.signal, impact: row.impact })),\n weights,\n };\n }\n return { v: RECORD_VERSION, kind: 'event', installId, mode, event: { name, at }, decisions };\n}\n\n/**\n * A recorder record for the end of an episode. Write one whenever the app calls\n * {@link endEpisode}, with the same `at`, so that replay can end the episode at the same moment\n * and reproduce the misses it records. Episodes that close through `episodeTimeout` need none:\n * replay applies the timeout itself.\n *\n * @param at - The time passed to `endEpisode`.\n * @param opts - The same options as for {@link createRecord}; `top` is accepted and ignored.\n * @returns A plain, JSON-serializable {@link EndRecord}.\n * @throws `TypeError` when `at` is not a finite number or `opts` is malformed.\n * @throws `RangeError` when `opts.top` is negative or fractional.\n * @example\n * ```ts\n * const at = Date.now();\n * state = endEpisode(state, at);\n * appendLine(JSON.stringify(createEndRecord(at, recording)));\n * ```\n */\nexport function createEndRecord(at: number, opts: RecordOptions): EndRecord {\n const t = expectTimestamp(at, 'at');\n const { installId, mode } = normalizeRecordOptions(opts);\n return { v: RECORD_VERSION, kind: 'end', installId, mode, at: t };\n}\n","import { hasOwn, isRecord } from './util';\n\ntype Stored = Record<string, unknown>;\n\n/**\n * Migrations this library applies itself, keyed by the version they upgrade from. Each turns the\n * parsed JSON of one version into the shape of the next. Input that is malformed in ways a\n * migration does not need to look at is passed through untouched, so that parsing afterwards\n * rejects it with the same precise error it would give any other malformed state.\n */\nconst MIGRATIONS: Record<number, (stored: Stored) => Stored> = {\n 1: fromV1,\n 2: fromV2,\n 3: fromV3,\n};\n\n/** Whether `version` is one this library can bring up to date on its own. */\nexport function canMigrate(version: number): boolean {\n return hasOwn(MIGRATIONS, String(version));\n}\n\n/** Applies the built-in migrations, one version at a time, until none applies. */\nexport function migrateStored(stored: Stored): Stored {\n let current = stored;\n while (typeof current.version === 'number' && canMigrate(current.version)) {\n current = (MIGRATIONS[current.version] as (stored: Stored) => Stored)(current);\n }\n return current;\n}\n\n/**\n * Version 1 (oracular 0.1.0 to 0.2.x) → 2. Version 2 counts how often each signal occurred in the\n * open episode, so that repeats can saturate. A version 1 state only knows which signals were\n * seen, not how often, so each seen signal counts once: the lower bound. Nothing else changes, so\n * α, β and every learned count, and therefore every estimate, are exactly what they were.\n */\nfunction fromV1(stored: Stored): Stored {\n const episode = stored.episode;\n if (!isRecord(episode) || !isRecord(episode.intents)) return { ...stored, version: 2 };\n const intents: Stored = {};\n for (const key of Object.keys(episode.intents)) {\n if (key === '__proto__') continue;\n const record = episode.intents[key];\n if (isRecord(record) && Array.isArray(record.seen)) {\n const counts: Record<string, number> = {};\n for (const signal of record.seen) {\n if (typeof signal === 'string' && signal !== '__proto__') counts[signal] = 1;\n }\n intents[key] = { ...record, counts };\n } else {\n intents[key] = record;\n }\n }\n return { ...stored, version: 2, episode: { ...episode, intents } };\n}\n\n/**\n * Version 2 (oracular 0.3.0 to 0.5.x) → 3. Version 3 lets an intent hold closed episodes that wait\n * for the outcome under `IntentConfig.attribution`. A version 2 state holds none, so every intent\n * gets an empty list and nothing else changes: α, β and every learned count, and therefore every\n * estimate, are exactly what they were.\n */\nfunction fromV2(stored: Stored): Stored {\n if (!isRecord(stored.intents)) return { ...stored, version: 3 };\n const intents: Stored = {};\n for (const key of Object.keys(stored.intents)) {\n if (key === '__proto__') continue;\n const intent = stored.intents[key];\n intents[key] = isRecord(intent) ? { ...intent, pending: [] } : intent;\n }\n return { ...stored, version: 3, intents };\n}\n\n/**\n * Version 3 (oracular 0.6.0 to 0.11.x) → 4. Version 4 adds the engine's clock: the latest event\n * time it trusts, and one event stamped behind it awaiting confirmation. The migration adds an\n * empty clock; `deserialize` then sets it to the latest time the stored anchors were written at,\n * as it does for any state whose anchors are ahead of its clock. Nothing else changes, so every\n * estimate is exactly what it was.\n */\nfunction fromV3(stored: Stored): Stored {\n return { ...stored, version: 4, clock: { at: null, behindAt: null } };\n}\n","import { MAX_PENDING } from './attribution';\nimport { normalizeConfig, resolveLearning } from './config';\nimport { initIntent, withContributions } from './intent';\nimport { signalWeights } from './learning';\nimport { canMigrate, migrateStored } from './migrate';\nimport { requireState } from './state';\nimport type {\n ClockState,\n DeserializeOptions,\n EngineConfig,\n EngineState,\n EpisodeIntentRecord,\n EpisodeState,\n IntentState,\n PendingEpisode,\n SignalContribution,\n SignalRecord,\n} from './types';\nimport { getOwn, hasOwn, isRecord } from './util';\nimport { STATE_VERSION } from './version';\n\n/**\n * The state as a JSON string, for the host app to persist wherever it likes. The state is plain\n * data, so this is `JSON.stringify` after a shape check. The output never contains event props.\n *\n * @param state - The state to persist.\n * @returns A JSON string that {@link deserialize} restores losslessly.\n * @throws `TypeError` when `state` is not an engine state.\n * @example\n * ```ts\n * localStorage.setItem('oracular', serialize(state));\n * ```\n */\nexport function serialize(state: EngineState): string {\n return JSON.stringify(requireState(state));\n}\n\n/**\n * Restores a state saved with {@link serialize}.\n *\n * Always pass the app's current `config`: it is validated and replaces the stored snapshot,\n * which is then not read at all, so a state written by a newer release, with a config key or\n * value this one does not know, still loads after a rollback. Intents and signals no longer\n * declared are dropped (α and β are recomputed from the kept contributions), and newly declared\n * intents start at their prior. Without a config the stored snapshot runs the engine: it is read\n * without the checks that refuse a config that cannot work, so a state saved before those checks\n * existed still loads, but a key the library does not know is an error, since the engine would\n * otherwise run without an option the state was built under. States saved by oracular\n * 0.1.0 to 0.11.x are upgraded to the current shape on their own, and a state one version newer\n * than {@link STATE_VERSION} (written by the next release, read after a rollback) is read as the\n * current one, ignoring the fields it adds; `migrate` is only for a version this library does\n * not know.\n *\n * @param json - A string produced by {@link serialize}.\n * @param opts - `config`: the app's current config. `migrate`: called as\n * `migrate(stored, version)` when the stored version is neither {@link STATE_VERSION} nor one\n * this library migrates itself; it must return a state of the current version.\n * @returns A validated state that satisfies the engine's invariants.\n * @throws `SyntaxError` when `json` is not valid JSON.\n * @throws `TypeError` when the stored data, the result of `migrate`, `opts` or `opts.config`\n * has the wrong shape.\n * @throws `RangeError` when the stored version is neither one this library reads (1 to one past\n * {@link STATE_VERSION}) nor handled by a given `migrate`, when `migrate` does not return the\n * current version, when a stored number is out of range, or\n * when stored numbers are finite but too large to compute with (a tampered or corrupted state\n * that would otherwise answer NaN).\n * @example\n * ```ts\n * const saved = localStorage.getItem('oracular');\n * let state = saved ? deserialize(saved, { config }) : createState(config);\n * ```\n */\nexport function deserialize(json: string, opts: DeserializeOptions = {}): EngineState {\n if (typeof json !== 'string') throw new TypeError('oracular: deserialize expects a JSON string');\n if (!isRecord(opts)) throw new TypeError('oracular: options must be a plain object');\n for (const key of Object.keys(opts)) {\n if (key !== 'config' && key !== 'migrate') {\n throw new TypeError(\n `oracular: options.${key} is not a recognised option (expected one of: config, migrate)`,\n );\n }\n }\n if (opts.migrate !== undefined && typeof opts.migrate !== 'function') {\n throw new TypeError('oracular: options.migrate must be a function');\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch (error) {\n throw new SyntaxError(`oracular: stored state is not valid JSON (${(error as Error).message})`);\n }\n if (!isRecord(parsed) || typeof parsed.version !== 'number') {\n throw new TypeError('oracular: stored state has no numeric version field');\n }\n\n let stored: unknown = parsed;\n if (parsed.version !== STATE_VERSION) {\n if (canMigrate(parsed.version)) {\n stored = migrateStored(parsed);\n } else if (parsed.version === STATE_VERSION + 1) {\n // The next state version only adds fields (the stability policy), so this release reads it\n // as its own and ignores what it does not know: a rollback by one release keeps the user's\n // history, and only what the newer version added is lost.\n stored = { ...parsed, version: STATE_VERSION };\n } else if (opts.migrate === undefined) {\n throw new RangeError(\n `oracular: stored state is version ${parsed.version} but this library reads versions 1 to ${STATE_VERSION + 1}; pass a migrate function`,\n );\n } else {\n stored = opts.migrate(parsed, parsed.version);\n }\n }\n\n const config = opts.config === undefined ? undefined : normalizeConfig(opts.config);\n const raw = parseState(stored, config);\n return requireComputable(reconcile(raw, raw.config));\n}\n\n// ---- parsing: field types only; keys are reconciled against the config afterwards ----\n\nfunction typeError(path: string, message: string): never {\n throw new TypeError(`oracular: ${path} ${message}`);\n}\n\nfunction record(value: unknown, path: string): Record<string, unknown> {\n if (!isRecord(value)) typeError(path, 'must be a plain object');\n return value;\n}\n\nfunction finite(value: unknown, path: string): number {\n if (typeof value !== 'number' || !Number.isFinite(value))\n typeError(path, 'must be a finite number');\n return value;\n}\n\nfunction nonNegative(value: unknown, path: string): number {\n const n = finite(value, path);\n if (n < 0) throw new RangeError(`oracular: ${path} must be 0 or greater`);\n return n;\n}\n\nfunction nullOrFinite(value: unknown, path: string): number | null {\n return value === null ? null : finite(value, path);\n}\n\nfunction signalRecord(value: unknown, path: string): SignalRecord {\n const r = record(value, path);\n return {\n hits: nonNegative(r.hits, `${path}.hits`),\n misses: nonNegative(r.misses, `${path}.misses`),\n };\n}\n\nfunction contribution(value: unknown, path: string): SignalContribution {\n const r = record(value, path);\n return {\n alpha: nonNegative(r.alpha, `${path}.alpha`),\n beta: nonNegative(r.beta, `${path}.beta`),\n };\n}\n\nfunction mapOwn<T>(\n value: unknown,\n path: string,\n fn: (item: unknown, itemPath: string) => T,\n): Record<string, T> {\n const r = record(value, path);\n const out: Record<string, T> = {};\n for (const key of Object.keys(r)) {\n if (key === '__proto__') continue;\n out[key] = fn(r[key], `${path}[${JSON.stringify(key)}]`);\n }\n return out;\n}\n\nfunction pendingEpisodes(value: unknown, path: string): PendingEpisode[] {\n if (!Array.isArray(value)) typeError(path, 'must be an array');\n if (value.length > MAX_PENDING) {\n throw new RangeError(`oracular: ${path} must hold at most ${MAX_PENDING} episodes`);\n }\n return value.map((item, i) => {\n const r = record(item, `${path}[${i}]`);\n if (!Array.isArray(r.seen) || !r.seen.every((s) => typeof s === 'string')) {\n typeError(`${path}[${i}].seen`, 'must be an array of strings');\n }\n return { endedAt: finite(r.endedAt, `${path}[${i}].endedAt`), seen: r.seen as string[] };\n });\n}\n\nfunction intentState(value: unknown, path: string): IntentState {\n const r = record(value, path);\n const revealCount = finite(r.revealCount, `${path}.revealCount`);\n if (!Number.isInteger(revealCount) || revealCount < 0) {\n throw new RangeError(`oracular: ${path}.revealCount must be a non-negative integer`);\n }\n return {\n alpha: finite(r.alpha, `${path}.alpha`),\n beta: finite(r.beta, `${path}.beta`),\n updatedAt: nullOrFinite(r.updatedAt, `${path}.updatedAt`),\n contributions: mapOwn(r.contributions, `${path}.contributions`, contribution),\n learned: mapOwn(r.learned, `${path}.learned`, signalRecord),\n episodes: signalRecord(r.episodes, `${path}.episodes`),\n pending: pendingEpisodes(r.pending, `${path}.pending`),\n learnedAt: nullOrFinite(r.learnedAt, `${path}.learnedAt`),\n lastRevealedAt: nullOrFinite(r.lastRevealedAt, `${path}.lastRevealedAt`),\n lastOutcomeAt: nullOrFinite(r.lastOutcomeAt, `${path}.lastOutcomeAt`),\n revealCount,\n };\n}\n\nfunction occurrenceCount(value: unknown, path: string): number {\n const n = finite(value, path);\n if (!Number.isInteger(n) || n < 1) {\n throw new RangeError(`oracular: ${path} must be a positive integer`);\n }\n return n;\n}\n\nfunction episodeIntent(value: unknown, path: string): EpisodeIntentRecord {\n const r = record(value, path);\n if (!Array.isArray(r.seen) || !r.seen.every((s) => typeof s === 'string')) {\n typeError(`${path}.seen`, 'must be an array of strings');\n }\n const counts = mapOwn(r.counts, `${path}.counts`, occurrenceCount);\n if (typeof r.resolved !== 'boolean') typeError(`${path}.resolved`, 'must be a boolean');\n return { seen: r.seen as string[], counts, resolved: r.resolved };\n}\n\nfunction episodeState(value: unknown, path: string): EpisodeState {\n const r = record(value, path);\n return {\n startedAt: nullOrFinite(r.startedAt, `${path}.startedAt`),\n lastEventAt: nullOrFinite(r.lastEventAt, `${path}.lastEventAt`),\n intents: mapOwn(r.intents, `${path}.intents`, episodeIntent),\n };\n}\n\nfunction clockState(value: unknown, path: string): ClockState {\n const r = record(value, path);\n return {\n at: nullOrFinite(r.at, `${path}.at`),\n behindAt: nullOrFinite(r.behindAt, `${path}.behindAt`),\n };\n}\n\n/**\n * The stored state's fields, typed. With `config` given it replaces the stored snapshot, which is\n * then only required to be an object and not read: a key or value a newer release wrote into it\n * is no obstacle to a rollback (rule 6 of the stability policy). Without one the snapshot runs the\n * engine, read without the strict checks, so a config this release would refuse at `createState`\n * still loads when it is only stored; a key the library does not know stays an error there.\n */\nfunction parseState(value: unknown, config: EngineConfig | undefined): EngineState {\n const r = record(value, 'state');\n if (r.version !== STATE_VERSION) {\n throw new RangeError(`oracular: state.version must be ${STATE_VERSION} after migration`);\n }\n const snapshot = record(r.config, 'state.config');\n return {\n version: STATE_VERSION,\n config: config ?? normalizeConfig(snapshot, false),\n intents: mapOwn(r.intents, 'state.intents', intentState),\n episode: episodeState(r.episode, 'state.episode'),\n clock: clockState(r.clock, 'state.clock'),\n };\n}\n\n// ---- computability: finite numbers that are still too large to compute with ----\n\n/**\n * Every stored number is checked to be finite, but finite is not enough: a contribution near\n * 1e308 makes α·β overflow, and learned counts near 1e308 make the contrast weighting overflow,\n * so the state would answer NaN. Such a state was tampered with or corrupted; reject it.\n */\nfunction requireComputable(state: EngineState): EngineState {\n const learning = resolveLearning(state.config);\n for (const [name, intent] of Object.entries(state.config.intents)) {\n const is = state.intents[name] as IntentState;\n const path = `state.intents[${JSON.stringify(name)}]`;\n if (!Number.isFinite(is.alpha + is.beta) || !Number.isFinite(is.alpha * is.beta)) {\n throw new RangeError(`oracular: ${path} holds more evidence than can be computed with`);\n }\n for (const signal of Object.keys(intent.signals)) {\n const w = signalWeights(is, intent, learning, signal);\n if (!Number.isFinite(w.learned) || !Number.isFinite(w.effective)) {\n throw new RangeError(\n `oracular: ${path} holds learned counts for ${JSON.stringify(signal)} too large to compute with`,\n );\n }\n }\n }\n return state;\n}\n\n// ---- reconciling: make the state agree with a config ----\n\nfunction keep<T>(source: Record<string, T>, declared: Record<string, unknown>): Record<string, T> {\n const out: Record<string, T> = {};\n for (const [key, value] of Object.entries(source)) {\n if (hasOwn(declared, key)) out[key] = value;\n }\n return out;\n}\n\n/** Waiting episodes with their seen lists pruned to declared signals, each once, in order of close. */\nfunction keepPending(\n pending: readonly PendingEpisode[],\n signals: Record<string, number>,\n): PendingEpisode[] {\n return pending\n .map((episode) => ({\n endedAt: episode.endedAt,\n seen: episode.seen.filter((s, i) => hasOwn(signals, s) && episode.seen.indexOf(s) === i),\n }))\n .sort((a, b) => a.endedAt - b.endedAt);\n}\n\n/**\n * Drops intents and signals the config no longer declares, starts newly declared intents at\n * their prior, and recomputes α and β as the (possibly new) prior plus the kept contributions.\n */\nfunction reconcile(raw: EngineState, config: EngineConfig): EngineState {\n const intents: Record<string, IntentState> = {};\n const episodeIntents: Record<string, EpisodeIntentRecord> = {};\n\n for (const [name, intent] of Object.entries(config.intents)) {\n const stored = getOwn(raw.intents, name);\n if (stored === undefined) {\n intents[name] = initIntent(intent);\n } else {\n intents[name] = withContributions(\n {\n ...stored,\n learned: keep(stored.learned, intent.signals),\n pending: keepPending(stored.pending, intent.signals),\n },\n intent,\n keep(stored.contributions, intent.signals),\n );\n }\n }\n\n // The open episode's records stay in the order the intents were first touched, as `observe`\n // writes them, so a save after a load is the same string; intents no longer declared are dropped.\n if (raw.episode.startedAt !== null) {\n for (const [name, episode] of Object.entries(raw.episode.intents)) {\n const intent = getOwn(config.intents, name);\n if (intent === undefined) continue;\n const seen = episode.seen.filter(\n (s, i) => hasOwn(intent.signals, s) && episode.seen.indexOf(s) === i,\n );\n // One count per seen signal and no other: a seen signal without one counts once.\n const counts: Record<string, number> = {};\n for (const s of seen) counts[s] = getOwn(episode.counts, s) ?? 1;\n episodeIntents[name] = { seen, counts, resolved: episode.resolved };\n }\n }\n\n return {\n version: STATE_VERSION,\n config,\n intents,\n episode: {\n startedAt: raw.episode.startedAt,\n lastEventAt: raw.episode.startedAt === null ? null : raw.episode.lastEventAt,\n intents: episodeIntents,\n },\n clock: trustedClock(raw.clock, intents, raw.episode),\n };\n}\n\n/**\n * The clock no anchor `observe` writes is ahead of: a migrated version 3 state gets the latest\n * time its anchors were written at (reveals left out, so one stamped by a clock that was ahead\n * is pinned by the next event rather than trusted), and a tampered clock is raised to them. A\n * held stamp that is not behind the clock is dropped. A state `observe` wrote comes back as it was.\n */\nfunction trustedClock(\n clock: ClockState,\n intents: Record<string, IntentState>,\n episode: EpisodeState,\n): ClockState {\n let at = clock.at;\n const see = (value: number | null): void => {\n if (value !== null && (at === null || value > at)) at = value;\n };\n see(episode.startedAt);\n see(episode.lastEventAt);\n for (const is of Object.values(intents)) {\n see(is.updatedAt);\n see(is.lastOutcomeAt);\n }\n const behindAt =\n clock.behindAt !== null && at !== null && clock.behindAt < at ? clock.behindAt : null;\n return at === clock.at && behindAt === clock.behindAt ? clock : { at, behindAt };\n}\n","/** The units of {@link ms}: each takes a count and returns milliseconds. */\nexport interface Units {\n /** `n` seconds in milliseconds: `n × 1000`. */\n readonly seconds: (n: number) => number;\n /** `n` minutes in milliseconds: `n × 60 000`. */\n readonly minutes: (n: number) => number;\n /** `n` hours in milliseconds: `n × 3 600 000`. */\n readonly hours: (n: number) => number;\n /** `n` days in milliseconds: `n × 86 400 000`. */\n readonly days: (n: number) => number;\n /** `n` weeks in milliseconds: `n × 604 800 000`. */\n readonly weeks: (n: number) => number;\n}\n\n/**\n * Durations in milliseconds, the unit of `Date.now()`: `ms.days(7)` is `604800000`. Plain\n * multiplications and nothing else, for `halfLife`, `cooldown`, `episodeTimeout` and\n * `learning.halfLife` when your timestamps are in milliseconds. If your `at` is in another unit,\n * write durations in that unit instead: the engine only needs the two to agree.\n *\n * @example\n * ```ts\n * const config = {\n * episodeTimeout: ms.minutes(30),\n * intents: {\n * upgrade: {\n * prior: 0.05,\n * priorStrength: 10,\n * halfLife: ms.days(7),\n * signals: { 'pricing.viewed': 3 },\n * reveal: { cooldown: ms.weeks(2) },\n * },\n * },\n * };\n * ```\n */\nexport const ms: Units = {\n seconds: (n) => n * 1_000,\n minutes: (n) => n * 60_000,\n hours: (n) => n * 3_600_000,\n days: (n) => n * 86_400_000,\n weeks: (n) => n * 604_800_000,\n};\n","import { normalizeConfig } from './config';\nimport type { EngineConfig } from './types';\n\n/**\n * Checks a config exactly as {@link createState} and {@link deserialize} do, without building a\n * state, and returns the normalized copy they would store: only the recognised keys, in a fixed\n * order, with every `undefined` dropped, so it survives a JSON round trip unchanged. Use it to\n * fail fast at startup or in a test, or on a config loaded from a file, before the engine runs.\n *\n * @param config - The config to check. Typed `unknown` so parsed JSON can be passed as it is.\n * @returns A fresh, normalized {@link EngineConfig}. `config` is not mutated.\n * @throws `TypeError` when a value has the wrong type, a key is not recognised, or an intent's\n * `outcome` is also one of its signals while `resetOnOutcome` is on.\n * @throws `RangeError` when a number is out of range: a `prior` outside (0, 1), a signal weight of\n * 0, a reveal `threshold` of 0 or 1, a `z` above 10, or a weight, `priorStrength`,\n * `learning.gain` or `learning.priorEpisodes` beyond 1e6.\n * @example\n * ```ts\n * import { readFileSync } from 'node:fs';\n * import { validateConfig } from 'oracular';\n *\n * // Throws with the offending path in the message, e.g. config.intents[\"upgrade\"].prior\n * const config = validateConfig(JSON.parse(readFileSync('oracular.config.json', 'utf8')));\n * ```\n */\nexport function validateConfig(config: unknown): EngineConfig {\n return normalizeConfig(config);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/math.ts","../src/util.ts","../src/learning.ts","../src/attribution.ts","../src/intent.ts","../src/config.ts","../src/episode.ts","../src/version.ts","../src/state.ts","../src/assess.ts","../src/evaluate.ts","../src/evidence.ts","../src/explain.ts","../src/observe.ts","../src/predict.ts","../src/recorder.ts","../src/migrate.ts","../src/serialize.ts","../src/units.ts","../src/validate.ts"],"names":["record","explain","typeError"],"mappings":"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","file":"index.js","sourcesContent":["import type { LiftType } from './types';\n\n/** 2^(−elapsed / halfLife): 1 for zero, negative or NaN elapsed time, 0 for an infinite one. */\nexport function decayFactor(elapsed: number, halfLife: number): number {\n if (!(elapsed > 0)) return 1;\n return 2 ** (-elapsed / halfLife);\n}\n\nexport function betaMean(alpha: number, beta: number): number {\n return alpha / (alpha + beta);\n}\n\nexport function betaVariance(alpha: number, beta: number): number {\n const n = alpha + beta;\n return (alpha * beta) / (n * n * (n + 1));\n}\n\nexport function betaSd(alpha: number, beta: number): number {\n return Math.sqrt(betaVariance(alpha, beta));\n}\n\nexport function clamp01(x: number): number {\n if (x < 0) return 0;\n if (x > 1) return 1;\n return x;\n}\n\n/**\n * Φ(−z) for z ≥ 0: the one-sided tail of the standard normal, so that `z` names the same level\n * under both bounds. Abramowitz–Stegun 7.1.26, |error| below 1.5e-7.\n */\nexport function normalTail(z: number): number {\n const x = z / Math.SQRT2;\n const t = 1 / (1 + 0.3275911 * x);\n const poly =\n t *\n (0.254829592 + t * (-0.284496736 + t * (1.421413741 + t * (-1.453152027 + t * 1.061405429))));\n return 0.5 * poly * Math.exp(-x * x);\n}\n\n/** ln Γ(x) for x > 0: Stirling's series once x is shifted up to 8 or more (about 1e-11 relative). */\nexport function lgamma(x: number): number {\n let acc = 0;\n let v = x;\n while (v < 8) {\n acc -= Math.log(v);\n v += 1;\n }\n const r = 1 / v;\n const r2 = r * r;\n return (\n acc +\n (v - 0.5) * Math.log(v) -\n v +\n 0.9189385332046728 +\n r * (1 / 12 - r2 * (1 / 360 - r2 * (1 / 1260 - r2 / 1680)))\n );\n}\n\n/**\n * The continued fraction of the incomplete Beta function, by the modified Lentz method. Both\n * halves of each step share the denominator (a + i − 1)(a + i), so one loop over i covers them,\n * and i = 1 is the usual initialisation. Converges in about √max(a, b) steps; the cap covers the\n * largest counts a config allows.\n */\nfunction betacf(x: number, a: number, b: number): number {\n const tiny = 1e-300;\n const guard = (v: number): number => (Math.abs(v) < tiny ? tiny : v);\n let c = 1 / tiny;\n let d = 1;\n let h = 1;\n for (let i = 1; i < 20_000; i++) {\n const m = i >> 1;\n const aa = ((i & 1 ? -(a + m) * (a + b + m) : m * (b - m)) * x) / ((a + i - 1) * (a + i));\n d = 1 / guard(1 + aa * d);\n c = guard(1 + aa / c);\n const del = c * d;\n h *= del;\n if (Math.abs(del - 1) < 1e-12) break;\n }\n return h;\n}\n\n/** The regularized incomplete Beta function I_x(a, b): P(X ≤ x) for X ~ Beta(a, b). */\nexport function incompleteBeta(x: number, a: number, b: number): number {\n if (x <= 0) return 0;\n if (x >= 1) return 1;\n const front = Math.exp(\n lgamma(a + b) - lgamma(a) - lgamma(b) + a * Math.log(x) + b * Math.log(1 - x),\n );\n // The fraction converges fast on the near side of the mean; symmetry covers the far side.\n return x < (a + 1) / (a + b + 2)\n ? (front * betacf(x, a, b)) / a\n : 1 - (front * betacf(1 - x, b, a)) / b;\n}\n\n/**\n * The q-quantile of Beta(a, b), by bisection to a width of 1e-9. The answer is the middle of the\n * last bracket, so it is always strictly inside (0, 1), however small a or b.\n */\nexport function betaQuantile(q: number, a: number, b: number): number {\n let lo = 0;\n let hi = 1;\n for (let i = 0; i < 40 && hi - lo > 1e-9; i++) {\n const mid = (lo + hi) / 2;\n if (incompleteBeta(mid, a, b) < q) lo = mid;\n else hi = mid;\n }\n return (lo + hi) / 2;\n}\n\n/**\n * The lower bound `shouldReveal` compares to the threshold: p − z·sd clamped to [0, 1], or\n * with `'exact'` the Beta quantile at the same one-sided level, Φ(−z).\n */\nexport function lowerBound(\n alpha: number,\n beta: number,\n z: number,\n bound: 'normal' | 'exact',\n): number {\n if (bound === 'exact') return betaQuantile(normalTail(z), alpha, beta);\n return clamp01(betaMean(alpha, beta) - z * betaSd(alpha, beta));\n}\n\n/**\n * What the n-th occurrence of a signal within one episode adds, as a fraction of its weight:\n * log2(1 + 1/n), so that n occurrences add log2(1 + n) weights in total. 1 for the first\n * occurrence, 0.585 for the second, 0.415 for the third; every doubling adds one more weight.\n */\nexport function repeatFactor(n: number): number {\n return Math.log1p(1 / n) / Math.LN2;\n}\n\n/** Laplace-smoothed rate: (successes + 1) / (total + 2). Strictly inside (0, 1) in exact arithmetic. */\nexport function laplace(successes: number, total: number): number {\n return (successes + 1) / (total + 2);\n}\n\n/**\n * A rate shrunk toward `rate` by two pseudo-episodes: (successes + 2·rate) / (total + 2). With a\n * `rate` of 0.5 this is Laplace smoothing; with the intent's own base rate, two groups whose\n * observed rates both equal it agree exactly whatever their sizes, and with no outcome yet every\n * rate is 0.\n */\nexport function smoothRate(successes: number, total: number, rate: number): number {\n return (successes + 2 * rate) / (total + 2);\n}\n\n/**\n * The raw association measure comparing rate `q` with baseline `b`. Convert it with\n * `learningScore` before using it as signed evidence; raw ratios have a neutral value of 1.\n * For association-rule lift, `b` must be the overall outcome rate rather than the rate without\n * the signal: P(outcome | signal) / P(outcome) = P(signal, outcome) / (P(signal) P(outcome)).\n * Ratio/log inputs are bounded away from 0 and 1: tune's Wilson interval endpoints can be\n * exactly 0 or 1, and large smoothed counts can round there too. This keeps raw metrics and\n * their evidence scores finite. The default retains its original arithmetic.\n */\nexport function lift(q: number, b: number, type: LiftType = 'normalized-difference'): number {\n if (type === 'absolute-difference') return q - b;\n if (type !== 'normalized-difference') {\n const rate = Math.max(Number.EPSILON, Math.min(1 - Number.EPSILON, q));\n const base = Math.max(Number.EPSILON, Math.min(1 - Number.EPSILON, b));\n switch (type) {\n case 'relative-lift':\n return (rate - base) / base;\n case 'log-lift':\n return Math.log(rate / base);\n case 'odds-ratio':\n return rate / (1 - rate) / (base / (1 - base));\n case 'risk-ratio':\n case 'association-rule':\n return rate / base;\n }\n }\n if (q >= b) return b >= 1 ? 0 : (q - b) / (1 - b);\n return b <= 0 ? 0 : (q - b) / b;\n}\n\n/**\n * Converts raw lift to signed evidence in [−1, 1], with independence at 0. Bounded differences\n * keep their original scale. Ratios use (R − 1)/(R + 1); unbounded differences and log lift use\n * x/(1 + |x|). Both transforms are monotone, so direction and interval ordering are preserved.\n */\nexport function learningScore(value: number, type: LiftType = 'normalized-difference'): number {\n switch (type) {\n case 'risk-ratio':\n case 'odds-ratio':\n case 'association-rule':\n return (value - 1) / (value + 1);\n case 'relative-lift':\n case 'log-lift':\n return value / (1 + Math.abs(value));\n default:\n return value;\n }\n}\n","export function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** Own-property check, so event names like \"constructor\" never hit Object.prototype. */\nexport function hasOwn(record: object, key: string): boolean {\n // biome-ignore lint/suspicious/noPrototypeBuiltins: Object.hasOwn is ES2022; this library targets ES2020 runtimes.\n return Object.prototype.hasOwnProperty.call(record, key);\n}\n\nexport function getOwn<T>(record: Record<string, T>, key: string): T | undefined {\n return hasOwn(record, key) ? record[key] : undefined;\n}\n\nexport function mapRecord<T, U>(\n record: Record<string, T>,\n fn: (value: T, key: string) => U,\n): Record<string, U> {\n const out: Record<string, U> = {};\n for (const [key, value] of Object.entries(record)) {\n out[key] = fn(value, key);\n }\n return out;\n}\n","import type { ResolvedLearning } from './config';\nimport { decayFactor, learningScore, lift, smoothRate } from './math';\nimport type { IntentConfig, IntentState, SignalRecord } from './types';\nimport { getOwn, mapRecord } from './util';\n\nconst NONE: SignalRecord = { hits: 0, misses: 0 };\n\n/**\n * Decays learned counts toward 0 by 2^(−Δt / learning.halfLife) and moves the anchor to `at`; an\n * `at` before the anchor holds the counts and leaves the anchor, as `decayIntent` does.\n */\nexport function decayLearned(\n state: IntentState,\n learning: ResolvedLearning,\n at: number,\n): IntentState {\n if (state.learnedAt === null) return { ...state, learnedAt: at };\n if (!(at > state.learnedAt)) return state;\n const d = learning.halfLife === null ? 1 : decayFactor(at - state.learnedAt, learning.halfLife);\n if (d === 1) return { ...state, learnedAt: at };\n return {\n ...state,\n learnedAt: at,\n learned: mapRecord(state.learned, (r) => ({ hits: r.hits * d, misses: r.misses * d })),\n episodes: { hits: state.episodes.hits * d, misses: state.episodes.misses * d },\n };\n}\n\nexport interface SignalWeights {\n initial: number;\n learned: number;\n effective: number;\n hits: number;\n misses: number;\n}\n\n/**\n * initial: the developer's weight w0.\n * learned: gain · |w0| · the signed, bounded score of the configured lift. qWith is the outcome\n * rate where the signal was seen (hits / (hits + misses)) and qWithout the outcome rate\n * of the intent's other episodes, both shrunk toward the intent's own base rate by two\n * pseudo-episodes, so that a signal whose rate equals the base rate learns nothing\n * whatever the sample sizes, and nothing moves before the first outcome. 0 until the\n * signal has completed an episode.\n * effective: (k · w0 + nEff · learned) / (k + nEff), with k = learning.priorEpisodes and\n * nEff = (nWith · nWithout) / (nWith + nWithout): the comparison is only trusted once\n * the signal has been both present and absent. A signal that has never been absent\n * (or never present) has no counterfactual, nEff is 0, and the developer's weight stands.\n */\nexport function signalWeights(\n state: IntentState,\n intent: IntentConfig,\n learning: ResolvedLearning,\n signal: string,\n): SignalWeights {\n const initial = getOwn(intent.signals, signal);\n if (initial === undefined) {\n throw new RangeError(`oracular: ${JSON.stringify(signal)} is not a signal of this intent`);\n }\n const record = getOwn(state.learned, signal) ?? NONE;\n const nWith = record.hits + record.misses;\n // The contrast: episodes of this intent in which the signal was not seen. hits + misses counts\n // the episodes it was seen in (one record per episode), so the rest is the complement.\n const totalEpisodes = state.episodes.hits + state.episodes.misses;\n const nWithout = Math.max(0, totalEpisodes - nWith);\n const outcomesWithout = Math.min(nWithout, Math.max(0, state.episodes.hits - record.hits));\n // Both rates are shrunk toward the intent's own base rate, not toward 0.5: two groups that\n // differ only in size then agree, and before the first outcome every rate is 0.\n const base = totalEpisodes === 0 ? 0 : state.episodes.hits / totalEpisodes;\n const qWith = smoothRate(record.hits, nWith, base);\n const qWithout = smoothRate(outcomesWithout, nWithout, base);\n // Nothing has been learned about a signal until it has been seen in a completed episode. The\n // association-rule baseline is the pooled rate, shrunk the same way (so, the base rate itself).\n const baseline =\n learning.lift === 'association-rule'\n ? smoothRate(record.hits + outcomesWithout, nWith + nWithout, base)\n : qWithout;\n const score = learningScore(lift(qWith, baseline, learning.lift), learning.lift);\n const learned = nWith === 0 ? 0 : learning.gain * Math.abs(initial) * score;\n // Learning needs contrast: weight the comparison by how much of both sides has been seen.\n const nEff = nWith + nWithout === 0 ? 0 : (nWith * nWithout) / (nWith + nWithout);\n const k = learning.priorEpisodes;\n const effective = (k * initial + nEff * learned) / (k + nEff);\n return { initial, learned, effective, hits: record.hits, misses: record.misses };\n}\n\n/**\n * Counts one episode for the listed signals and for the base rate: `credit` of a hit and\n * `1 − credit` of a miss. 1 when the outcome arrived in the episode, 0 when it ended without it,\n * and in between for an episode a later outcome credits under `attribution` (see attribution.ts).\n * Whatever the credit, the episode counts exactly once.\n */\nexport function recordEpisode(\n state: IntentState,\n signals: readonly string[],\n credit: number,\n): IntentState {\n const miss = 1 - credit;\n const learned = { ...state.learned };\n for (const signal of signals) {\n const r = getOwn(learned, signal) ?? NONE;\n learned[signal] = { hits: r.hits + credit, misses: r.misses + miss };\n }\n const episodes = { hits: state.episodes.hits + credit, misses: state.episodes.misses + miss };\n return { ...state, learned, episodes };\n}\n","import type { ResolvedLearning } from './config';\nimport { decayLearned, recordEpisode } from './learning';\nimport { decayFactor } from './math';\nimport type { IntentConfig, IntentState, PendingEpisode } from './types';\n\n/** Most closed episodes one intent keeps waiting for its outcome. Past it the oldest is a miss at once. */\nexport const MAX_PENDING = 32;\n\n/**\n * When a waiting episode's window ends: its close plus the intent's `attribution`. 0 when the\n * intent no longer sets one, so an episode held under an earlier config settles on the next touch.\n */\nfunction expiry(episode: PendingEpisode, intent: IntentConfig): number {\n return episode.endedAt + (intent.attribution ?? 0);\n}\n\n/**\n * Brings the learned counts up to `at`. Every waiting episode whose window has ended by then is a\n * miss, recorded at the moment its window ended (the counts are decayed to that moment first, as\n * for an episode that closes by timing out), and the counts are then decayed to `at`. Every path\n * that reads or writes learned counts goes through here, so no verdict lands out of order.\n */\nexport function settlePending(\n state: IntentState,\n intent: IntentConfig,\n learning: ResolvedLearning,\n at: number,\n): IntentState {\n let is = state;\n let settled = 0;\n for (const episode of state.pending) {\n const end = expiry(episode, intent);\n if (!(end < at)) break;\n is = recordEpisode(decayLearned(is, learning, end), episode.seen, 0);\n settled++;\n }\n if (settled > 0) is = { ...is, pending: state.pending.slice(settled) };\n return decayLearned(is, learning, at);\n}\n\n/**\n * Holds a closed episode for the intent's outcome instead of counting it, in order of close. Past\n * {@link MAX_PENDING} the oldest is a miss at once, so the stored state stays bounded whatever the\n * session cadence.\n */\nexport function deferEpisode(\n state: IntentState,\n seen: readonly string[],\n endedAt: number,\n): IntentState {\n const pending = insert(state.pending, { endedAt, seen: [...seen] });\n if (pending.length <= MAX_PENDING) return { ...state, pending };\n const [oldest, ...rest] = pending;\n return { ...recordEpisode(state, (oldest as PendingEpisode).seen, 0), pending: rest };\n}\n\n/** Keeps the list in order of close; a clock that went backwards inserts before later closes. */\nfunction insert(pending: readonly PendingEpisode[], episode: PendingEpisode): PendingEpisode[] {\n let i = pending.length;\n while (i > 0 && (pending[i - 1] as PendingEpisode).endedAt > episode.endedAt) i--;\n return [...pending.slice(0, i), episode, ...pending.slice(i)];\n}\n\n/**\n * The outcome arrived at `at`: every waiting episode gets the share `2^(−age / halfLife)` of a hit\n * that its evidence would still hold now, and the rest of a miss, so each episode still counts\n * exactly once. The list is then empty.\n */\nexport function creditPending(state: IntentState, intent: IntentConfig, at: number): IntentState {\n if (state.pending.length === 0) return state;\n let is = state;\n for (const episode of state.pending) {\n is = recordEpisode(is, episode.seen, decayFactor(at - episode.endedAt, intent.halfLife));\n }\n return { ...is, pending: [] };\n}\n","import { decayFactor } from './math';\nimport type { IntentConfig, IntentState, SignalContribution } from './types';\nimport { getOwn, mapRecord } from './util';\n\nexport function priorCounts(intent: IntentConfig): { alpha0: number; beta0: number } {\n return {\n alpha0: intent.prior * intent.priorStrength,\n beta0: (1 - intent.prior) * intent.priorStrength,\n };\n}\n\nexport function initIntent(intent: IntentConfig): IntentState {\n const { alpha0, beta0 } = priorCounts(intent);\n return {\n alpha: alpha0,\n beta: beta0,\n updatedAt: null,\n contributions: {},\n learned: {},\n episodes: { hits: 0, misses: 0 },\n pending: [],\n learnedAt: null,\n lastRevealedAt: null,\n lastOutcomeAt: null,\n revealCount: 0,\n };\n}\n\n/**\n * The one place α and β are written: always the prior plus the sum of contributions,\n * so the invariant α = α0 + Σ contributions.alpha (and β likewise) holds by construction.\n */\nexport function withContributions(\n state: IntentState,\n intent: IntentConfig,\n contributions: Record<string, SignalContribution>,\n): IntentState {\n const { alpha0, beta0 } = priorCounts(intent);\n let alpha = alpha0;\n let beta = beta0;\n for (const c of Object.values(contributions)) {\n alpha += c.alpha;\n beta += c.beta;\n }\n return { ...state, alpha, beta, contributions };\n}\n\n/**\n * Decays evidence toward the prior by 2^(−Δt / halfLife) and moves the anchor to `at`. An `at`\n * before the anchor holds the evidence and leaves the anchor where it is: `observe` resolves the\n * clock before it writes (see `syncClock` there), and a read before the anchor sees what the\n * anchor sees.\n */\nexport function decayIntent(state: IntentState, intent: IntentConfig, at: number): IntentState {\n if (state.updatedAt === null) return { ...state, updatedAt: at };\n if (!(at > state.updatedAt)) return state;\n const d = decayFactor(at - state.updatedAt, intent.halfLife);\n if (d === 1) return { ...state, updatedAt: at };\n const contributions = mapRecord(state.contributions, (c) => ({\n alpha: c.alpha * d,\n beta: c.beta * d,\n }));\n return withContributions({ ...state, updatedAt: at }, intent, contributions);\n}\n\n/** Adds `weight` pseudo-counts for the intent (positive → α) or against it (negative → β). */\nexport function applySignal(\n state: IntentState,\n intent: IntentConfig,\n signal: string,\n weight: number,\n): IntentState {\n const prev = getOwn(state.contributions, signal) ?? { alpha: 0, beta: 0 };\n const next: SignalContribution =\n weight >= 0\n ? { alpha: prev.alpha + weight, beta: prev.beta }\n : { alpha: prev.alpha, beta: prev.beta - weight };\n return withContributions(state, intent, { ...state.contributions, [signal]: next });\n}\n\n/** Drops all evidence; α and β return to the prior. Learned data is untouched. */\nexport function resetToPrior(state: IntentState, intent: IntentConfig): IntentState {\n return withContributions(state, intent, {});\n}\n","import type {\n EngineConfig,\n EvaluateOptions,\n ExplainOptions,\n IntentConfig,\n LearningConfig,\n LiftType,\n RevealOptions,\n} from './types';\nimport { hasOwn, isRecord } from './util';\n\nexport const DEFAULT_THRESHOLD = 0.5;\nexport const DEFAULT_Z = 1.28;\nexport const DEFAULT_GAIN = 2;\nexport const DEFAULT_PRIOR_EPISODES = 10;\n/**\n * Largest accepted magnitude for weights, `priorStrength`, `learning.gain` and\n * `learning.priorEpisodes`: far beyond any real config, and small enough that the Beta and\n * learning arithmetic can never overflow to Infinity or NaN.\n */\nexport const MAX_MAGNITUDE = 1e6;\n/** Largest accepted `z`: 3.09 is already a one-sided 99.9% bound, and 128 is a misplaced 1.28. */\nexport const MAX_Z = 10;\n\n// Exported for tests/schema.test.ts, which pins schema/config.schema.json to these lists.\nexport const CONFIG_KEYS = ['intents', 'episodeTimeout', 'learning', 'reveal'] as const;\nexport const INTENT_KEYS = [\n 'prior',\n 'priorStrength',\n 'halfLife',\n 'signals',\n 'outcome',\n 'resetOnOutcome',\n 'saturate',\n 'episodePerOutcome',\n 'attribution',\n 'reveal',\n] as const;\nexport const REVEAL_KEYS = ['threshold', 'z', 'cooldown', 'outcomeCooldown', 'bound'] as const;\nexport const LEARNING_KEYS = ['halfLife', 'gain', 'priorEpisodes', 'lift'] as const;\nexport const LIFT_TYPES: readonly LiftType[] = [\n 'absolute-difference',\n 'relative-lift',\n 'risk-ratio',\n 'log-lift',\n 'odds-ratio',\n 'normalized-difference',\n 'association-rule',\n];\nconst EXPLAIN_KEYS = ['nonZero', 'limit'] as const;\n\nfunction typeError(path: string, message: string): never {\n throw new TypeError(`oracular: ${path} ${message}`);\n}\n\nfunction rangeError(path: string, message: string): never {\n throw new RangeError(`oracular: ${path} ${message}`);\n}\n\nfunction expectRecord(value: unknown, path: string): Record<string, unknown> {\n if (!isRecord(value)) typeError(path, 'must be a plain object');\n return value;\n}\n\nfunction expectKeys(\n record: Record<string, unknown>,\n allowed: readonly string[],\n path: string,\n): void {\n for (const key of Object.keys(record)) {\n if (!allowed.includes(key)) {\n typeError(\n `${path}.${key}`,\n `is not a recognised option (expected one of: ${allowed.join(', ')})`,\n );\n }\n }\n}\n\nfunction expectNumber(value: unknown, path: string): number {\n if (typeof value !== 'number' || !Number.isFinite(value))\n typeError(path, 'must be a finite number');\n return value;\n}\n\nfunction expectPositive(value: unknown, path: string): number {\n const n = expectNumber(value, path);\n if (n <= 0) rangeError(path, 'must be greater than 0');\n return n;\n}\n\n/** A positive number no larger than {@link MAX_MAGNITUDE}. */\nfunction expectBoundedPositive(value: unknown, path: string): number {\n const n = expectPositive(value, path);\n if (n > MAX_MAGNITUDE) rangeError(path, `must be at most ${MAX_MAGNITUDE}`);\n return n;\n}\n\nfunction expectNonNegative(value: unknown, path: string): number {\n const n = expectNumber(value, path);\n if (n < 0) rangeError(path, 'must be 0 or greater');\n return n;\n}\n\nfunction expectOpenUnit(value: unknown, path: string): number {\n const n = expectNumber(value, path);\n if (n <= 0 || n >= 1) rangeError(path, 'must be strictly between 0 and 1');\n return n;\n}\n\nfunction expectClosedUnit(value: unknown, path: string): number {\n const n = expectNumber(value, path);\n if (n < 0 || n > 1) rangeError(path, 'must be between 0 and 1');\n return n;\n}\n\nexport function expectName(value: unknown, path: string): string {\n if (typeof value !== 'string' || value.length === 0)\n typeError(path, 'must be a non-empty string');\n return value;\n}\n\n/** Keys of user-named records must be usable as own properties of a plain object. */\nfunction expectKeyName(name: string, path: string): string {\n if (name.length === 0) typeError(path, 'names must be non-empty strings');\n if (name === '__proto__') typeError(path, 'must not use the reserved name \"__proto__\"');\n return name;\n}\n\n/**\n * Validates reveal options and returns a copy with only the defined keys. `strict` adds the checks\n * that catch a config that cannot work (a threshold of 0 or 1, a `z` past {@link MAX_Z}); a\n * stored config is read without them, so a state saved before those checks existed still loads.\n */\nexport function normalizeRevealOptions(value: unknown, path: string, strict = true): RevealOptions {\n const record = expectRecord(value, path);\n expectKeys(record, REVEAL_KEYS, path);\n const out: RevealOptions = {};\n if (record.threshold !== undefined) {\n out.threshold = strict\n ? expectOpenUnit(record.threshold, `${path}.threshold`)\n : expectClosedUnit(record.threshold, `${path}.threshold`);\n }\n if (record.z !== undefined) {\n out.z = expectNonNegative(record.z, `${path}.z`);\n if (strict && out.z > MAX_Z) rangeError(`${path}.z`, `must be at most ${MAX_Z}`);\n }\n if (record.cooldown !== undefined) {\n out.cooldown = expectNonNegative(record.cooldown, `${path}.cooldown`);\n }\n if (record.outcomeCooldown !== undefined) {\n out.outcomeCooldown = expectNonNegative(record.outcomeCooldown, `${path}.outcomeCooldown`);\n }\n if (record.bound !== undefined) {\n if (record.bound !== 'normal' && record.bound !== 'exact') {\n typeError(`${path}.bound`, 'must be \"normal\" or \"exact\"');\n }\n out.bound = record.bound;\n }\n return out;\n}\n\nfunction normalizeLearning(value: unknown, path: string): LearningConfig {\n const record = expectRecord(value, path);\n expectKeys(record, LEARNING_KEYS, path);\n const out: LearningConfig = {};\n if (record.lift !== undefined) {\n if (!LIFT_TYPES.includes(record.lift as LiftType)) {\n typeError(`${path}.lift`, `must be one of: ${LIFT_TYPES.join(', ')}`);\n }\n out.lift = record.lift as LiftType;\n }\n if (record.halfLife !== undefined)\n out.halfLife = expectPositive(record.halfLife, `${path}.halfLife`);\n if (record.gain !== undefined) out.gain = expectBoundedPositive(record.gain, `${path}.gain`);\n if (record.priorEpisodes !== undefined) {\n out.priorEpisodes = expectBoundedPositive(record.priorEpisodes, `${path}.priorEpisodes`);\n }\n return out;\n}\n\n/**\n * Validates one intent's config and returns a copy with only the defined, recognised keys. See\n * {@link normalizeRevealOptions} for `strict`: here it also rejects an outcome that is one of the\n * intent's own signals while `resetOnOutcome` is on.\n */\nexport function normalizeIntentConfig(value: unknown, path: string, strict = true): IntentConfig {\n const record = expectRecord(value, path);\n expectKeys(record, INTENT_KEYS, path);\n const signalsRecord = expectRecord(record.signals, `${path}.signals`);\n const signals: Record<string, number> = {};\n for (const [name, weight] of Object.entries(signalsRecord)) {\n expectKeyName(name, `${path}.signals`);\n const w = expectNumber(weight, `${path}.signals[${JSON.stringify(name)}]`);\n if (w === 0) {\n rangeError(\n `${path}.signals[${JSON.stringify(name)}]`,\n 'must be non-zero (positive is evidence for the intent, negative is evidence against)',\n );\n }\n if (Math.abs(w) > MAX_MAGNITUDE) {\n rangeError(\n `${path}.signals[${JSON.stringify(name)}]`,\n `must be between -${MAX_MAGNITUDE} and ${MAX_MAGNITUDE}`,\n );\n }\n signals[name] = w;\n }\n const out: IntentConfig = {\n prior: expectOpenUnit(record.prior, `${path}.prior`),\n priorStrength: expectBoundedPositive(record.priorStrength, `${path}.priorStrength`),\n halfLife: expectPositive(record.halfLife, `${path}.halfLife`),\n signals,\n };\n if (record.outcome !== undefined) out.outcome = expectName(record.outcome, `${path}.outcome`);\n if (record.resetOnOutcome !== undefined) {\n if (typeof record.resetOnOutcome !== 'boolean') {\n typeError(`${path}.resetOnOutcome`, 'must be a boolean');\n }\n out.resetOnOutcome = record.resetOnOutcome;\n }\n if (record.saturate !== undefined) {\n if (typeof record.saturate !== 'boolean') typeError(`${path}.saturate`, 'must be a boolean');\n out.saturate = record.saturate;\n }\n if (record.episodePerOutcome !== undefined) {\n if (typeof record.episodePerOutcome !== 'boolean') {\n typeError(`${path}.episodePerOutcome`, 'must be a boolean');\n }\n out.episodePerOutcome = record.episodePerOutcome;\n }\n if (record.attribution !== undefined) {\n out.attribution = expectPositive(record.attribution, `${path}.attribution`);\n }\n if (record.reveal !== undefined) {\n out.reveal = normalizeRevealOptions(record.reveal, `${path}.reveal`, strict);\n }\n if (\n strict &&\n out.outcome !== undefined &&\n hasOwn(signals, out.outcome) &&\n out.resetOnOutcome !== false\n ) {\n typeError(\n `${path}.outcome`,\n 'is also one of its signals: the reset on outcome would wipe what it adds; set resetOnOutcome: false to keep it',\n );\n }\n return out;\n}\n\n/**\n * Validates a config and returns a fresh copy holding only the defined, recognised keys,\n * so that it survives a JSON round trip unchanged. `strict` (the default) adds the checks that\n * catch a config that cannot work; `deserialize` reads a stored config without them.\n */\nexport function normalizeConfig(value: unknown, strict = true): EngineConfig {\n const record = expectRecord(value, 'config');\n expectKeys(record, CONFIG_KEYS, 'config');\n const intentsRecord = expectRecord(record.intents, 'config.intents');\n const names = Object.keys(intentsRecord);\n if (names.length === 0) typeError('config.intents', 'must declare at least one intent');\n const intents: Record<string, IntentConfig> = {};\n for (const name of names) {\n expectKeyName(name, 'config.intents');\n intents[name] = normalizeIntentConfig(\n intentsRecord[name],\n `config.intents[${JSON.stringify(name)}]`,\n strict,\n );\n }\n const out: EngineConfig = { intents };\n if (record.episodeTimeout !== undefined) {\n out.episodeTimeout = expectPositive(record.episodeTimeout, 'config.episodeTimeout');\n }\n if (record.learning !== undefined)\n out.learning = normalizeLearning(record.learning, 'config.learning');\n if (record.reveal !== undefined) {\n out.reveal = normalizeRevealOptions(record.reveal, 'config.reveal', strict);\n }\n return out;\n}\n\n/** Validates explain filters and returns a copy with only the defined keys. */\nexport function normalizeExplainOptions(value: unknown, path: string): ExplainOptions {\n const record = expectRecord(value, path);\n expectKeys(record, EXPLAIN_KEYS, path);\n const out: ExplainOptions = {};\n if (record.nonZero !== undefined) {\n if (typeof record.nonZero !== 'boolean') typeError(`${path}.nonZero`, 'must be a boolean');\n out.nonZero = record.nonZero;\n }\n if (record.limit !== undefined) {\n const n = expectNumber(record.limit, `${path}.limit`);\n if (!Number.isInteger(n) || n < 0)\n rangeError(`${path}.limit`, 'must be a non-negative integer');\n out.limit = n;\n }\n return out;\n}\n\n/** Splits `evaluate` options into reveal overrides and explain filters, rejecting unknown keys. */\nexport function splitEvaluateOptions(\n value: EvaluateOptions | undefined,\n path: string,\n): { reveal: RevealOptions; explain: ExplainOptions } {\n if (value === undefined) return { reveal: {}, explain: {} };\n const record = expectRecord(value, path);\n expectKeys(record, [...REVEAL_KEYS, ...EXPLAIN_KEYS], path);\n const reveal: Record<string, unknown> = {};\n const explain: Record<string, unknown> = {};\n for (const [key, v] of Object.entries(record)) {\n if ((REVEAL_KEYS as readonly string[]).includes(key)) reveal[key] = v;\n else explain[key] = v;\n }\n return {\n reveal: normalizeRevealOptions(reveal, path, false),\n explain: normalizeExplainOptions(explain, path),\n };\n}\n\nexport interface ResolvedReveal {\n threshold: number;\n z: number;\n cooldown: number;\n /** The pause after the outcome event; the resolved `cooldown` unless set. */\n outcomeCooldown: number;\n bound: 'normal' | 'exact';\n}\n\nexport function resolveReveal(\n config: EngineConfig | undefined,\n intent: IntentConfig,\n opts: RevealOptions | undefined,\n normalized = false,\n): ResolvedReveal {\n // Per-call options are read without the strict checks: a probe at threshold 0 or 1 is a\n // legitimate question (evidenceToReveal asks it); a config that commits to one is not.\n const o =\n opts === undefined ? {} : normalized ? opts : normalizeRevealOptions(opts, 'options', false);\n const cooldown =\n o.cooldown ?? intent.reveal?.cooldown ?? config?.reveal?.cooldown ?? intent.halfLife;\n return {\n threshold:\n o.threshold ?? intent.reveal?.threshold ?? config?.reveal?.threshold ?? DEFAULT_THRESHOLD,\n z: o.z ?? intent.reveal?.z ?? config?.reveal?.z ?? DEFAULT_Z,\n cooldown,\n outcomeCooldown:\n o.outcomeCooldown ??\n intent.reveal?.outcomeCooldown ??\n config?.reveal?.outcomeCooldown ??\n cooldown,\n bound: o.bound ?? intent.reveal?.bound ?? config?.reveal?.bound ?? 'normal',\n };\n}\n\nexport interface ResolvedLearning {\n lift: LiftType;\n /** null means learned counts never decay. */\n halfLife: number | null;\n gain: number;\n priorEpisodes: number;\n}\n\nexport function resolveLearning(config: EngineConfig): ResolvedLearning {\n return {\n lift: config.learning?.lift ?? 'normalized-difference',\n halfLife: config.learning?.halfLife ?? null,\n gain: config.learning?.gain ?? DEFAULT_GAIN,\n priorEpisodes: config.learning?.priorEpisodes ?? DEFAULT_PRIOR_EPISODES,\n };\n}\n\nexport function expectTimestamp(value: unknown, path: string): number {\n return expectNumber(value, path);\n}\n\nexport function validateEvent(event: unknown): { name: string; at: number } {\n if (!isRecord(event)) typeError('event', 'must be an object like { name, at }');\n const name = expectName(event.name, 'event.name');\n const at = expectTimestamp(event.at, 'event.at');\n if (event.props !== undefined && !isRecord(event.props)) {\n typeError('event.props', 'must be a plain object when present');\n }\n return { name, at };\n}\n","import type { EpisodeIntentRecord, EpisodeState } from './types';\nimport { getOwn } from './util';\n\nexport function emptyEpisode(): EpisodeState {\n return { startedAt: null, lastEventAt: null, intents: {} };\n}\n\n/** If the episode has been idle longer than `timeout` by `at`, the moment it timed out; otherwise null. */\nexport function timedOutAt(\n episode: EpisodeState,\n timeout: number | undefined,\n at: number,\n): number | null {\n if (timeout === undefined || episode.lastEventAt === null) return null;\n return at - episode.lastEventAt > timeout ? episode.lastEventAt + timeout : null;\n}\n\n/** Opens the episode if needed and records activity at `at` (never behind the last activity: `observe` resolves the clock first). */\nexport function extendEpisode(episode: EpisodeState, at: number): EpisodeState {\n return { startedAt: episode.startedAt ?? at, lastEventAt: at, intents: episode.intents };\n}\n\nexport function episodeRecord(episode: EpisodeState, intent: string): EpisodeIntentRecord {\n return getOwn(episode.intents, intent) ?? { seen: [], counts: {}, resolved: false };\n}\n\n/** How many times `signal` has occurred for `intent` in this episode (since its last outcome). */\nexport function occurrences(episode: EpisodeState, intent: string, signal: string): number {\n return getOwn(episodeRecord(episode, intent).counts, signal) ?? 0;\n}\n\n/** Remembers one more occurrence of `signal`: added to `seen` the first time, counted every time. */\nexport function markSeen(episode: EpisodeState, intent: string, signal: string): EpisodeState {\n const record = episodeRecord(episode, intent);\n const seen = record.seen.includes(signal) ? record.seen : [...record.seen, signal];\n const counts = { ...record.counts, [signal]: (getOwn(record.counts, signal) ?? 0) + 1 };\n return { ...episode, intents: { ...episode.intents, [intent]: { ...record, seen, counts } } };\n}\n\nexport function markResolved(episode: EpisodeState, intent: string): EpisodeState {\n return {\n ...episode,\n intents: { ...episode.intents, [intent]: { seen: [], counts: {}, resolved: true } },\n };\n}\n","/**\n * Version of the serialized state shape, stored in every state as `state.version`. Bumped only\n * when `EngineState` changes shape, and every bump ships its migration: {@link deserialize}\n * upgrades states saved by earlier versions of this library on its own (version 1, written by\n * oracular 0.1.0 to 0.2.x, version 2, written by 0.3.0 to 0.5.x, and version 3, written by 0.6.0\n * to 0.11.x, become version 4), reads a state one version newer than its own as its own (a\n * version bump only adds fields, so a rollback by one release keeps the user's history), and\n * calls your `migrate` function only for a version it does not know.\n *\n * @example\n * ```ts\n * import { STATE_VERSION, deserialize } from 'oracular';\n *\n * const state = deserialize(saved, {\n * config,\n * // Only reached for versions this library cannot migrate itself, such as a state written by a\n * // newer oracular before a rollback.\n * migrate: (stored, version) => {\n * throw new Error(`cannot read oracular state version ${version} (this build reads ${STATE_VERSION})`);\n * },\n * });\n * ```\n */\nexport const STATE_VERSION = 4 as const;\n\n/**\n * Version of the recorder format: the `v` field of every record that {@link createRecord} and\n * {@link createEndRecord} produce. A new optional field does not change it; readers ignore fields\n * they do not know and skip records of a `kind` they do not know. Anything a reader written for\n * this version could misread bumps it.\n *\n * @example\n * ```ts\n * import { RECORD_VERSION } from 'oracular';\n *\n * const record = JSON.parse(line);\n * if (record.v !== RECORD_VERSION) throw new Error(`unsupported recorder format ${record.v}`);\n * ```\n */\nexport const RECORD_VERSION = 1 as const;\n","import { normalizeConfig } from './config';\nimport { emptyEpisode } from './episode';\nimport { initIntent } from './intent';\nimport type { EngineConfig, EngineState, IntentConfig, IntentState } from './types';\nimport { getOwn, isRecord } from './util';\nimport { STATE_VERSION } from './version';\n\n/**\n * Builds a fresh engine state from a config. Every intent starts at its prior and no episode is\n * open. The config is validated and a normalized copy is stored inside the state, so a persisted\n * state remembers the weights it was built with; pass your current config to {@link deserialize}\n * when loading. `config.learning.lift` selects the lift formula; omitting it preserves the\n * normalized difference used by existing configs and states.\n *\n * @param config - Intents with their priors and signals, plus engine-wide options. Validated\n * strictly: unknown keys, non-finite numbers and out-of-range values throw.\n * @returns A new, JSON-serializable state. `config` is not mutated.\n * @throws `TypeError` when a value has the wrong type, a key is not recognised, or an intent's\n * `outcome` is also one of its signals while `resetOnOutcome` is on (the reset would wipe what\n * the signal just added).\n * @throws `RangeError` when a number is out of range, for example a `prior` outside (0, 1), a\n * signal weight of 0, a reveal `threshold` of 0 or 1, a `z` above 10, or a weight,\n * `priorStrength`, `learning.gain` or `learning.priorEpisodes` beyond 1e6 (larger values could\n * overflow the arithmetic).\n * @example\n * ```ts\n * const state = createState({\n * intents: {\n * upgrade: {\n * prior: 0.05,\n * priorStrength: 10,\n * halfLife: 7 * 24 * 60 * 60 * 1000,\n * signals: { 'pricing.viewed': 3, 'limit.hit': 2, 'plan.downgraded': -4 },\n * outcome: 'upgrade.completed',\n * },\n * },\n * });\n * ```\n */\nexport function createState(config: EngineConfig): EngineState {\n const normalized = normalizeConfig(config);\n const intents: Record<string, IntentState> = {};\n for (const [name, intent] of Object.entries(normalized.intents)) {\n intents[name] = initIntent(intent);\n }\n return {\n version: STATE_VERSION,\n config: normalized,\n intents,\n episode: emptyEpisode(),\n clock: { at: null, behindAt: null },\n };\n}\n\nexport function requireState(state: unknown): EngineState {\n if (\n !isRecord(state) ||\n state.version !== STATE_VERSION ||\n !isRecord(state.config) ||\n !isRecord(state.intents) ||\n !isRecord(state.episode) ||\n !isRecord(state.clock)\n ) {\n throw new TypeError('oracular: state must be an EngineState from createState or deserialize');\n }\n return state as unknown as EngineState;\n}\n\nexport function requireIntentConfig(state: EngineState, name: string): IntentConfig {\n const intent = getOwn(state.config.intents, name);\n if (intent === undefined) {\n throw new RangeError(`oracular: unknown intent ${JSON.stringify(name)}`);\n }\n return intent;\n}\n\n/** The stored intent state, or a fresh prior if the intent was added to the config after the state was created. */\nexport function getIntentState(\n state: EngineState,\n name: string,\n intent: IntentConfig,\n): IntentState {\n return getOwn(state.intents, name) ?? initIntent(intent);\n}\n","import { settlePending } from './attribution';\nimport type { ResolvedLearning, ResolvedReveal } from './config';\nimport { decayIntent } from './intent';\nimport { signalWeights } from './learning';\nimport { betaMean, betaSd, clamp01, lowerBound } from './math';\nimport { getIntentState } from './state';\nimport type {\n EngineState,\n ExplainOptions,\n IntentConfig,\n IntentState,\n Prediction,\n SignalExplanation,\n} from './types';\nimport { getOwn } from './util';\n\n/**\n * The intent brought up to `at` without storing anything: evidence decayed, waiting episodes whose\n * window has passed settled as misses, learned counts decayed.\n */\nexport function assessIntent(\n state: EngineState,\n name: string,\n intent: IntentConfig,\n learning: ResolvedLearning,\n at: number,\n): IntentState {\n const is = decayIntent(getIntentState(state, name, intent), intent, at);\n return settlePending(is, intent, learning, at);\n}\n\n/**\n * The end of a cooldown that started at `since`, if it is still running at `at`. A start ahead of\n * `at` (stamped by a clock that was ahead) counts as having happened now, so the cooldown ends\n * one `cooldown` from `at` rather than from a date that may never come; the next event pins the\n * stored time to `at` (see `observe`).\n */\nfunction cooldownEnd(since: number | null, cooldown: number, at: number): number | null {\n if (since === null) return null;\n const end = Math.min(since, at) + cooldown;\n return at < end ? end : null;\n}\n\nexport function buildPrediction(\n is: IntentState,\n name: string,\n reveal: ResolvedReveal,\n at: number,\n): Prediction {\n const p = betaMean(is.alpha, is.beta);\n const sd = betaSd(is.alpha, is.beta);\n const revealEnd = cooldownEnd(is.lastRevealedAt, reveal.cooldown, at);\n const outcomeEnd = cooldownEnd(is.lastOutcomeAt, reveal.outcomeCooldown, at);\n const suppressedUntil =\n revealEnd === null\n ? outcomeEnd\n : outcomeEnd === null\n ? revealEnd\n : Math.max(revealEnd, outcomeEnd);\n return {\n intent: name,\n p,\n sd,\n lower: lowerBound(is.alpha, is.beta, reveal.z, reveal.bound),\n confidence: clamp01(1 - 2 * sd),\n evidence: is.alpha + is.beta,\n revealed: revealEnd !== null,\n revealedAt: is.lastRevealedAt,\n suppressedUntil,\n };\n}\n\nexport function decideReveal(prediction: Prediction, reveal: ResolvedReveal): boolean {\n return (\n prediction.suppressedUntil === null &&\n prediction.p >= reveal.threshold &&\n prediction.lower >= reveal.threshold\n );\n}\n\nexport function buildExplanation(\n is: IntentState,\n intent: IntentConfig,\n learning: ResolvedLearning,\n opts: ExplainOptions,\n): SignalExplanation[] {\n const p = betaMean(is.alpha, is.beta);\n const out: SignalExplanation[] = [];\n for (const signal of Object.keys(intent.signals)) {\n const c = getOwn(is.contributions, signal) ?? { alpha: 0, beta: 0 };\n const w = signalWeights(is, intent, learning, signal);\n const without = betaMean(is.alpha - c.alpha, is.beta - c.beta);\n out.push({\n signal,\n contribution: c.alpha - c.beta,\n impact: p - without,\n initialWeight: w.initial,\n learnedWeight: w.learned,\n effectiveWeight: w.effective,\n hits: w.hits,\n misses: w.misses,\n });\n }\n out.sort((a, b) => Math.abs(b.impact) - Math.abs(a.impact) || compare(a.signal, b.signal));\n const filtered = opts.nonZero ? out.filter((row) => row.contribution !== 0) : out;\n return opts.limit === undefined ? filtered : filtered.slice(0, opts.limit);\n}\n\nfunction compare(a: string, b: string): number {\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n}\n","import { assessIntent, buildExplanation, buildPrediction, decideReveal } from './assess';\nimport {\n expectName,\n expectTimestamp,\n resolveLearning,\n resolveReveal,\n splitEvaluateOptions,\n} from './config';\nimport { requireIntentConfig, requireState } from './state';\nimport type { EngineState, EvaluateOptions, Evaluation, Snapshot } from './types';\n\n/**\n * {@link predict}, {@link shouldReveal} and {@link explain} in one call, from a single decay\n * pass over the intent. The three results are identical to what the separate functions return\n * for the same inputs; this is the one to call on every event when you need all of them.\n * Read-only.\n *\n * @param state - The current state. Not mutated.\n * @param intent - Name of an intent declared in the config.\n * @param at - The time to evaluate at.\n * @param opts - Reveal overrides (`threshold`, `z`, `cooldown`, `bound`) and explain filters\n * (`nonZero`, `limit`) in one object.\n * @returns `prediction` (as `predict`), `reveal` (as `shouldReveal`) and `explanation` (as\n * `explain` with the same filters).\n * @throws `RangeError` when `intent` is not declared in the config.\n * @throws `TypeError` when `state` is not an engine state, `at` is not finite, or `opts` is\n * malformed.\n * @example\n * ```ts\n * const { prediction, reveal, explanation } = evaluate(state, 'upgrade', Date.now(), { limit: 3 });\n * if (reveal) showOffer(explanation[0]?.signal);\n * ```\n */\nexport function evaluate(\n state: EngineState,\n intent: string,\n at: number,\n opts?: EvaluateOptions,\n): Evaluation {\n const s = requireState(state);\n const name = expectName(intent, 'intent');\n const t = expectTimestamp(at, 'at');\n const config = requireIntentConfig(s, name);\n const split = splitEvaluateOptions(opts, 'options');\n const reveal = resolveReveal(s.config, config, split.reveal, true);\n const learning = resolveLearning(s.config);\n const is = assessIntent(s, name, config, learning, t);\n const prediction = buildPrediction(is, name, reveal, t);\n return {\n prediction,\n reveal: decideReveal(prediction, reveal),\n explanation: buildExplanation(is, config, learning, split.explain),\n };\n}\n\n/**\n * {@link evaluate} for every declared intent at once, in config order: the whole engine's view at\n * one moment, as plain data. This is what to log, assert on, or hand to `renderInspector` from\n * `oracular/inspect` for a live panel. Read-only.\n *\n * @param state - The current state. Not mutated.\n * @param at - The time to evaluate at.\n * @param opts - Reveal overrides and explain filters, applied to every intent.\n * @returns `at` and one {@link IntentSnapshot} per intent.\n * @throws `TypeError` when `state` is not an engine state, `at` is not finite, or `opts` is\n * malformed.\n * @example\n * ```ts\n * for (const { intent, prediction, reveal } of inspect(state, Date.now()).intents) {\n * console.log(intent, prediction.p.toFixed(3), reveal ? 'reveal' : '');\n * }\n * ```\n */\nexport function inspect(state: EngineState, at: number, opts?: EvaluateOptions): Snapshot {\n const s = requireState(state);\n const intents = Object.keys(s.config.intents).map((intent) => ({\n intent,\n ...evaluate(s, intent, at, opts),\n }));\n return { at, intents };\n}\n","import { normalizeIntentConfig, resolveReveal } from './config';\nimport { priorCounts } from './intent';\nimport { betaMean, lowerBound } from './math';\nimport type { IntentConfig, RevealOptions } from './types';\n\n/**\n * How much positive evidence an intent needs before {@link shouldReveal} first becomes true:\n * the smallest pseudo-count `w` such that Beta(α₀ + w, β₀) clears both `p ≥ threshold` and\n * `lower ≥ threshold`, with `lower` as `bound` defines it (p − z·sd, or the exact Beta quantile).\n * Divide by a signal's weight and round up for the number of full-weight\n * occurrences that open the gate: distinct signals, or one occurrence per episode. Repeats within\n * one episode add less (n of them add `w × log2(1 + n)`, see {@link IntentConfig.saturate}).\n * Solved numerically to 1e-9.\n *\n * Cooldowns and decay are not part of the answer: this is the evidence needed at one instant.\n *\n * @param intent - One intent's config, validated as `createState` would.\n * @param opts - `threshold`, `z` and `bound` overrides, resolved as call → intent → defaults\n * (there is no engine config here). `cooldown` is accepted and ignored.\n * @returns The pseudo-count sum; 0 when the prior alone already clears the gate; `Infinity`\n * when no finite amount of evidence can (threshold 1).\n * @throws `TypeError` or `RangeError` when `intent` or `opts` is invalid.\n * @example\n * ```ts\n * const needed = evidenceToReveal(config.intents.upgrade); // ≈ 15.1 for the quickstart config\n * Math.ceil(needed / 3); // 6 full-weight signals of weight 3\n * ```\n */\nexport function evidenceToReveal(intent: IntentConfig, opts?: RevealOptions): number {\n const config = normalizeIntentConfig(intent, 'intent');\n const { threshold, z, bound } = resolveReveal(undefined, config, opts);\n const { alpha0, beta0 } = priorCounts(config);\n\n const open = (w: number): boolean =>\n betaMean(alpha0 + w, beta0) >= threshold &&\n lowerBound(alpha0 + w, beta0, z, bound) >= threshold;\n\n if (threshold >= 1) return Number.POSITIVE_INFINITY;\n if (open(0)) return 0;\n\n // Bracket the first crossing geometrically, then bisect. Both p and the lower bound keep\n // rising with evidence past the first crossing, so the first opening is the answer.\n let lo = 0;\n let hi = 1;\n while (!open(hi)) {\n lo = hi;\n hi *= 2;\n if (hi > 1e15) return Number.POSITIVE_INFINITY;\n }\n for (let i = 0; i < 200 && hi - lo > 1e-9; i++) {\n const mid = (lo + hi) / 2;\n if (open(mid)) hi = mid;\n else lo = mid;\n }\n return hi;\n}\n","import { assessIntent, buildExplanation } from './assess';\nimport { expectName, expectTimestamp, normalizeExplainOptions, resolveLearning } from './config';\nimport { requireIntentConfig, requireState } from './state';\nimport type { EngineState, ExplainOptions, SignalExplanation } from './types';\n\n/**\n * Why the intent's p is what it is at time `at`: one entry per declared signal, the ones that\n * matter most first. `contribution` is the signed pseudo-count the signal currently holds after\n * decay, `impact` is how much p would change if that contribution were removed, and the three\n * weights show what the developer said, what this user's history says, and what the next\n * occurrence will actually add. Read-only.\n *\n * @param state - The current state. Not mutated.\n * @param intent - Name of an intent declared in the config.\n * @param at - The time to evaluate at; contributions and learned counts are decayed to it.\n * @param opts - Optional filters: `nonZero` keeps only signals that currently hold evidence,\n * `limit` caps the number of rows. Default: every declared signal.\n * @returns One {@link SignalExplanation} per declared signal, sorted by |impact| descending,\n * then by name, then filtered by `opts`. Empty for an intent that declares no signals.\n * @throws `RangeError` when `intent` is not declared in the config.\n * @throws `TypeError` when `state` is not an engine state, `at` is not finite, or `opts` is\n * malformed.\n * @example\n * ```ts\n * for (const row of explain(state, 'upgrade', Date.now(), { nonZero: true })) {\n * console.log(row.signal, row.impact.toFixed(2), row.effectiveWeight.toFixed(2));\n * }\n * ```\n */\nexport function explain(\n state: EngineState,\n intent: string,\n at: number,\n opts?: ExplainOptions,\n): SignalExplanation[] {\n const s = requireState(state);\n const name = expectName(intent, 'intent');\n const t = expectTimestamp(at, 'at');\n const config = requireIntentConfig(s, name);\n const filters = opts === undefined ? {} : normalizeExplainOptions(opts, 'options');\n const learning = resolveLearning(s.config);\n return buildExplanation(assessIntent(s, name, config, learning, t), config, learning, filters);\n}\n","import { creditPending, deferEpisode, settlePending } from './attribution';\nimport { expectTimestamp, resolveLearning, validateEvent } from './config';\nimport {\n emptyEpisode,\n episodeRecord,\n extendEpisode,\n markResolved,\n markSeen,\n occurrences,\n timedOutAt,\n} from './episode';\nimport { applySignal, decayIntent, resetToPrior } from './intent';\nimport { recordEpisode, signalWeights } from './learning';\nimport { repeatFactor } from './math';\nimport { getIntentState, requireState } from './state';\nimport type { EngineState, IntentEvent, IntentState } from './types';\nimport { hasOwn } from './util';\n\n/**\n * Feeds one event to the engine.\n *\n * For every intent the event is a signal of: decay its evidence to `event.at`, then add the\n * signal's effective weight to α (positive) or β (negative) and remember the signal for this\n * episode. Repeats within an episode saturate: the n-th occurrence of a signal adds\n * `w × log2(1 + 1/n)`, counted since the episode started or the intent's outcome last arrived.\n * That is the default when `config.episodeTimeout` is set, and `IntentConfig.saturate` overrides\n * it either way; otherwise every occurrence adds all of `w`. For every intent the event is the\n * outcome of: give the signals remembered since the episode started or the outcome last arrived a\n * hit and count the episode toward the base rate (a repeated outcome with nothing seen since\n * counts nothing, unless `IntentConfig.episodePerOutcome` makes every outcome an episode of its\n * own for the intent), credit\n * the closed episodes still waiting under `IntentConfig.attribution` by `2^(−age / halfLife)`\n * each, record `lastOutcomeAt`, and (by default) reset the evidence to the prior. Any event opens\n * or extends the current episode; an idle gap longer than `config.episodeTimeout` closes the\n * previous episode first.\n *\n * The clock. An event at or after the latest event time moves the engine's clock there, and\n * anything stamped ahead of it (a reveal stamped by a clock that was ahead) is pinned to it. An\n * event stamped *behind* the clock counts now, at the clock's time, and its stamp is held: if the\n * next event is also behind the clock, the clock was corrected, and every anchor ahead of the\n * held stamp moves back to it so decay and cooldowns resume from the corrected time; if the next\n * event is at or after the clock, the held stamp was one glitch and nothing moved. So one event\n * stamped years ahead cannot hold an intent past the two events that follow it, and one stamped\n * years behind cannot wipe the evidence or close the session.\n *\n * @param state - The current state. Not mutated.\n * @param event - `name` is matched against every intent's signals and outcome; `at` is the\n * event's timestamp, in the same unit as your durations; `props` are accepted and ignored,\n * and never stored.\n * @returns The next state. Intents the event does not touch keep their stored numbers; their\n * decay is applied when they are next read or updated.\n * @throws `TypeError` when `state` is not an engine state, or the event has no non-empty\n * `name`, no finite `at`, or a `props` that is not a plain object.\n * @example\n * ```ts\n * let state = createState(config);\n * state = observe(state, { name: 'pricing.viewed', at: Date.now() });\n * state = observe(state, { name: 'upgrade.completed', at: Date.now() }); // outcome\n * ```\n */\nexport function observe(state: EngineState, event: IntentEvent): EngineState {\n const { name, at: stamp } = validateEvent(event);\n const synced = syncClock(requireState(state), stamp);\n let s = synced.state;\n const at = synced.at;\n\n const closeAt = timedOutAt(s.episode, s.config.episodeTimeout, at);\n if (closeAt !== null) s = closeEpisode(s, closeAt);\n\n const learning = resolveLearning(s.config);\n const intents: Record<string, IntentState> = { ...s.intents };\n let episode = extendEpisode(s.episode, at);\n\n for (const [intentName, intent] of Object.entries(s.config.intents)) {\n const isSignal = hasOwn(intent.signals, name);\n const isOutcome = intent.outcome === name;\n if (!isSignal && !isOutcome) continue;\n\n let is = getIntentState(s, intentName, intent);\n is = decayIntent(is, intent, at);\n is = settlePending(is, intent, learning, at);\n\n if (isSignal) {\n const { effective } = signalWeights(is, intent, learning, name);\n const n = occurrences(episode, intentName, name) + 1;\n const saturate = intent.saturate ?? s.config.episodeTimeout !== undefined;\n const factor = saturate ? repeatFactor(n) : 1;\n is = applySignal(is, intent, name, effective * factor);\n // An event that is also the intent's outcome must not learn from itself.\n if (!isOutcome) episode = markSeen(episode, intentName, name);\n }\n\n if (isOutcome) {\n // The signals seen since the episode started, or since the intent's outcome last arrived,\n // get the hit. A repeated outcome with no signal seen since is a duplicate, not another\n // episode, so it does not count toward the base rate; with episodePerOutcome every outcome\n // is an episode of its own, and it counts.\n const record = episodeRecord(episode, intentName);\n if (!record.resolved || record.seen.length > 0 || intent.episodePerOutcome === true) {\n is = recordEpisode(is, record.seen, 1);\n }\n is = creditPending(is, intent, at);\n episode = markResolved(episode, intentName);\n is = { ...is, lastOutcomeAt: at };\n if (intent.resetOnOutcome ?? true) is = resetToPrior(is, intent);\n }\n\n intents[intentName] = is;\n }\n\n return { ...s, intents, episode };\n}\n\n/**\n * Resolves an event's stamp against the clock and says when the event counts. At or after the\n * clock (or the first event): the clock moves to the stamp and every anchor ahead of it is pinned\n * to it. Behind the clock with nothing held: the event counts now, at the clock's time, and the\n * stamp is held. Behind the clock with a stamp already held: two in a row confirm a correction,\n * so everything ahead of the held stamp moves back to it and the event is resolved again from\n * there. At or after the clock with a stamp held: the held one was a glitch, forgotten.\n */\nfunction syncClock(state: EngineState, stamp: number): { state: EngineState; at: number } {\n const { at, behindAt } = state.clock;\n if (at === null || stamp >= at) return { state: pinTo(state, stamp), at: stamp };\n if (behindAt !== null) return syncClock(pinTo(state, behindAt), stamp);\n return { state: { ...state, clock: { at, behindAt: stamp } }, at };\n}\n\nconst INTENT_ANCHORS = ['updatedAt', 'learnedAt', 'lastRevealedAt', 'lastOutcomeAt'] as const;\nconst EPISODE_ANCHORS = ['startedAt', 'lastEventAt'] as const;\n\n/** Moves every anchor ahead of `t` back to `t` and sets the clock there; intents nothing moves in keep their objects. */\nfunction pinTo(state: EngineState, t: number): EngineState {\n let intents = state.intents;\n for (const [name, is] of Object.entries(state.intents)) {\n let pinned = pinKeys(is, INTENT_ANCHORS, t);\n if (is.pending.some((p) => p.endedAt > t)) {\n pinned = {\n ...pinned,\n pending: is.pending.map((p) => (p.endedAt > t ? { ...p, endedAt: t } : p)),\n };\n }\n if (pinned !== is) intents = { ...intents, [name]: pinned };\n }\n const episode = pinKeys(state.episode, EPISODE_ANCHORS, t);\n return { ...state, intents, episode, clock: { at: t, behindAt: null } };\n}\n\n/** `obj` with every listed key that holds a number above `t` set to `t`; the same object when none does. */\nfunction pinKeys<T extends object>(obj: T, keys: readonly (keyof T)[], t: number): T {\n let out = obj;\n for (const key of keys) {\n const value: unknown = obj[key];\n if (typeof value === 'number' && value > t) out = { ...out, [key]: t };\n }\n return out;\n}\n\n/**\n * Ends the current episode at `at`. Every intent whose outcome did not arrive gives a miss to\n * each signal seen this episode and counts the episode toward its base rate, or, with\n * `IntentConfig.attribution` set, holds the episode for the outcome instead. Call it when a\n * session ends: tab closed, app backgrounded, user signed out.\n *\n * @param state - The current state. Not mutated.\n * @param at - When the episode ended. If it had already timed out under\n * `config.episodeTimeout`, it is closed at the moment it timed out instead.\n * @returns The next state with no open episode, or the very same state object when no episode\n * was open.\n * @throws `TypeError` when `state` is not an engine state or `at` is not a finite number.\n * @example\n * ```ts\n * window.addEventListener('pagehide', () => {\n * state = endEpisode(state, Date.now());\n * localStorage.setItem('oracular', serialize(state));\n * });\n * ```\n */\nexport function endEpisode(state: EngineState, at: number): EngineState {\n const s = requireState(state);\n const t = expectTimestamp(at, 'at');\n if (s.episode.startedAt === null) return s;\n const closeAt = timedOutAt(s.episode, s.config.episodeTimeout, t);\n return closeEpisode(s, closeAt ?? t);\n}\n\nfunction closeEpisode(state: EngineState, at: number): EngineState {\n const learning = resolveLearning(state.config);\n const intents: Record<string, IntentState> = { ...state.intents };\n for (const [intentName, intent] of Object.entries(state.config.intents)) {\n const record = episodeRecord(state.episode, intentName);\n // Resolved: the outcome arrived. Signals seen after it stay neutral at the close; they are\n // judged only if another outcome follows them in the same episode. With episodePerOutcome\n // they are a new attempt, judged at the close like a first one; nothing seen is nothing.\n if (record.resolved && (intent.episodePerOutcome !== true || record.seen.length === 0))\n continue;\n let is = getIntentState(state, intentName, intent);\n is = settlePending(is, intent, learning, at);\n is =\n intent.attribution === undefined\n ? recordEpisode(is, record.seen, 0)\n : deferEpisode(is, record.seen, at);\n intents[intentName] = is;\n }\n return { ...state, intents, episode: emptyEpisode() };\n}\n\n/**\n * Whether an episode closed between two states: `prev` had an open episode and `next` either\n * has none or has a different one. Useful after `observe` or `endEpisode` to react to a\n * session ending, for example to persist, or to read the misses it produced as\n * `next.intents[x].episodes.misses - prev.intents[x].episodes.misses` (0 for an intent with\n * `attribution` set, whose verdict waits).\n *\n * @param prev - The state before the operation.\n * @param next - The state after it.\n * @returns True when `prev.episode.startedAt` is not null and differs from\n * `next.episode.startedAt`.\n * @throws `TypeError` when either argument is not an engine state.\n * @example\n * ```ts\n * const next = observe(state, event);\n * if (episodeClosed(state, next)) persist(next);\n * ```\n */\nexport function episodeClosed(prev: EngineState, next: EngineState): boolean {\n const a = requireState(prev);\n const b = requireState(next);\n return a.episode.startedAt !== null && b.episode.startedAt !== a.episode.startedAt;\n}\n","import { buildPrediction, decideReveal } from './assess';\nimport { expectName, expectTimestamp, resolveReveal } from './config';\nimport { decayIntent } from './intent';\nimport { getIntentState, requireIntentConfig, requireState } from './state';\nimport type { EngineState, Prediction, RevealOptions } from './types';\n\n/**\n * The intent's current estimate at time `at`: the Beta mean p, its standard deviation, the\n * lower confidence bound that {@link shouldReveal} tests, and the cooldown status. Read-only:\n * the stored state is decayed to `at` for the reading but not changed.\n *\n * @param state - The current state. Not mutated.\n * @param intent - Name of an intent declared in the config.\n * @param at - The time to evaluate at, in the same unit as your durations.\n * @param opts - Overrides for `threshold`, `z`, `cooldown`, `outcomeCooldown` and `bound`,\n * resolved as call → intent → engine → defaults. `z` and `bound` set `lower`; `cooldown` sets\n * `revealed` and, with `outcomeCooldown` (default: `cooldown`), `suppressedUntil`;\n * `threshold` only matters to {@link shouldReveal}.\n * @returns The prediction. `p`, `sd`, `lower` and `confidence` are in [0, 1]; `evidence` is\n * α + β.\n * @throws `RangeError` when `intent` is not declared in the config.\n * @throws `TypeError` when `state` is not an engine state, `at` is not finite, or `opts` is\n * malformed.\n * @example\n * ```ts\n * const { p, lower, suppressedUntil } = predict(state, 'upgrade', Date.now());\n * if (suppressedUntil !== null) scheduleNextCheck(suppressedUntil);\n * ```\n */\nexport function predict(\n state: EngineState,\n intent: string,\n at: number,\n opts?: RevealOptions,\n): Prediction {\n const s = requireState(state);\n const name = expectName(intent, 'intent');\n const t = expectTimestamp(at, 'at');\n const config = requireIntentConfig(s, name);\n const reveal = resolveReveal(s.config, config, opts);\n const is = decayIntent(getIntentState(s, name, config), config, t);\n return buildPrediction(is, name, reveal, t);\n}\n\n/**\n * Whether to act on the intent now. True when p ≥ `threshold`, the lower confidence bound\n * (p − z·sd, or the exact Beta quantile with `bound: 'exact'`) also clears `threshold`, and no\n * cooldown is running: neither the one started by\n * {@link markRevealed} nor the one started by the intent's outcome event.\n *\n * @param state - The current state. Not mutated.\n * @param intent - Name of an intent declared in the config.\n * @param at - The time to evaluate at.\n * @param opts - Overrides for `threshold` (default 0.5), `z` (default 1.28, a one-sided 90%\n * bound), `cooldown` (default: the intent's `halfLife`) and `outcomeCooldown` (default:\n * `cooldown`; 0 lets the outcome pause nothing).\n * @returns True when the app should show, offer or reveal whatever this intent gates.\n * @throws `RangeError` when `intent` is not declared in the config.\n * @throws `TypeError` when `state` is not an engine state, `at` is not finite, or `opts` is\n * malformed.\n * @example\n * ```ts\n * if (shouldReveal(state, 'upgrade', Date.now())) {\n * showUpgradeOffer();\n * state = markRevealed(state, 'upgrade', Date.now());\n * }\n * ```\n */\nexport function shouldReveal(\n state: EngineState,\n intent: string,\n at: number,\n opts?: RevealOptions,\n): boolean {\n const s = requireState(state);\n const name = expectName(intent, 'intent');\n const config = requireIntentConfig(s, name);\n const reveal = resolveReveal(s.config, config, opts);\n return decideReveal(predict(s, name, at, opts), reveal);\n}\n\n/**\n * Records that the app acted on the intent at `at`. Starts the reveal cooldown, during which\n * `predict().revealed` is true and {@link shouldReveal} is false, and increments\n * `revealCount`. Evidence and learned data are untouched.\n *\n * @param state - The current state. Not mutated.\n * @param intent - Name of an intent declared in the config.\n * @param at - When the reveal happened.\n * @returns The next state.\n * @throws `RangeError` when `intent` is not declared in the config.\n * @throws `TypeError` when `state` is not an engine state or `at` is not finite.\n * @example\n * ```ts\n * state = markRevealed(state, 'upgrade', Date.now());\n * predict(state, 'upgrade', Date.now()).revealed; // true until the cooldown ends\n * ```\n */\nexport function markRevealed(state: EngineState, intent: string, at: number): EngineState {\n const s = requireState(state);\n const name = expectName(intent, 'intent');\n const t = expectTimestamp(at, 'at');\n const config = requireIntentConfig(s, name);\n const is = getIntentState(s, name, config);\n return {\n ...s,\n intents: {\n ...s.intents,\n [name]: { ...is, lastRevealedAt: t, revealCount: is.revealCount + 1 },\n },\n };\n}\n","import { assessIntent, buildExplanation, buildPrediction, decideReveal } from './assess';\nimport {\n expectName,\n expectTimestamp,\n resolveLearning,\n resolveReveal,\n validateEvent,\n} from './config';\nimport { requireState } from './state';\nimport type {\n EndRecord,\n EngineState,\n EventRecord,\n IntentEvent,\n RecordedDecision,\n RecordMode,\n RecordOptions,\n} from './types';\nimport { getOwn, isRecord } from './util';\nimport { RECORD_VERSION } from './version';\n\nconst RECORD_KEYS = ['installId', 'mode', 'top'];\nconst DEFAULT_TOP = 3;\n\nfunction normalizeRecordOptions(value: unknown): Required<RecordOptions> {\n if (!isRecord(value)) {\n throw new TypeError('oracular: options must be an object like { installId, mode }');\n }\n for (const key of Object.keys(value)) {\n if (!RECORD_KEYS.includes(key)) {\n throw new TypeError(\n `oracular: options.${key} is not a recognised option (expected one of: ${RECORD_KEYS.join(', ')})`,\n );\n }\n }\n const installId = expectName(value.installId, 'options.installId');\n const mode = value.mode;\n if (mode !== 'shadow' && mode !== 'live') {\n throw new TypeError('oracular: options.mode must be \"shadow\" or \"live\"');\n }\n let top = DEFAULT_TOP;\n if (value.top !== undefined) {\n if (typeof value.top !== 'number' || !Number.isFinite(value.top)) {\n throw new TypeError('oracular: options.top must be a finite number');\n }\n if (!Number.isInteger(value.top) || value.top < 0) {\n throw new RangeError('oracular: options.top must be a non-negative integer');\n }\n top = value.top;\n }\n return { installId, mode: mode as RecordMode, top };\n}\n\n/**\n * A recorder record for an event: the event itself and, for every intent, what the engine decides\n * right after it. Call it with the state `observe` returned for that event, then append\n * `JSON.stringify(record)` as one line of the log (NDJSON). The record holds the event's `name` and\n * `at`, never its `props`.\n *\n * Each decision is what {@link evaluate} reports at `event.at` with the state's own reveal\n * options: `p`, `lower`, `shouldReveal`, `suppressedUntil`, the signals with the largest impact,\n * and the effective weight of every signal. Pure: the install id comes from the app, never from\n * here. See the Shadow mode guide for the whole workflow.\n *\n * On the record of an intent's own outcome event, `p` is what the engine decides right after it,\n * which with `resetOnOutcome` is the prior: the estimate the outcome confirmed is gone. Pass the\n * state from before the event as `previous` and that intent's decision gains `before`, its `p`\n * and `lower` at `event.at` on that state. Replay never reads it; people reading the log do.\n *\n * @param state - The state after `observe(state, event)`. Not mutated.\n * @param event - The event just observed. Only `name` and `at` are recorded.\n * @param opts - `installId` (generated and stored by the app), `mode` (`'shadow'` while\n * reveals are computed but not shown, `'live'` once they are), and `top` (default 3).\n * @param previous - The state before `observe(state, event)`, optional. Only read for the\n * intents whose outcome the event is.\n * @returns A plain, JSON-serializable {@link EventRecord}.\n * @throws `TypeError` when `state` or `previous` is not an engine state, the event is\n * malformed, `opts` is not an object, has an unknown key, an empty `installId` or a `mode`\n * other than `'shadow'` or `'live'`.\n * @throws `RangeError` when `opts.top` is negative or fractional.\n * @example\n * ```ts\n * const recording = { installId: localStorage.getItem('oracular.install')!, mode: 'shadow' } as const;\n *\n * const event = { name: 'pricing.viewed', at: Date.now() };\n * const previous = state;\n * state = observe(state, event);\n * appendLine(JSON.stringify(createRecord(state, event, recording, previous)));\n * ```\n */\nexport function createRecord(\n state: EngineState,\n event: IntentEvent,\n opts: RecordOptions,\n previous?: EngineState,\n): EventRecord {\n const s = requireState(state);\n const { name, at } = validateEvent(event);\n const { installId, mode, top } = normalizeRecordOptions(opts);\n const prev = previous === undefined ? undefined : requireState(previous);\n const learning = resolveLearning(s.config);\n const decisions: Record<string, RecordedDecision> = {};\n for (const [intentName, intent] of Object.entries(s.config.intents)) {\n const reveal = resolveReveal(s.config, intent, undefined);\n const is = assessIntent(s, intentName, intent, learning, at);\n const prediction = buildPrediction(is, intentName, reveal, at);\n const rows = buildExplanation(is, intent, learning, {});\n const weights: Record<string, number> = {};\n for (const signal of Object.keys(intent.signals)) {\n weights[signal] = (\n rows.find((row) => row.signal === signal) as { effectiveWeight: number }\n ).effectiveWeight;\n }\n const decision: RecordedDecision = {\n p: prediction.p,\n lower: prediction.lower,\n shouldReveal: decideReveal(prediction, reveal),\n suppressedUntil: prediction.suppressedUntil,\n top: rows\n .filter((row) => row.contribution !== 0)\n .slice(0, top)\n .map((row) => ({ signal: row.signal, impact: row.impact })),\n weights,\n };\n // The outcome's record: the estimate just before it, which the reset wipes, when the state\n // before the event was given and still declared the intent.\n const prevIntent = prev === undefined ? undefined : getOwn(prev.config.intents, intentName);\n if (prev !== undefined && prevIntent !== undefined && intent.outcome === name) {\n const was = buildPrediction(\n assessIntent(prev, intentName, prevIntent, resolveLearning(prev.config), at),\n intentName,\n resolveReveal(prev.config, prevIntent, undefined),\n at,\n );\n decision.before = { p: was.p, lower: was.lower };\n }\n decisions[intentName] = decision;\n }\n return { v: RECORD_VERSION, kind: 'event', installId, mode, event: { name, at }, decisions };\n}\n\n/**\n * A recorder record for the end of an episode. Write one whenever the app calls\n * {@link endEpisode}, with the same `at`, so that replay can end the episode at the same moment\n * and reproduce the misses it records. Episodes that close through `episodeTimeout` need none:\n * replay applies the timeout itself.\n *\n * @param at - The time passed to `endEpisode`.\n * @param opts - The same options as for {@link createRecord}; `top` is accepted and ignored.\n * @returns A plain, JSON-serializable {@link EndRecord}.\n * @throws `TypeError` when `at` is not a finite number or `opts` is malformed.\n * @throws `RangeError` when `opts.top` is negative or fractional.\n * @example\n * ```ts\n * const at = Date.now();\n * state = endEpisode(state, at);\n * appendLine(JSON.stringify(createEndRecord(at, recording)));\n * ```\n */\nexport function createEndRecord(at: number, opts: RecordOptions): EndRecord {\n const t = expectTimestamp(at, 'at');\n const { installId, mode } = normalizeRecordOptions(opts);\n return { v: RECORD_VERSION, kind: 'end', installId, mode, at: t };\n}\n","import { hasOwn, isRecord } from './util';\n\ntype Stored = Record<string, unknown>;\n\n/**\n * Migrations this library applies itself, keyed by the version they upgrade from. Each turns the\n * parsed JSON of one version into the shape of the next. Input that is malformed in ways a\n * migration does not need to look at is passed through untouched, so that parsing afterwards\n * rejects it with the same precise error it would give any other malformed state.\n */\nconst MIGRATIONS: Record<number, (stored: Stored) => Stored> = {\n 1: fromV1,\n 2: fromV2,\n 3: fromV3,\n};\n\n/** Whether `version` is one this library can bring up to date on its own. */\nexport function canMigrate(version: number): boolean {\n return hasOwn(MIGRATIONS, String(version));\n}\n\n/** Applies the built-in migrations, one version at a time, until none applies. */\nexport function migrateStored(stored: Stored): Stored {\n let current = stored;\n while (typeof current.version === 'number' && canMigrate(current.version)) {\n current = (MIGRATIONS[current.version] as (stored: Stored) => Stored)(current);\n }\n return current;\n}\n\n/**\n * Version 1 (oracular 0.1.0 to 0.2.x) → 2. Version 2 counts how often each signal occurred in the\n * open episode, so that repeats can saturate. A version 1 state only knows which signals were\n * seen, not how often, so each seen signal counts once: the lower bound. Nothing else changes, so\n * α, β and every learned count, and therefore every estimate, are exactly what they were.\n */\nfunction fromV1(stored: Stored): Stored {\n const episode = stored.episode;\n if (!isRecord(episode) || !isRecord(episode.intents)) return { ...stored, version: 2 };\n const intents: Stored = {};\n for (const key of Object.keys(episode.intents)) {\n if (key === '__proto__') continue;\n const record = episode.intents[key];\n if (isRecord(record) && Array.isArray(record.seen)) {\n const counts: Record<string, number> = {};\n for (const signal of record.seen) {\n if (typeof signal === 'string' && signal !== '__proto__') counts[signal] = 1;\n }\n intents[key] = { ...record, counts };\n } else {\n intents[key] = record;\n }\n }\n return { ...stored, version: 2, episode: { ...episode, intents } };\n}\n\n/**\n * Version 2 (oracular 0.3.0 to 0.5.x) → 3. Version 3 lets an intent hold closed episodes that wait\n * for the outcome under `IntentConfig.attribution`. A version 2 state holds none, so every intent\n * gets an empty list and nothing else changes: α, β and every learned count, and therefore every\n * estimate, are exactly what they were.\n */\nfunction fromV2(stored: Stored): Stored {\n if (!isRecord(stored.intents)) return { ...stored, version: 3 };\n const intents: Stored = {};\n for (const key of Object.keys(stored.intents)) {\n if (key === '__proto__') continue;\n const intent = stored.intents[key];\n intents[key] = isRecord(intent) ? { ...intent, pending: [] } : intent;\n }\n return { ...stored, version: 3, intents };\n}\n\n/**\n * Version 3 (oracular 0.6.0 to 0.11.x) → 4. Version 4 adds the engine's clock: the latest event\n * time it trusts, and one event stamped behind it awaiting confirmation. The migration adds an\n * empty clock; `deserialize` then sets it to the latest time the stored anchors were written at,\n * as it does for any state whose anchors are ahead of its clock. Nothing else changes, so every\n * estimate is exactly what it was.\n */\nfunction fromV3(stored: Stored): Stored {\n return { ...stored, version: 4, clock: { at: null, behindAt: null } };\n}\n","import { MAX_PENDING } from './attribution';\nimport { normalizeConfig, resolveLearning } from './config';\nimport { initIntent, withContributions } from './intent';\nimport { signalWeights } from './learning';\nimport { canMigrate, migrateStored } from './migrate';\nimport { requireState } from './state';\nimport type {\n ClockState,\n DeserializeOptions,\n EngineConfig,\n EngineState,\n EpisodeIntentRecord,\n EpisodeState,\n IntentState,\n PendingEpisode,\n SignalContribution,\n SignalRecord,\n} from './types';\nimport { getOwn, hasOwn, isRecord } from './util';\nimport { STATE_VERSION } from './version';\n\n/**\n * The state as a JSON string, for the host app to persist wherever it likes. The state is plain\n * data, so this is `JSON.stringify` after a shape check. The output never contains event props.\n *\n * @param state - The state to persist.\n * @returns A JSON string that {@link deserialize} restores losslessly.\n * @throws `TypeError` when `state` is not an engine state.\n * @example\n * ```ts\n * localStorage.setItem('oracular', serialize(state));\n * ```\n */\nexport function serialize(state: EngineState): string {\n return JSON.stringify(requireState(state));\n}\n\n/**\n * Restores a state saved with {@link serialize}.\n *\n * Always pass the app's current `config`: it is validated and replaces the stored snapshot,\n * which is then not read at all, so a state written by a newer release, with a config key or\n * value this one does not know, still loads after a rollback. Intents and signals no longer\n * declared are dropped (α and β are recomputed from the kept contributions), and newly declared\n * intents start at their prior. Without a config the stored snapshot runs the engine: it is read\n * without the checks that refuse a config that cannot work, so a state saved before those checks\n * existed still loads, but a key the library does not know is an error, since the engine would\n * otherwise run without an option the state was built under. States saved by oracular\n * 0.1.0 to 0.11.x are upgraded to the current shape on their own, and a state one version newer\n * than {@link STATE_VERSION} (written by the next release, read after a rollback) is read as the\n * current one, ignoring the fields it adds; `migrate` is only for a version this library does\n * not know.\n *\n * @param json - A string produced by {@link serialize}.\n * @param opts - `config`: the app's current config. `migrate`: called as\n * `migrate(stored, version)` when the stored version is neither {@link STATE_VERSION} nor one\n * this library migrates itself; it must return a state of the current version.\n * @returns A validated state that satisfies the engine's invariants.\n * @throws `SyntaxError` when `json` is not valid JSON.\n * @throws `TypeError` when the stored data, the result of `migrate`, `opts` or `opts.config`\n * has the wrong shape.\n * @throws `RangeError` when the stored version is neither one this library reads (1 to one past\n * {@link STATE_VERSION}) nor handled by a given `migrate`, when `migrate` does not return the\n * current version, when a stored number is out of range, or\n * when stored numbers are finite but too large to compute with (a tampered or corrupted state\n * that would otherwise answer NaN).\n * @example\n * ```ts\n * const saved = localStorage.getItem('oracular');\n * let state = saved ? deserialize(saved, { config }) : createState(config);\n * ```\n */\nexport function deserialize(json: string, opts: DeserializeOptions = {}): EngineState {\n if (typeof json !== 'string') throw new TypeError('oracular: deserialize expects a JSON string');\n if (!isRecord(opts)) throw new TypeError('oracular: options must be a plain object');\n for (const key of Object.keys(opts)) {\n if (key !== 'config' && key !== 'migrate') {\n throw new TypeError(\n `oracular: options.${key} is not a recognised option (expected one of: config, migrate)`,\n );\n }\n }\n if (opts.migrate !== undefined && typeof opts.migrate !== 'function') {\n throw new TypeError('oracular: options.migrate must be a function');\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch (error) {\n throw new SyntaxError(`oracular: stored state is not valid JSON (${(error as Error).message})`);\n }\n if (!isRecord(parsed) || typeof parsed.version !== 'number') {\n throw new TypeError('oracular: stored state has no numeric version field');\n }\n\n let stored: unknown = parsed;\n if (parsed.version !== STATE_VERSION) {\n if (canMigrate(parsed.version)) {\n stored = migrateStored(parsed);\n } else if (parsed.version === STATE_VERSION + 1) {\n // The next state version only adds fields (the stability policy), so this release reads it\n // as its own and ignores what it does not know: a rollback by one release keeps the user's\n // history, and only what the newer version added is lost.\n stored = { ...parsed, version: STATE_VERSION };\n } else if (opts.migrate === undefined) {\n throw new RangeError(\n `oracular: stored state is version ${parsed.version} but this library reads versions 1 to ${STATE_VERSION + 1}; pass a migrate function`,\n );\n } else {\n stored = opts.migrate(parsed, parsed.version);\n }\n }\n\n const config = opts.config === undefined ? undefined : normalizeConfig(opts.config);\n const raw = parseState(stored, config);\n return requireComputable(reconcile(raw, raw.config));\n}\n\n// ---- parsing: field types only; keys are reconciled against the config afterwards ----\n\nfunction typeError(path: string, message: string): never {\n throw new TypeError(`oracular: ${path} ${message}`);\n}\n\nfunction record(value: unknown, path: string): Record<string, unknown> {\n if (!isRecord(value)) typeError(path, 'must be a plain object');\n return value;\n}\n\nfunction finite(value: unknown, path: string): number {\n if (typeof value !== 'number' || !Number.isFinite(value))\n typeError(path, 'must be a finite number');\n return value;\n}\n\nfunction nonNegative(value: unknown, path: string): number {\n const n = finite(value, path);\n if (n < 0) throw new RangeError(`oracular: ${path} must be 0 or greater`);\n return n;\n}\n\nfunction nullOrFinite(value: unknown, path: string): number | null {\n return value === null ? null : finite(value, path);\n}\n\nfunction signalRecord(value: unknown, path: string): SignalRecord {\n const r = record(value, path);\n return {\n hits: nonNegative(r.hits, `${path}.hits`),\n misses: nonNegative(r.misses, `${path}.misses`),\n };\n}\n\nfunction contribution(value: unknown, path: string): SignalContribution {\n const r = record(value, path);\n return {\n alpha: nonNegative(r.alpha, `${path}.alpha`),\n beta: nonNegative(r.beta, `${path}.beta`),\n };\n}\n\nfunction mapOwn<T>(\n value: unknown,\n path: string,\n fn: (item: unknown, itemPath: string) => T,\n): Record<string, T> {\n const r = record(value, path);\n const out: Record<string, T> = {};\n for (const key of Object.keys(r)) {\n if (key === '__proto__') continue;\n out[key] = fn(r[key], `${path}[${JSON.stringify(key)}]`);\n }\n return out;\n}\n\nfunction pendingEpisodes(value: unknown, path: string): PendingEpisode[] {\n if (!Array.isArray(value)) typeError(path, 'must be an array');\n if (value.length > MAX_PENDING) {\n throw new RangeError(`oracular: ${path} must hold at most ${MAX_PENDING} episodes`);\n }\n return value.map((item, i) => {\n const r = record(item, `${path}[${i}]`);\n if (!Array.isArray(r.seen) || !r.seen.every((s) => typeof s === 'string')) {\n typeError(`${path}[${i}].seen`, 'must be an array of strings');\n }\n return { endedAt: finite(r.endedAt, `${path}[${i}].endedAt`), seen: r.seen as string[] };\n });\n}\n\nfunction intentState(value: unknown, path: string): IntentState {\n const r = record(value, path);\n const revealCount = finite(r.revealCount, `${path}.revealCount`);\n if (!Number.isInteger(revealCount) || revealCount < 0) {\n throw new RangeError(`oracular: ${path}.revealCount must be a non-negative integer`);\n }\n return {\n alpha: finite(r.alpha, `${path}.alpha`),\n beta: finite(r.beta, `${path}.beta`),\n updatedAt: nullOrFinite(r.updatedAt, `${path}.updatedAt`),\n contributions: mapOwn(r.contributions, `${path}.contributions`, contribution),\n learned: mapOwn(r.learned, `${path}.learned`, signalRecord),\n episodes: signalRecord(r.episodes, `${path}.episodes`),\n pending: pendingEpisodes(r.pending, `${path}.pending`),\n learnedAt: nullOrFinite(r.learnedAt, `${path}.learnedAt`),\n lastRevealedAt: nullOrFinite(r.lastRevealedAt, `${path}.lastRevealedAt`),\n lastOutcomeAt: nullOrFinite(r.lastOutcomeAt, `${path}.lastOutcomeAt`),\n revealCount,\n };\n}\n\nfunction occurrenceCount(value: unknown, path: string): number {\n const n = finite(value, path);\n if (!Number.isInteger(n) || n < 1) {\n throw new RangeError(`oracular: ${path} must be a positive integer`);\n }\n return n;\n}\n\nfunction episodeIntent(value: unknown, path: string): EpisodeIntentRecord {\n const r = record(value, path);\n if (!Array.isArray(r.seen) || !r.seen.every((s) => typeof s === 'string')) {\n typeError(`${path}.seen`, 'must be an array of strings');\n }\n const counts = mapOwn(r.counts, `${path}.counts`, occurrenceCount);\n if (typeof r.resolved !== 'boolean') typeError(`${path}.resolved`, 'must be a boolean');\n return { seen: r.seen as string[], counts, resolved: r.resolved };\n}\n\nfunction episodeState(value: unknown, path: string): EpisodeState {\n const r = record(value, path);\n return {\n startedAt: nullOrFinite(r.startedAt, `${path}.startedAt`),\n lastEventAt: nullOrFinite(r.lastEventAt, `${path}.lastEventAt`),\n intents: mapOwn(r.intents, `${path}.intents`, episodeIntent),\n };\n}\n\nfunction clockState(value: unknown, path: string): ClockState {\n const r = record(value, path);\n return {\n at: nullOrFinite(r.at, `${path}.at`),\n behindAt: nullOrFinite(r.behindAt, `${path}.behindAt`),\n };\n}\n\n/**\n * The stored state's fields, typed. With `config` given it replaces the stored snapshot, which is\n * then only required to be an object and not read: a key or value a newer release wrote into it\n * is no obstacle to a rollback (rule 6 of the stability policy). Without one the snapshot runs the\n * engine, read without the strict checks, so a config this release would refuse at `createState`\n * still loads when it is only stored; a key the library does not know stays an error there.\n */\nfunction parseState(value: unknown, config: EngineConfig | undefined): EngineState {\n const r = record(value, 'state');\n if (r.version !== STATE_VERSION) {\n throw new RangeError(`oracular: state.version must be ${STATE_VERSION} after migration`);\n }\n const snapshot = record(r.config, 'state.config');\n return {\n version: STATE_VERSION,\n config: config ?? normalizeConfig(snapshot, false),\n intents: mapOwn(r.intents, 'state.intents', intentState),\n episode: episodeState(r.episode, 'state.episode'),\n clock: clockState(r.clock, 'state.clock'),\n };\n}\n\n// ---- computability: finite numbers that are still too large to compute with ----\n\n/**\n * Every stored number is checked to be finite, but finite is not enough: a contribution near\n * 1e308 makes α·β overflow, and learned counts near 1e308 make the contrast weighting overflow,\n * so the state would answer NaN. Such a state was tampered with or corrupted; reject it.\n */\nfunction requireComputable(state: EngineState): EngineState {\n const learning = resolveLearning(state.config);\n for (const [name, intent] of Object.entries(state.config.intents)) {\n const is = state.intents[name] as IntentState;\n const path = `state.intents[${JSON.stringify(name)}]`;\n if (!Number.isFinite(is.alpha + is.beta) || !Number.isFinite(is.alpha * is.beta)) {\n throw new RangeError(`oracular: ${path} holds more evidence than can be computed with`);\n }\n for (const signal of Object.keys(intent.signals)) {\n const w = signalWeights(is, intent, learning, signal);\n if (!Number.isFinite(w.learned) || !Number.isFinite(w.effective)) {\n throw new RangeError(\n `oracular: ${path} holds learned counts for ${JSON.stringify(signal)} too large to compute with`,\n );\n }\n }\n }\n return state;\n}\n\n// ---- reconciling: make the state agree with a config ----\n\nfunction keep<T>(source: Record<string, T>, declared: Record<string, unknown>): Record<string, T> {\n const out: Record<string, T> = {};\n for (const [key, value] of Object.entries(source)) {\n if (hasOwn(declared, key)) out[key] = value;\n }\n return out;\n}\n\n/** Waiting episodes with their seen lists pruned to declared signals, each once, in order of close. */\nfunction keepPending(\n pending: readonly PendingEpisode[],\n signals: Record<string, number>,\n): PendingEpisode[] {\n return pending\n .map((episode) => ({\n endedAt: episode.endedAt,\n seen: episode.seen.filter((s, i) => hasOwn(signals, s) && episode.seen.indexOf(s) === i),\n }))\n .sort((a, b) => a.endedAt - b.endedAt);\n}\n\n/**\n * Drops intents and signals the config no longer declares, starts newly declared intents at\n * their prior, and recomputes α and β as the (possibly new) prior plus the kept contributions.\n */\nfunction reconcile(raw: EngineState, config: EngineConfig): EngineState {\n const intents: Record<string, IntentState> = {};\n const episodeIntents: Record<string, EpisodeIntentRecord> = {};\n\n for (const [name, intent] of Object.entries(config.intents)) {\n const stored = getOwn(raw.intents, name);\n if (stored === undefined) {\n intents[name] = initIntent(intent);\n } else {\n intents[name] = withContributions(\n {\n ...stored,\n learned: keep(stored.learned, intent.signals),\n pending: keepPending(stored.pending, intent.signals),\n },\n intent,\n keep(stored.contributions, intent.signals),\n );\n }\n }\n\n // The open episode's records stay in the order the intents were first touched, as `observe`\n // writes them, so a save after a load is the same string; intents no longer declared are dropped.\n if (raw.episode.startedAt !== null) {\n for (const [name, episode] of Object.entries(raw.episode.intents)) {\n const intent = getOwn(config.intents, name);\n if (intent === undefined) continue;\n const seen = episode.seen.filter(\n (s, i) => hasOwn(intent.signals, s) && episode.seen.indexOf(s) === i,\n );\n // One count per seen signal and no other: a seen signal without one counts once.\n const counts: Record<string, number> = {};\n for (const s of seen) counts[s] = getOwn(episode.counts, s) ?? 1;\n episodeIntents[name] = { seen, counts, resolved: episode.resolved };\n }\n }\n\n return {\n version: STATE_VERSION,\n config,\n intents,\n episode: {\n startedAt: raw.episode.startedAt,\n lastEventAt: raw.episode.startedAt === null ? null : raw.episode.lastEventAt,\n intents: episodeIntents,\n },\n clock: trustedClock(raw.clock, intents, raw.episode),\n };\n}\n\n/**\n * The clock no anchor `observe` writes is ahead of: a migrated version 3 state gets the latest\n * time its anchors were written at (reveals left out, so one stamped by a clock that was ahead\n * is pinned by the next event rather than trusted), and a tampered clock is raised to them. A\n * held stamp that is not behind the clock is dropped. A state `observe` wrote comes back as it was.\n */\nfunction trustedClock(\n clock: ClockState,\n intents: Record<string, IntentState>,\n episode: EpisodeState,\n): ClockState {\n let at = clock.at;\n const see = (value: number | null): void => {\n if (value !== null && (at === null || value > at)) at = value;\n };\n see(episode.startedAt);\n see(episode.lastEventAt);\n for (const is of Object.values(intents)) {\n see(is.updatedAt);\n see(is.lastOutcomeAt);\n }\n const behindAt =\n clock.behindAt !== null && at !== null && clock.behindAt < at ? clock.behindAt : null;\n return at === clock.at && behindAt === clock.behindAt ? clock : { at, behindAt };\n}\n","/** The units of {@link ms}: each takes a count and returns milliseconds. */\nexport interface Units {\n /** `n` seconds in milliseconds: `n × 1000`. */\n readonly seconds: (n: number) => number;\n /** `n` minutes in milliseconds: `n × 60 000`. */\n readonly minutes: (n: number) => number;\n /** `n` hours in milliseconds: `n × 3 600 000`. */\n readonly hours: (n: number) => number;\n /** `n` days in milliseconds: `n × 86 400 000`. */\n readonly days: (n: number) => number;\n /** `n` weeks in milliseconds: `n × 604 800 000`. */\n readonly weeks: (n: number) => number;\n}\n\n/**\n * Durations in milliseconds, the unit of `Date.now()`: `ms.days(7)` is `604800000`. Plain\n * multiplications and nothing else, for `halfLife`, `cooldown`, `episodeTimeout` and\n * `learning.halfLife` when your timestamps are in milliseconds. If your `at` is in another unit,\n * write durations in that unit instead: the engine only needs the two to agree.\n *\n * @example\n * ```ts\n * const config = {\n * episodeTimeout: ms.minutes(30),\n * intents: {\n * upgrade: {\n * prior: 0.05,\n * priorStrength: 10,\n * halfLife: ms.days(7),\n * signals: { 'pricing.viewed': 3 },\n * reveal: { cooldown: ms.weeks(2) },\n * },\n * },\n * };\n * ```\n */\nexport const ms: Units = {\n seconds: (n) => n * 1_000,\n minutes: (n) => n * 60_000,\n hours: (n) => n * 3_600_000,\n days: (n) => n * 86_400_000,\n weeks: (n) => n * 604_800_000,\n};\n","import { normalizeConfig } from './config';\nimport type { EngineConfig } from './types';\n\n/**\n * Checks a config exactly as {@link createState} and {@link deserialize} do, without building a\n * state, and returns the normalized copy they would store: only the recognised keys, in a fixed\n * order, with every `undefined` dropped, so it survives a JSON round trip unchanged. Use it to\n * fail fast at startup or in a test, or on a config loaded from a file, before the engine runs.\n *\n * @param config - The config to check. Typed `unknown` so parsed JSON can be passed as it is.\n * @returns A fresh, normalized {@link EngineConfig}. `config` is not mutated.\n * @throws `TypeError` when a value has the wrong type, a key is not recognised, or an intent's\n * `outcome` is also one of its signals while `resetOnOutcome` is on.\n * @throws `RangeError` when a number is out of range: a `prior` outside (0, 1), a signal weight of\n * 0, a reveal `threshold` of 0 or 1, a `z` above 10, or a weight, `priorStrength`,\n * `learning.gain` or `learning.priorEpisodes` beyond 1e6.\n * @example\n * ```ts\n * import { readFileSync } from 'node:fs';\n * import { validateConfig } from 'oracular';\n *\n * // Throws with the offending path in the message, e.g. config.intents[\"upgrade\"].prior\n * const config = validateConfig(JSON.parse(readFileSync('oracular.config.json', 'utf8')));\n * ```\n */\nexport function validateConfig(config: unknown): EngineConfig {\n return normalizeConfig(config);\n}\n"]}
|