vite-plugin-ai-code-review 1.0.3 → 1.0.5

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/reviewer.ts","../src/git-utils.ts","../src/reporter.ts","../src/index.ts"],"names":["ChatOpenAI","SystemMessage","HumanMessage","crypto","path","fs","execSync"],"mappings":";;;;;;;;;;;;;;;;;;AAgCO,IAAM,eAAN,MAAmB;AAAA,EAKxB,YAAY,OAAA,EAA0B;AAJtC,IAAA,IAAA,CAAQ,GAAA,GAAyB,IAAA;AAEjC,IAAA,IAAA,CAAQ,KAAA,uBAAwC,GAAA,EAAI;AAGlD,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAEf,IAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,MAAA,IAAA,CAAK,GAAA,GAAM,IAAIA,iBAAA,CAAW;AAAA,QACxB,cAAc,OAAA,CAAQ,MAAA;AAAA,QACtB,aAAA,EAAe,EAAE,OAAA,EAAS,OAAA,CAAQ,MAAA,EAAO;AAAA,QACzC,WAAW,OAAA,CAAQ,KAAA;AAAA,QACnB,WAAA,EAAa,GAAA;AAAA,QACb,SAAA,EAAW;AAAA,OACZ,CAAA;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAA,CAAO,IAAA,EAAc,QAAA,EAA0C;AACnE,IAAA,IAAI,CAAC,KAAK,GAAA,EAAK;AACb,MAAA,OAAO,EAAC;AAAA,IACV;AAGA,IAAA,IAAI,IAAA,CAAK,QAAQ,KAAA,EAAO;AACtB,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,WAAA,CAAY,IAAI,CAAA;AACtC,MAAA,IAAI,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,QAAQ,CAAA,EAAG;AAC5B,QAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,QAAQ,CAAA;AAAA,MAChC;AAAA,IACF;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,aAAA,CAAc,MAAM,QAAQ,CAAA;AAGtD,MAAA,IAAI,IAAA,CAAK,QAAQ,KAAA,EAAO;AACtB,QAAA,MAAM,QAAA,GAAW,IAAA,CAAK,WAAA,CAAY,IAAI,CAAA;AACtC,QAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,QAAA,EAAU,MAAM,CAAA;AAAA,MACjC;AAEA,MAAA,OAAO,MAAA;AAAA,IACT,SAAS,KAAA,EAAY;AACnB,MAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,iCAAA,EAAW,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AACxC,MAAA,OAAO,EAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,aAAA,CACZ,IAAA,EACA,QAAA,EACwB;AACxB,IAAA,MAAM,YAAA,GAAe,KAAK,iBAAA,EAAkB;AAC5C,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,eAAA,CAAgB,IAAA,EAAM,QAAQ,CAAA;AAEtD,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,GAAA,CAAK,OAAO,CAAC,YAAA,EAAc,UAAU,CAAC,CAAA;AAClE,IAAA,MAAM,OAAA,GAAU,QAAA,CAAS,OAAA,CAAQ,QAAA,EAAS;AAG1C,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA;AACjC,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,WAAA,CAAY,MAAA,EAAQ,QAAQ,CAAA;AAChD,MAAA,OAAO,MAAA;AAAA,IACT,SAAS,KAAA,EAAO;AAEd,MAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,KAAA,CAAM,aAAa,CAAA;AAC7C,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,SAAA,CAAU,CAAC,CAAC,CAAA;AACtC,QAAA,MAAM,MAAA,GAAS,IAAA,CAAK,WAAA,CAAY,MAAA,EAAQ,QAAQ,CAAA;AAChD,QAAA,OAAO,MAAA;AAAA,MACT;AACA,MAAA,OAAO,EAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAA,GAAmC;AACzC,IAAA,MAAM,EAAE,KAAA,EAAO,KAAA,EAAM,GAAI,IAAA,CAAK,OAAA;AAE9B,IAAA,IAAI,MAAA,GAAS,CAAA;;AAAA,0BAAA,EAET,KAAK;AAAA,CAAA;AAIT,IAAA,IAAI,KAAA,CAAM,aAAa,KAAA,EAAO;AAC5B,MAAA,MAAA,IAAU;AAAA,oCAAA,EAAc,MAAM,QAAQ,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sCAAA,CAAA;AAAA,IAMxC;AAEA,IAAA,IAAI,KAAA,CAAM,gBAAgB,KAAA,EAAO;AAC/B,MAAA,MAAA,IAAU;AAAA,iCAAA,EAAa,MAAM,WAAW,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAAA,CAAA;AAAA,IAM1C;AAEA,IAAA,IAAI,KAAA,CAAM,UAAU,KAAA,EAAO;AACzB,MAAA,MAAA,IAAU;AAAA,oCAAA,EAAc,MAAM,KAAK,CAAA;AAAA;AAAA;AAAA;AAAA,gCAAA,CAAA;AAAA,IAKrC;AAEA,IAAA,IAAI,KAAA,CAAM,iBAAiB,KAAA,EAAO;AAChC,MAAA,MAAA,IAAU;AAAA,oCAAA,EAAc,MAAM,YAAY,CAAA;AAAA;AAAA;AAAA;AAAA,0BAAA,CAAA;AAAA,IAK5C;AAEA,IAAA,MAAA,IAAU;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,oEAAA,CAAA;AAkBV,IAAA,OAAO,IAAIC,uBAAc,MAAM,CAAA;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAA,CAAgB,MAAc,QAAA,EAAgC;AACpE,IAAA,MAAM,OAAA,GAAU,QAAA,CAAS,KAAA,CAAM,GAAG,EAAE,GAAA,EAAI;AACxC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,WAAA,CAAY,OAAA,IAAW,EAAE,CAAA;AAC/C,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAG7B,IAAA,MAAM,mBAAA,GAAsB,KAAA,CACzB,GAAA,CAAI,CAAC,MAAM,KAAA,KAAU,CAAA,EAAG,KAAA,GAAQ,CAAC,CAAA,EAAA,EAAK,IAAI,CAAA,CAAE,CAAA,CAC5C,KAAK,IAAI,CAAA;AAEZ,IAAA,OAAO,IAAIC,qBAAA,CAAa;AAAA,+BAAA,EACpB,QAAQ,CAAA;;AAAA,cAAA,EAEV,QAAQ;AAAA,oBAAA,EACP,MAAM,MAAM;;AAAA;AAAA,MAAA,EAGX,QAAQ;AAAA,EACd,mBAAmB;AAAA;;AAAA;;AAAA;AAAA,CAMpB,CAAA;AAAA,EACC;AAAA;AAAA;AAAA;AAAA,EAKQ,WAAA,CAAY,QAAa,QAAA,EAAiC;AAChE,IAAA,IAAI,CAAC,OAAO,MAAA,IAAU,CAAC,MAAM,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAA,EAAG;AACnD,MAAA,OAAO,EAAC;AAAA,IACV;AAEA,IAAA,OAAO,MAAA,CAAO,MAAA,CACX,GAAA,CAAI,CAAC,KAAA,MAAgB;AAAA,MACpB,IAAA,EAAM,QAAA;AAAA,MACN,MAAM,KAAA,CAAM,IAAA;AAAA,MACZ,QAAA,EAAU,MAAM,QAAA,IAAY,eAAA;AAAA,MAC5B,QAAA,EAAU,MAAM,QAAA,IAAY,MAAA;AAAA,MAC5B,OAAA,EAAS,MAAM,OAAA,IAAW,0BAAA;AAAA,MAC1B,YAAY,KAAA,CAAM,UAAA;AAAA,MAClB,MAAM,KAAA,CAAM;AAAA,KACd,CAAE,CAAA,CACD,MAAA,CAAO,CAAC,KAAA,KAAuB;AAE9B,MAAA,MAAM,WAAA,GACJ,KAAA,CAAM,QAAA,KAAa,eAAA,GAAkB,iBAAiB,KAAA,CAAM,QAAA;AAC9D,MAAA,MAAM,IAAA,GACJ,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,WAA8C,CAAA;AACnE,MAAA,OAAO,QAAQ,IAAA,KAAS,KAAA;AAAA,IAC1B,CAAC,CAAA;AAAA,EACL;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,GAAA,EAAqB;AACvC,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,EAAA,EAAI,YAAA;AAAA,MACJ,GAAA,EAAK,YAAA;AAAA,MACL,EAAA,EAAI,YAAA;AAAA,MACJ,GAAA,EAAK,YAAA;AAAA,MACL,GAAA,EAAK,KAAA;AAAA,MACL,GAAA,EAAK,KAAA;AAAA,MACL,IAAA,EAAM,MAAA;AAAA,MACN,IAAA,EAAM;AAAA,KACR;AAEA,IAAA,OAAO,OAAA,CAAQ,GAAG,CAAA,IAAK,GAAA;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,IAAA,EAAsB;AACxC,IAAA,OAAOC,uBAAA,CAAO,WAAW,KAAK,CAAA,CAAE,OAAO,IAAI,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA,EAKA,UAAA,GAAmB;AACjB,IAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,aAAA,GAAgD;AAC9C,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,KAAK,KAAA,CAAM,IAAA;AAAA,MACjB,IAAA,EAAM;AAAA;AAAA,KACR;AAAA,EACF;AACF;AC7QO,IAAM,WAAN,MAAe;AAAA;AAAA;AAAA;AAAA;AAAA,EAKpB,MAAM,eAAA,GAAqC;AACzC,IAAA,IAAI;AAEF,MAAA,IAAI,CAAC,IAAA,CAAK,eAAA,EAAgB,EAAG;AAC3B,QAAA,OAAA,CAAQ,KAAK,yGAAyB,CAAA;AACtC,QAAA,OAAO,EAAC;AAAA,MACV;AAEA,MAAA,OAAA,CAAQ,IAAI,CAAA,wDAAA,CAA+B,CAAA;AAG3C,MAAA,MAAM,YAAA,GAAe,KAAK,kBAAA,EAAmB;AAE7C,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,mCAAA,EAAgB,YAAA,CAAa,MAAM,CAAA,+BAAA,CAAQ,CAAA;AACvD,MAAA,YAAA,CAAa,OAAA,CAAQ,CAAC,CAAA,KAAM,OAAA,CAAQ,IAAI,CAAA,KAAA,EAAQ,CAAC,EAAE,CAAC,CAAA;AAGpD,MAAA,MAAM,aAAA,GAAgB,YAAA,CACnB,GAAA,CAAI,CAAC,IAAA,KAAS;AAEb,QAAA,MAAM,SAAA,GAAY,IAAA,CAAK,OAAA,CAAQ,UAAA,EAAY,EAAE,CAAA;AAC7C,QAAA,OAAO,SAAA;AAAA,MACT,CAAC,CAAA,CACA,MAAA,CAAO,CAAC,IAAA,KAAS;AAChB,QAAA,MAAM,WAAWC,sBAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,GAAA,IAAO,IAAI,CAAA;AACjD,QAAA,MAAM,MAAA,GAASC,oBAAA,CAAG,UAAA,CAAW,QAAQ,CAAA;AACrC,QAAA,IAAI,CAAC,MAAA,EAAQ;AACX,UAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,iDAAA,EAAiB,QAAQ,CAAA,CAAE,CAAA;AAAA,QACzC;AACA,QAAA,OAAO,MAAA;AAAA,MACT,CAAC,CAAA;AAEH,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,gDAAA,EAAmB,aAAA,CAAc,MAAM,CAAA,OAAA,CAAI,CAAA;AACvD,MAAA,aAAA,CAAc,OAAA,CAAQ,CAAC,CAAA,KAAM,OAAA,CAAQ,IAAI,CAAA,UAAA,EAAQ,CAAC,EAAE,CAAC,CAAA;AAErD,MAAA,OAAO,aAAA;AAAA,IACT,SAAS,KAAA,EAAY;AACnB,MAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,qEAAA,EAAsB,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AAClD,MAAA,OAAO,EAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAA,GAA2B;AACjC,IAAA,IAAI;AACF,MAAAC,sBAAA,CAAS,yBAAA,EAA2B;AAAA,QAClC,KAAA,EAAO,QAAA;AAAA,QACP,GAAA,EAAK,QAAQ,GAAA;AAAI,OAClB,CAAA;AACD,MAAA,OAAO,IAAA;AAAA,IACT,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAA,GAA+B;AACrC,IAAA,IAAI;AAEF,MAAA,MAAM,MAAA,GAASA,uBAAS,kCAAA,EAAoC;AAAA,QAC1D,QAAA,EAAU,OAAA;AAAA,QACV,GAAA,EAAK,QAAQ,GAAA;AAAI,OAClB,CAAA;AAED,MAAA,MAAM,KAAA,GAAQ,MAAA,CACX,IAAA,EAAK,CACL,KAAA,CAAM,IAAI,CAAA,CACV,MAAA,CAAO,CAAC,IAAA,KAAS,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA;AAEnC,MAAA,IAAI,KAAA,CAAM,SAAS,CAAA,EAAG;AACpB,QAAA,OAAO,KAAA;AAAA,MACT;AAGA,MAAA,OAAA,CAAQ,IAAI,CAAA,mIAAA,CAA4B,CAAA;AACxC,MAAA,OAAO,KAAK,kBAAA,EAAmB;AAAA,IACjC,SAAS,KAAA,EAAO;AAEd,MAAA,OAAA,CAAQ,IAAI,CAAA,uHAAA,CAA0B,CAAA;AACtC,MAAA,OAAO,KAAK,mBAAA,EAAoB;AAAA,IAClC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAA,GAA+B;AACrC,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAASA,sBAAA;AAAA,QACb,kDAAA;AAAA,QACA;AAAA,UACE,QAAA,EAAU,OAAA;AAAA,UACV,GAAA,EAAK,QAAQ,GAAA;AAAI;AACnB,OACF;AAEA,MAAA,OAAO,MAAA,CACJ,IAAA,EAAK,CACL,KAAA,CAAM,IAAI,CAAA,CACV,MAAA,CAAO,CAAC,IAAA,KAAS,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA;AAAA,IACrC,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,EAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAA,GAAgC;AACtC,IAAA,IAAI;AAEF,MAAA,MAAM,cAAA,GAAiBA,uBAAS,sBAAA,EAAwB;AAAA,QACtD,QAAA,EAAU,OAAA;AAAA,QACV,GAAA,EAAK,QAAQ,GAAA;AAAI,OAClB,CAAA;AAGD,MAAA,MAAM,YAAA,GAAeA,uBAAS,+BAAA,EAAiC;AAAA,QAC7D,QAAA,EAAU,OAAA;AAAA,QACV,GAAA,EAAK,QAAQ,GAAA;AAAI,OAClB,CAAA;AAED,MAAA,MAAM,aAAA,GAAgB,cAAA,CACnB,IAAA,EAAK,CACL,KAAA,CAAM,IAAI,CAAA,CACV,MAAA,CAAO,CAAC,IAAA,KAAS,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA;AAEnC,MAAA,MAAM,WAAA,GAAc,YAAA,CACjB,IAAA,EAAK,CACL,KAAA,CAAM,IAAI,CAAA,CACV,MAAA,CAAO,CAAC,IAAA,KAAS,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA;AAGnC,MAAA,OAAO,CAAC,mBAAG,IAAI,GAAA,CAAI,CAAC,GAAG,aAAA,EAAe,GAAG,WAAW,CAAC,CAAC,CAAA;AAAA,IACxD,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,EAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,qBAAA,CAAsB,OAAA,GAAkB,CAAA,EAAsB;AAClE,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAASA,sBAAA,CAAS,CAAA,0BAAA,EAA6B,OAAO,CAAA,CAAA,EAAI;AAAA,QAC9D,QAAA,EAAU,OAAA;AAAA,QACV,GAAA,EAAK,QAAQ,GAAA;AAAI,OAClB,CAAA;AAED,MAAA,OAAO,MAAA,CACJ,IAAA,EAAK,CACL,KAAA,CAAM,IAAI,CAAA,CACV,MAAA,CAAO,CAAC,IAAA,KAAS,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA;AAAA,IACrC,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,EAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAA,GAA2B;AACzB,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAASA,uBAAS,iCAAA,EAAmC;AAAA,QACzD,QAAA,EAAU,OAAA;AAAA,QACV,GAAA,EAAK,QAAQ,GAAA;AAAI,OAClB,CAAA;AAED,MAAA,OAAO,OAAO,IAAA,EAAK;AAAA,IACrB,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,SAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,QAAA,EAA0B;AACtC,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAASA,sBAAA,CAAS,CAAA,oBAAA,EAAuB,QAAQ,CAAA,CAAA,CAAA,EAAK;AAAA,QAC1D,QAAA,EAAU,OAAA;AAAA,QACV,GAAA,EAAK,QAAQ,GAAA;AAAI,OAClB,CAAA;AAED,MAAA,MAAM,SAAS,MAAA,CAAO,IAAA,EAAK,CAAE,SAAA,CAAU,GAAG,CAAC,CAAA;AAG3C,MAAA,IAAI,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,EAAG,OAAO,UAAA;AACjC,MAAA,IAAI,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,EAAG,OAAO,OAAA;AACjC,MAAA,IAAI,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,EAAG,OAAO,SAAA;AACjC,MAAA,IAAI,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,EAAG,OAAO,SAAA;AACjC,MAAA,IAAI,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,EAAG,OAAO,WAAA;AAEjC,MAAA,OAAO,WAAA;AAAA,IACT,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,SAAA;AAAA,IACT;AAAA,EACF;AACF;ACzMO,IAAM,WAAN,MAAe;AAAA,EAGpB,WAAA,CAAY,OAAA,GAA2B,EAAC,EAAG;AACzC,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,MAAA,EAAsC;AAEnD,IAAA,IAAI,IAAA,CAAK,QAAQ,OAAA,EAAS;AACxB,MAAA,IAAA,CAAK,sBAAsB,MAAM,CAAA;AAAA,IACnC;AAGA,IAAA,IAAI,IAAA,CAAK,QAAQ,IAAA,EAAM;AACrB,MAAA,MAAM,IAAA,CAAK,mBAAmB,MAAM,CAAA;AAAA,IACtC;AAGA,IAAA,IAAI,IAAA,CAAK,QAAQ,QAAA,EAAU;AACzB,MAAA,MAAM,IAAA,CAAK,uBAAuB,MAAM,CAAA;AAAA,IAC1C;AAGA,IAAA,IAAI,IAAA,CAAK,QAAQ,IAAA,EAAM;AACrB,MAAA,MAAM,IAAA,CAAK,mBAAmB,MAAM,CAAA;AAAA,IACtC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAAsB,MAAA,EAA6B;AACzD,IAAA,OAAA,CAAQ,IAAI,gNAAsC,CAAA;AAClD,IAAA,OAAA,CAAQ,IAAI,gDAAW,CAAA;AACvB,IAAA,OAAA,CAAQ,IAAI,gNAAsC,CAAA;AAGlD,IAAA,MAAM,SAAS,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,OAAO,CAAA;AAC1D,IAAA,MAAM,WAAW,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,MAAM,CAAA;AAC3D,IAAA,MAAM,QAAQ,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,MAAM,CAAA;AAExD,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,qBAAA,EAAS,MAAA,CAAO,MAAM,CAAA,CAAE,CAAA;AACpC,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,4BAAA,EAAW,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AACxC,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,4BAAA,EAAW,KAAA,CAAM,MAAM,CAAA,CAAE,CAAA;AACrC,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,wBAAA,EAAU,MAAA,CAAO,MAAM;AAAA,CAAI,CAAA;AAGvC,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,eAAA,CAAgB,MAAM,CAAA;AAC9C,IAAA,OAAA,CAAQ,IAAI,qCAAU,CAAA;AACtB,IAAA,MAAA,CAAO,OAAA,CAAQ,UAAU,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAC,QAAA,EAAU,KAAK,CAAA,KAAM;AACxD,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAA,EAAK,IAAA,CAAK,eAAA,CAAgB,QAAQ,CAAC,CAAA,CAAA,EAAI,QAAQ,CAAA,EAAA,EAAK,KAAK,CAAA,CAAE,CAAA;AAAA,IACzE,CAAC,CAAA;AAED,IAAA,OAAA,CAAQ,IAAI,kNAAwC,CAAA;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,mBAAmB,MAAA,EAAsC;AACrE,IAAA,MAAM,IAAA,GAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kDAAA,EAAA,iBAmMe,IAAI,IAAA,EAAK,EAAE,cAAA,CAAe,OAAO,CAAC,CAAA;AAAA;;AAAA;AAAA;AAAA;AAAA,cAAA,EAMlD,MAAA,CAAO,OAAO,CAAC,CAAA,KAAM,EAAE,QAAA,KAAa,OAAO,EAAE,MAAM,CAAA;AAAA;AAAA;AAAA;AAAA,cAAA,EAInD,MAAA,CAAO,OAAO,CAAC,CAAA,KAAM,EAAE,QAAA,KAAa,MAAM,EAAE,MAAM,CAAA;AAAA;AAAA;AAAA;AAAA,cAAA,EAIlD,MAAA,CAAO,OAAO,CAAC,CAAA,KAAM,EAAE,QAAA,KAAa,MAAM,EAAE,MAAM,CAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,QAAA,EAOxD,OAAO,OAAA,CAAQ,IAAA,CAAK,eAAA,CAAgB,MAAM,CAAC,CAAA,CAC1C,GAAA;AAAA,MACC,CAAC,CAAC,QAAA,EAAU,KAAK,CAAA,KACf,6BAA6B,IAAA,CAAK,eAAA;AAAA,QAChC;AAAA,OACD,CAAA,CAAA,EAAI,QAAQ,CAAA,EAAA,EAAK,KAAK,CAAA,MAAA;AAAA,KAC3B,CACC,IAAA,CAAK,EAAE,CAAC;AAAA;;AAAA;AAAA,MAAA,EAIX,MAAA,CACC,GAAA;AAAA,MACC,CAAC,KAAA,KAAU;AAAA;AAAA;AAAA,mCAAA,EAIT,MAAM,QACR,CAAA,EAAA,EAAK,KAAA,CAAM,QAAA,CAAS,aAAa,CAAA;AAAA,uCAAA,EACF,MAAM,QAAQ,CAAA;AAAA,mCAAA,EAClB,MAAM,IAAI,CAAA;AAAA,UAAA,EAEnC,MAAM,IAAA,GAAO,CAAA,gCAAA,EAA8B,KAAA,CAAM,IAAI,YAAY,EACnE;AAAA;AAAA,mCAAA,EAE2B,MAAM,OAAO,CAAA;AAAA,QAAA,EAExC,MAAM,UAAA,GACF,CAAA,8BAAA,EAAiC,KAAA,CAAM,UAAU,WACjD,EACN;AAAA;AAAA,IAAA;AAAA,KAGA,CACC,IAAA,CAAK,EAAE,CAAC;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA,CAAA;AAab,IAAA,MAAM,aAAaF,sBAAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,GAAA,IAAO,YAAY,CAAA;AACxD,IAAA,IAAI,CAACC,oBAAAA,CAAG,UAAA,CAAW,UAAU,CAAA,EAAG;AAC9B,MAAAA,qBAAG,SAAA,CAAU,UAAA,EAAY,EAAE,SAAA,EAAW,MAAM,CAAA;AAAA,IAC9C;AAEA,IAAA,MAAM,UAAA,GAAaD,sBAAAA,CAAK,IAAA,CAAK,UAAA,EAAY,yBAAyB,CAAA;AAClE,IAAAC,oBAAAA,CAAG,aAAA,CAAc,UAAA,EAAY,IAAA,EAAM,OAAO,CAAA;AAC1C,IAAA,OAAA,CAAQ,GAAA,CAAI,kDAAkB,UAAU;AAAA,CAAI,CAAA;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,uBAAuB,MAAA,EAAsC;AACzE,IAAA,MAAM,SAAS,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,OAAO,CAAA;AAC1D,IAAA,MAAM,WAAW,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,MAAM,CAAA;AAC3D,IAAA,MAAM,QAAQ,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,MAAM,CAAA;AAExD,IAAA,IAAI,QAAA,GAAW,CAAA;;AAAA,0BAAA,EAAA,iBAEX,IAAI,IAAA,EAAK,EAAE,cAAA,CAAe,OAAO,CAAC;;AAAA;;AAAA;AAAA;AAAA,wBAAA,EAM/B,OAAO,MAAM,CAAA;AAAA,8BAAA,EACZ,SAAS,MAAM,CAAA;AAAA,8BAAA,EACf,MAAM,MAAM,CAAA;AAAA,2BAAA,EACZ,OAAO,MAAM,CAAA;;AAAA;;AAAA,CAAA;AAMrB,IAAA,MAAA,CAAO,OAAA,CAAQ,CAAC,KAAA,EAAO,KAAA,KAAU;AAC/B,MAAA,MAAM,IAAA,GAAO,IAAA,CAAK,eAAA,CAAgB,KAAA,CAAM,QAAQ,CAAA;AAChD,MAAA,QAAA,IAAY,OAAO,KAAA,GAAQ,CAAC,KAAK,IAAI,CAAA,CAAA,EAAI,MAAM,QAAQ;;AAAA,oBAAA,EAEjD,KAAA,CAAM,IAAI,CAAA,EAAG,KAAA,CAAM,OAAO,CAAA,CAAA,EAAI,KAAA,CAAM,IAAI,CAAA,CAAA,GAAK,EAAE,CAAA;AAAA,8BAAA,EAC/C,MAAM,QAAQ,CAAA;AAAA,kBAAA,EAChB,MAAM,OAAO;;AAAA,CAAA;AAIjB,MAAA,IAAI,MAAM,UAAA,EAAY;AACpB,QAAA,QAAA,IAAY,CAAA,4BAAA,EAAc,MAAM,UAAU;;AAAA,CAAA;AAAA,MAC5C;AAEA,MAAA,QAAA,IAAY,SAAA;AAAA,IACd,CAAC,CAAA;AAGD,IAAA,MAAM,aAAaD,sBAAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,GAAA,IAAO,YAAY,CAAA;AACxD,IAAA,IAAI,CAACC,oBAAAA,CAAG,UAAA,CAAW,UAAU,CAAA,EAAG;AAC9B,MAAAA,qBAAG,SAAA,CAAU,UAAA,EAAY,EAAE,SAAA,EAAW,MAAM,CAAA;AAAA,IAC9C;AAEA,IAAA,MAAM,UAAA,GAAaD,sBAAAA,CAAK,IAAA,CAAK,UAAA,EAAY,uBAAuB,CAAA;AAChE,IAAAC,oBAAAA,CAAG,aAAA,CAAc,UAAA,EAAY,QAAA,EAAU,OAAO,CAAA;AAC9C,IAAA,OAAA,CAAQ,GAAA,CAAI,sDAAsB,UAAU;AAAA,CAAI,CAAA;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,mBAAmB,MAAA,EAAsC;AACrE,IAAA,MAAM,MAAA,GAAS;AAAA,MACb,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,MAClC,OAAA,EAAS;AAAA,QACP,OAAO,MAAA,CAAO,MAAA;AAAA,QACd,MAAA,EAAQ,OAAO,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,QAAA,KAAa,OAAO,CAAA,CAAE,MAAA;AAAA,QACrD,QAAA,EAAU,OAAO,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,QAAA,KAAa,MAAM,CAAA,CAAE,MAAA;AAAA,QACtD,KAAA,EAAO,OAAO,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,QAAA,KAAa,MAAM,CAAA,CAAE;AAAA,OACrD;AAAA,MACA;AAAA,KACF;AAGA,IAAA,MAAM,aAAaD,sBAAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,GAAA,IAAO,YAAY,CAAA;AACxD,IAAA,IAAI,CAACC,oBAAAA,CAAG,UAAA,CAAW,UAAU,CAAA,EAAG;AAC9B,MAAAA,qBAAG,SAAA,CAAU,UAAA,EAAY,EAAE,SAAA,EAAW,MAAM,CAAA;AAAA,IAC9C;AAEA,IAAA,MAAM,UAAA,GAAaD,sBAAAA,CAAK,IAAA,CAAK,UAAA,EAAY,yBAAyB,CAAA;AAClE,IAAAC,oBAAAA,CAAG,cAAc,UAAA,EAAY,IAAA,CAAK,UAAU,MAAA,EAAQ,IAAA,EAAM,CAAC,CAAA,EAAG,OAAO,CAAA;AACrE,IAAA,OAAA,CAAQ,GAAA,CAAI,kDAAkB,UAAU;AAAA,CAAI,CAAA;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB,MAAA,EAA+C;AACrE,IAAA,MAAM,SAAiC,EAAC;AAExC,IAAA,MAAA,CAAO,OAAA,CAAQ,CAAC,KAAA,KAAU;AACxB,MAAA,MAAA,CAAO,MAAM,QAAQ,CAAA,GAAA,CAAK,OAAO,KAAA,CAAM,QAAQ,KAAK,CAAA,IAAK,CAAA;AAAA,IAC3D,CAAC,CAAA;AAED,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB,QAAA,EAA0B;AAChD,IAAA,MAAM,KAAA,GAAgC;AAAA,MACpC,QAAA,EAAU,WAAA;AAAA,MACV,WAAA,EAAa,QAAA;AAAA,MACb,KAAA,EAAO,WAAA;AAAA,MACP,eAAA,EAAiB;AAAA,KACnB;AAEA,IAAA,OAAO,KAAA,CAAM,QAAQ,CAAA,IAAK,WAAA;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB,QAAA,EAA0B;AAChD,IAAA,QAAQ,QAAA;AAAU,MAChB,KAAK,OAAA;AACH,QAAA,OAAO,QAAA;AAAA,MACT,KAAK,MAAA;AACH,QAAA,OAAO,cAAA;AAAA,MACT,KAAK,MAAA;AACH,QAAA,OAAO,cAAA;AAAA,MACT;AACE,QAAA,OAAO,WAAA;AAAA;AACX,EACF;AACF;;;AChaO,SAAS,sBAAA,CACd,OAAA,GAA6B,EAAC,EACtB;AACR,EAAA,MAAM;AAAA,IACJ,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,cAAA,IAAkB,EAAA;AAAA,IACvC,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,cAAA,IAAkB,2BAAA;AAAA,IACvC,KAAA,GAAQ,OAAA;AAAA,IACR,IAAA,GAAO,SAAA;AAAA,IACP,QAAQ,EAAC;AAAA,IACT,KAAA,GAAQ,UAAA;AAAA,IACR,KAAA,GAAQ;AAAA,MACN,QAAA,EAAU,OAAA;AAAA,MACV,WAAA,EAAa,MAAA;AAAA,MACb,KAAA,EAAO,MAAA;AAAA,MACP,YAAA,EAAc;AAAA,KAChB;AAAA,IACA,OAAA,GAAU,CAAC,0BAA0B,CAAA;AAAA,IACrC,OAAA,GAAU,CAAC,oBAAA,EAAsB,YAAA,EAAc,mBAAmB,CAAA;AAAA,IAClE,MAAA,GAAS;AAAA,MACP,OAAA,EAAS,IAAA;AAAA,MACT,IAAA,EAAM,IAAA;AAAA,MACN,QAAA,EAAU,KAAA;AAAA,MACV,IAAA,EAAM,KAAA;AAAA,MACN,WAAA,EAAa;AAAA,KACf;AAAA,IACA,KAAA,GAAQ,IAAA;AAAA,IACR,SAAA,GAAY,CAAA;AAAA,IACZ,aAAA,GAAgB,CAAA;AAAA,IAChB,OAAA,GAAU;AAAA,GACZ,GAAI,OAAA;AAEJ,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAO;AAAA,MACL,IAAA,EAAM;AAAA,KACR;AAAA,EACF;AAEA,EAAA,MAAM,QAAA,GAAW,IAAI,YAAA,CAAa;AAAA,IAChC,MAAA;AAAA,IACA,MAAA;AAAA,IACA,KAAA;AAAA,IACA,KAAA;AAAA,IACA,KAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,QAAA,GAAW,IAAI,QAAA,EAAS;AAC9B,EAAA,MAAM,QAAA,GAAW,IAAI,QAAA,CAAS,MAAM,CAAA;AAEpC,EAAA,IAAI,gBAA0B,EAAC;AAC/B,EAAA,IAAI,YAAmB,EAAC;AAExB,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,4BAAA;AAAA,IACN,OAAA,EAAS,MAAA;AAAA,IAET,eAAe,MAAA,EAAQ;AACrB,MAAA,OAAA,CAAQ,IAAI,kDAA4B,CAAA;AACxC,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,oCAAA,EAAY,IAAI,CAAA,CAAE,CAAA;AAC9B,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,oCAAA,EAAY,KAAK,CAAA,CAAE,CAAA;AAC/B,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,mBAAA,EAAe,MAAA,GAAS,oBAAA,GAAQ,oBAAK;AAAA,CAAI,CAAA;AAAA,IACvD,CAAA;AAAA,IAEA,MAAM,UAAA,GAAa;AACjB,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,OAAA,CAAQ,KAAK,oFAAwB,CAAA;AACrC,QAAA;AAAA,MACF;AAGA,MAAA,IAAI,SAAS,SAAA,EAAW;AACtB,QAAA,aAAA,GAAgB,MAAM,SAAS,eAAA,EAAgB;AAC/C,QAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,mCAAA,EAAgB,aAAA,CAAc,MAAM,CAAA,+BAAA,CAAQ,CAAA;AACxD,QAAA,aAAA,CAAc,OAAA,CAAQ,CAAC,CAAA,KAAM,OAAA,CAAQ,IAAI,CAAA,KAAA,EAAQ,CAAC,EAAE,CAAC,CAAA;AAAA,MACvD,CAAA,MAAA,IAAW,SAAS,QAAA,EAAU;AAC5B,QAAA,aAAA,GAAgB,KAAA;AAAA,MAClB,CAAA,MAAO;AAEL,QAAA,aAAA,GAAgB,EAAC;AAAA,MACnB;AAGA,MAAA,aAAA,GAAgB,aAAA,CAAc,MAAA;AAAA,QAAO,CAAC,IAAA,KACpC,YAAA,CAAa,IAAA,EAAM,SAAS,OAAO;AAAA,OACrC;AAEA,MAAA,IAAI,IAAA,KAAS,KAAA,IAAS,aAAA,CAAc,MAAA,GAAS,CAAA,EAAG;AAC9C,QAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,qDAAA,EAAc,aAAA,CAAc,MAAM,CAAA;AAAA,CAAQ,CAAA;AAGtD,QAAA,KAAA,MAAW,QAAQ,aAAA,EAAe;AAChC,UAAA,IAAI;AACF,YAAA,MAAMA,GAAAA,GAAK,MAAM,OAAO,IAAI,CAAA;AAC5B,YAAA,MAAMD,KAAAA,GAAO,MAAM,OAAO,MAAM,CAAA;AAChC,YAAA,MAAM,WAAWA,KAAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,GAAA,IAAO,IAAI,CAAA;AAEjD,YAAA,IAAIC,GAAAA,CAAG,UAAA,CAAW,QAAQ,CAAA,EAAG;AAC3B,cAAA,MAAM,IAAA,GAAOA,GAAAA,CAAG,YAAA,CAAa,QAAA,EAAU,OAAO,CAAA;AAC9C,cAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,yBAAA,EAAW,IAAI,CAAA,CAAE,CAAA;AAE7B,cAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,MAAA,CAAO,MAAM,IAAI,CAAA;AAE/C,cAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,gBAAA,SAAA,CAAU,IAAA,CAAK,GAAG,MAAM,CAAA;AAGxB,gBAAA,IAAI,OAAO,OAAA,EAAS;AAClB,kBAAA,MAAA,CAAO,OAAA,CAAQ,CAAC,KAAA,KAAU;AACxB,oBAAA,MAAM,IAAA,GAAO,eAAA,CAAgB,KAAA,CAAM,QAAQ,CAAA;AAC3C,oBAAA,OAAA,CAAQ,GAAA;AAAA,sBACN,CAAA,EAAG,IAAI,CAAA,EAAA,EAAK,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK,KAAA,CAAM,IAAI,CAAA,CAAA,EACvC,KAAA,CAAM,IAAA,IAAQ,GAChB,CAAA;AAAA,qBACF;AACA,oBAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,GAAA,EAAM,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AACjC,oBAAA,IAAI,MAAM,UAAA,EAAY;AACpB,sBAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,aAAA,EAAS,KAAA,CAAM,UAAU,CAAA,CAAE,CAAA;AAAA,oBACzC;AAAA,kBACF,CAAC,CAAA;AACD,kBAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AAAA,gBAChB;AAAA,cACF,CAAA,MAAO;AACL,gBAAA,OAAA,CAAQ,GAAA,CAAI,CAAA;AAAA,CAAW,CAAA;AAAA,cACzB;AAAA,YACF;AAAA,UACF,SAAS,KAAA,EAAY;AACnB,YAAA,OAAA,CAAQ,KAAK,CAAA,uCAAA,EAAY,IAAI,CAAA,EAAA,EAAK,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AAAA,UACnD;AAAA,QACF;AAAA,MACF,CAAA,MAAA,IAAW,SAAS,KAAA,EAAO;AACzB,QAAA,OAAA,CAAQ,GAAA,CAAI,CAAA;AAAA,CAAgB,CAAA;AAAA,MAC9B;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,SAAA,CAAU,IAAA,EAAc,EAAA,EAAY;AAExC,MAAA,IAAI,SAAS,KAAA,EAAO;AAClB,QAAA,OAAO,IAAA;AAAA,MACT;AAGA,MAAA,IAAI,EAAA,CAAG,SAAS,cAAc,CAAA,IAAK,CAAC,YAAA,CAAa,EAAA,EAAI,OAAA,EAAS,OAAO,CAAA,EAAG;AACtE,QAAA,OAAO,IAAA;AAAA,MACT;AAGA,MAAA,IAAI,CAAC,EAAA,CAAG,KAAA,CAAM,wBAAwB,CAAA,EAAG;AACvC,QAAA,OAAO,IAAA;AAAA,MACT;AAEA,MAAA,IAAI;AACF,QAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,yBAAA,EAAW,EAAE,CAAA,CAAE,CAAA;AAG3B,QAAA,MAAMA,GAAAA,GAAK,MAAM,OAAO,IAAI,CAAA;AAC5B,QAAA,IAAI,UAAA,GAAa,IAAA;AAGjB,QAAA,IAAIA,GAAAA,CAAG,UAAA,CAAW,EAAE,CAAA,EAAG;AACrB,UAAA,UAAA,GAAaA,GAAAA,CAAG,YAAA,CAAa,EAAA,EAAI,OAAO,CAAA;AAAA,QAC1C;AAEA,QAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,MAAA,CAAO,YAAY,EAAE,CAAA;AAEnD,QAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,UAAA,SAAA,CAAU,IAAA,CAAK,GAAG,MAAM,CAAA;AAGxB,UAAA,IAAI,OAAO,OAAA,EAAS;AAClB,YAAA,MAAA,CAAO,OAAA,CAAQ,CAAC,KAAA,KAAU;AACxB,cAAA,MAAM,IAAA,GAAO,eAAA,CAAgB,KAAA,CAAM,QAAQ,CAAA;AAC3C,cAAA,OAAA,CAAQ,GAAA;AAAA,gBACN,CAAA,EAAG,IAAI,CAAA,EAAA,EAAK,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK,KAAA,CAAM,IAAI,CAAA,CAAA,EACvC,KAAA,CAAM,IAAA,IAAQ,GAChB,CAAA;AAAA,eACF;AACA,cAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,GAAA,EAAM,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AACjC,cAAA,IAAI,MAAM,UAAA,EAAY;AACpB,gBAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,aAAA,EAAS,KAAA,CAAM,UAAU,CAAA,CAAE,CAAA;AAAA,cACzC;AAAA,YACF,CAAC,CAAA;AACD,YAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AAAA,UAChB;AAAA,QACF;AAAA,MACF,SAAS,KAAA,EAAY;AACnB,QAAA,OAAA,CAAQ,KAAK,CAAA,uCAAA,EAAY,EAAE,CAAA,EAAA,EAAK,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AAAA,MACjD;AAEA,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IAEA,MAAM,QAAA,GAAW;AACf,MAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EAAG;AAC1B,QAAA,OAAA,CAAQ,IAAI,mFAAkB,CAAA;AAC9B,QAAA;AAAA,MACF;AAGA,MAAA,MAAM,QAAA,CAAS,SAAS,SAAS,CAAA;AAGjC,MAAA,IAAI,OAAO,WAAA,EAAa;AACtB,QAAA,MAAM,SAAS,SAAA,CAAU,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,OAAO,CAAA;AAC7D,QAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,UAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qCAAA,EAAU,MAAA,CAAO,MAAM,CAAA,mBAAA,CAAM,CAAA;AAAA,QAC/C;AAAA,MACF;AAAA,IACF;AAAA,GACF;AACF;AAKA,SAAS,YAAA,CACP,QAAA,EACA,OAAA,EACA,OAAA,EACS;AAET,EAAA,KAAA,MAAW,WAAW,OAAA,EAAS;AAC7B,IAAA,IAAI,YAAA,CAAa,QAAA,EAAU,OAAO,CAAA,EAAG;AACnC,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAGA,EAAA,KAAA,MAAW,WAAW,OAAA,EAAS;AAC7B,IAAA,IAAI,YAAA,CAAa,QAAA,EAAU,OAAO,CAAA,EAAG;AACnC,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,OAAO,KAAA;AACT;AAKA,SAAS,YAAA,CAAa,UAAkB,OAAA,EAA0B;AAEhE,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,OAAA,CAAQ,SAAA,EAAW,EAAE,CAAA;AAGlD,EAAA,MAAM,QAAA,GAAW,YAAA,CAAa,KAAA,CAAM,UAAU,CAAA;AAC9C,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,CAAC,CAAA,CAAE,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,EAAM,CAAA;AACvD,IAAA,OAAO,KAAK,IAAA,CAAK,CAAC,QAAQ,QAAA,CAAS,QAAA,CAAS,GAAG,CAAC,CAAA;AAAA,EAClD;AAGA,EAAA,OAAO,SAAS,QAAA,CAAS,YAAA,CAAa,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA;AAC1D;AAKA,SAAS,gBAAgB,QAAA,EAA0B;AACjD,EAAA,QAAQ,QAAA;AAAU,IAChB,KAAK,OAAA;AACH,MAAA,OAAO,QAAA;AAAA,IACT,KAAK,MAAA;AACH,MAAA,OAAO,cAAA;AAAA,IACT,KAAK,MAAA;AACH,MAAA,OAAO,cAAA;AAAA,IACT;AACE,MAAA,OAAO,WAAA;AAAA;AAEb;AAMA,IAAO,aAAA,GAAQ","file":"index.js","sourcesContent":["/**\r\n * AI 代码审查器\r\n */\r\n\r\nimport { ChatOpenAI } from \"@langchain/openai\";\r\nimport { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\r\nimport crypto from \"crypto\";\r\n\r\nexport interface ReviewIssue {\r\n file: string;\r\n line?: number;\r\n category: \"security\" | \"performance\" | \"style\" | \"best-practice\";\r\n severity: \"error\" | \"warn\" | \"info\";\r\n message: string;\r\n suggestion?: string;\r\n code?: string;\r\n}\r\n\r\nexport interface ReviewerOptions {\r\n apiKey: string;\r\n apiUrl: string;\r\n model: string;\r\n level: \"quick\" | \"standard\" | \"thorough\";\r\n rules: {\r\n security?: string;\r\n performance?: string;\r\n style?: string;\r\n bestPractice?: string;\r\n };\r\n cache: boolean;\r\n}\r\n\r\nexport class CodeReviewer {\r\n private llm: ChatOpenAI | null = null;\r\n private options: ReviewerOptions;\r\n private cache: Map<string, ReviewIssue[]> = new Map();\r\n\r\n constructor(options: ReviewerOptions) {\r\n this.options = options;\r\n\r\n if (options.apiKey) {\r\n this.llm = new ChatOpenAI({\r\n openAIApiKey: options.apiKey,\r\n configuration: { baseURL: options.apiUrl },\r\n modelName: options.model,\r\n temperature: 0.2,\r\n maxTokens: 4000,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * 审查代码\r\n */\r\n async review(code: string, filePath: string): Promise<ReviewIssue[]> {\r\n if (!this.llm) {\r\n return [];\r\n }\r\n\r\n // 检查缓存\r\n if (this.options.cache) {\r\n const cacheKey = this.getCacheKey(code);\r\n if (this.cache.has(cacheKey)) {\r\n return this.cache.get(cacheKey)!;\r\n }\r\n }\r\n\r\n try {\r\n const issues = await this.performReview(code, filePath);\r\n\r\n // 保存到缓存\r\n if (this.options.cache) {\r\n const cacheKey = this.getCacheKey(code);\r\n this.cache.set(cacheKey, issues);\r\n }\r\n\r\n return issues;\r\n } catch (error: any) {\r\n console.error(`❌ 审查失败: ${error.message}`);\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * 执行审查\r\n */\r\n private async performReview(\r\n code: string,\r\n filePath: string\r\n ): Promise<ReviewIssue[]> {\r\n const systemPrompt = this.buildSystemPrompt();\r\n const userPrompt = this.buildUserPrompt(code, filePath);\r\n\r\n const response = await this.llm!.invoke([systemPrompt, userPrompt]);\r\n const content = response.content.toString();\r\n\r\n // 解析 JSON 响应\r\n try {\r\n const result = JSON.parse(content);\r\n const issues = this.parseIssues(result, filePath);\r\n return issues;\r\n } catch (error) {\r\n // 如果解析失败,尝试提取 JSON\r\n const jsonMatch = content.match(/\\{[\\s\\S]*\\}/);\r\n if (jsonMatch) {\r\n const result = JSON.parse(jsonMatch[0]);\r\n const issues = this.parseIssues(result, filePath);\r\n return issues;\r\n }\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * 构建系统提示\r\n */\r\n private buildSystemPrompt(): SystemMessage {\r\n const { level, rules } = this.options;\r\n\r\n let prompt = `你是一个专业的代码审查专家。请审查代码并识别问题。\r\n\r\n审查级别: ${level}\r\n`;\r\n\r\n // 添加规则说明\r\n if (rules.security !== \"off\") {\r\n prompt += `\\n🔒 安全问题 (${rules.security}):\r\n- XSS 漏洞\r\n- SQL 注入\r\n- eval() 使用\r\n- 敏感信息泄露\r\n- 不安全的依赖`;\r\n }\r\n\r\n if (rules.performance !== \"off\") {\r\n prompt += `\\n⚡ 性能问题 (${rules.performance}):\r\n- 大循环\r\n- 内存泄漏\r\n- 重复计算\r\n- 不必要的渲染\r\n- 阻塞操作`;\r\n }\r\n\r\n if (rules.style !== \"off\") {\r\n prompt += `\\n📝 代码规范 (${rules.style}):\r\n- 命名规范\r\n- 代码复杂度\r\n- 重复代码\r\n- 注释完整性`;\r\n }\r\n\r\n if (rules.bestPractice !== \"off\") {\r\n prompt += `\\n🎨 最佳实践 (${rules.bestPractice}):\r\n- 错误处理\r\n- 类型安全\r\n- 组件设计\r\n- 状态管理`;\r\n }\r\n\r\n prompt += `\\n\\n返回 JSON 格式:\r\n{\r\n \"issues\": [\r\n {\r\n \"line\": 10, // 必须是准确的行号!\r\n \"category\": \"security\",\r\n \"severity\": \"error\",\r\n \"message\": \"使用了 eval(),存在安全风险\",\r\n \"suggestion\": \"使用 JSON.parse() 或其他安全方法\"\r\n }\r\n ]\r\n}\r\n\r\n**重要提示**:\r\n1. line 字段必须是准确的行号,与代码中的行号一致\r\n2. 如果代码带有行号前缀(如 \"10: const x = 1\"),请提取正确的行号\r\n3. 只返回 JSON,不要其他解释`;\r\n\r\n return new SystemMessage(prompt);\r\n }\r\n\r\n /**\r\n * 构建用户提示\r\n */\r\n private buildUserPrompt(code: string, filePath: string): HumanMessage {\r\n const fileExt = filePath.split(\".\").pop();\r\n const language = this.getLanguage(fileExt || \"\");\r\n const lines = code.split(\"\\n\");\r\n\r\n // 添加行号到代码中,帮助 AI 准确定位\r\n const codeWithLineNumbers = lines\r\n .map((line, index) => `${index + 1}: ${line}`)\r\n .join(\"\\n\");\r\n\r\n return new HumanMessage(`\r\n请审查以下 ${language} 代码:\r\n\r\n文件: ${filePath}\r\n总行数: ${lines.length}\r\n\r\n代码(带行号):\r\n\\`\\`\\`${language}\r\n${codeWithLineNumbers}\r\n\\`\\`\\`\r\n\r\n**重要**:请返回准确的行号!行号必须与上面代码中的行号一致。\r\n\r\n请返回 JSON 格式的问题列表。\r\n`);\r\n }\r\n\r\n /**\r\n * 解析问题\r\n */\r\n private parseIssues(result: any, filePath: string): ReviewIssue[] {\r\n if (!result.issues || !Array.isArray(result.issues)) {\r\n return [];\r\n }\r\n\r\n return result.issues\r\n .map((issue: any) => ({\r\n file: filePath,\r\n line: issue.line,\r\n category: issue.category || \"best-practice\",\r\n severity: issue.severity || \"info\",\r\n message: issue.message || \"未知问题\",\r\n suggestion: issue.suggestion,\r\n code: issue.code,\r\n }))\r\n .filter((issue: ReviewIssue) => {\r\n // 根据规则过滤 - 处理连字符和驼峰命名的转换\r\n const categoryKey =\r\n issue.category === \"best-practice\" ? \"bestPractice\" : issue.category;\r\n const rule =\r\n this.options.rules[categoryKey as keyof typeof this.options.rules];\r\n return rule && rule !== \"off\";\r\n });\r\n }\r\n\r\n /**\r\n * 获取语言类型\r\n */\r\n private getLanguage(ext: string): string {\r\n const langMap: Record<string, string> = {\r\n ts: \"typescript\",\r\n tsx: \"typescript\",\r\n js: \"javascript\",\r\n jsx: \"javascript\",\r\n vue: \"vue\",\r\n css: \"css\",\r\n scss: \"scss\",\r\n less: \"less\",\r\n };\r\n\r\n return langMap[ext] || ext;\r\n }\r\n\r\n /**\r\n * 生成缓存键\r\n */\r\n private getCacheKey(code: string): string {\r\n return crypto.createHash(\"md5\").update(code).digest(\"hex\");\r\n }\r\n\r\n /**\r\n * 清除缓存\r\n */\r\n clearCache(): void {\r\n this.cache.clear();\r\n }\r\n\r\n /**\r\n * 获取缓存统计\r\n */\r\n getCacheStats(): { size: number; hits: number } {\r\n return {\r\n size: this.cache.size,\r\n hits: 0, // 可以添加计数器跟踪\r\n };\r\n }\r\n}\r\n","/**\r\n * Git 工具类\r\n * 用于获取 Git 变更信息\r\n * 统一策略:对比上一次提交(HEAD~1)\r\n */\r\n\r\nimport { execSync } from \"child_process\";\r\nimport fs from \"fs\";\r\nimport path from \"path\";\r\n\r\nexport class GitUtils {\r\n /**\r\n * 获取 Git 变更的文件列表\r\n * 统一策略:对比上一次提交(HEAD~1)\r\n */\r\n async getChangedFiles(): Promise<string[]> {\r\n try {\r\n // 检查是否在 Git 仓库中\r\n if (!this.isGitRepository()) {\r\n console.warn(\"⚠️ 不在 Git 仓库中,无法获取变更文件\");\r\n return [];\r\n }\r\n\r\n console.log(`🔍 [Git] 对比策略: HEAD~1 vs HEAD`);\r\n\r\n // 统一使用对比上一次提交的方式\r\n const changedFiles = this.getCommitDiffFiles();\r\n\r\n console.log(`🔍 [Git] 检测到 ${changedFiles.length} 个变更文件`);\r\n changedFiles.forEach((f) => console.log(` - ${f}`));\r\n\r\n // 过滤存在的文件,并处理路径\r\n const existingFiles = changedFiles\r\n .map((file) => {\r\n // 移除可能的前缀路径(如 ai-uni-app/)\r\n const cleanFile = file.replace(/^[^/]+\\//, \"\");\r\n return cleanFile;\r\n })\r\n .filter((file) => {\r\n const fullPath = path.resolve(process.cwd(), file);\r\n const exists = fs.existsSync(fullPath);\r\n if (!exists) {\r\n console.log(` ⚠️ 文件不存在: ${fullPath}`);\r\n }\r\n return exists;\r\n });\r\n\r\n console.log(`🔍 [Git] 过滤后文件: ${existingFiles.length} 个`);\r\n existingFiles.forEach((f) => console.log(` ✓ ${f}`));\r\n\r\n return existingFiles;\r\n } catch (error: any) {\r\n console.warn(`⚠️ 获取 Git 变更文件失败: ${error.message}`);\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * 检查是否在 Git 仓库中\r\n */\r\n private isGitRepository(): boolean {\r\n try {\r\n execSync(\"git rev-parse --git-dir\", {\r\n stdio: \"ignore\",\r\n cwd: process.cwd(),\r\n });\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * 获取与上一次提交的差异文件\r\n */\r\n private getCommitDiffFiles(): string[] {\r\n try {\r\n // 尝试对比上一次提交\r\n const output = execSync(\"git diff --name-only HEAD~1 HEAD\", {\r\n encoding: \"utf-8\",\r\n cwd: process.cwd(),\r\n });\r\n\r\n const files = output\r\n .trim()\r\n .split(\"\\n\")\r\n .filter((file) => file.length > 0);\r\n\r\n if (files.length > 0) {\r\n return files;\r\n }\r\n\r\n // 如果没有上一次提交(首次提交),获取当前提交的所有文件\r\n console.log(` ℹ️ 没有上一次提交,获取当前提交的所有文件`);\r\n return this.getLastCommitFiles();\r\n } catch (error) {\r\n // 降级:获取未提交的变更\r\n console.log(` ℹ️ 无法对比提交,尝试获取未提交的变更`);\r\n return this.getUncommittedFiles();\r\n }\r\n }\r\n\r\n /**\r\n * 获取最近一次提交的所有文件\r\n */\r\n private getLastCommitFiles(): string[] {\r\n try {\r\n const output = execSync(\r\n \"git diff-tree --no-commit-id --name-only -r HEAD\",\r\n {\r\n encoding: \"utf-8\",\r\n cwd: process.cwd(),\r\n }\r\n );\r\n\r\n return output\r\n .trim()\r\n .split(\"\\n\")\r\n .filter((file) => file.length > 0);\r\n } catch {\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * 获取未提交的变更文件(降级方案)\r\n */\r\n private getUncommittedFiles(): string[] {\r\n try {\r\n // 获取未暂存的文件\r\n const unstagedOutput = execSync(\"git diff --name-only\", {\r\n encoding: \"utf-8\",\r\n cwd: process.cwd(),\r\n });\r\n\r\n // 获取已暂存的文件\r\n const stagedOutput = execSync(\"git diff --cached --name-only\", {\r\n encoding: \"utf-8\",\r\n cwd: process.cwd(),\r\n });\r\n\r\n const unstagedFiles = unstagedOutput\r\n .trim()\r\n .split(\"\\n\")\r\n .filter((file) => file.length > 0);\r\n\r\n const stagedFiles = stagedOutput\r\n .trim()\r\n .split(\"\\n\")\r\n .filter((file) => file.length > 0);\r\n\r\n // 合并并去重\r\n return [...new Set([...unstagedFiles, ...stagedFiles])];\r\n } catch {\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * 获取最近 N 次提交的变更文件\r\n */\r\n async getRecentChangedFiles(commits: number = 1): Promise<string[]> {\r\n try {\r\n const output = execSync(`git diff --name-only HEAD~${commits}`, {\r\n encoding: \"utf-8\",\r\n cwd: process.cwd(),\r\n });\r\n\r\n return output\r\n .trim()\r\n .split(\"\\n\")\r\n .filter((file) => file.length > 0);\r\n } catch {\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * 获取当前分支名\r\n */\r\n getCurrentBranch(): string {\r\n try {\r\n const output = execSync(\"git rev-parse --abbrev-ref HEAD\", {\r\n encoding: \"utf-8\",\r\n cwd: process.cwd(),\r\n });\r\n\r\n return output.trim();\r\n } catch {\r\n return \"unknown\";\r\n }\r\n }\r\n\r\n /**\r\n * 获取文件的 Git 状态\r\n */\r\n getFileStatus(filePath: string): string {\r\n try {\r\n const output = execSync(`git status --short \"${filePath}\"`, {\r\n encoding: \"utf-8\",\r\n cwd: process.cwd(),\r\n });\r\n\r\n const status = output.trim().substring(0, 2);\r\n\r\n // 解析状态\r\n if (status.includes(\"M\")) return \"modified\";\r\n if (status.includes(\"A\")) return \"added\";\r\n if (status.includes(\"D\")) return \"deleted\";\r\n if (status.includes(\"R\")) return \"renamed\";\r\n if (status.includes(\"?\")) return \"untracked\";\r\n\r\n return \"unchanged\";\r\n } catch {\r\n return \"unknown\";\r\n }\r\n }\r\n}\r\n","/**\r\n * 报告生成器\r\n */\r\n\r\nimport fs from \"fs\";\r\nimport path from \"path\";\r\nimport type { ReviewIssue } from \"./reviewer\";\r\n\r\nexport interface ReporterOptions {\r\n console?: boolean;\r\n html?: boolean;\r\n markdown?: boolean;\r\n json?: boolean;\r\n failOnError?: boolean;\r\n}\r\n\r\nexport class Reporter {\r\n private options: ReporterOptions;\r\n\r\n constructor(options: ReporterOptions = {}) {\r\n this.options = options;\r\n }\r\n\r\n /**\r\n * 生成报告\r\n */\r\n async generate(issues: ReviewIssue[]): Promise<void> {\r\n // 控制台报告\r\n if (this.options.console) {\r\n this.generateConsoleReport(issues);\r\n }\r\n\r\n // HTML 报告\r\n if (this.options.html) {\r\n await this.generateHTMLReport(issues);\r\n }\r\n\r\n // Markdown 报告\r\n if (this.options.markdown) {\r\n await this.generateMarkdownReport(issues);\r\n }\r\n\r\n // JSON 报告\r\n if (this.options.json) {\r\n await this.generateJSONReport(issues);\r\n }\r\n }\r\n\r\n /**\r\n * 生成控制台报告\r\n */\r\n private generateConsoleReport(issues: ReviewIssue[]): void {\r\n console.log(\"\\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\");\r\n console.log(\"📊 代码审查报告\");\r\n console.log(\"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\\n\");\r\n\r\n // 按严重程度分组\r\n const errors = issues.filter((i) => i.severity === \"error\");\r\n const warnings = issues.filter((i) => i.severity === \"warn\");\r\n const infos = issues.filter((i) => i.severity === \"info\");\r\n\r\n console.log(`❌ 错误: ${errors.length}`);\r\n console.log(`⚠️ 警告: ${warnings.length}`);\r\n console.log(`ℹ️ 信息: ${infos.length}`);\r\n console.log(`📝 总计: ${issues.length}\\n`);\r\n\r\n // 按类别分组\r\n const byCategory = this.groupByCategory(issues);\r\n console.log(\"📋 问题分类:\");\r\n Object.entries(byCategory).forEach(([category, count]) => {\r\n console.log(` ${this.getCategoryIcon(category)} ${category}: ${count}`);\r\n });\r\n\r\n console.log(\"\\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\\n\");\r\n }\r\n\r\n /**\r\n * 生成 HTML 报告\r\n */\r\n private async generateHTMLReport(issues: ReviewIssue[]): Promise<void> {\r\n const html = `\r\n<!DOCTYPE html>\r\n<html lang=\"zh-CN\">\r\n<head>\r\n <meta charset=\"UTF-8\">\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n <title>代码审查报告</title>\r\n <style>\r\n * { margin: 0; padding: 0; box-sizing: border-box; }\r\n body {\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\r\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\r\n padding: 20px;\r\n min-height: 100vh;\r\n }\r\n .container {\r\n max-width: 1200px;\r\n margin: 0 auto;\r\n background: white;\r\n border-radius: 12px;\r\n box-shadow: 0 8px 32px rgba(0,0,0,0.2);\r\n overflow: hidden;\r\n }\r\n .header {\r\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\r\n color: white;\r\n padding: 30px;\r\n text-align: center;\r\n }\r\n .header h1 {\r\n font-size: 32px;\r\n margin-bottom: 10px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 10px;\r\n }\r\n .header .time {\r\n font-size: 14px;\r\n opacity: 0.9;\r\n }\r\n .content {\r\n padding: 30px;\r\n }\r\n .summary {\r\n display: grid;\r\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\r\n gap: 20px;\r\n margin: 30px 0;\r\n }\r\n .summary-card {\r\n padding: 25px;\r\n border-radius: 12px;\r\n text-align: center;\r\n box-shadow: 0 4px 12px rgba(0,0,0,0.1);\r\n transition: transform 0.2s;\r\n }\r\n .summary-card:hover {\r\n transform: translateY(-4px);\r\n }\r\n .summary-card.error { \r\n background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%);\r\n color: white;\r\n }\r\n .summary-card.warn { \r\n background: linear-gradient(135deg, #feca57 0%, #ff9ff3 100%);\r\n color: #333;\r\n }\r\n .summary-card.info { \r\n background: linear-gradient(135deg, #48dbfb 0%, #0abde3 100%);\r\n color: white;\r\n }\r\n .summary-card h2 { \r\n font-size: 42px; \r\n margin: 10px 0;\r\n font-weight: bold;\r\n }\r\n .summary-card p { \r\n font-size: 16px;\r\n font-weight: 500;\r\n }\r\n .section-title {\r\n font-size: 24px;\r\n font-weight: bold;\r\n color: #333;\r\n margin: 30px 0 20px 0;\r\n padding-bottom: 10px;\r\n border-bottom: 3px solid #667eea;\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n }\r\n .issue {\r\n border: 1px solid #e0e0e0;\r\n border-radius: 12px;\r\n padding: 20px;\r\n margin: 15px 0;\r\n background: #fafafa;\r\n box-shadow: 0 2px 8px rgba(0,0,0,0.05);\r\n transition: box-shadow 0.2s;\r\n }\r\n .issue:hover {\r\n box-shadow: 0 4px 16px rgba(0,0,0,0.1);\r\n }\r\n .issue-header {\r\n display: flex;\r\n align-items: center;\r\n gap: 10px;\r\n margin-bottom: 15px;\r\n flex-wrap: wrap;\r\n }\r\n .issue-badge {\r\n padding: 6px 14px;\r\n border-radius: 16px;\r\n font-size: 12px;\r\n font-weight: bold;\r\n text-transform: uppercase;\r\n }\r\n .issue-badge.error { background: #ff6b6b; color: white; }\r\n .issue-badge.warn { background: #feca57; color: #333; }\r\n .issue-badge.info { background: #48dbfb; color: white; }\r\n .issue-category {\r\n padding: 6px 14px;\r\n border-radius: 16px;\r\n font-size: 12px;\r\n font-weight: bold;\r\n background: #667eea;\r\n color: white;\r\n }\r\n .issue-file {\r\n color: #666;\r\n font-size: 14px;\r\n font-family: 'Courier New', monospace;\r\n background: #f0f0f0;\r\n padding: 4px 10px;\r\n border-radius: 6px;\r\n flex: 1;\r\n min-width: 200px;\r\n }\r\n .issue-line {\r\n color: #667eea;\r\n font-weight: bold;\r\n font-size: 14px;\r\n }\r\n .issue-message {\r\n margin: 15px 0;\r\n color: #333;\r\n line-height: 1.8;\r\n font-size: 15px;\r\n }\r\n .issue-suggestion {\r\n background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%);\r\n border-left: 4px solid #4caf50;\r\n padding: 15px;\r\n margin-top: 15px;\r\n border-radius: 8px;\r\n line-height: 1.6;\r\n }\r\n .issue-suggestion::before {\r\n content: \"💡 建议: \";\r\n font-weight: bold;\r\n color: #2e7d32;\r\n font-size: 16px;\r\n }\r\n .category-stats {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 15px;\r\n margin: 20px 0;\r\n }\r\n .category-tag {\r\n padding: 8px 16px;\r\n border-radius: 20px;\r\n background: #f0f0f0;\r\n color: #333;\r\n font-size: 14px;\r\n font-weight: 500;\r\n }\r\n .footer {\r\n background: #f7fafc;\r\n padding: 25px;\r\n text-align: center;\r\n color: #718096;\r\n font-size: 14px;\r\n border-top: 1px solid #e2e8f0;\r\n }\r\n .footer p {\r\n margin: 5px 0;\r\n }\r\n </style>\r\n</head>\r\n<body>\r\n <div class=\"container\">\r\n <div class=\"header\">\r\n <h1>🔍 代码审查报告</h1>\r\n <div class=\"time\">生成时间: ${new Date().toLocaleString(\"zh-CN\")}</div>\r\n </div>\r\n\r\n <div class=\"content\">\r\n <div class=\"summary\">\r\n <div class=\"summary-card error\">\r\n <h2>${issues.filter((i) => i.severity === \"error\").length}</h2>\r\n <p>错误</p>\r\n </div>\r\n <div class=\"summary-card warn\">\r\n <h2>${issues.filter((i) => i.severity === \"warn\").length}</h2>\r\n <p>警告</p>\r\n </div>\r\n <div class=\"summary-card info\">\r\n <h2>${issues.filter((i) => i.severity === \"info\").length}</h2>\r\n <p>信息</p>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section-title\">📊 问题分类统计</div>\r\n <div class=\"category-stats\">\r\n ${Object.entries(this.groupByCategory(issues))\r\n .map(\r\n ([category, count]) =>\r\n `<div class=\"category-tag\">${this.getCategoryIcon(\r\n category\r\n )} ${category}: ${count}</div>`\r\n )\r\n .join(\"\")}\r\n </div>\r\n\r\n <div class=\"section-title\">📋 问题详情</div>\r\n ${issues\r\n .map(\r\n (issue) => `\r\n <div class=\"issue\">\r\n <div class=\"issue-header\">\r\n <span class=\"issue-badge ${\r\n issue.severity\r\n }\">${issue.severity.toUpperCase()}</span>\r\n <span class=\"issue-category\">${issue.category}</span>\r\n <span class=\"issue-file\">${issue.file}</span>\r\n ${\r\n issue.line ? `<span class=\"issue-line\">行 ${issue.line}</span>` : \"\"\r\n }\r\n </div>\r\n <div class=\"issue-message\">${issue.message}</div>\r\n ${\r\n issue.suggestion\r\n ? `<div class=\"issue-suggestion\">${issue.suggestion}</div>`\r\n : \"\"\r\n }\r\n </div>\r\n `\r\n )\r\n .join(\"\")}\r\n </div>\r\n\r\n <div class=\"footer\">\r\n <p>AI Code Review Plugin v1.0.0</p>\r\n <p>Powered by LangChain & OpenAI</p>\r\n </div>\r\n </div>\r\n</body>\r\n</html>\r\n `;\r\n\r\n // 创建报告目录\r\n const reportsDir = path.join(process.cwd(), \"ai-reports\");\r\n if (!fs.existsSync(reportsDir)) {\r\n fs.mkdirSync(reportsDir, { recursive: true });\r\n }\r\n\r\n const reportPath = path.join(reportsDir, \"code-review-report.html\");\r\n fs.writeFileSync(reportPath, html, \"utf-8\");\r\n console.log(`📄 HTML 报告已生成: ${reportPath}\\n`);\r\n }\r\n\r\n /**\r\n * 生成 Markdown 报告\r\n */\r\n private async generateMarkdownReport(issues: ReviewIssue[]): Promise<void> {\r\n const errors = issues.filter((i) => i.severity === \"error\");\r\n const warnings = issues.filter((i) => i.severity === \"warn\");\r\n const infos = issues.filter((i) => i.severity === \"info\");\r\n\r\n let markdown = `# 🔍 代码审查报告\r\n\r\n生成时间: ${new Date().toLocaleString(\"zh-CN\")}\r\n\r\n## 📊 概览\r\n\r\n| 类型 | 数量 |\r\n|------|------|\r\n| ❌ 错误 | ${errors.length} |\r\n| ⚠️ 警告 | ${warnings.length} |\r\n| ℹ️ 信息 | ${infos.length} |\r\n| 📝 总计 | ${issues.length} |\r\n\r\n## 📋 问题详情\r\n\r\n`;\r\n\r\n issues.forEach((issue, index) => {\r\n const icon = this.getSeverityIcon(issue.severity);\r\n markdown += `### ${index + 1}. ${icon} ${issue.category}\r\n\r\n**文件**: \\`${issue.file}${issue.line ? `:${issue.line}` : \"\"}\\` \r\n**严重程度**: ${issue.severity} \r\n**问题**: ${issue.message}\r\n\r\n`;\r\n\r\n if (issue.suggestion) {\r\n markdown += `💡 **建议**: ${issue.suggestion}\\n\\n`;\r\n }\r\n\r\n markdown += \"---\\n\\n\";\r\n });\r\n\r\n // 创建报告目录\r\n const reportsDir = path.join(process.cwd(), \"ai-reports\");\r\n if (!fs.existsSync(reportsDir)) {\r\n fs.mkdirSync(reportsDir, { recursive: true });\r\n }\r\n\r\n const reportPath = path.join(reportsDir, \"code-review-report.md\");\r\n fs.writeFileSync(reportPath, markdown, \"utf-8\");\r\n console.log(`📄 Markdown 报告已生成: ${reportPath}\\n`);\r\n }\r\n\r\n /**\r\n * 生成 JSON 报告\r\n */\r\n private async generateJSONReport(issues: ReviewIssue[]): Promise<void> {\r\n const report = {\r\n timestamp: new Date().toISOString(),\r\n summary: {\r\n total: issues.length,\r\n errors: issues.filter((i) => i.severity === \"error\").length,\r\n warnings: issues.filter((i) => i.severity === \"warn\").length,\r\n infos: issues.filter((i) => i.severity === \"info\").length,\r\n },\r\n issues: issues,\r\n };\r\n\r\n // 创建报告目录\r\n const reportsDir = path.join(process.cwd(), \"ai-reports\");\r\n if (!fs.existsSync(reportsDir)) {\r\n fs.mkdirSync(reportsDir, { recursive: true });\r\n }\r\n\r\n const reportPath = path.join(reportsDir, \"code-review-report.json\");\r\n fs.writeFileSync(reportPath, JSON.stringify(report, null, 2), \"utf-8\");\r\n console.log(`📄 JSON 报告已生成: ${reportPath}\\n`);\r\n }\r\n\r\n /**\r\n * 按类别分组\r\n */\r\n private groupByCategory(issues: ReviewIssue[]): Record<string, number> {\r\n const groups: Record<string, number> = {};\r\n\r\n issues.forEach((issue) => {\r\n groups[issue.category] = (groups[issue.category] || 0) + 1;\r\n });\r\n\r\n return groups;\r\n }\r\n\r\n /**\r\n * 获取类别图标\r\n */\r\n private getCategoryIcon(category: string): string {\r\n const icons: Record<string, string> = {\r\n security: \"🔒\",\r\n performance: \"⚡\",\r\n style: \"📝\",\r\n \"best-practice\": \"🎨\",\r\n };\r\n\r\n return icons[category] || \"📋\";\r\n }\r\n\r\n /**\r\n * 获取严重程度图标\r\n */\r\n private getSeverityIcon(severity: string): string {\r\n switch (severity) {\r\n case \"error\":\r\n return \"❌\";\r\n case \"warn\":\r\n return \"⚠️\";\r\n case \"info\":\r\n return \"ℹ️\";\r\n default:\r\n return \"📝\";\r\n }\r\n }\r\n}\r\n","/**\r\n * AI Code Review Plugin\r\n *\r\n * 功能:\r\n * - 审查代码质量\r\n * - 检测安全问题\r\n * - 发现性能问题\r\n * - 提供改进建议\r\n */\r\n\r\nimport type { Plugin } from \"vite\";\r\nimport { CodeReviewer } from \"./reviewer\";\r\nimport { GitUtils } from \"./git-utils\";\r\nimport { Reporter } from \"./reporter\";\r\n\r\nexport interface CodeReviewOptions {\r\n // AI 配置\r\n apiKey?: string;\r\n apiUrl?: string;\r\n model?: string;\r\n\r\n // 审查模式\r\n mode?: \"changed\" | \"all\" | \"manual\";\r\n files?: string[]; // manual 模式下指定的文件\r\n\r\n // 审查级别\r\n level?: \"quick\" | \"standard\" | \"thorough\";\r\n\r\n // 规则配置\r\n rules?: {\r\n security?: \"error\" | \"warn\" | \"info\" | \"off\";\r\n performance?: \"error\" | \"warn\" | \"info\" | \"off\";\r\n style?: \"error\" | \"warn\" | \"info\" | \"off\";\r\n bestPractice?: \"error\" | \"warn\" | \"info\" | \"off\";\r\n };\r\n\r\n // 文件过滤\r\n include?: string[];\r\n exclude?: string[];\r\n\r\n // 输出配置\r\n output?: {\r\n console?: boolean;\r\n html?: boolean;\r\n markdown?: boolean;\r\n json?: boolean;\r\n failOnError?: boolean;\r\n };\r\n\r\n // 性能优化\r\n cache?: boolean;\r\n batchSize?: number;\r\n maxConcurrent?: number;\r\n\r\n // 功能开关\r\n enabled?: boolean;\r\n}\r\n\r\nexport function vitePluginAICodeReview(\r\n options: CodeReviewOptions = {},\r\n): Plugin {\r\n const {\r\n apiKey = process.env.OPENAI_API_KEY || \"\",\r\n apiUrl = process.env.OPENAI_API_URL || \"https://api.openai.com/v1\",\r\n model = \"gpt-4\",\r\n mode = \"changed\",\r\n files = [],\r\n level = \"standard\",\r\n rules = {\r\n security: \"error\",\r\n performance: \"warn\",\r\n style: \"info\",\r\n bestPractice: \"info\",\r\n },\r\n include = [\"**/*.{ts,tsx,js,jsx,vue}\"],\r\n exclude = [\"**/node_modules/**\", \"**/dist/**\", \"**/*.test.{ts,js}\"],\r\n output = {\r\n console: true,\r\n html: true,\r\n markdown: false,\r\n json: false,\r\n failOnError: false,\r\n },\r\n cache = true,\r\n batchSize = 5,\r\n maxConcurrent = 3,\r\n enabled = true,\r\n } = options;\r\n\r\n if (!enabled) {\r\n return {\r\n name: \"vite-plugin-ai-code-review\",\r\n };\r\n }\r\n\r\n const reviewer = new CodeReviewer({\r\n apiKey,\r\n apiUrl,\r\n model,\r\n level,\r\n rules,\r\n cache,\r\n });\r\n\r\n const gitUtils = new GitUtils();\r\n const reporter = new Reporter(output);\r\n\r\n let filesToReview: string[] = [];\r\n let allIssues: any[] = [];\r\n\r\n return {\r\n name: \"vite-plugin-ai-code-review\",\r\n enforce: \"post\",\r\n\r\n configResolved(config) {\r\n console.log(\"\\n🔍 AI Code Review 已启动...\");\r\n console.log(`📂 审查模式: ${mode}`);\r\n console.log(`📊 审查级别: ${level}`);\r\n console.log(`🔑 API Key: ${apiKey ? \"已配置\" : \"未配置\"}\\n`);\r\n },\r\n\r\n async buildStart() {\r\n if (!apiKey) {\r\n console.warn(\"⚠️ 未配置 API Key,跳过代码审查\");\r\n return;\r\n }\r\n\r\n // 确定要审查的文件\r\n if (mode === \"changed\") {\r\n filesToReview = await gitUtils.getChangedFiles();\r\n console.log(`🔍 [Git] 检测到 ${filesToReview.length} 个变更文件`);\r\n filesToReview.forEach((f) => console.log(` - ${f}`));\r\n } else if (mode === \"manual\") {\r\n filesToReview = files;\r\n } else {\r\n // mode === \"all\" 时在 transform 中处理\r\n filesToReview = [];\r\n }\r\n\r\n // 过滤文件\r\n filesToReview = filesToReview.filter((file) =>\r\n shouldReview(file, include, exclude),\r\n );\r\n\r\n if (mode !== \"all\" && filesToReview.length > 0) {\r\n console.log(`📝 过滤后需要审查 ${filesToReview.length} 个文件\\n`);\r\n\r\n // 在 buildStart 时直接审查文件(因为 transform 可能不会被调用)\r\n for (const file of filesToReview) {\r\n try {\r\n const fs = await import(\"fs\");\r\n const path = await import(\"path\");\r\n const fullPath = path.resolve(process.cwd(), file);\r\n\r\n if (fs.existsSync(fullPath)) {\r\n const code = fs.readFileSync(fullPath, \"utf-8\");\r\n console.log(`🔍 [审查] ${file}`);\r\n\r\n const issues = await reviewer.review(code, file);\r\n\r\n if (issues.length > 0) {\r\n allIssues.push(...issues);\r\n\r\n // 实时输出问题\r\n if (output.console) {\r\n issues.forEach((issue) => {\r\n const icon = getSeverityIcon(issue.severity);\r\n console.log(\r\n `${icon} [${issue.category}] ${issue.file}:${\r\n issue.line || \"?\"\r\n }`,\r\n );\r\n console.log(` ${issue.message}`);\r\n if (issue.suggestion) {\r\n console.log(` 💡 ${issue.suggestion}`);\r\n }\r\n });\r\n console.log(\"\");\r\n }\r\n } else {\r\n console.log(`✅ 未发现问题\\n`);\r\n }\r\n }\r\n } catch (error: any) {\r\n console.warn(`⚠️ 审查失败 ${file}: ${error.message}`);\r\n }\r\n }\r\n } else if (mode !== \"all\") {\r\n console.log(`📝 没有需要审查的文件\\n`);\r\n }\r\n },\r\n\r\n async transform(code: string, id: string) {\r\n // 只在 all 模式下使用 transform\r\n if (mode !== \"all\") {\r\n return null;\r\n }\r\n\r\n // 跳过非源码文件\r\n if (id.includes(\"node_modules\") || !shouldReview(id, include, exclude)) {\r\n return null;\r\n }\r\n\r\n // 只审查源文件(不是编译后的文件)\r\n if (!id.match(/\\.(vue|ts|tsx|js|jsx)$/)) {\r\n return null;\r\n }\r\n\r\n try {\r\n console.log(`🔍 [审查] ${id}`);\r\n\r\n // 读取原始源文件(而不是使用 transform 中的 code)\r\n const fs = await import(\"fs\");\r\n let sourceCode = code;\r\n\r\n // 如果文件存在,读取原始内容\r\n if (fs.existsSync(id)) {\r\n sourceCode = fs.readFileSync(id, \"utf-8\");\r\n }\r\n\r\n const issues = await reviewer.review(sourceCode, id);\r\n\r\n if (issues.length > 0) {\r\n allIssues.push(...issues);\r\n\r\n // 实时输出问题\r\n if (output.console) {\r\n issues.forEach((issue) => {\r\n const icon = getSeverityIcon(issue.severity);\r\n console.log(\r\n `${icon} [${issue.category}] ${issue.file}:${\r\n issue.line || \"?\"\r\n }`,\r\n );\r\n console.log(` ${issue.message}`);\r\n if (issue.suggestion) {\r\n console.log(` 💡 ${issue.suggestion}`);\r\n }\r\n });\r\n console.log(\"\");\r\n }\r\n }\r\n } catch (error: any) {\r\n console.warn(`⚠️ 审查失败 ${id}: ${error.message}`);\r\n }\r\n\r\n return null;\r\n },\r\n\r\n async buildEnd() {\r\n if (allIssues.length === 0) {\r\n console.log(\"✨ 代码审查完成,未发现问题\\n\");\r\n return;\r\n }\r\n\r\n // 生成报告\r\n await reporter.generate(allIssues);\r\n\r\n // 检查是否需要失败构建\r\n if (output.failOnError) {\r\n const errors = allIssues.filter((i) => i.severity === \"error\");\r\n if (errors.length > 0) {\r\n throw new Error(`代码审查发现 ${errors.length} 个错误`);\r\n }\r\n }\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * 判断文件是否需要审查\r\n */\r\nfunction shouldReview(\r\n filePath: string,\r\n include: string[],\r\n exclude: string[],\r\n): boolean {\r\n // 检查排除规则\r\n for (const pattern of exclude) {\r\n if (matchPattern(filePath, pattern)) {\r\n return false;\r\n }\r\n }\r\n\r\n // 检查包含规则\r\n for (const pattern of include) {\r\n if (matchPattern(filePath, pattern)) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * 简单的模式匹配\r\n */\r\nfunction matchPattern(filePath: string, pattern: string): boolean {\r\n // 移除 **/ 前缀\r\n const cleanPattern = pattern.replace(/^\\*\\*\\//, \"\");\r\n\r\n // 提取扩展名\r\n const extMatch = cleanPattern.match(/\\{(.+)\\}/);\r\n if (extMatch) {\r\n const exts = extMatch[1].split(\",\").map((e) => e.trim());\r\n return exts.some((ext) => filePath.endsWith(ext));\r\n }\r\n\r\n // 简单的包含匹配\r\n return filePath.includes(cleanPattern.replace(/\\*/g, \"\"));\r\n}\r\n\r\n/**\r\n * 获取严重程度图标\r\n */\r\nfunction getSeverityIcon(severity: string): string {\r\n switch (severity) {\r\n case \"error\":\r\n return \"❌\";\r\n case \"warn\":\r\n return \"⚠️\";\r\n case \"info\":\r\n return \"ℹ️\";\r\n default:\r\n return \"📝\";\r\n }\r\n}\r\n\r\n// 导出类\r\nexport { CodeReviewer, GitUtils, Reporter };\r\n\r\n// 默认导出\r\nexport default vitePluginAICodeReview;\r\n"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/reviewer.ts","../src/git-utils.ts","../src/reporter.ts"],"sourcesContent":["/**\r\n * AI Code Review Plugin\r\n *\r\n * 功能:\r\n * - 审查代码质量\r\n * - 检测安全问题\r\n * - 发现性能问题\r\n * - 提供改进建议\r\n */\r\n\r\nimport type { Plugin } from \"vite\";\r\nimport { CodeReviewer } from \"./reviewer\";\r\nimport { GitUtils } from \"./git-utils\";\r\nimport { Reporter } from \"./reporter\";\r\n\r\nexport interface CodeReviewOptions {\r\n // AI 配置\r\n apiKey?: string;\r\n apiUrl?: string;\r\n model?: string;\r\n\r\n // 审查模式\r\n mode?: \"changed\" | \"all\" | \"manual\";\r\n files?: string[]; // manual 模式下指定的文件\r\n\r\n // 审查级别\r\n level?: \"quick\" | \"standard\" | \"thorough\";\r\n\r\n // 规则配置\r\n rules?: {\r\n security?: \"error\" | \"warn\" | \"info\" | \"off\";\r\n performance?: \"error\" | \"warn\" | \"info\" | \"off\";\r\n style?: \"error\" | \"warn\" | \"info\" | \"off\";\r\n bestPractice?: \"error\" | \"warn\" | \"info\" | \"off\";\r\n };\r\n\r\n // 文件过滤\r\n include?: string[];\r\n exclude?: string[];\r\n\r\n // 输出配置\r\n output?: {\r\n console?: boolean;\r\n html?: boolean;\r\n markdown?: boolean;\r\n json?: boolean;\r\n failOnError?: boolean;\r\n };\r\n\r\n // 性能优化\r\n cache?: boolean;\r\n batchSize?: number;\r\n maxConcurrent?: number;\r\n\r\n // 功能开关\r\n enabled?: boolean;\r\n}\r\n\r\nexport function vitePluginAICodeReview(\r\n options: CodeReviewOptions = {},\r\n): Plugin {\r\n const {\r\n apiKey = process.env.OPENAI_API_KEY || \"\",\r\n apiUrl = process.env.OPENAI_API_URL || \"https://api.openai.com/v1\",\r\n model = \"gpt-4\",\r\n mode = \"changed\",\r\n files = [],\r\n level = \"standard\",\r\n rules = {\r\n security: \"error\",\r\n performance: \"warn\",\r\n style: \"info\",\r\n bestPractice: \"info\",\r\n },\r\n include = [\"**/*.{ts,tsx,js,jsx,vue}\"],\r\n exclude = [\"**/node_modules/**\", \"**/dist/**\", \"**/*.test.{ts,js}\"],\r\n output = {\r\n console: true,\r\n html: true,\r\n markdown: false,\r\n json: false,\r\n failOnError: false,\r\n },\r\n cache = true,\r\n batchSize = 5,\r\n maxConcurrent = 3,\r\n enabled = true,\r\n } = options;\r\n\r\n if (!enabled) {\r\n return {\r\n name: \"vite-plugin-ai-code-review\",\r\n };\r\n }\r\n\r\n const reviewer = new CodeReviewer({\r\n apiKey,\r\n apiUrl,\r\n model,\r\n level,\r\n rules,\r\n cache,\r\n });\r\n\r\n const gitUtils = new GitUtils();\r\n const reporter = new Reporter(output);\r\n\r\n let filesToReview: string[] = [];\r\n let allIssues: any[] = [];\r\n\r\n return {\r\n name: \"vite-plugin-ai-code-review\",\r\n enforce: \"post\",\r\n\r\n configResolved(config) {\r\n console.log(\"\\n🔍 AI Code Review 已启动...\");\r\n console.log(`📂 审查模式: ${mode}`);\r\n console.log(`📊 审查级别: ${level}`);\r\n console.log(`🔑 API Key: ${apiKey ? \"已配置\" : \"未配置\"}\\n`);\r\n },\r\n\r\n async buildStart() {\r\n if (!apiKey) {\r\n console.warn(\"⚠️ 未配置 API Key,跳过代码审查\");\r\n return;\r\n }\r\n\r\n // 确定要审查的文件\r\n if (mode === \"changed\") {\r\n filesToReview = await gitUtils.getChangedFiles();\r\n console.log(`🔍 [Git] 检测到 ${filesToReview.length} 个变更文件`);\r\n filesToReview.forEach((f) => console.log(` - ${f}`));\r\n } else if (mode === \"manual\") {\r\n filesToReview = files;\r\n } else {\r\n // mode === \"all\" 时在 transform 中处理\r\n filesToReview = [];\r\n }\r\n\r\n // 过滤文件\r\n filesToReview = filesToReview.filter((file) =>\r\n shouldReview(file, include, exclude),\r\n );\r\n\r\n if (mode !== \"all\" && filesToReview.length > 0) {\r\n console.log(`📝 过滤后需要审查 ${filesToReview.length} 个文件\\n`);\r\n\r\n // 在 buildStart 时直接审查文件(因为 transform 可能不会被调用)\r\n for (const file of filesToReview) {\r\n try {\r\n const fs = await import(\"fs\");\r\n const path = await import(\"path\");\r\n const fullPath = path.resolve(process.cwd(), file);\r\n\r\n if (fs.existsSync(fullPath)) {\r\n const code = fs.readFileSync(fullPath, \"utf-8\");\r\n console.log(`🔍 [审查] ${file}`);\r\n\r\n const issues = await reviewer.review(code, file);\r\n\r\n if (issues.length > 0) {\r\n allIssues.push(...issues);\r\n\r\n // 实时输出问题\r\n if (output.console) {\r\n issues.forEach((issue) => {\r\n const icon = getSeverityIcon(issue.severity);\r\n console.log(\r\n `${icon} [${issue.category}] ${issue.file}:${\r\n issue.line || \"?\"\r\n }`,\r\n );\r\n console.log(` ${issue.message}`);\r\n if (issue.suggestion) {\r\n console.log(` 💡 ${issue.suggestion}`);\r\n }\r\n });\r\n console.log(\"\");\r\n }\r\n } else {\r\n console.log(`✅ 未发现问题\\n`);\r\n }\r\n }\r\n } catch (error: any) {\r\n console.warn(`⚠️ 审查失败 ${file}: ${error.message}`);\r\n }\r\n }\r\n } else if (mode !== \"all\") {\r\n console.log(`📝 没有需要审查的文件\\n`);\r\n }\r\n },\r\n\r\n async transform(code: string, id: string) {\r\n // 只在 all 模式下使用 transform\r\n if (mode !== \"all\") {\r\n return null;\r\n }\r\n\r\n // 跳过非源码文件\r\n if (id.includes(\"node_modules\") || !shouldReview(id, include, exclude)) {\r\n return null;\r\n }\r\n\r\n // 只审查源文件(不是编译后的文件)\r\n if (!id.match(/\\.(vue|ts|tsx|js|jsx)$/)) {\r\n return null;\r\n }\r\n\r\n try {\r\n console.log(`🔍 [审查] ${id}`);\r\n\r\n // 读取原始源文件(而不是使用 transform 中的 code)\r\n const fs = await import(\"fs\");\r\n let sourceCode = code;\r\n\r\n // 如果文件存在,读取原始内容\r\n if (fs.existsSync(id)) {\r\n sourceCode = fs.readFileSync(id, \"utf-8\");\r\n }\r\n\r\n const issues = await reviewer.review(sourceCode, id);\r\n\r\n if (issues.length > 0) {\r\n allIssues.push(...issues);\r\n\r\n // 实时输出问题\r\n if (output.console) {\r\n issues.forEach((issue) => {\r\n const icon = getSeverityIcon(issue.severity);\r\n console.log(\r\n `${icon} [${issue.category}] ${issue.file}:${\r\n issue.line || \"?\"\r\n }`,\r\n );\r\n console.log(` ${issue.message}`);\r\n if (issue.suggestion) {\r\n console.log(` 💡 ${issue.suggestion}`);\r\n }\r\n });\r\n console.log(\"\");\r\n }\r\n }\r\n } catch (error: any) {\r\n console.warn(`⚠️ 审查失败 ${id}: ${error.message}`);\r\n }\r\n\r\n return null;\r\n },\r\n\r\n async buildEnd() {\r\n if (allIssues.length === 0) {\r\n console.log(\"✨ 代码审查完成,未发现问题\\n\");\r\n return;\r\n }\r\n\r\n // 生成报告\r\n await reporter.generate(allIssues);\r\n\r\n // 检查是否需要失败构建\r\n if (output.failOnError) {\r\n const errors = allIssues.filter((i) => i.severity === \"error\");\r\n if (errors.length > 0) {\r\n throw new Error(`代码审查发现 ${errors.length} 个错误`);\r\n }\r\n }\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * 判断文件是否需要审查\r\n */\r\nfunction shouldReview(\r\n filePath: string,\r\n include: string[],\r\n exclude: string[],\r\n): boolean {\r\n // 检查排除规则\r\n for (const pattern of exclude) {\r\n if (matchPattern(filePath, pattern)) {\r\n return false;\r\n }\r\n }\r\n\r\n // 检查包含规则\r\n for (const pattern of include) {\r\n if (matchPattern(filePath, pattern)) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * 简单的模式匹配\r\n */\r\nfunction matchPattern(filePath: string, pattern: string): boolean {\r\n // 移除 **/ 前缀\r\n const cleanPattern = pattern.replace(/^\\*\\*\\//, \"\");\r\n\r\n // 提取扩展名\r\n const extMatch = cleanPattern.match(/\\{(.+)\\}/);\r\n if (extMatch) {\r\n const exts = extMatch[1].split(\",\").map((e) => e.trim());\r\n return exts.some((ext) => filePath.endsWith(ext));\r\n }\r\n\r\n // 简单的包含匹配\r\n return filePath.includes(cleanPattern.replace(/\\*/g, \"\"));\r\n}\r\n\r\n/**\r\n * 获取严重程度图标\r\n */\r\nfunction getSeverityIcon(severity: string): string {\r\n switch (severity) {\r\n case \"error\":\r\n return \"❌\";\r\n case \"warn\":\r\n return \"⚠️\";\r\n case \"info\":\r\n return \"ℹ️\";\r\n default:\r\n return \"📝\";\r\n }\r\n}\r\n\r\n// 导出类\r\nexport { CodeReviewer, GitUtils, Reporter };\r\n\r\n// 默认导出\r\nexport default vitePluginAICodeReview;\r\n","/**\r\n * AI 代码审查器\r\n */\r\n\r\nimport { ChatOpenAI } from \"@langchain/openai\";\r\nimport { HumanMessage, SystemMessage } from \"@langchain/core/messages\";\r\nimport crypto from \"crypto\";\r\n\r\nexport interface ReviewIssue {\r\n file: string;\r\n line?: number;\r\n category: \"security\" | \"performance\" | \"style\" | \"best-practice\";\r\n severity: \"error\" | \"warn\" | \"info\";\r\n message: string;\r\n suggestion?: string;\r\n code?: string;\r\n}\r\n\r\nexport interface ReviewerOptions {\r\n apiKey: string;\r\n apiUrl: string;\r\n model: string;\r\n level: \"quick\" | \"standard\" | \"thorough\";\r\n rules: {\r\n security?: string;\r\n performance?: string;\r\n style?: string;\r\n bestPractice?: string;\r\n };\r\n cache: boolean;\r\n}\r\n\r\nexport class CodeReviewer {\r\n private llm: ChatOpenAI | null = null;\r\n private options: ReviewerOptions;\r\n private cache: Map<string, ReviewIssue[]> = new Map();\r\n\r\n constructor(options: ReviewerOptions) {\r\n this.options = options;\r\n\r\n if (options.apiKey) {\r\n this.llm = new ChatOpenAI({\r\n openAIApiKey: options.apiKey,\r\n configuration: { baseURL: options.apiUrl },\r\n modelName: options.model,\r\n temperature: 0.2,\r\n maxTokens: 4000,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * 审查代码\r\n */\r\n async review(code: string, filePath: string): Promise<ReviewIssue[]> {\r\n if (!this.llm) {\r\n return [];\r\n }\r\n\r\n // 检查缓存\r\n if (this.options.cache) {\r\n const cacheKey = this.getCacheKey(code);\r\n if (this.cache.has(cacheKey)) {\r\n return this.cache.get(cacheKey)!;\r\n }\r\n }\r\n\r\n try {\r\n const issues = await this.performReview(code, filePath);\r\n\r\n // 保存到缓存\r\n if (this.options.cache) {\r\n const cacheKey = this.getCacheKey(code);\r\n this.cache.set(cacheKey, issues);\r\n }\r\n\r\n return issues;\r\n } catch (error: any) {\r\n console.error(`❌ 审查失败: ${error.message}`);\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * 执行审查\r\n */\r\n private async performReview(\r\n code: string,\r\n filePath: string\r\n ): Promise<ReviewIssue[]> {\r\n const systemPrompt = this.buildSystemPrompt();\r\n const userPrompt = this.buildUserPrompt(code, filePath);\r\n\r\n const response = await this.llm!.invoke([systemPrompt, userPrompt]);\r\n const content = response.content.toString();\r\n\r\n // 解析 JSON 响应\r\n try {\r\n const result = JSON.parse(content);\r\n const issues = this.parseIssues(result, filePath);\r\n return issues;\r\n } catch (error) {\r\n // 如果解析失败,尝试提取 JSON\r\n const jsonMatch = content.match(/\\{[\\s\\S]*\\}/);\r\n if (jsonMatch) {\r\n const result = JSON.parse(jsonMatch[0]);\r\n const issues = this.parseIssues(result, filePath);\r\n return issues;\r\n }\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * 构建系统提示\r\n */\r\n private buildSystemPrompt(): SystemMessage {\r\n const { level, rules } = this.options;\r\n\r\n let prompt = `你是一个专业的代码审查专家。请审查代码并识别问题。\r\n\r\n审查级别: ${level}\r\n`;\r\n\r\n // 添加规则说明\r\n if (rules.security !== \"off\") {\r\n prompt += `\\n🔒 安全问题 (${rules.security}):\r\n- XSS 漏洞\r\n- SQL 注入\r\n- eval() 使用\r\n- 敏感信息泄露\r\n- 不安全的依赖`;\r\n }\r\n\r\n if (rules.performance !== \"off\") {\r\n prompt += `\\n⚡ 性能问题 (${rules.performance}):\r\n- 大循环\r\n- 内存泄漏\r\n- 重复计算\r\n- 不必要的渲染\r\n- 阻塞操作`;\r\n }\r\n\r\n if (rules.style !== \"off\") {\r\n prompt += `\\n📝 代码规范 (${rules.style}):\r\n- 命名规范\r\n- 代码复杂度\r\n- 重复代码\r\n- 注释完整性`;\r\n }\r\n\r\n if (rules.bestPractice !== \"off\") {\r\n prompt += `\\n🎨 最佳实践 (${rules.bestPractice}):\r\n- 错误处理\r\n- 类型安全\r\n- 组件设计\r\n- 状态管理`;\r\n }\r\n\r\n prompt += `\\n\\n返回 JSON 格式:\r\n{\r\n \"issues\": [\r\n {\r\n \"line\": 10, // 必须是准确的行号!\r\n \"category\": \"security\",\r\n \"severity\": \"error\",\r\n \"message\": \"使用了 eval(),存在安全风险\",\r\n \"suggestion\": \"使用 JSON.parse() 或其他安全方法\"\r\n }\r\n ]\r\n}\r\n\r\n**重要提示**:\r\n1. line 字段必须是准确的行号,与代码中的行号一致\r\n2. 如果代码带有行号前缀(如 \"10: const x = 1\"),请提取正确的行号\r\n3. 只返回 JSON,不要其他解释`;\r\n\r\n return new SystemMessage(prompt);\r\n }\r\n\r\n /**\r\n * 构建用户提示\r\n */\r\n private buildUserPrompt(code: string, filePath: string): HumanMessage {\r\n const fileExt = filePath.split(\".\").pop();\r\n const language = this.getLanguage(fileExt || \"\");\r\n const lines = code.split(\"\\n\");\r\n\r\n // 添加行号到代码中,帮助 AI 准确定位\r\n const codeWithLineNumbers = lines\r\n .map((line, index) => `${index + 1}: ${line}`)\r\n .join(\"\\n\");\r\n\r\n return new HumanMessage(`\r\n请审查以下 ${language} 代码:\r\n\r\n文件: ${filePath}\r\n总行数: ${lines.length}\r\n\r\n代码(带行号):\r\n\\`\\`\\`${language}\r\n${codeWithLineNumbers}\r\n\\`\\`\\`\r\n\r\n**重要**:请返回准确的行号!行号必须与上面代码中的行号一致。\r\n\r\n请返回 JSON 格式的问题列表。\r\n`);\r\n }\r\n\r\n /**\r\n * 解析问题\r\n */\r\n private parseIssues(result: any, filePath: string): ReviewIssue[] {\r\n if (!result.issues || !Array.isArray(result.issues)) {\r\n return [];\r\n }\r\n\r\n return result.issues\r\n .map((issue: any) => ({\r\n file: filePath,\r\n line: issue.line,\r\n category: issue.category || \"best-practice\",\r\n severity: issue.severity || \"info\",\r\n message: issue.message || \"未知问题\",\r\n suggestion: issue.suggestion,\r\n code: issue.code,\r\n }))\r\n .filter((issue: ReviewIssue) => {\r\n // 根据规则过滤 - 处理连字符和驼峰命名的转换\r\n const categoryKey =\r\n issue.category === \"best-practice\" ? \"bestPractice\" : issue.category;\r\n const rule =\r\n this.options.rules[categoryKey as keyof typeof this.options.rules];\r\n return rule && rule !== \"off\";\r\n });\r\n }\r\n\r\n /**\r\n * 获取语言类型\r\n */\r\n private getLanguage(ext: string): string {\r\n const langMap: Record<string, string> = {\r\n ts: \"typescript\",\r\n tsx: \"typescript\",\r\n js: \"javascript\",\r\n jsx: \"javascript\",\r\n vue: \"vue\",\r\n css: \"css\",\r\n scss: \"scss\",\r\n less: \"less\",\r\n };\r\n\r\n return langMap[ext] || ext;\r\n }\r\n\r\n /**\r\n * 生成缓存键\r\n */\r\n private getCacheKey(code: string): string {\r\n return crypto.createHash(\"md5\").update(code).digest(\"hex\");\r\n }\r\n\r\n /**\r\n * 清除缓存\r\n */\r\n clearCache(): void {\r\n this.cache.clear();\r\n }\r\n\r\n /**\r\n * 获取缓存统计\r\n */\r\n getCacheStats(): { size: number; hits: number } {\r\n return {\r\n size: this.cache.size,\r\n hits: 0, // 可以添加计数器跟踪\r\n };\r\n }\r\n}\r\n","/**\r\n * Git 工具类\r\n * 用于获取 Git 变更信息\r\n * 统一策略:对比上一次提交(HEAD~1)\r\n */\r\n\r\nimport { execSync } from \"child_process\";\r\nimport fs from \"fs\";\r\nimport path from \"path\";\r\n\r\nexport class GitUtils {\r\n /**\r\n * 获取 Git 变更的文件列表\r\n * 统一策略:对比上一次提交(HEAD~1)\r\n */\r\n async getChangedFiles(): Promise<string[]> {\r\n try {\r\n // 检查是否在 Git 仓库中\r\n if (!this.isGitRepository()) {\r\n console.warn(\"⚠️ 不在 Git 仓库中,无法获取变更文件\");\r\n return [];\r\n }\r\n\r\n console.log(`🔍 [Git] 对比策略: HEAD~1 vs HEAD`);\r\n\r\n // 统一使用对比上一次提交的方式\r\n const changedFiles = this.getCommitDiffFiles();\r\n\r\n console.log(`🔍 [Git] 检测到 ${changedFiles.length} 个变更文件`);\r\n changedFiles.forEach((f) => console.log(` - ${f}`));\r\n\r\n // 过滤存在的文件,并处理路径\r\n const existingFiles = changedFiles\r\n .map((file) => {\r\n // 移除可能的前缀路径(如 ai-uni-app/)\r\n const cleanFile = file.replace(/^[^/]+\\//, \"\");\r\n return cleanFile;\r\n })\r\n .filter((file) => {\r\n const fullPath = path.resolve(process.cwd(), file);\r\n const exists = fs.existsSync(fullPath);\r\n if (!exists) {\r\n console.log(` ⚠️ 文件不存在: ${fullPath}`);\r\n }\r\n return exists;\r\n });\r\n\r\n console.log(`🔍 [Git] 过滤后文件: ${existingFiles.length} 个`);\r\n existingFiles.forEach((f) => console.log(` ✓ ${f}`));\r\n\r\n return existingFiles;\r\n } catch (error: any) {\r\n console.warn(`⚠️ 获取 Git 变更文件失败: ${error.message}`);\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * 检查是否在 Git 仓库中\r\n */\r\n private isGitRepository(): boolean {\r\n try {\r\n execSync(\"git rev-parse --git-dir\", {\r\n stdio: \"ignore\",\r\n cwd: process.cwd(),\r\n });\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * 获取与上一次提交的差异文件\r\n */\r\n private getCommitDiffFiles(): string[] {\r\n try {\r\n // 尝试对比上一次提交\r\n const output = execSync(\"git diff --name-only HEAD~1 HEAD\", {\r\n encoding: \"utf-8\",\r\n cwd: process.cwd(),\r\n });\r\n\r\n const files = output\r\n .trim()\r\n .split(\"\\n\")\r\n .filter((file) => file.length > 0);\r\n\r\n if (files.length > 0) {\r\n return files;\r\n }\r\n\r\n // 如果没有上一次提交(首次提交),获取当前提交的所有文件\r\n console.log(` ℹ️ 没有上一次提交,获取当前提交的所有文件`);\r\n return this.getLastCommitFiles();\r\n } catch (error) {\r\n // 降级:获取未提交的变更\r\n console.log(` ℹ️ 无法对比提交,尝试获取未提交的变更`);\r\n return this.getUncommittedFiles();\r\n }\r\n }\r\n\r\n /**\r\n * 获取最近一次提交的所有文件\r\n */\r\n private getLastCommitFiles(): string[] {\r\n try {\r\n const output = execSync(\r\n \"git diff-tree --no-commit-id --name-only -r HEAD\",\r\n {\r\n encoding: \"utf-8\",\r\n cwd: process.cwd(),\r\n }\r\n );\r\n\r\n return output\r\n .trim()\r\n .split(\"\\n\")\r\n .filter((file) => file.length > 0);\r\n } catch {\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * 获取未提交的变更文件(降级方案)\r\n */\r\n private getUncommittedFiles(): string[] {\r\n try {\r\n // 获取未暂存的文件\r\n const unstagedOutput = execSync(\"git diff --name-only\", {\r\n encoding: \"utf-8\",\r\n cwd: process.cwd(),\r\n });\r\n\r\n // 获取已暂存的文件\r\n const stagedOutput = execSync(\"git diff --cached --name-only\", {\r\n encoding: \"utf-8\",\r\n cwd: process.cwd(),\r\n });\r\n\r\n const unstagedFiles = unstagedOutput\r\n .trim()\r\n .split(\"\\n\")\r\n .filter((file) => file.length > 0);\r\n\r\n const stagedFiles = stagedOutput\r\n .trim()\r\n .split(\"\\n\")\r\n .filter((file) => file.length > 0);\r\n\r\n // 合并并去重\r\n return [...new Set([...unstagedFiles, ...stagedFiles])];\r\n } catch {\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * 获取最近 N 次提交的变更文件\r\n */\r\n async getRecentChangedFiles(commits: number = 1): Promise<string[]> {\r\n try {\r\n const output = execSync(`git diff --name-only HEAD~${commits}`, {\r\n encoding: \"utf-8\",\r\n cwd: process.cwd(),\r\n });\r\n\r\n return output\r\n .trim()\r\n .split(\"\\n\")\r\n .filter((file) => file.length > 0);\r\n } catch {\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * 获取当前分支名\r\n */\r\n getCurrentBranch(): string {\r\n try {\r\n const output = execSync(\"git rev-parse --abbrev-ref HEAD\", {\r\n encoding: \"utf-8\",\r\n cwd: process.cwd(),\r\n });\r\n\r\n return output.trim();\r\n } catch {\r\n return \"unknown\";\r\n }\r\n }\r\n\r\n /**\r\n * 获取文件的 Git 状态\r\n */\r\n getFileStatus(filePath: string): string {\r\n try {\r\n const output = execSync(`git status --short \"${filePath}\"`, {\r\n encoding: \"utf-8\",\r\n cwd: process.cwd(),\r\n });\r\n\r\n const status = output.trim().substring(0, 2);\r\n\r\n // 解析状态\r\n if (status.includes(\"M\")) return \"modified\";\r\n if (status.includes(\"A\")) return \"added\";\r\n if (status.includes(\"D\")) return \"deleted\";\r\n if (status.includes(\"R\")) return \"renamed\";\r\n if (status.includes(\"?\")) return \"untracked\";\r\n\r\n return \"unchanged\";\r\n } catch {\r\n return \"unknown\";\r\n }\r\n }\r\n}\r\n","/**\r\n * 报告生成器\r\n */\r\n\r\nimport fs from \"fs\";\r\nimport path from \"path\";\r\nimport type { ReviewIssue } from \"./reviewer\";\r\n\r\nexport interface ReporterOptions {\r\n console?: boolean;\r\n html?: boolean;\r\n markdown?: boolean;\r\n json?: boolean;\r\n failOnError?: boolean;\r\n}\r\n\r\nexport class Reporter {\r\n private options: ReporterOptions;\r\n\r\n constructor(options: ReporterOptions = {}) {\r\n this.options = options;\r\n }\r\n\r\n /**\r\n * 生成报告\r\n */\r\n async generate(issues: ReviewIssue[]): Promise<void> {\r\n // 控制台报告\r\n if (this.options.console) {\r\n this.generateConsoleReport(issues);\r\n }\r\n\r\n // HTML 报告\r\n if (this.options.html) {\r\n await this.generateHTMLReport(issues);\r\n }\r\n\r\n // Markdown 报告\r\n if (this.options.markdown) {\r\n await this.generateMarkdownReport(issues);\r\n }\r\n\r\n // JSON 报告\r\n if (this.options.json) {\r\n await this.generateJSONReport(issues);\r\n }\r\n }\r\n\r\n /**\r\n * 生成控制台报告\r\n */\r\n private generateConsoleReport(issues: ReviewIssue[]): void {\r\n console.log(\"\\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\");\r\n console.log(\"📊 代码审查报告\");\r\n console.log(\"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\\n\");\r\n\r\n // 按严重程度分组\r\n const errors = issues.filter((i) => i.severity === \"error\");\r\n const warnings = issues.filter((i) => i.severity === \"warn\");\r\n const infos = issues.filter((i) => i.severity === \"info\");\r\n\r\n console.log(`❌ 错误: ${errors.length}`);\r\n console.log(`⚠️ 警告: ${warnings.length}`);\r\n console.log(`ℹ️ 信息: ${infos.length}`);\r\n console.log(`📝 总计: ${issues.length}\\n`);\r\n\r\n // 按类别分组\r\n const byCategory = this.groupByCategory(issues);\r\n console.log(\"📋 问题分类:\");\r\n Object.entries(byCategory).forEach(([category, count]) => {\r\n console.log(` ${this.getCategoryIcon(category)} ${category}: ${count}`);\r\n });\r\n\r\n console.log(\"\\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\\n\");\r\n }\r\n\r\n /**\r\n * 生成 HTML 报告\r\n */\r\n private async generateHTMLReport(issues: ReviewIssue[]): Promise<void> {\r\n const html = `\r\n<!DOCTYPE html>\r\n<html lang=\"zh-CN\">\r\n<head>\r\n <meta charset=\"UTF-8\">\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n <title>代码审查报告</title>\r\n <style>\r\n * { margin: 0; padding: 0; box-sizing: border-box; }\r\n body {\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\r\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\r\n padding: 20px;\r\n min-height: 100vh;\r\n }\r\n .container {\r\n max-width: 1200px;\r\n margin: 0 auto;\r\n background: white;\r\n border-radius: 12px;\r\n box-shadow: 0 8px 32px rgba(0,0,0,0.2);\r\n overflow: hidden;\r\n }\r\n .header {\r\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\r\n color: white;\r\n padding: 30px;\r\n text-align: center;\r\n }\r\n .header h1 {\r\n font-size: 32px;\r\n margin-bottom: 10px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 10px;\r\n }\r\n .header .time {\r\n font-size: 14px;\r\n opacity: 0.9;\r\n }\r\n .content {\r\n padding: 30px;\r\n }\r\n .summary {\r\n display: grid;\r\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\r\n gap: 20px;\r\n margin: 30px 0;\r\n }\r\n .summary-card {\r\n padding: 25px;\r\n border-radius: 12px;\r\n text-align: center;\r\n box-shadow: 0 4px 12px rgba(0,0,0,0.1);\r\n transition: transform 0.2s;\r\n }\r\n .summary-card:hover {\r\n transform: translateY(-4px);\r\n }\r\n .summary-card.error { \r\n background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%);\r\n color: white;\r\n }\r\n .summary-card.warn { \r\n background: linear-gradient(135deg, #feca57 0%, #ff9ff3 100%);\r\n color: #333;\r\n }\r\n .summary-card.info { \r\n background: linear-gradient(135deg, #48dbfb 0%, #0abde3 100%);\r\n color: white;\r\n }\r\n .summary-card h2 { \r\n font-size: 42px; \r\n margin: 10px 0;\r\n font-weight: bold;\r\n }\r\n .summary-card p { \r\n font-size: 16px;\r\n font-weight: 500;\r\n }\r\n .section-title {\r\n font-size: 24px;\r\n font-weight: bold;\r\n color: #333;\r\n margin: 30px 0 20px 0;\r\n padding-bottom: 10px;\r\n border-bottom: 3px solid #667eea;\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n }\r\n .issue {\r\n border: 1px solid #e0e0e0;\r\n border-radius: 12px;\r\n padding: 20px;\r\n margin: 15px 0;\r\n background: #fafafa;\r\n box-shadow: 0 2px 8px rgba(0,0,0,0.05);\r\n transition: box-shadow 0.2s;\r\n }\r\n .issue:hover {\r\n box-shadow: 0 4px 16px rgba(0,0,0,0.1);\r\n }\r\n .issue-header {\r\n display: flex;\r\n align-items: center;\r\n gap: 10px;\r\n margin-bottom: 15px;\r\n flex-wrap: wrap;\r\n }\r\n .issue-badge {\r\n padding: 6px 14px;\r\n border-radius: 16px;\r\n font-size: 12px;\r\n font-weight: bold;\r\n text-transform: uppercase;\r\n }\r\n .issue-badge.error { background: #ff6b6b; color: white; }\r\n .issue-badge.warn { background: #feca57; color: #333; }\r\n .issue-badge.info { background: #48dbfb; color: white; }\r\n .issue-category {\r\n padding: 6px 14px;\r\n border-radius: 16px;\r\n font-size: 12px;\r\n font-weight: bold;\r\n background: #667eea;\r\n color: white;\r\n }\r\n .issue-file {\r\n color: #666;\r\n font-size: 14px;\r\n font-family: 'Courier New', monospace;\r\n background: #f0f0f0;\r\n padding: 4px 10px;\r\n border-radius: 6px;\r\n flex: 1;\r\n min-width: 200px;\r\n }\r\n .issue-line {\r\n color: #667eea;\r\n font-weight: bold;\r\n font-size: 14px;\r\n }\r\n .issue-message {\r\n margin: 15px 0;\r\n color: #333;\r\n line-height: 1.8;\r\n font-size: 15px;\r\n }\r\n .issue-suggestion {\r\n background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%);\r\n border-left: 4px solid #4caf50;\r\n padding: 15px;\r\n margin-top: 15px;\r\n border-radius: 8px;\r\n line-height: 1.6;\r\n }\r\n .issue-suggestion::before {\r\n content: \"💡 建议: \";\r\n font-weight: bold;\r\n color: #2e7d32;\r\n font-size: 16px;\r\n }\r\n .category-stats {\r\n display: flex;\r\n flex-wrap: wrap;\r\n gap: 15px;\r\n margin: 20px 0;\r\n }\r\n .category-tag {\r\n padding: 8px 16px;\r\n border-radius: 20px;\r\n background: #f0f0f0;\r\n color: #333;\r\n font-size: 14px;\r\n font-weight: 500;\r\n }\r\n .footer {\r\n background: #f7fafc;\r\n padding: 25px;\r\n text-align: center;\r\n color: #718096;\r\n font-size: 14px;\r\n border-top: 1px solid #e2e8f0;\r\n }\r\n .footer p {\r\n margin: 5px 0;\r\n }\r\n </style>\r\n</head>\r\n<body>\r\n <div class=\"container\">\r\n <div class=\"header\">\r\n <h1>🔍 代码审查报告</h1>\r\n <div class=\"time\">生成时间: ${new Date().toLocaleString(\"zh-CN\")}</div>\r\n </div>\r\n\r\n <div class=\"content\">\r\n <div class=\"summary\">\r\n <div class=\"summary-card error\">\r\n <h2>${issues.filter((i) => i.severity === \"error\").length}</h2>\r\n <p>错误</p>\r\n </div>\r\n <div class=\"summary-card warn\">\r\n <h2>${issues.filter((i) => i.severity === \"warn\").length}</h2>\r\n <p>警告</p>\r\n </div>\r\n <div class=\"summary-card info\">\r\n <h2>${issues.filter((i) => i.severity === \"info\").length}</h2>\r\n <p>信息</p>\r\n </div>\r\n </div>\r\n\r\n <div class=\"section-title\">📊 问题分类统计</div>\r\n <div class=\"category-stats\">\r\n ${Object.entries(this.groupByCategory(issues))\r\n .map(\r\n ([category, count]) =>\r\n `<div class=\"category-tag\">${this.getCategoryIcon(\r\n category\r\n )} ${category}: ${count}</div>`\r\n )\r\n .join(\"\")}\r\n </div>\r\n\r\n <div class=\"section-title\">📋 问题详情</div>\r\n ${issues\r\n .map(\r\n (issue) => `\r\n <div class=\"issue\">\r\n <div class=\"issue-header\">\r\n <span class=\"issue-badge ${\r\n issue.severity\r\n }\">${issue.severity.toUpperCase()}</span>\r\n <span class=\"issue-category\">${issue.category}</span>\r\n <span class=\"issue-file\">${issue.file}</span>\r\n ${\r\n issue.line ? `<span class=\"issue-line\">行 ${issue.line}</span>` : \"\"\r\n }\r\n </div>\r\n <div class=\"issue-message\">${issue.message}</div>\r\n ${\r\n issue.suggestion\r\n ? `<div class=\"issue-suggestion\">${issue.suggestion}</div>`\r\n : \"\"\r\n }\r\n </div>\r\n `\r\n )\r\n .join(\"\")}\r\n </div>\r\n\r\n <div class=\"footer\">\r\n <p>AI Code Review Plugin v1.0.0</p>\r\n <p>Powered by LangChain & OpenAI</p>\r\n </div>\r\n </div>\r\n</body>\r\n</html>\r\n `;\r\n\r\n // 创建报告目录\r\n const reportsDir = path.join(process.cwd(), \"ai-reports\");\r\n if (!fs.existsSync(reportsDir)) {\r\n fs.mkdirSync(reportsDir, { recursive: true });\r\n }\r\n\r\n const reportPath = path.join(reportsDir, \"code-review-report.html\");\r\n fs.writeFileSync(reportPath, html, \"utf-8\");\r\n console.log(`📄 HTML 报告已生成: ${reportPath}\\n`);\r\n }\r\n\r\n /**\r\n * 生成 Markdown 报告\r\n */\r\n private async generateMarkdownReport(issues: ReviewIssue[]): Promise<void> {\r\n const errors = issues.filter((i) => i.severity === \"error\");\r\n const warnings = issues.filter((i) => i.severity === \"warn\");\r\n const infos = issues.filter((i) => i.severity === \"info\");\r\n\r\n let markdown = `# 🔍 代码审查报告\r\n\r\n生成时间: ${new Date().toLocaleString(\"zh-CN\")}\r\n\r\n## 📊 概览\r\n\r\n| 类型 | 数量 |\r\n|------|------|\r\n| ❌ 错误 | ${errors.length} |\r\n| ⚠️ 警告 | ${warnings.length} |\r\n| ℹ️ 信息 | ${infos.length} |\r\n| 📝 总计 | ${issues.length} |\r\n\r\n## 📋 问题详情\r\n\r\n`;\r\n\r\n issues.forEach((issue, index) => {\r\n const icon = this.getSeverityIcon(issue.severity);\r\n markdown += `### ${index + 1}. ${icon} ${issue.category}\r\n\r\n**文件**: \\`${issue.file}${issue.line ? `:${issue.line}` : \"\"}\\` \r\n**严重程度**: ${issue.severity} \r\n**问题**: ${issue.message}\r\n\r\n`;\r\n\r\n if (issue.suggestion) {\r\n markdown += `💡 **建议**: ${issue.suggestion}\\n\\n`;\r\n }\r\n\r\n markdown += \"---\\n\\n\";\r\n });\r\n\r\n // 创建报告目录\r\n const reportsDir = path.join(process.cwd(), \"ai-reports\");\r\n if (!fs.existsSync(reportsDir)) {\r\n fs.mkdirSync(reportsDir, { recursive: true });\r\n }\r\n\r\n const reportPath = path.join(reportsDir, \"code-review-report.md\");\r\n fs.writeFileSync(reportPath, markdown, \"utf-8\");\r\n console.log(`📄 Markdown 报告已生成: ${reportPath}\\n`);\r\n }\r\n\r\n /**\r\n * 生成 JSON 报告\r\n */\r\n private async generateJSONReport(issues: ReviewIssue[]): Promise<void> {\r\n const report = {\r\n timestamp: new Date().toISOString(),\r\n summary: {\r\n total: issues.length,\r\n errors: issues.filter((i) => i.severity === \"error\").length,\r\n warnings: issues.filter((i) => i.severity === \"warn\").length,\r\n infos: issues.filter((i) => i.severity === \"info\").length,\r\n },\r\n issues: issues,\r\n };\r\n\r\n // 创建报告目录\r\n const reportsDir = path.join(process.cwd(), \"ai-reports\");\r\n if (!fs.existsSync(reportsDir)) {\r\n fs.mkdirSync(reportsDir, { recursive: true });\r\n }\r\n\r\n const reportPath = path.join(reportsDir, \"code-review-report.json\");\r\n fs.writeFileSync(reportPath, JSON.stringify(report, null, 2), \"utf-8\");\r\n console.log(`📄 JSON 报告已生成: ${reportPath}\\n`);\r\n }\r\n\r\n /**\r\n * 按类别分组\r\n */\r\n private groupByCategory(issues: ReviewIssue[]): Record<string, number> {\r\n const groups: Record<string, number> = {};\r\n\r\n issues.forEach((issue) => {\r\n groups[issue.category] = (groups[issue.category] || 0) + 1;\r\n });\r\n\r\n return groups;\r\n }\r\n\r\n /**\r\n * 获取类别图标\r\n */\r\n private getCategoryIcon(category: string): string {\r\n const icons: Record<string, string> = {\r\n security: \"🔒\",\r\n performance: \"⚡\",\r\n style: \"📝\",\r\n \"best-practice\": \"🎨\",\r\n };\r\n\r\n return icons[category] || \"📋\";\r\n }\r\n\r\n /**\r\n * 获取严重程度图标\r\n */\r\n private getSeverityIcon(severity: string): string {\r\n switch (severity) {\r\n case \"error\":\r\n return \"❌\";\r\n case \"warn\":\r\n return \"⚠️\";\r\n case \"info\":\r\n return \"ℹ️\";\r\n default:\r\n return \"📝\";\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":["crypto","path","fs","import_fs","import_path","path","fs","fs","path"]}