aemeathcli 1.0.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/README.md +607 -0
- package/dist/App-P4MYD4QY.js +2719 -0
- package/dist/App-P4MYD4QY.js.map +1 -0
- package/dist/api-key-fallback-YQQBOQIL.js +11 -0
- package/dist/api-key-fallback-YQQBOQIL.js.map +1 -0
- package/dist/chunk-4IJD72YB.js +184 -0
- package/dist/chunk-4IJD72YB.js.map +1 -0
- package/dist/chunk-6PDJ45T4.js +325 -0
- package/dist/chunk-6PDJ45T4.js.map +1 -0
- package/dist/chunk-CARHU3DO.js +562 -0
- package/dist/chunk-CARHU3DO.js.map +1 -0
- package/dist/chunk-CGEV3ARR.js +80 -0
- package/dist/chunk-CGEV3ARR.js.map +1 -0
- package/dist/chunk-CS5X3BWX.js +27 -0
- package/dist/chunk-CS5X3BWX.js.map +1 -0
- package/dist/chunk-CYQNBB25.js +44 -0
- package/dist/chunk-CYQNBB25.js.map +1 -0
- package/dist/chunk-DAHGLHNR.js +657 -0
- package/dist/chunk-DAHGLHNR.js.map +1 -0
- package/dist/chunk-H66O5Z2V.js +305 -0
- package/dist/chunk-H66O5Z2V.js.map +1 -0
- package/dist/chunk-HCIHOHLX.js +322 -0
- package/dist/chunk-HCIHOHLX.js.map +1 -0
- package/dist/chunk-HMJRPNPZ.js +1031 -0
- package/dist/chunk-HMJRPNPZ.js.map +1 -0
- package/dist/chunk-I5PZ4JTS.js +119 -0
- package/dist/chunk-I5PZ4JTS.js.map +1 -0
- package/dist/chunk-IYW62KKR.js +255 -0
- package/dist/chunk-IYW62KKR.js.map +1 -0
- package/dist/chunk-JAXXTYID.js +51 -0
- package/dist/chunk-JAXXTYID.js.map +1 -0
- package/dist/chunk-LSOYPSAT.js +183 -0
- package/dist/chunk-LSOYPSAT.js.map +1 -0
- package/dist/chunk-MFBHNWGV.js +416 -0
- package/dist/chunk-MFBHNWGV.js.map +1 -0
- package/dist/chunk-MXZSI3AY.js +311 -0
- package/dist/chunk-MXZSI3AY.js.map +1 -0
- package/dist/chunk-NBR3GHMT.js +72 -0
- package/dist/chunk-NBR3GHMT.js.map +1 -0
- package/dist/chunk-O3ZF22SW.js +246 -0
- package/dist/chunk-O3ZF22SW.js.map +1 -0
- package/dist/chunk-SUSJPZU2.js +181 -0
- package/dist/chunk-SUSJPZU2.js.map +1 -0
- package/dist/chunk-TEVZS4FA.js +310 -0
- package/dist/chunk-TEVZS4FA.js.map +1 -0
- package/dist/chunk-UY2SYSEZ.js +211 -0
- package/dist/chunk-UY2SYSEZ.js.map +1 -0
- package/dist/chunk-WAHVZH7V.js +260 -0
- package/dist/chunk-WAHVZH7V.js.map +1 -0
- package/dist/chunk-WPP3PEDE.js +234 -0
- package/dist/chunk-WPP3PEDE.js.map +1 -0
- package/dist/chunk-Y5XVD2CD.js +1610 -0
- package/dist/chunk-Y5XVD2CD.js.map +1 -0
- package/dist/chunk-YL5XFHR3.js +56 -0
- package/dist/chunk-YL5XFHR3.js.map +1 -0
- package/dist/chunk-ZGOHARPV.js +122 -0
- package/dist/chunk-ZGOHARPV.js.map +1 -0
- package/dist/claude-adapter-QMLFMSP3.js +6 -0
- package/dist/claude-adapter-QMLFMSP3.js.map +1 -0
- package/dist/claude-login-5WELXPKT.js +324 -0
- package/dist/claude-login-5WELXPKT.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +703 -0
- package/dist/cli.js.map +1 -0
- package/dist/codex-login-7HHLJHBF.js +164 -0
- package/dist/codex-login-7HHLJHBF.js.map +1 -0
- package/dist/config-store-W6FBCQAQ.js +6 -0
- package/dist/config-store-W6FBCQAQ.js.map +1 -0
- package/dist/executor-6RIKIGXK.js +4 -0
- package/dist/executor-6RIKIGXK.js.map +1 -0
- package/dist/gemini-adapter-6JIHZ7WI.js +6 -0
- package/dist/gemini-adapter-6JIHZ7WI.js.map +1 -0
- package/dist/gemini-login-ZZLYC3J6.js +346 -0
- package/dist/gemini-login-ZZLYC3J6.js.map +1 -0
- package/dist/index.d.ts +2210 -0
- package/dist/index.js +1419 -0
- package/dist/index.js.map +1 -0
- package/dist/kimi-adapter-JN4HFFHU.js +6 -0
- package/dist/kimi-adapter-JN4HFFHU.js.map +1 -0
- package/dist/kimi-login-CZPS63NK.js +149 -0
- package/dist/kimi-login-CZPS63NK.js.map +1 -0
- package/dist/native-cli-adapters-OLW3XX57.js +6 -0
- package/dist/native-cli-adapters-OLW3XX57.js.map +1 -0
- package/dist/ollama-adapter-OJQ3FKWK.js +6 -0
- package/dist/ollama-adapter-OJQ3FKWK.js.map +1 -0
- package/dist/openai-adapter-XU46EN7B.js +6 -0
- package/dist/openai-adapter-XU46EN7B.js.map +1 -0
- package/dist/registry-4KD24ZC3.js +6 -0
- package/dist/registry-4KD24ZC3.js.map +1 -0
- package/dist/registry-H7B3AHPQ.js +5 -0
- package/dist/registry-H7B3AHPQ.js.map +1 -0
- package/dist/server-manager-PTGBHCLS.js +5 -0
- package/dist/server-manager-PTGBHCLS.js.map +1 -0
- package/dist/session-manager-ECEEACGY.js +12 -0
- package/dist/session-manager-ECEEACGY.js.map +1 -0
- package/dist/team-manager-HC4XGCFY.js +11 -0
- package/dist/team-manager-HC4XGCFY.js.map +1 -0
- package/dist/tmux-manager-GPYZ3WQH.js +6 -0
- package/dist/tmux-manager-GPYZ3WQH.js.map +1 -0
- package/dist/tools-TSMXMHIF.js +6 -0
- package/dist/tools-TSMXMHIF.js.map +1 -0
- package/package.json +89 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/model-router.ts","../src/core/context-manager.ts","../src/core/cost-tracker.ts","../src/core/permission-manager.ts","../src/core/task-orchestrator.ts"],"names":[],"mappings":";;;;;;;;AAwBO,IAAM,cAAN,MAAkB;AAAA,EACN,MAAA;AAAA,EACT,YAAA;AAAA,EAER,YAAY,MAAA,EAA4B;AACtC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,OAAA,EAAmC;AACjD,IAAA,IAAI,YAAY,MAAA,EAAW;AACzB,MAAA,IAAA,CAAK,cAAc,OAAO,CAAA;AAAA,IAC5B;AACA,IAAA,IAAA,CAAK,YAAA,GAAe,OAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,IAAA,EAAoC;AAE1C,IAAA,IAAI,KAAK,YAAA,EAAc;AACrB,MAAA,MAAM,IAAA,GAAO,IAAA,CAAK,YAAA,CAAa,IAAA,CAAK,YAAY,CAAA;AAChD,MAAA,OAAO;AAAA,QACL,SAAS,IAAA,CAAK,YAAA;AAAA,QACd,UAAU,IAAA,CAAK,QAAA;AAAA,QACf,MAAA,EAAQ,eAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AAGA,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,MAAM,UAAA,GAAa,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA;AACzC,MAAA,IAAI,UAAA,EAAY;AAEd,QAAA,IAAI,IAAA,CAAK,gBAAA,CAAiB,UAAA,CAAW,OAAO,CAAA,EAAG;AAC7C,UAAA,MAAM,IAAA,GAAO,IAAA,CAAK,YAAA,CAAa,UAAA,CAAW,OAAO,CAAA;AACjD,UAAA,OAAO;AAAA,YACL,SAAS,UAAA,CAAW,OAAA;AAAA,YACpB,UAAU,IAAA,CAAK,QAAA;AAAA,YACf,MAAA,EAAQ,aAAA;AAAA,YACR;AAAA,WACF;AAAA,QACF;AAGA,QAAA,KAAA,MAAW,aAAA,IAAiB,WAAW,QAAA,EAAU;AAC/C,UAAA,IAAI,IAAA,CAAK,gBAAA,CAAiB,aAAa,CAAA,EAAG;AACxC,YAAA,MAAM,IAAA,GAAO,IAAA,CAAK,YAAA,CAAa,aAAa,CAAA;AAC5C,YAAA,MAAA,CAAO,IAAA;AAAA,cACL,EAAE,IAAA,EAAM,OAAA,EAAS,UAAA,CAAW,OAAA,EAAS,UAAU,aAAA,EAAc;AAAA,cAC7D;AAAA,aACF;AACA,YAAA,OAAO;AAAA,cACL,OAAA,EAAS,aAAA;AAAA,cACT,UAAU,IAAA,CAAK,QAAA;AAAA,cACf,MAAA,EAAQ,gBAAA;AAAA,cACR;AAAA,aACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,IAAA,MAAM,YAAA,GAAe,KAAK,MAAA,CAAO,YAAA;AACjC,IAAA,IAAI,IAAA,CAAK,gBAAA,CAAiB,YAAY,CAAA,EAAG;AACvC,MAAA,MAAM,IAAA,GAAO,IAAA,CAAK,YAAA,CAAa,YAAY,CAAA;AAC3C,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,YAAA;AAAA,QACT,UAAU,IAAA,CAAK,QAAA;AAAA,QACf,MAAA,EAAQ,gBAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AAGA,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,kBAAA,EAAmB,CAAE,CAAC,CAAA;AAChD,IAAA,IAAI,YAAA,EAAc;AAChB,MAAA,OAAO;AAAA,QACL,SAAS,YAAA,CAAa,EAAA;AAAA,QACtB,UAAU,YAAA,CAAa,QAAA;AAAA,QACvB,MAAA,EAAQ,gBAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AAEA,IAAA,MAAM,IAAI,mBAAmB,YAAY,CAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,OAAA,EAA0B;AACzC,IAAA,MAAM,IAAA,GAAO,iBAAiB,OAAO,CAAA;AACrC,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,gBAAA,CAAiB,QAAA,CAAS,KAAK,QAAQ,CAAA;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,OAAA,EAA6B;AACxC,IAAA,MAAM,IAAA,GAAO,iBAAiB,OAAO,CAAA;AACrC,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,MAAM,IAAI,mBAAmB,OAAO,CAAA;AAAA,IACtC;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAA,GAA4C;AAC1C,IAAA,OAAO,MAAA,CAAO,MAAA,CAAO,gBAAgB,CAAA,CAAE,MAAA;AAAA,MAAO,CAAC,KAAA,KAC7C,IAAA,CAAK,OAAO,gBAAA,CAAiB,QAAA,CAAS,MAAM,QAAQ;AAAA,KACtD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,IAAA,EAAwC;AACvD,IAAA,OAAO,IAAA,CAAK,oBAAmB,CAAE,MAAA;AAAA,MAAO,CAAC,KAAA,KACvC,KAAA,CAAM,cAAA,CAAe,SAAS,IAAI;AAAA,KACpC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,OAAA,EAAuB;AAC3C,IAAA,IAAI,CAAC,gBAAA,CAAiB,OAAO,CAAA,EAAG;AAC9B,MAAA,MAAM,IAAI,mBAAmB,OAAO,CAAA;AAAA,IACtC;AAAA,EACF;AACF;AAKO,SAAS,kBAAkB,MAAA,EAAoC;AACpE,EAAA,MAAM,gBAAA,GAAmB,OAAO,OAAA,CAAQ,MAAA,CAAO,SAAS,CAAA,CACrD,MAAA,CAAO,CAAC,GAAG,cAAc,CAAA,KAAM,cAAA,EAAgB,OAAO,CAAA,CACtD,GAAA,CAAI,CAAC,CAAC,IAAI,MAAM,IAAoB,CAAA;AAEvC,EAAA,OAAO,IAAI,WAAA,CAAY;AAAA,IACrB,cAAc,MAAA,CAAO,YAAA;AAAA,IACrB,OAAO,MAAA,CAAO,KAAA;AAAA,IACd;AAAA,GACD,CAAA;AACH;;;ACxKA,IAAM,oBAAA,GAAuB,IAAA;AAC7B,IAAM,qBAAA,GAAwB,GAAA;AAQvB,IAAM,iBAAN,MAAqB;AAAA,EACT,SAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA,uBAAkB,GAAA,EAA+B;AAAA,EAC1D,iBAAA,GAAoB,CAAA;AAAA,EAE5B,YAAY,SAAA,EAAuB;AACjC,IAAA,IAAA,CAAK,YAAY,SAAA,CAAU,aAAA;AAC3B,IAAA,IAAA,CAAK,YAAA,GAAe,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,YAAY,oBAAoB,CAAA;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAA,GAA6B;AAC3B,IAAA,OAAO,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,YAAA,GAAe,IAAA,CAAK,oBAAoB,qBAAqB,CAAA;AAAA,EACvF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAA,GAA8E;AAC5E,IAAA,OAAO;AAAA,MACL,MAAM,IAAA,CAAK,iBAAA;AAAA,MACX,QAAQ,IAAA,CAAK,YAAA;AAAA,MACb,KAAK,IAAA,CAAK,SAAA;AAAA,MACV,YAAY,IAAA,CAAK,KAAA,CAAO,KAAK,iBAAA,GAAoB,IAAA,CAAK,eAAgB,GAAG;AAAA,KAC3E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAA,CAAa,UAAmC,YAAA,EAAuC;AACrF,IAAA,MAAM,YAAA,GAAe,YAAA,GAAe,kBAAA,CAAmB,YAAY,CAAA,GAAI,CAAA;AACvE,IAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,YAAA,GAAe,YAAA,GAAe,qBAAA;AAE3D,IAAA,IAAI,mBAAmB,CAAA,EAAG;AACxB,MAAA,MAAA,CAAO,KAAK,4CAA4C,CAAA;AACxD,MAAA,OAAO,EAAC;AAAA,IACV;AAGA,IAAA,MAAM,SAAyB,EAAC;AAChC,IAAA,IAAI,UAAA,GAAa,CAAA;AAEjB,IAAA,KAAA,IAAS,IAAI,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG,CAAA,IAAK,GAAG,CAAA,EAAA,EAAK;AAC7C,MAAA,MAAM,GAAA,GAAM,SAAS,CAAC,CAAA;AACtB,MAAA,IAAI,CAAC,GAAA,EAAK;AACR,QAAA;AAAA,MACF;AACA,MAAA,MAAM,SAAA,GAAY,kBAAA,CAAmB,GAAA,CAAI,OAAO,CAAA;AAEhD,MAAA,IAAI,UAAA,GAAa,YAAY,eAAA,EAAiB;AAC5C,QAAA;AAAA,MACF;AAEA,MAAA,MAAA,CAAO,QAAQ,GAAG,CAAA;AAClB,MAAA,UAAA,IAAc,SAAA;AAAA,IAChB;AAEA,IAAA,IAAA,CAAK,oBAAoB,UAAA,GAAa,YAAA;AAEtC,IAAA,IAAI,MAAA,CAAO,MAAA,GAAS,QAAA,CAAS,MAAA,EAAQ;AACnC,MAAA,MAAA,CAAO,IAAA;AAAA,QACL;AAAA,UACE,UAAU,QAAA,CAAS,MAAA;AAAA,UACnB,SAAS,MAAA,CAAO,MAAA;AAAA,UAChB,eAAA,EAAiB,QAAA,CAAS,MAAA,GAAS,MAAA,CAAO;AAAA,SAC5C;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,cAAA,CAAe,UAAkB,OAAA,EAAuB;AACtD,IAAA,MAAM,UAAA,GAAa,mBAAmB,OAAO,CAAA;AAC7C,IAAA,IAAA,CAAK,WAAA,CAAY,IAAI,QAAA,EAAU;AAAA,MAC7B,QAAA;AAAA,MACA,UAAA;AAAA,MACA,cAAA,EAAgB,KAAK,GAAA;AAAI,KAC1B,CAAA;AACD,IAAA,IAAA,CAAK,iBAAA,IAAqB,UAAA;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,QAAA,EAAwB;AAChC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,QAAQ,CAAA;AAC3C,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,KAAA,CAAM,cAAA,GAAiB,KAAK,GAAA,EAAI;AAAA,IAClC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB,QAAA,EAAwB;AACxC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,QAAQ,CAAA;AAC3C,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,IAAA,CAAK,qBAAqB,KAAA,CAAM,UAAA;AAChC,MAAA,IAAA,CAAK,WAAA,CAAY,OAAO,QAAQ,CAAA;AAAA,IAClC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,YAAA,EAAgC;AACvC,IAAA,MAAM,UAAoB,EAAC;AAC3B,IAAA,MAAM,SAAS,CAAC,GAAG,KAAK,WAAA,CAAY,OAAA,EAAS,CAAA,CAAE,IAAA;AAAA,MAC7C,CAAC,GAAG,CAAC,CAAA,EAAG,GAAG,CAAC,CAAA,KAAM,CAAA,CAAE,cAAA,GAAiB,CAAA,CAAE;AAAA,KACzC;AAEA,IAAA,IAAI,WAAA,GAAc,CAAA;AAClB,IAAA,KAAA,MAAW,CAAC,QAAA,EAAU,KAAK,CAAA,IAAK,MAAA,EAAQ;AACtC,MAAA,IAAI,eAAe,YAAA,EAAc;AAC/B,QAAA;AAAA,MACF;AACA,MAAA,IAAA,CAAK,kBAAkB,QAAQ,CAAA;AAC/B,MAAA,WAAA,IAAe,KAAA,CAAM,UAAA;AACrB,MAAA,OAAA,CAAQ,KAAK,QAAQ,CAAA;AAAA,IACvB;AAEA,IAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,EAAG;AACtB,MAAA,MAAA,CAAO,IAAA;AAAA,QACL,EAAE,SAAS,WAAA,EAAY;AAAA,QACvB;AAAA,OACF;AAAA,IACF;AAEA,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,eAAA,GAAgD;AAC9C,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,WAAA,CAAY,QAAQ,CAAA;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,YAAY,KAAA,EAAM;AACvB,IAAA,IAAA,CAAK,iBAAA,GAAoB,CAAA;AAAA,EAC3B;AACF;;;ACrJO,IAAM,cAAN,MAAkB;AAAA,EACN,UAAwB,EAAC;AAAA,EACzB,YAAA;AAAA,EACT,cAAA,GAAiB,KAAA;AAAA,EAEzB,YAAY,YAAA,EAA2B;AACrC,IAAA,IAAA,CAAK,YAAA,GAAe,YAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAA,CACE,QAAA,EACA,KAAA,EACA,WAAA,EACA,cACA,IAAA,EACa;AACb,IAAA,MAAM,KAAA,GAAQ,gBAAA,CAAiB,KAAA,EAAO,WAAA,EAAa,YAAY,CAAA;AAE/D,IAAA,MAAM,KAAA,GAAoB;AAAA,MACxB,QAAA;AAAA,MACA,KAAA;AAAA,MACA,IAAA;AAAA,MACA,KAAA;AAAA,MACA,SAAA,sBAAe,IAAA;AAAK,KACtB;AAEA,IAAA,IAAA,CAAK,OAAA,CAAQ,KAAK,KAAK,CAAA;AAEvB,IAAA,MAAM,KAAA,GAAQ,KAAK,eAAA,EAAgB;AACnC,IAAA,MAAM,WAAW,WAAA,EAAY;AAE7B,IAAA,QAAA,CAAS,KAAK,cAAA,EAAgB;AAAA,MAC5B,KAAA;AAAA,MACA,QAAA;AAAA,MACA,OAAO,KAAA,CAAM;AAAA,KACd,CAAA;AAGD,IAAA,IAAI,SAAS,IAAA,CAAK,YAAA,CAAa,aAAA,IAAiB,CAAC,KAAK,cAAA,EAAgB;AACpE,MAAA,IAAA,CAAK,cAAA,GAAiB,IAAA;AACtB,MAAA,QAAA,CAAS,KAAK,cAAA,EAAgB;AAAA,QAC5B,OAAA,EAAS,KAAA;AAAA,QACT,KAAA,EAAO,KAAK,YAAA,CAAa;AAAA,OAC1B,CAAA;AACD,MAAA,MAAA,CAAO,IAAA;AAAA,QACL,EAAE,OAAA,EAAS,UAAA,CAAW,KAAK,CAAA,EAAG,SAAS,UAAA,CAAW,IAAA,CAAK,YAAA,CAAa,aAAa,CAAA,EAAE;AAAA,QACnF;AAAA,OACF;AAAA,IACF;AAGA,IAAA,IAAI,KAAA,IAAS,IAAA,CAAK,YAAA,CAAa,cAAA,EAAgB;AAC7C,MAAA,QAAA,CAAS,KAAK,eAAA,EAAiB;AAAA,QAC7B,OAAA,EAAS,KAAA;AAAA,QACT,KAAA,EAAO,KAAK,YAAA,CAAa;AAAA,OAC1B,CAAA;AACD,MAAA,MAAA,CAAO,KAAA;AAAA,QACL,EAAE,OAAA,EAAS,UAAA,CAAW,KAAK,CAAA,EAAG,OAAO,UAAA,CAAW,IAAA,CAAK,YAAA,CAAa,cAAc,CAAA,EAAE;AAAA,QAClF;AAAA,OACF;AAAA,IACF;AAEA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,eAAA,GAA0B;AACxB,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,CAAC,GAAA,EAAK,UAAU,GAAA,GAAM,KAAA,CAAM,KAAA,CAAM,OAAA,EAAS,CAAC,CAAA;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAA,GAAqE;AACnE,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,CAAC,GAAA,EAAK,CAAA,KAAM,GAAA,GAAM,CAAA,CAAE,KAAA,CAAM,WAAA,EAAa,CAAC,CAAA;AAC1E,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,CAAC,GAAA,EAAK,CAAA,KAAM,GAAA,GAAM,CAAA,CAAE,KAAA,CAAM,YAAA,EAAc,CAAC,CAAA;AAC5E,IAAA,OAAO,EAAE,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAO,QAAQ,MAAA,EAAO;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,YAAA,GAA+B;AAC7B,IAAA,MAAM,aAAqC,EAAC;AAC5C,IAAA,MAAM,UAAkC,EAAC;AACzC,IAAA,MAAM,SAAiC,EAAC;AAExC,IAAA,KAAA,MAAW,KAAA,IAAS,KAAK,OAAA,EAAS;AAChC,MAAA,UAAA,CAAW,KAAA,CAAM,QAAQ,CAAA,GAAA,CAAK,UAAA,CAAW,MAAM,QAAQ,CAAA,IAAK,CAAA,IAAK,KAAA,CAAM,KAAA,CAAM,OAAA;AAC7E,MAAA,OAAA,CAAQ,KAAA,CAAM,KAAK,CAAA,GAAA,CAAK,OAAA,CAAQ,MAAM,KAAK,CAAA,IAAK,CAAA,IAAK,KAAA,CAAM,KAAA,CAAM,OAAA;AACjE,MAAA,IAAI,MAAM,IAAA,EAAM;AACd,QAAA,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA,GAAA,CAAK,MAAA,CAAO,MAAM,IAAI,CAAA,IAAK,CAAA,IAAK,KAAA,CAAM,KAAA,CAAM,OAAA;AAAA,MAC/D;AAAA,IACF;AAEA,IAAA,OAAO,EAAE,UAAA,EAAY,OAAA,EAAS,MAAA,EAAO;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAA,GAA4B;AAC1B,IAAA,OAAO,IAAA,CAAK,eAAA,EAAgB,IAAK,IAAA,CAAK,YAAA,CAAa,cAAA;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,UAAA,GAAqB;AACnB,IAAA,MAAM,KAAA,GAAQ,KAAK,eAAA,EAAgB;AACnC,IAAA,MAAM,MAAA,GAAS,KAAK,gBAAA,EAAiB;AACrC,IAAA,OAAO,CAAA,EAAG,WAAW,KAAK,CAAC,KAAK,MAAA,CAAO,KAAA,CAAM,gBAAgB,CAAA,QAAA,CAAA;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA,EAKA,UAAA,GAAoC;AAClC,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,QAAQ,MAAA,GAAS,CAAA;AACtB,IAAA,IAAA,CAAK,cAAA,GAAiB,KAAA;AAAA,EACxB;AACF;;;ACtJA,IAAM,kBAAA,GAAqB;AAAA,EACzB,QAAA;AAAA,EACA,kBAAA;AAAA,EACA,kBAAA;AAAA,EACA,gBAAA;AAAA,EACA,cAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,eAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAA;AAgBO,IAAM,oBAAN,MAAwB;AAAA,EACrB,IAAA;AAAA,EACS,YAAA;AAAA,EACA,eAAA;AAAA,EACA,kBAAA,uBAAyB,GAAA,EAAY;AAAA,EAEtD,WAAA,CACE,IAAA,EACA,YAAA,EACA,eAAA,EACA;AACA,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,YAAA,GAAe,YAAA;AACpB,IAAA,IAAA,CAAK,eAAA,GAAkB,eAAA;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAA,EAAgD;AAEpD,IAAA,IAAI,QAAQ,OAAA,IAAW,IAAA,CAAK,kBAAA,CAAmB,OAAA,CAAQ,OAAO,CAAA,EAAG;AAC/D,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,MAAA,EAAQ,CAAA,6BAAA,EAAgC,OAAA,CAAQ,OAAO,CAAA,CAAA,CAAA;AAAA,QACvD,oBAAA,EAAsB;AAAA,OACxB;AAAA,IACF;AAGA,IAAA,IAAI,QAAQ,OAAA,IAAW,gBAAA,CAAiB,QAAQ,OAAA,EAAS,IAAA,CAAK,eAAe,CAAA,EAAG;AAC9E,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,MAAA,EAAQ,CAAA,8BAAA,CAAA;AAAA,QACR,oBAAA,EAAsB;AAAA,OACxB;AAAA,IACF;AAGA,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,eAAA,CAAgB,OAAO,CAAA;AAC1C,IAAA,IAAI,IAAA,CAAK,kBAAA,CAAmB,GAAA,CAAI,KAAK,CAAA,EAAG;AACtC,MAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,oBAAA,EAAsB,KAAA,EAAM;AAAA,IACtD;AAGA,IAAA,QAAQ,KAAK,IAAA;AAAM,MACjB,KAAK,YAAA;AACH,QAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,oBAAA,EAAsB,KAAA,EAAM;AAAA,MAEtD,KAAK,UAAA;AACH,QAAA,OAAO,IAAA,CAAK,kBAAkB,OAAO,CAAA;AAAA,MAEvC,KAAK,QAAA;AACH,QAAA,OAAO,IAAA,CAAK,gBAAgB,OAAO,CAAA;AAAA;AACvC,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,OAAA,EAAmC;AACzC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,eAAA,CAAgB,OAAO,CAAA;AAC1C,IAAA,IAAA,CAAK,kBAAA,CAAmB,IAAI,KAAK,CAAA;AACjC,IAAA,MAAA,CAAO,IAAA,CAAK,EAAE,SAAA,EAAW,KAAA,IAAS,4BAA4B,CAAA;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,IAAA,EAA4B;AAClC,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,mBAAmB,KAAA,EAAM;AAC9B,IAAA,MAAA,CAAO,IAAA,CAAK,EAAE,IAAA,EAAK,EAAG,yBAAyB,CAAA;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAA,GAA0B;AACxB,IAAA,OAAO,IAAA,CAAK,IAAA;AAAA,EACd;AAAA,EAEQ,kBAAkB,OAAA,EAAgD;AAExE,IAAA,IAAI,IAAA,CAAK,eAAA,CAAgB,OAAO,CAAA,EAAG;AACjC,MAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,oBAAA,EAAsB,KAAA,EAAM;AAAA,IACtD;AAGA,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT,MAAA,EAAQ,CAAA,EAAG,OAAA,CAAQ,SAAS,CAAA,mCAAA,CAAA;AAAA,MAC5B,oBAAA,EAAsB;AAAA,KACxB;AAAA,EACF;AAAA,EAEQ,gBAAgB,OAAA,EAAgD;AAEtE,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT,MAAA,EAAQ,CAAA,EAAG,OAAA,CAAQ,SAAS,CAAA,iCAAA,CAAA;AAAA,MAC5B,oBAAA,EAAsB;AAAA,KACxB;AAAA,EACF;AAAA,EAEQ,gBAAgB,OAAA,EAAsC;AAC5D,IAAA,MAAM,YAAY,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAA,EAAQ,cAAc,WAAW,CAAA;AACpE,IAAA,OAAO,SAAA,CAAU,QAAA,CAAS,OAAA,CAAQ,QAAQ,CAAA;AAAA,EAC5C;AAAA,EAEQ,mBAAmB,OAAA,EAA0B;AACnD,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,WAAA,EAAY,CAAE,IAAA,EAAK;AACzC,IAAA,OAAO,mBAAmB,IAAA,CAAK,CAAC,cAAc,KAAA,CAAM,QAAA,CAAS,SAAS,CAAC,CAAA;AAAA,EACzE;AAAA,EAEQ,gBAAgB,OAAA,EAAqC;AAC3D,IAAA,OAAO,CAAA,EAAG,QAAQ,QAAQ,CAAA,CAAA,EAAI,QAAQ,SAAS,CAAA,CAAA,EAAI,OAAA,CAAQ,QAAA,IAAY,EAAE,CAAA,CAAA;AAAA,EAC3E;AACF;;;ACnJA,IAAI,UAAA,GAAa,CAAA;AAEjB,SAAS,cAAA,GAAyB;AAChC,EAAA,OAAO,OAAO,UAAA,EAAY,CAAA;AAC5B;AAEO,IAAM,mBAAN,MAAuB;AAAA,EACX,KAAA,uBAAY,GAAA,EAAmB;AAAA;AAAA;AAAA;AAAA,EAKhD,UAAA,CACE,OAAA,EACA,WAAA,EACA,OAAA,EAMO;AACP,IAAA,MAAM,KAAK,cAAA,EAAe;AAC1B,IAAA,MAAM,GAAA,uBAAU,IAAA,EAAK;AAErB,IAAA,MAAM,IAAA,GAAc;AAAA,MAClB,EAAA;AAAA,MACA,OAAA;AAAA,MACA,WAAA;AAAA,MACA,MAAA,EAAQ,SAAA;AAAA,MACR,OAAO,OAAA,EAAS,KAAA;AAAA,MAChB,OAAO,OAAA,EAAS,KAAA;AAAA,MAChB,MAAM,OAAA,EAAS,IAAA;AAAA,MACf,QAAQ,EAAC;AAAA,MACT,SAAA,EAAW,SAAS,SAAA,GAAY,CAAC,GAAG,OAAA,CAAQ,SAAS,IAAI,EAAC;AAAA,MAC1D,SAAA,EAAW,GAAA;AAAA,MACX,SAAA,EAAW;AAAA,KACb;AAEA,IAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,EAAA,EAAI,IAAI,CAAA;AAGvB,IAAA,IAAI,SAAS,SAAA,EAAW;AACtB,MAAA,KAAA,MAAW,SAAA,IAAa,QAAQ,SAAA,EAAW;AACzC,QAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,SAAS,CAAA;AACxC,QAAA,IAAI,WAAW,CAAC,OAAA,CAAQ,MAAA,CAAO,QAAA,CAAS,EAAE,CAAA,EAAG;AAC3C,UAAA,OAAA,CAAQ,MAAA,CAAO,KAAK,EAAE,CAAA;AAAA,QACxB;AAAA,MACF;AAAA,IACF;AAEA,IAAA,WAAA,GAAc,IAAA,CAAK,cAAA,EAAgB,EAAE,MAAA,EAAQ,EAAA,EAAI,SAAS,CAAA;AAC1D,IAAA,MAAA,CAAO,KAAK,EAAE,MAAA,EAAQ,EAAA,EAAI,OAAA,IAAW,cAAc,CAAA;AAEnD,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,YAAA,CAAa,QAAgB,MAAA,EAA0B;AACrD,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,MAAM,CAAA;AAChC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,SAAA,uBAAgB,IAAA,EAAK;AAE1B,IAAA,WAAA,GAAc,IAAA,CAAK,cAAA,EAAgB,EAAE,MAAA,EAAQ,QAAQ,CAAA;AAErD,IAAA,IAAI,WAAW,WAAA,EAAa;AAC1B,MAAA,WAAA,EAAY,CAAE,IAAA,CAAK,gBAAA,EAAkB,EAAE,QAAQ,CAAA;AAC/C,MAAA,IAAA,CAAK,oBAAoB,MAAM,CAAA;AAAA,IACjC;AAEA,IAAA,MAAA,CAAO,IAAA,CAAK,EAAE,MAAA,EAAQ,MAAA,IAAU,qBAAqB,CAAA;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,UAAA,CAAW,MAAA,EAAgB,KAAA,EAAe,KAAA,EAAsB;AAC9D,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,MAAM,CAAA;AAChC,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AACb,IAAA,IAAI,KAAA,EAAO;AACT,MAAC,KAA4B,KAAA,GAAQ,KAAA;AAAA,IACvC;AACA,IAAA,IAAA,CAAK,SAAA,uBAAgB,IAAA,EAAK;AAC1B,IAAA,MAAA,CAAO,KAAK,EAAE,MAAA,EAAQ,KAAA,EAAO,KAAA,IAAS,eAAe,CAAA;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,MAAA,EAAuB;AAC7B,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,MAAM,CAAA;AAClC,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gBAAA,EAAmB,MAAM,CAAA,CAAE,CAAA;AAAA,IAC7C;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,WAAA,GAAgC;AAC9B,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,KAAA,CAAM,QAAQ,CAAA;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,MAAA,EAAsC;AACrD,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,KAAA,CAAM,MAAA,EAAQ,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,KAAW,MAAM,CAAA;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,KAAA,EAAiC;AAC/C,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,KAAA,CAAM,MAAA,EAAQ,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,KAAU,KAAK,CAAA;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAA,GAAsC;AACpC,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,KAAA,CAAM,MAAA,EAAQ,CAAA,CAAE,MAAA;AAAA,MAC9B,CAAC,CAAA,KACC,CAAA,CAAE,MAAA,KAAW,SAAA,IACb,CAAC,CAAA,CAAE,KAAA,IACH,CAAA,CAAE,SAAA,CAAU,KAAA,CAAM,CAAC,SAAA,KAAc;AAC/B,QAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,SAAS,CAAA;AACxC,QAAA,OAAO,SAAS,MAAA,KAAW,WAAA;AAAA,MAC7B,CAAC;AAAA,KACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAA,GAAyB;AACvB,IAAA,OAAO,CAAC,GAAG,IAAA,CAAK,KAAA,CAAM,MAAA,EAAQ,CAAA,CAAE,KAAA,CAAM,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,KAAW,WAAW,CAAA;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA,EAKA,WAAA,GAA0G;AACxG,IAAA,MAAM,QAAQ,CAAC,GAAG,IAAA,CAAK,KAAA,CAAM,QAAQ,CAAA;AACrC,IAAA,OAAO;AAAA,MACL,OAAO,KAAA,CAAM,MAAA;AAAA,MACb,SAAA,EAAW,MAAM,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,WAAW,CAAA,CAAE,MAAA;AAAA,MACzD,UAAA,EAAY,MAAM,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,aAAa,CAAA,CAAE,MAAA;AAAA,MAC5D,OAAA,EAAS,MAAM,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,SAAS,CAAA,CAAE,MAAA;AAAA,MACrD,OAAA,EAAS,MAAM,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,SAAS,CAAA,CAAE;AAAA,KACvD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,MAAA,EAAsB;AAC/B,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,MAAM,CAAA;AAClC,IAAA,IAAI,IAAA,EAAM;AAER,MAAA,KAAA,MAAW,GAAG,SAAS,CAAA,IAAK,KAAK,KAAA,EAAO;AACtC,QAAA,SAAA,CAAU,YAAY,SAAA,CAAU,SAAA,CAAU,OAAO,CAAC,EAAA,KAAO,OAAO,MAAM,CAAA;AACtE,QAAA,SAAA,CAAU,SAAS,SAAA,CAAU,MAAA,CAAO,OAAO,CAAC,EAAA,KAAO,OAAO,MAAM,CAAA;AAAA,MAClE;AACA,MAAA,IAAA,CAAK,KAAA,CAAM,OAAO,MAAM,CAAA;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAoB,eAAA,EAA+B;AACzD,IAAA,KAAA,MAAW,GAAG,IAAI,CAAA,IAAK,KAAK,KAAA,EAAO;AACjC,MAAA,IAAI,IAAA,CAAK,MAAA,KAAW,SAAA,IAAa,IAAA,CAAK,WAAW,SAAA,EAAW;AAC1D,QAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,SAAA,CAAU,KAAA,CAAM,CAAC,KAAA,KAAU;AACtD,UAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,KAAK,CAAA;AAChC,UAAA,OAAO,KAAK,MAAA,KAAW,WAAA;AAAA,QACzB,CAAC,CAAA;AAED,QAAA,IAAI,eAAA,IAAmB,IAAA,CAAK,MAAA,KAAW,SAAA,EAAW;AAChD,UAAA,IAAA,CAAK,MAAA,GAAS,SAAA;AACd,UAAA,IAAA,CAAK,SAAA,uBAAgB,IAAA,EAAK;AAC1B,UAAA,MAAA,CAAO,IAAA;AAAA,YACL,EAAE,MAAA,EAAQ,IAAA,CAAK,EAAA,EAAI,aAAa,eAAA,EAAgB;AAAA,YAChD;AAAA,WACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF","file":"chunk-DAHGLHNR.js","sourcesContent":["/**\n * Role-based model selection per PRD section 7.2\n * Resolution pipeline: user override → role config → fallback chain → system default\n */\n\nimport type {\n ModelRole,\n IModelResolution,\n ModelResolutionSource,\n IRoleConfig,\n IGlobalConfig,\n ProviderName,\n IModelInfo,\n} from \"../types/index.js\";\nimport { SUPPORTED_MODELS, DEFAULT_MODEL_ID, ModelNotFoundError } from \"../types/index.js\";\nimport { logger } from \"../utils/index.js\";\nimport { getEventBus } from \"./event-bus.js\";\n\nexport interface IModelRouterConfig {\n readonly defaultModel: string;\n readonly roles: Partial<Record<ModelRole, IRoleConfig>>;\n readonly enabledProviders: readonly ProviderName[];\n}\n\nexport class ModelRouter {\n private readonly config: IModelRouterConfig;\n private userOverride: string | undefined;\n\n constructor(config: IModelRouterConfig) {\n this.config = config;\n }\n\n /**\n * Set a temporary user override that takes highest priority.\n */\n setUserOverride(modelId: string | undefined): void {\n if (modelId !== undefined) {\n this.validateModel(modelId);\n }\n this.userOverride = modelId;\n }\n\n /**\n * Resolve the best model for a given role through the priority pipeline.\n */\n resolve(role?: ModelRole): IModelResolution {\n // 1. User override (explicit flag: --model claude-opus-4-6)\n if (this.userOverride) {\n const info = this.getModelInfo(this.userOverride);\n return {\n modelId: this.userOverride,\n provider: info.provider,\n source: \"user_override\",\n role,\n };\n }\n\n // 2. Role config\n if (role) {\n const roleConfig = this.config.roles[role];\n if (roleConfig) {\n // Try primary model\n if (this.isModelAvailable(roleConfig.primary)) {\n const info = this.getModelInfo(roleConfig.primary);\n return {\n modelId: roleConfig.primary,\n provider: info.provider,\n source: \"role_config\",\n role,\n };\n }\n\n // 3. Fallback chain\n for (const fallbackModel of roleConfig.fallback) {\n if (this.isModelAvailable(fallbackModel)) {\n const info = this.getModelInfo(fallbackModel);\n logger.info(\n { role, primary: roleConfig.primary, fallback: fallbackModel },\n \"Using fallback model for role\",\n );\n return {\n modelId: fallbackModel,\n provider: info.provider,\n source: \"fallback_chain\",\n role,\n };\n }\n }\n }\n }\n\n // 4. System default\n const defaultModel = this.config.defaultModel;\n if (this.isModelAvailable(defaultModel)) {\n const info = this.getModelInfo(defaultModel);\n return {\n modelId: defaultModel,\n provider: info.provider,\n source: \"system_default\",\n role,\n };\n }\n\n // Last resort: find any available model\n const anyAvailable = this.getAvailableModels()[0];\n if (anyAvailable) {\n return {\n modelId: anyAvailable.id,\n provider: anyAvailable.provider,\n source: \"system_default\",\n role,\n };\n }\n\n throw new ModelNotFoundError(defaultModel);\n }\n\n /**\n * Check if a model is available (provider is enabled and model is known).\n */\n isModelAvailable(modelId: string): boolean {\n const info = SUPPORTED_MODELS[modelId];\n if (!info) {\n return false;\n }\n return this.config.enabledProviders.includes(info.provider);\n }\n\n /**\n * Get model info by ID. Throws if not found.\n */\n getModelInfo(modelId: string): IModelInfo {\n const info = SUPPORTED_MODELS[modelId];\n if (!info) {\n throw new ModelNotFoundError(modelId);\n }\n return info;\n }\n\n /**\n * Get all available models (from enabled providers).\n */\n getAvailableModels(): readonly IModelInfo[] {\n return Object.values(SUPPORTED_MODELS).filter((model) =>\n this.config.enabledProviders.includes(model.provider),\n );\n }\n\n /**\n * List models recommended for a specific role.\n */\n getModelsForRole(role: ModelRole): readonly IModelInfo[] {\n return this.getAvailableModels().filter((model) =>\n model.supportedRoles.includes(role),\n );\n }\n\n /**\n * Validate that a model ID exists. Throws ModelNotFoundError if not.\n */\n private validateModel(modelId: string): void {\n if (!SUPPORTED_MODELS[modelId]) {\n throw new ModelNotFoundError(modelId);\n }\n }\n}\n\n/**\n * Create a ModelRouter from the global config.\n */\nexport function createModelRouter(config: IGlobalConfig): ModelRouter {\n const enabledProviders = Object.entries(config.providers)\n .filter(([, providerConfig]) => providerConfig?.enabled)\n .map(([name]) => name as ProviderName);\n\n return new ModelRouter({\n defaultModel: config.defaultModel,\n roles: config.roles,\n enabledProviders,\n });\n}\n","/**\n * Context window management per PRD section 7.4\n * - Token budgeting: 85% conversation, 15% buffer\n * - Smart truncation: prioritize recent + system prompt\n * - Compression: summarize old messages when approaching limits\n * - File context tracking with LRU eviction\n */\n\nimport type { IChatMessage, IModelInfo } from \"../types/index.js\";\nimport { estimateTokenCount } from \"../utils/index.js\";\nimport { logger } from \"../utils/index.js\";\n\nconst CONTEXT_BUDGET_RATIO = 0.85;\nconst SYSTEM_PROMPT_RESERVE = 4_000;\n\ninterface IFileContextEntry {\n readonly filePath: string;\n readonly tokenCount: number;\n lastAccessedAt: number;\n}\n\nexport class ContextManager {\n private readonly maxTokens: number;\n private readonly budgetTokens: number;\n private readonly fileContext = new Map<string, IFileContextEntry>();\n private currentTokenCount = 0;\n\n constructor(modelInfo: IModelInfo) {\n this.maxTokens = modelInfo.contextWindow;\n this.budgetTokens = Math.floor(this.maxTokens * CONTEXT_BUDGET_RATIO);\n }\n\n /**\n * Get the available token budget for new content.\n */\n getAvailableBudget(): number {\n return Math.max(0, this.budgetTokens - this.currentTokenCount - SYSTEM_PROMPT_RESERVE);\n }\n\n /**\n * Get total context usage.\n */\n getUsage(): { used: number; budget: number; max: number; percentage: number } {\n return {\n used: this.currentTokenCount,\n budget: this.budgetTokens,\n max: this.maxTokens,\n percentage: Math.round((this.currentTokenCount / this.budgetTokens) * 100),\n };\n }\n\n /**\n * Trim messages to fit within the context window.\n * Preserves system prompt and most recent messages.\n */\n trimMessages(messages: readonly IChatMessage[], systemPrompt?: string): IChatMessage[] {\n const systemTokens = systemPrompt ? estimateTokenCount(systemPrompt) : 0;\n const availableTokens = this.budgetTokens - systemTokens - SYSTEM_PROMPT_RESERVE;\n\n if (availableTokens <= 0) {\n logger.warn(\"System prompt alone exceeds context budget\");\n return [];\n }\n\n // Work backwards from most recent, accumulating tokens\n const result: IChatMessage[] = [];\n let usedTokens = 0;\n\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i];\n if (!msg) {\n continue;\n }\n const msgTokens = estimateTokenCount(msg.content);\n\n if (usedTokens + msgTokens > availableTokens) {\n break;\n }\n\n result.unshift(msg);\n usedTokens += msgTokens;\n }\n\n this.currentTokenCount = usedTokens + systemTokens;\n\n if (result.length < messages.length) {\n logger.info(\n {\n original: messages.length,\n trimmed: result.length,\n droppedMessages: messages.length - result.length,\n },\n \"Trimmed conversation to fit context window\",\n );\n }\n\n return result;\n }\n\n /**\n * Track a file being added to context.\n */\n addFileContext(filePath: string, content: string): void {\n const tokenCount = estimateTokenCount(content);\n this.fileContext.set(filePath, {\n filePath,\n tokenCount,\n lastAccessedAt: Date.now(),\n });\n this.currentTokenCount += tokenCount;\n }\n\n /**\n * Touch a file (update last accessed time).\n */\n touchFile(filePath: string): void {\n const entry = this.fileContext.get(filePath);\n if (entry) {\n entry.lastAccessedAt = Date.now();\n }\n }\n\n /**\n * Remove a file from context.\n */\n removeFileContext(filePath: string): void {\n const entry = this.fileContext.get(filePath);\n if (entry) {\n this.currentTokenCount -= entry.tokenCount;\n this.fileContext.delete(filePath);\n }\n }\n\n /**\n * Evict least-recently-used files to free space.\n */\n evictLRU(tokensNeeded: number): string[] {\n const evicted: string[] = [];\n const sorted = [...this.fileContext.entries()].sort(\n ([, a], [, b]) => a.lastAccessedAt - b.lastAccessedAt,\n );\n\n let freedTokens = 0;\n for (const [filePath, entry] of sorted) {\n if (freedTokens >= tokensNeeded) {\n break;\n }\n this.removeFileContext(filePath);\n freedTokens += entry.tokenCount;\n evicted.push(filePath);\n }\n\n if (evicted.length > 0) {\n logger.info(\n { evicted, freedTokens },\n \"Evicted files from context to free space\",\n );\n }\n\n return evicted;\n }\n\n /**\n * Get all tracked files.\n */\n getTrackedFiles(): readonly IFileContextEntry[] {\n return [...this.fileContext.values()];\n }\n\n /**\n * Reset context tracking (for model switch).\n */\n reset(): void {\n this.fileContext.clear();\n this.currentTokenCount = 0;\n }\n}\n","/**\n * Real-time cost tracking per PRD section 7.5\n * - Per-request cost calculation\n * - Session total\n * - Breakdown by provider, model, and role\n * - Configurable budget alerts\n */\n\nimport type { ProviderName, ModelRole, ITokenUsage, ICostConfig } from \"../types/index.js\";\nimport { createTokenUsage, formatCost } from \"../utils/index.js\";\nimport { logger } from \"../utils/index.js\";\nimport { getEventBus } from \"./event-bus.js\";\n\ninterface ICostEntry {\n readonly provider: ProviderName;\n readonly model: string;\n readonly role?: ModelRole | undefined;\n readonly usage: ITokenUsage;\n readonly timestamp: Date;\n}\n\ninterface ICostBreakdown {\n readonly byProvider: Record<string, number>;\n readonly byModel: Record<string, number>;\n readonly byRole: Record<string, number>;\n}\n\nexport class CostTracker {\n private readonly entries: ICostEntry[] = [];\n private readonly budgetConfig: ICostConfig;\n private warningEmitted = false;\n\n constructor(budgetConfig: ICostConfig) {\n this.budgetConfig = budgetConfig;\n }\n\n /**\n * Record a cost entry from a model response.\n */\n record(\n provider: ProviderName,\n model: string,\n inputTokens: number,\n outputTokens: number,\n role?: ModelRole,\n ): ITokenUsage {\n const usage = createTokenUsage(model, inputTokens, outputTokens);\n\n const entry: ICostEntry = {\n provider,\n model,\n role,\n usage,\n timestamp: new Date(),\n };\n\n this.entries.push(entry);\n\n const total = this.getSessionTotal();\n const eventBus = getEventBus();\n\n eventBus.emit(\"cost:updated\", {\n total,\n provider,\n delta: usage.costUsd,\n });\n\n // Budget warning\n if (total >= this.budgetConfig.budgetWarning && !this.warningEmitted) {\n this.warningEmitted = true;\n eventBus.emit(\"cost:warning\", {\n current: total,\n limit: this.budgetConfig.budgetWarning,\n });\n logger.warn(\n { current: formatCost(total), warning: formatCost(this.budgetConfig.budgetWarning) },\n \"Budget warning threshold reached\",\n );\n }\n\n // Budget hard stop\n if (total >= this.budgetConfig.budgetHardStop) {\n eventBus.emit(\"cost:exceeded\", {\n current: total,\n limit: this.budgetConfig.budgetHardStop,\n });\n logger.error(\n { current: formatCost(total), limit: formatCost(this.budgetConfig.budgetHardStop) },\n \"Budget hard stop reached\",\n );\n }\n\n return usage;\n }\n\n /**\n * Get total session cost.\n */\n getSessionTotal(): number {\n return this.entries.reduce((sum, entry) => sum + entry.usage.costUsd, 0);\n }\n\n /**\n * Get total token counts.\n */\n getSessionTokens(): { input: number; output: number; total: number } {\n const input = this.entries.reduce((sum, e) => sum + e.usage.inputTokens, 0);\n const output = this.entries.reduce((sum, e) => sum + e.usage.outputTokens, 0);\n return { input, output, total: input + output };\n }\n\n /**\n * Get cost breakdown by provider, model, and role.\n */\n getBreakdown(): ICostBreakdown {\n const byProvider: Record<string, number> = {};\n const byModel: Record<string, number> = {};\n const byRole: Record<string, number> = {};\n\n for (const entry of this.entries) {\n byProvider[entry.provider] = (byProvider[entry.provider] ?? 0) + entry.usage.costUsd;\n byModel[entry.model] = (byModel[entry.model] ?? 0) + entry.usage.costUsd;\n if (entry.role) {\n byRole[entry.role] = (byRole[entry.role] ?? 0) + entry.usage.costUsd;\n }\n }\n\n return { byProvider, byModel, byRole };\n }\n\n /**\n * Check if budget hard stop has been exceeded.\n */\n isBudgetExceeded(): boolean {\n return this.getSessionTotal() >= this.budgetConfig.budgetHardStop;\n }\n\n /**\n * Get formatted session summary.\n */\n getSummary(): string {\n const total = this.getSessionTotal();\n const tokens = this.getSessionTokens();\n return `${formatCost(total)} (${tokens.total.toLocaleString()} tokens)`;\n }\n\n /**\n * Get all cost entries (for export).\n */\n getEntries(): readonly ICostEntry[] {\n return this.entries;\n }\n\n /**\n * Reset cost tracking for a new session.\n */\n reset(): void {\n this.entries.length = 0;\n this.warningEmitted = false;\n }\n}\n","/**\n * Tool permission management per PRD section 14.4\n * Permission modes: strict, standard, permissive\n */\n\nimport type { PermissionMode, ToolCategory } from \"../types/index.js\";\nimport { logger } from \"../utils/index.js\";\nimport { isCommandBlocked } from \"../utils/index.js\";\n\n// Commands that ALWAYS require confirmation regardless of mode\nconst DANGEROUS_COMMANDS = [\n \"rm -rf\",\n \"git push --force\",\n \"git reset --hard\",\n \"git checkout .\",\n \"git clean -f\",\n \"git branch -D\",\n \"drop table\",\n \"drop database\",\n \"truncate\",\n \"format c:\",\n \"del /f /s /q\",\n] as const;\n\nexport interface IPermissionRequest {\n readonly toolName: string;\n readonly category: ToolCategory;\n readonly operation: string;\n readonly resource?: string;\n readonly command?: string;\n}\n\nexport interface IPermissionResult {\n readonly allowed: boolean;\n readonly reason?: string;\n readonly requiresUserApproval: boolean;\n}\n\nexport class PermissionManager {\n private mode: PermissionMode;\n private readonly allowedPaths: readonly string[];\n private readonly blockedCommands: readonly string[];\n private readonly approvedOperations = new Set<string>();\n\n constructor(\n mode: PermissionMode,\n allowedPaths: readonly string[],\n blockedCommands: readonly string[],\n ) {\n this.mode = mode;\n this.allowedPaths = allowedPaths;\n this.blockedCommands = blockedCommands;\n }\n\n /**\n * Check if an operation is permitted.\n */\n check(request: IPermissionRequest): IPermissionResult {\n // Always-blocked operations\n if (request.command && this.isDangerousCommand(request.command)) {\n return {\n allowed: false,\n reason: `Dangerous command detected: \"${request.command}\"`,\n requiresUserApproval: true,\n };\n }\n\n // Check against blocked commands list\n if (request.command && isCommandBlocked(request.command, this.blockedCommands)) {\n return {\n allowed: false,\n reason: `Command is on the blocked list`,\n requiresUserApproval: true,\n };\n }\n\n // Previously approved operations\n const opKey = this.getOperationKey(request);\n if (this.approvedOperations.has(opKey)) {\n return { allowed: true, requiresUserApproval: false };\n }\n\n // Mode-based permissions\n switch (this.mode) {\n case \"permissive\":\n return { allowed: true, requiresUserApproval: false };\n\n case \"standard\":\n return this.checkStandardMode(request);\n\n case \"strict\":\n return this.checkStrictMode(request);\n }\n }\n\n /**\n * Record that the user has approved an operation.\n */\n approve(request: IPermissionRequest): void {\n const opKey = this.getOperationKey(request);\n this.approvedOperations.add(opKey);\n logger.info({ operation: opKey }, \"Operation approved by user\");\n }\n\n /**\n * Update permission mode.\n */\n setMode(mode: PermissionMode): void {\n this.mode = mode;\n this.approvedOperations.clear();\n logger.info({ mode }, \"Permission mode changed\");\n }\n\n /**\n * Get current mode.\n */\n getMode(): PermissionMode {\n return this.mode;\n }\n\n private checkStandardMode(request: IPermissionRequest): IPermissionResult {\n // Read operations auto-approved in standard mode\n if (this.isReadOperation(request)) {\n return { allowed: true, requiresUserApproval: false };\n }\n\n // Write and shell operations require approval\n return {\n allowed: false,\n reason: `${request.operation} requires approval in standard mode`,\n requiresUserApproval: true,\n };\n }\n\n private checkStrictMode(request: IPermissionRequest): IPermissionResult {\n // Everything requires approval in strict mode\n return {\n allowed: false,\n reason: `${request.operation} requires approval in strict mode`,\n requiresUserApproval: true,\n };\n }\n\n private isReadOperation(request: IPermissionRequest): boolean {\n const readTools = [\"read\", \"glob\", \"grep\", \"web-search\", \"web-fetch\"];\n return readTools.includes(request.toolName);\n }\n\n private isDangerousCommand(command: string): boolean {\n const lower = command.toLowerCase().trim();\n return DANGEROUS_COMMANDS.some((dangerous) => lower.includes(dangerous));\n }\n\n private getOperationKey(request: IPermissionRequest): string {\n return `${request.toolName}:${request.operation}:${request.resource ?? \"\"}`;\n }\n}\n","/**\n * Agent team task coordination per PRD section 8\n * Manages task creation, assignment, dependency resolution, and completion tracking.\n */\n\nimport type { ITask, TaskStatus, ModelRole } from \"../types/index.js\";\nimport { logger } from \"../utils/index.js\";\nimport { getEventBus } from \"./event-bus.js\";\n\nlet nextTaskId = 1;\n\nfunction generateTaskId(): string {\n return String(nextTaskId++);\n}\n\nexport class TaskOrchestrator {\n private readonly tasks = new Map<string, ITask>();\n\n /**\n * Create a new task.\n */\n createTask(\n subject: string,\n description: string,\n options?: {\n owner?: string;\n model?: string;\n role?: ModelRole;\n blockedBy?: string[];\n },\n ): ITask {\n const id = generateTaskId();\n const now = new Date();\n\n const task: ITask = {\n id,\n subject,\n description,\n status: \"pending\",\n owner: options?.owner,\n model: options?.model,\n role: options?.role,\n blocks: [],\n blockedBy: options?.blockedBy ? [...options.blockedBy] : [],\n createdAt: now,\n updatedAt: now,\n };\n\n this.tasks.set(id, task);\n\n // Set up reverse blocking relationships\n if (options?.blockedBy) {\n for (const blockerId of options.blockedBy) {\n const blocker = this.tasks.get(blockerId);\n if (blocker && !blocker.blocks.includes(id)) {\n blocker.blocks.push(id);\n }\n }\n }\n\n getEventBus().emit(\"task:created\", { taskId: id, subject });\n logger.info({ taskId: id, subject }, \"Task created\");\n\n return task;\n }\n\n /**\n * Update task status.\n */\n updateStatus(taskId: string, status: TaskStatus): void {\n const task = this.getTask(taskId);\n task.status = status;\n task.updatedAt = new Date();\n\n getEventBus().emit(\"task:updated\", { taskId, status });\n\n if (status === \"completed\") {\n getEventBus().emit(\"task:completed\", { taskId });\n this.resolveBlockedTasks(taskId);\n }\n\n logger.info({ taskId, status }, \"Task status updated\");\n }\n\n /**\n * Assign a task to an agent.\n */\n assignTask(taskId: string, owner: string, model?: string): void {\n const task = this.getTask(taskId);\n task.owner = owner;\n if (model) {\n (task as { model?: string }).model = model;\n }\n task.updatedAt = new Date();\n logger.info({ taskId, owner, model }, \"Task assigned\");\n }\n\n /**\n * Get a task by ID. Throws if not found.\n */\n getTask(taskId: string): ITask {\n const task = this.tasks.get(taskId);\n if (!task) {\n throw new Error(`Task not found: ${taskId}`);\n }\n return task;\n }\n\n /**\n * Get all tasks.\n */\n getAllTasks(): readonly ITask[] {\n return [...this.tasks.values()];\n }\n\n /**\n * Get tasks by status.\n */\n getTasksByStatus(status: TaskStatus): readonly ITask[] {\n return [...this.tasks.values()].filter((t) => t.status === status);\n }\n\n /**\n * Get tasks assigned to an agent.\n */\n getTasksByOwner(owner: string): readonly ITask[] {\n return [...this.tasks.values()].filter((t) => t.owner === owner);\n }\n\n /**\n * Get tasks that are ready to be worked on (pending, not blocked).\n */\n getAvailableTasks(): readonly ITask[] {\n return [...this.tasks.values()].filter(\n (t) =>\n t.status === \"pending\" &&\n !t.owner &&\n t.blockedBy.every((blockerId) => {\n const blocker = this.tasks.get(blockerId);\n return blocker?.status === \"completed\";\n }),\n );\n }\n\n /**\n * Check if all tasks are completed.\n */\n isAllComplete(): boolean {\n return [...this.tasks.values()].every((t) => t.status === \"completed\");\n }\n\n /**\n * Get progress summary.\n */\n getProgress(): { total: number; completed: number; inProgress: number; pending: number; blocked: number } {\n const tasks = [...this.tasks.values()];\n return {\n total: tasks.length,\n completed: tasks.filter((t) => t.status === \"completed\").length,\n inProgress: tasks.filter((t) => t.status === \"in_progress\").length,\n pending: tasks.filter((t) => t.status === \"pending\").length,\n blocked: tasks.filter((t) => t.status === \"blocked\").length,\n };\n }\n\n /**\n * Delete a task.\n */\n deleteTask(taskId: string): void {\n const task = this.tasks.get(taskId);\n if (task) {\n // Remove from blockedBy references\n for (const [, otherTask] of this.tasks) {\n otherTask.blockedBy = otherTask.blockedBy.filter((id) => id !== taskId);\n otherTask.blocks = otherTask.blocks.filter((id) => id !== taskId);\n }\n this.tasks.delete(taskId);\n }\n }\n\n /**\n * When a task completes, check if any blocked tasks can now proceed.\n */\n private resolveBlockedTasks(completedTaskId: string): void {\n for (const [, task] of this.tasks) {\n if (task.status === \"blocked\" || task.status === \"pending\") {\n const allDepsComplete = task.blockedBy.every((depId) => {\n const dep = this.tasks.get(depId);\n return dep?.status === \"completed\";\n });\n\n if (allDepsComplete && task.status === \"blocked\") {\n task.status = \"pending\";\n task.updatedAt = new Date();\n logger.info(\n { taskId: task.id, unblockedBy: completedTaskId },\n \"Task unblocked\",\n );\n }\n }\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { SUPPORTED_MODELS } from './chunk-HCIHOHLX.js';
|
|
2
|
+
import { logger } from './chunk-JAXXTYID.js';
|
|
3
|
+
|
|
4
|
+
// src/providers/ollama-adapter.ts
|
|
5
|
+
var PROVIDER_NAME = "ollama";
|
|
6
|
+
var DEFAULT_BASE_URL = "http://localhost:11434";
|
|
7
|
+
var CHARS_PER_TOKEN_ESTIMATE = 4;
|
|
8
|
+
function convertMessages(messages) {
|
|
9
|
+
return messages.map((msg) => ({ role: msg.role, content: msg.content }));
|
|
10
|
+
}
|
|
11
|
+
function convertTools(tools) {
|
|
12
|
+
if (tools === void 0 || tools.length === 0) {
|
|
13
|
+
return void 0;
|
|
14
|
+
}
|
|
15
|
+
return tools.map((tool) => {
|
|
16
|
+
const properties = {};
|
|
17
|
+
const required = [];
|
|
18
|
+
for (const param of tool.parameters) {
|
|
19
|
+
properties[param.name] = { type: param.type, description: param.description };
|
|
20
|
+
if (param.required) {
|
|
21
|
+
required.push(param.name);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
type: "function",
|
|
26
|
+
function: {
|
|
27
|
+
name: tool.name,
|
|
28
|
+
description: tool.description,
|
|
29
|
+
parameters: { type: "object", properties, required }
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function makeOllamaModelInfo(modelName) {
|
|
35
|
+
return {
|
|
36
|
+
id: modelName,
|
|
37
|
+
name: modelName,
|
|
38
|
+
provider: PROVIDER_NAME,
|
|
39
|
+
contextWindow: 128e3,
|
|
40
|
+
maxOutputTokens: 8192,
|
|
41
|
+
inputPricePerMToken: 0,
|
|
42
|
+
outputPricePerMToken: 0,
|
|
43
|
+
supportsStreaming: true,
|
|
44
|
+
supportsToolCalling: true,
|
|
45
|
+
supportedRoles: ["coding", "bugfix", "testing", "documentation"]
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
var OllamaAdapter = class {
|
|
49
|
+
name = PROVIDER_NAME;
|
|
50
|
+
baseUrl;
|
|
51
|
+
cachedModels;
|
|
52
|
+
constructor(options) {
|
|
53
|
+
this.baseUrl = options?.baseUrl ?? DEFAULT_BASE_URL;
|
|
54
|
+
}
|
|
55
|
+
get supportedModels() {
|
|
56
|
+
return this.cachedModels ?? [];
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Refresh available models from Ollama API.
|
|
60
|
+
* Call once during initialization.
|
|
61
|
+
*/
|
|
62
|
+
async refreshModels() {
|
|
63
|
+
try {
|
|
64
|
+
const response = await fetch(`${this.baseUrl}/api/tags`);
|
|
65
|
+
if (!response.ok) {
|
|
66
|
+
logger.warn({ status: response.status }, "Failed to list Ollama models");
|
|
67
|
+
this.cachedModels = [];
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
const data = await response.json();
|
|
71
|
+
this.cachedModels = data.models.map((m) => m.name);
|
|
72
|
+
logger.debug({ models: this.cachedModels }, "Ollama models discovered");
|
|
73
|
+
return this.cachedModels;
|
|
74
|
+
} catch (error) {
|
|
75
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
76
|
+
logger.warn({ error: errMsg }, "Ollama not reachable");
|
|
77
|
+
this.cachedModels = [];
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async chat(request) {
|
|
82
|
+
this.getModelInfo(request.model);
|
|
83
|
+
const messages = convertMessages(request.messages);
|
|
84
|
+
const tools = convertTools(request.tools);
|
|
85
|
+
if (request.system !== void 0) {
|
|
86
|
+
messages.unshift({ role: "system", content: request.system });
|
|
87
|
+
}
|
|
88
|
+
const body = {
|
|
89
|
+
model: request.model,
|
|
90
|
+
messages,
|
|
91
|
+
stream: false
|
|
92
|
+
};
|
|
93
|
+
if (request.maxTokens !== void 0) {
|
|
94
|
+
body["max_tokens"] = request.maxTokens;
|
|
95
|
+
}
|
|
96
|
+
if (request.temperature !== void 0) {
|
|
97
|
+
body["temperature"] = request.temperature;
|
|
98
|
+
}
|
|
99
|
+
if (tools !== void 0) {
|
|
100
|
+
body["tools"] = tools;
|
|
101
|
+
}
|
|
102
|
+
const response = await fetch(`${this.baseUrl}/v1/chat/completions`, {
|
|
103
|
+
method: "POST",
|
|
104
|
+
headers: { "Content-Type": "application/json" },
|
|
105
|
+
body: JSON.stringify(body)
|
|
106
|
+
});
|
|
107
|
+
if (!response.ok) {
|
|
108
|
+
const text = await response.text();
|
|
109
|
+
throw new Error(`Ollama API error (${response.status}): ${text}`);
|
|
110
|
+
}
|
|
111
|
+
const data = await response.json();
|
|
112
|
+
const choice = data.choices[0];
|
|
113
|
+
if (choice === void 0) {
|
|
114
|
+
throw new Error("Ollama API returned empty choices");
|
|
115
|
+
}
|
|
116
|
+
const toolCalls = extractToolCalls(choice);
|
|
117
|
+
const inputTokens = data.usage?.prompt_tokens ?? 0;
|
|
118
|
+
const outputTokens = data.usage?.completion_tokens ?? 0;
|
|
119
|
+
const usage = {
|
|
120
|
+
inputTokens,
|
|
121
|
+
outputTokens,
|
|
122
|
+
totalTokens: inputTokens + outputTokens,
|
|
123
|
+
costUsd: 0
|
|
124
|
+
};
|
|
125
|
+
const responseMessage = {
|
|
126
|
+
id: data.id,
|
|
127
|
+
role: "assistant",
|
|
128
|
+
content: choice.message.content ?? "",
|
|
129
|
+
model: request.model,
|
|
130
|
+
provider: PROVIDER_NAME,
|
|
131
|
+
toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
|
|
132
|
+
tokenUsage: usage,
|
|
133
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
134
|
+
};
|
|
135
|
+
return {
|
|
136
|
+
id: data.id,
|
|
137
|
+
model: request.model,
|
|
138
|
+
provider: PROVIDER_NAME,
|
|
139
|
+
message: responseMessage,
|
|
140
|
+
usage,
|
|
141
|
+
finishReason: mapFinishReason(choice.finish_reason)
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
async *stream(request) {
|
|
145
|
+
const modelInfo = this.getModelInfo(request.model);
|
|
146
|
+
const messages = convertMessages(request.messages);
|
|
147
|
+
const tools = convertTools(request.tools);
|
|
148
|
+
if (request.system !== void 0) {
|
|
149
|
+
messages.unshift({ role: "system", content: request.system });
|
|
150
|
+
}
|
|
151
|
+
const body = {
|
|
152
|
+
model: request.model,
|
|
153
|
+
messages,
|
|
154
|
+
stream: true
|
|
155
|
+
};
|
|
156
|
+
if (request.maxTokens !== void 0) {
|
|
157
|
+
body["max_tokens"] = request.maxTokens;
|
|
158
|
+
}
|
|
159
|
+
if (request.temperature !== void 0) {
|
|
160
|
+
body["temperature"] = request.temperature;
|
|
161
|
+
}
|
|
162
|
+
if (tools !== void 0) {
|
|
163
|
+
body["tools"] = tools;
|
|
164
|
+
}
|
|
165
|
+
const response = await fetch(`${this.baseUrl}/v1/chat/completions`, {
|
|
166
|
+
method: "POST",
|
|
167
|
+
headers: { "Content-Type": "application/json" },
|
|
168
|
+
body: JSON.stringify(body)
|
|
169
|
+
});
|
|
170
|
+
if (!response.ok) {
|
|
171
|
+
const text = await response.text();
|
|
172
|
+
yield { type: "error", error: `Ollama API error (${response.status}): ${text}` };
|
|
173
|
+
yield { type: "done" };
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (response.body === null) {
|
|
177
|
+
yield { type: "error", error: "Ollama returned empty stream body" };
|
|
178
|
+
yield { type: "done" };
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
try {
|
|
182
|
+
yield* this.parseSSEStream(response.body, modelInfo);
|
|
183
|
+
yield { type: "done" };
|
|
184
|
+
} catch (error) {
|
|
185
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
186
|
+
logger.error({ error: errMsg, model: request.model }, "Ollama stream error");
|
|
187
|
+
yield { type: "error", error: errMsg };
|
|
188
|
+
yield { type: "done" };
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async countTokens(text, _model) {
|
|
192
|
+
return Math.ceil(text.length / CHARS_PER_TOKEN_ESTIMATE);
|
|
193
|
+
}
|
|
194
|
+
getModelInfo(model) {
|
|
195
|
+
const staticInfo = SUPPORTED_MODELS[model];
|
|
196
|
+
if (staticInfo !== void 0 && staticInfo.provider === PROVIDER_NAME) {
|
|
197
|
+
return staticInfo;
|
|
198
|
+
}
|
|
199
|
+
if (this.cachedModels !== void 0 && this.cachedModels.includes(model)) {
|
|
200
|
+
return makeOllamaModelInfo(model);
|
|
201
|
+
}
|
|
202
|
+
return makeOllamaModelInfo(model);
|
|
203
|
+
}
|
|
204
|
+
async listAvailableModels() {
|
|
205
|
+
const models = await this.refreshModels();
|
|
206
|
+
return models;
|
|
207
|
+
}
|
|
208
|
+
async *parseSSEStream(body, _modelInfo) {
|
|
209
|
+
const reader = body.getReader();
|
|
210
|
+
const decoder = new TextDecoder();
|
|
211
|
+
let buffer = "";
|
|
212
|
+
try {
|
|
213
|
+
for (; ; ) {
|
|
214
|
+
const { done, value } = await reader.read();
|
|
215
|
+
if (done) {
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
buffer += decoder.decode(value, { stream: true });
|
|
219
|
+
const lines = buffer.split("\n");
|
|
220
|
+
buffer = lines.pop() ?? "";
|
|
221
|
+
for (const line of lines) {
|
|
222
|
+
const trimmed = line.trim();
|
|
223
|
+
if (trimmed === "" || trimmed === "data: [DONE]") {
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (!trimmed.startsWith("data: ")) {
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
const jsonStr = trimmed.slice(6);
|
|
230
|
+
let parsed;
|
|
231
|
+
try {
|
|
232
|
+
parsed = JSON.parse(jsonStr);
|
|
233
|
+
} catch {
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
const delta = parsed.choices?.[0]?.delta;
|
|
237
|
+
if (delta?.content !== void 0 && delta.content !== "") {
|
|
238
|
+
yield { type: "text", content: delta.content };
|
|
239
|
+
}
|
|
240
|
+
if (delta?.tool_calls !== void 0) {
|
|
241
|
+
for (const tc of delta.tool_calls) {
|
|
242
|
+
if (tc.id !== void 0 && tc.function?.name !== void 0) {
|
|
243
|
+
let args = {};
|
|
244
|
+
if (tc.function.arguments !== void 0) {
|
|
245
|
+
try {
|
|
246
|
+
args = JSON.parse(tc.function.arguments);
|
|
247
|
+
} catch {
|
|
248
|
+
args = {};
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
yield {
|
|
252
|
+
type: "tool_call",
|
|
253
|
+
toolCall: { id: tc.id, name: tc.function.name, arguments: args }
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (parsed.usage !== void 0) {
|
|
259
|
+
yield {
|
|
260
|
+
type: "usage",
|
|
261
|
+
usage: {
|
|
262
|
+
inputTokens: parsed.usage.prompt_tokens,
|
|
263
|
+
outputTokens: parsed.usage.completion_tokens,
|
|
264
|
+
totalTokens: parsed.usage.total_tokens,
|
|
265
|
+
costUsd: 0
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
} finally {
|
|
272
|
+
reader.releaseLock();
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
function extractToolCalls(choice) {
|
|
277
|
+
if (choice.message.tool_calls === void 0 || choice.message.tool_calls.length === 0) {
|
|
278
|
+
return [];
|
|
279
|
+
}
|
|
280
|
+
return choice.message.tool_calls.map((tc) => {
|
|
281
|
+
let args = {};
|
|
282
|
+
try {
|
|
283
|
+
args = JSON.parse(tc.function.arguments);
|
|
284
|
+
} catch {
|
|
285
|
+
args = {};
|
|
286
|
+
}
|
|
287
|
+
return { id: tc.id, name: tc.function.name, arguments: args };
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
function mapFinishReason(reason) {
|
|
291
|
+
switch (reason) {
|
|
292
|
+
case "stop":
|
|
293
|
+
return "stop";
|
|
294
|
+
case "tool_calls":
|
|
295
|
+
return "tool_calls";
|
|
296
|
+
case "length":
|
|
297
|
+
return "max_tokens";
|
|
298
|
+
default:
|
|
299
|
+
return "stop";
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export { OllamaAdapter };
|
|
304
|
+
//# sourceMappingURL=chunk-H66O5Z2V.js.map
|
|
305
|
+
//# sourceMappingURL=chunk-H66O5Z2V.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/providers/ollama-adapter.ts"],"names":[],"mappings":"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","file":"chunk-H66O5Z2V.js","sourcesContent":["/**\n * Ollama adapter — custom HTTP for local models per PRD section 7.1\n * Uses OpenAI-compatible API format at localhost:11434.\n * Dynamic model listing from Ollama API.\n */\n\nimport { logger } from \"../utils/logger.js\";\nimport { ModelNotFoundError } from \"../types/errors.js\";\nimport { SUPPORTED_MODELS } from \"../types/model.js\";\nimport type { IModelInfo, ProviderName, ModelRole } from \"../types/model.js\";\nimport type {\n IChatRequest,\n IChatResponse,\n IChatMessage,\n IStreamChunk,\n IToolCall,\n IToolDefinition,\n ITokenUsage,\n} from \"../types/message.js\";\nimport type { IModelProvider, IProviderOptions } from \"./types.js\";\n\nconst PROVIDER_NAME: ProviderName = \"ollama\";\nconst DEFAULT_BASE_URL = \"http://localhost:11434\";\nconst CHARS_PER_TOKEN_ESTIMATE = 4;\n\ninterface OllamaListResponse { models: Array<{ name: string; size: number }> }\ninterface OpenAIMessage { role: string; content: string }\ninterface OpenAITool { type: \"function\"; function: { name: string; description: string; parameters: Record<string, unknown> } }\ninterface OllamaToolCallRef { id: string; type: string; function: { name: string; arguments: string } }\ninterface OllamaChoice {\n index: number;\n message: { role: string; content: string | null; tool_calls?: readonly OllamaToolCallRef[] };\n finish_reason: string;\n}\ninterface OllamaUsage { prompt_tokens: number; completion_tokens: number; total_tokens: number }\ninterface OllamaChatResponse { id: string; choices: OllamaChoice[]; usage?: OllamaUsage }\n\nfunction convertMessages(messages: readonly IChatMessage[]): OpenAIMessage[] {\n return messages.map((msg) => ({ role: msg.role, content: msg.content }));\n}\n\nfunction convertTools(tools: readonly IToolDefinition[] | undefined): OpenAITool[] | undefined {\n if (tools === undefined || tools.length === 0) {\n return undefined;\n }\n return tools.map((tool) => {\n const properties: Record<string, unknown> = {};\n const required: string[] = [];\n for (const param of tool.parameters) {\n properties[param.name] = { type: param.type, description: param.description };\n if (param.required) {\n required.push(param.name);\n }\n }\n return {\n type: \"function\" as const,\n function: {\n name: tool.name,\n description: tool.description,\n parameters: { type: \"object\", properties, required },\n },\n };\n });\n}\n\nfunction makeOllamaModelInfo(modelName: string): IModelInfo {\n return {\n id: modelName,\n name: modelName,\n provider: PROVIDER_NAME,\n contextWindow: 128_000,\n maxOutputTokens: 8_192,\n inputPricePerMToken: 0,\n outputPricePerMToken: 0,\n supportsStreaming: true,\n supportsToolCalling: true,\n supportedRoles: [\"coding\", \"bugfix\", \"testing\", \"documentation\"] as readonly ModelRole[],\n };\n}\n\nexport class OllamaAdapter implements IModelProvider {\n readonly name = PROVIDER_NAME;\n\n private readonly baseUrl: string;\n private cachedModels: string[] | undefined;\n\n constructor(options?: IProviderOptions) {\n this.baseUrl = options?.baseUrl ?? DEFAULT_BASE_URL;\n }\n\n get supportedModels(): readonly string[] {\n return this.cachedModels ?? [];\n }\n\n /**\n * Refresh available models from Ollama API.\n * Call once during initialization.\n */\n async refreshModels(): Promise<readonly string[]> {\n try {\n const response = await fetch(`${this.baseUrl}/api/tags`);\n if (!response.ok) {\n logger.warn({ status: response.status }, \"Failed to list Ollama models\");\n this.cachedModels = [];\n return [];\n }\n const data = (await response.json()) as OllamaListResponse;\n this.cachedModels = data.models.map((m) => m.name);\n logger.debug({ models: this.cachedModels }, \"Ollama models discovered\");\n return this.cachedModels;\n } catch (error: unknown) {\n const errMsg = error instanceof Error ? error.message : String(error);\n logger.warn({ error: errMsg }, \"Ollama not reachable\");\n this.cachedModels = [];\n return [];\n }\n }\n\n async chat(request: IChatRequest): Promise<IChatResponse> {\n const modelInfo = this.getModelInfo(request.model);\n const messages = convertMessages(request.messages);\n const tools = convertTools(request.tools);\n\n if (request.system !== undefined) {\n messages.unshift({ role: \"system\", content: request.system });\n }\n\n const body: Record<string, unknown> = {\n model: request.model,\n messages,\n stream: false,\n };\n if (request.maxTokens !== undefined) {\n body[\"max_tokens\"] = request.maxTokens;\n }\n if (request.temperature !== undefined) {\n body[\"temperature\"] = request.temperature;\n }\n if (tools !== undefined) {\n body[\"tools\"] = tools;\n }\n\n const response = await fetch(`${this.baseUrl}/v1/chat/completions`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`Ollama API error (${response.status}): ${text}`);\n }\n\n const data = (await response.json()) as OllamaChatResponse;\n const choice = data.choices[0];\n if (choice === undefined) {\n throw new Error(\"Ollama API returned empty choices\");\n }\n\n const toolCalls = extractToolCalls(choice);\n const inputTokens = data.usage?.prompt_tokens ?? 0;\n const outputTokens = data.usage?.completion_tokens ?? 0;\n\n const usage: ITokenUsage = {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n costUsd: 0,\n };\n\n const responseMessage: IChatMessage = {\n id: data.id,\n role: \"assistant\",\n content: choice.message.content ?? \"\",\n model: request.model,\n provider: PROVIDER_NAME,\n toolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n tokenUsage: usage,\n createdAt: new Date(),\n };\n\n return {\n id: data.id,\n model: request.model,\n provider: PROVIDER_NAME,\n message: responseMessage,\n usage,\n finishReason: mapFinishReason(choice.finish_reason),\n };\n }\n\n async *stream(request: IChatRequest): AsyncIterable<IStreamChunk> {\n const modelInfo = this.getModelInfo(request.model);\n const messages = convertMessages(request.messages);\n const tools = convertTools(request.tools);\n\n if (request.system !== undefined) {\n messages.unshift({ role: \"system\", content: request.system });\n }\n\n const body: Record<string, unknown> = {\n model: request.model,\n messages,\n stream: true,\n };\n if (request.maxTokens !== undefined) {\n body[\"max_tokens\"] = request.maxTokens;\n }\n if (request.temperature !== undefined) {\n body[\"temperature\"] = request.temperature;\n }\n if (tools !== undefined) {\n body[\"tools\"] = tools;\n }\n\n const response = await fetch(`${this.baseUrl}/v1/chat/completions`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const text = await response.text();\n yield { type: \"error\", error: `Ollama API error (${response.status}): ${text}` };\n yield { type: \"done\" };\n return;\n }\n\n if (response.body === null) {\n yield { type: \"error\", error: \"Ollama returned empty stream body\" };\n yield { type: \"done\" };\n return;\n }\n\n try {\n yield* this.parseSSEStream(response.body, modelInfo);\n yield { type: \"done\" };\n } catch (error: unknown) {\n const errMsg = error instanceof Error ? error.message : String(error);\n logger.error({ error: errMsg, model: request.model }, \"Ollama stream error\");\n yield { type: \"error\", error: errMsg };\n yield { type: \"done\" };\n }\n }\n\n async countTokens(text: string, _model: string): Promise<number> {\n return Math.ceil(text.length / CHARS_PER_TOKEN_ESTIMATE);\n }\n\n getModelInfo(model: string): IModelInfo {\n const staticInfo = SUPPORTED_MODELS[model];\n if (staticInfo !== undefined && staticInfo.provider === PROVIDER_NAME) {\n return staticInfo;\n }\n if (this.cachedModels !== undefined && this.cachedModels.includes(model)) {\n return makeOllamaModelInfo(model);\n }\n return makeOllamaModelInfo(model);\n }\n\n async listAvailableModels(): Promise<readonly string[]> {\n const models = await this.refreshModels();\n return models;\n }\n\n private async *parseSSEStream(\n body: ReadableStream<Uint8Array>,\n _modelInfo: IModelInfo,\n ): AsyncIterable<IStreamChunk> {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed === \"\" || trimmed === \"data: [DONE]\") {\n continue;\n }\n if (!trimmed.startsWith(\"data: \")) {\n continue;\n }\n\n const jsonStr = trimmed.slice(6);\n let parsed: {\n choices?: Array<{\n delta?: {\n content?: string;\n tool_calls?: Array<{\n id?: string;\n function?: { name?: string; arguments?: string };\n }>;\n };\n }>;\n usage?: OllamaUsage;\n };\n\n try {\n parsed = JSON.parse(jsonStr) as typeof parsed;\n } catch {\n continue;\n }\n\n const delta = parsed.choices?.[0]?.delta;\n if (delta?.content !== undefined && delta.content !== \"\") {\n yield { type: \"text\", content: delta.content };\n }\n\n if (delta?.tool_calls !== undefined) {\n for (const tc of delta.tool_calls) {\n if (tc.id !== undefined && tc.function?.name !== undefined) {\n let args: Record<string, unknown> = {};\n if (tc.function.arguments !== undefined) {\n try {\n args = JSON.parse(tc.function.arguments) as Record<string, unknown>;\n } catch {\n args = {};\n }\n }\n yield {\n type: \"tool_call\",\n toolCall: { id: tc.id, name: tc.function.name, arguments: args },\n };\n }\n }\n }\n\n if (parsed.usage !== undefined) {\n yield {\n type: \"usage\",\n usage: {\n inputTokens: parsed.usage.prompt_tokens,\n outputTokens: parsed.usage.completion_tokens,\n totalTokens: parsed.usage.total_tokens,\n costUsd: 0,\n },\n };\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n}\n\nfunction extractToolCalls(choice: OllamaChoice): IToolCall[] {\n if (choice.message.tool_calls === undefined || choice.message.tool_calls.length === 0) {\n return [];\n }\n return choice.message.tool_calls.map((tc) => {\n let args: Record<string, unknown> = {};\n try {\n args = JSON.parse(tc.function.arguments) as Record<string, unknown>;\n } catch {\n args = {};\n }\n return { id: tc.id, name: tc.function.name, arguments: args };\n });\n}\n\nfunction mapFinishReason(\n reason: string,\n): \"stop\" | \"tool_calls\" | \"max_tokens\" | \"error\" {\n switch (reason) {\n case \"stop\":\n return \"stop\";\n case \"tool_calls\":\n return \"tool_calls\";\n case \"length\":\n return \"max_tokens\";\n default:\n return \"stop\";\n }\n}\n"]}
|