PHhTTPS commited on
Commit
b4d55d2
·
1 Parent(s): be2c50e

Fix Gemini routing, Claude aliases, and server stability (Multi-stage build)

Browse files
Files changed (32) hide show
  1. Dockerfile +43 -0
  2. auth/antigravity-christoph_buchmueller_gmail_com.json +1 -0
  3. auth/antigravity-citrondon666_gmail_com.json +1 -0
  4. auth/antigravity-claracouve342_gmail_com.json +1 -0
  5. auth/antigravity-diesmalwichtigsamuel_gmail_com.json +1 -0
  6. auth/antigravity-hintermaier_pascal_gmail_com.json +1 -0
  7. auth/antigravity-hintermaierpascal0_gmail_com.json +1 -0
  8. auth/antigravity-pascal_hintermaier_gmail_com.json +1 -0
  9. auth/antigravity-rave_riotofficial_gmail_com.json +1 -0
  10. auth/citrondon666@gmail.com-gen-lang-client-0171616182.json +1 -0
  11. auth/claracouve342@gmail.com-bluebirdhub-clara-2025.json +1 -0
  12. auth/hintermaier.pascal@gmail.com-gen-lang-client-0084172363.json +1 -0
  13. auth/hintermaierpascal0@gmail.com-gen-lang-client-0476252734.json +1 -0
  14. auth/kiro-aws-thewolfofvaalstreet@gmail.com.json +1 -0
  15. auth/kiro-imported.json +11 -0
  16. auth/pascal.hintermaier@gmail.com-uniqueuniquesfromuniquewa.json +1 -0
  17. auth/qwen-qwen-1767306169376.json +1 -0
  18. auth/qwen-qwen-1768083358627.json +1 -0
  19. auth/rave.riotofficial@gmail.com-gen-lang-client-0808033057.json +1 -0
  20. config.yaml +40 -1
  21. internal/api/handlers/management/config_basic.go +24 -0
  22. internal/api/modules/amp/routes.go +1 -0
  23. internal/api/server.go +23 -13
  24. internal/registry/model_definitions.go +60 -0
  25. internal/runtime/executor/claude_executor.go +2 -2
  26. internal/runtime/executor/codex_executor.go +2 -2
  27. internal/runtime/executor/gemini_cli_executor.go +2 -2
  28. internal/runtime/executor/gemini_executor.go +4 -8
  29. internal/runtime/executor/gemini_vertex_executor.go +8 -8
  30. internal/runtime/executor/openai_compat_executor.go +2 -2
  31. internal/runtime/executor/qwen_executor.go +2 -2
  32. static/management.html +0 -0
Dockerfile ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Build stage
2
+ FROM golang:1.23-alpine AS builder
3
+
4
+ # Install build dependencies
5
+ RUN apk add --no-cache git
6
+
7
+ WORKDIR /app
8
+
9
+ # Copy go.mod and go.sum and download dependencies
10
+ COPY go.mod go.sum ./
11
+ RUN go mod download
12
+
13
+ # Copy the entire source code
14
+ COPY . .
15
+
16
+ # Build the binary
17
+ RUN go build -o main ./cmd/server
18
+
19
+ # Final stage
20
+ FROM debian:stable-slim
21
+
22
+ # Install CA certificates for HTTPS requests
23
+ RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
24
+
25
+ # Create a non-root user
26
+ RUN useradd -m -u 1000 user
27
+ USER user
28
+ WORKDIR /app
29
+
30
+ # Copy the binary and necessary runtime files
31
+ COPY --from=builder --chown=user /app/main /app/cli-proxy-api-plus
32
+ COPY --chown=user config.yaml /app/config.yaml
33
+ COPY --chown=user static /app/static
34
+ COPY --chown=user auth /app/auth
35
+
36
+ # Ensure the binary is executable
37
+ RUN chmod +x /app/cli-proxy-api-plus
38
+
39
+ # CLIProxyAPI runs on port 7860 for HF Spaces
40
+ EXPOSE 7860
41
+
42
+ # Start the proxy server
43
+ CMD ["./cli-proxy-api-plus", "-config", "config.yaml"]
auth/antigravity-christoph_buchmueller_gmail_com.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"access_token":"ya29.a0Aa7pCA8KLdt68Cjv9kNObSx6rbJ0SJERwFI13GDfQqL8yQ9irGSFROlM4_awejZuWEXdn3C3xcyHnA2oG1nPtdjjLPSml9fupqOV78QpRTzn8cXxzze8bE9zEzfmfVx7-yPzybPGNuHsAX-t4dKfPL6hcyisrf-rJav_ZU532FCwP7_s7yKMmcYUKEwTGnEq2gxqP26YkfaraCgYKAdESARcSFQHGX2Mi-Pq8LF40cUPgv_sAvFGxZA0211","email":"christoph.buchmueller@gmail.com","expired":"2026-01-02T18:32:59+01:00","expires_in":3599,"project_id":"silent-handler-mgcm5","refresh_token":"1//09yHucCaBHDtOCgYIARAAGAkSNwF-L9IrEHLa0C_QeXxY7JeHDkFrGDMCdG5whxRd2EY16KtADKVdXsBDlIkTmX-fNXs0UZYZ05U","timestamp":1767371580076,"type":"antigravity"}
auth/antigravity-citrondon666_gmail_com.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"access_token":"ya29.a0Aa7pCA-OrgBS2TT7VWCWnWo6Lz2YTZdlIJAgoBXvPnE_vTK2BLZN70YPBOY17bnPgMUZWJ0b3Y7Gh_faq6yNFgZR-gl3_2g21mYtUKtCur3C4diNaZBjYZ28dxA2CtD1sTf7ogxNUXRDbSWx-l5jYqNLBJnjqaiwO1X9PMxE8JYeEHksu1b7Qr44Xl6afMuHXSU5997OxuWQaCgYKARISARASFQHGX2MiGe0Tf_54BVJ8TvjDtPzXVg0211","email":"citrondon666@gmail.com","expired":"2026-01-02T00:19:25+01:00","expires_in":3599,"project_id":"refined-shield-p6v41","refresh_token":"1//091tu8uSgBlZoCgYIARAAGAkSNwF-L9IrhZB5y3tWZlPXxa1iAnP1jcN9g9IW1FwWKfv4bwhL87ThOM_lQ_od35l27TERPGvunSs","timestamp":1767305966638,"type":"antigravity"}
auth/antigravity-claracouve342_gmail_com.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"access_token":"ya29.a0Aa7pCA_70alhbg9TxA_L64Qeh0jqH8bydreSpyVCFGrfN-RZ7MwiHdtjJW1pwp40ZwtHd1NoS4fjf52IH78GkO4F9lUHumCO6v0WaLbk-dSFrf9AwwT1BWmi7sVlvV6rOVBNS7Cc3kchwXz6nplxv2GQI7ZxvHSNdzzmWPIFQWUydMf25hnJl1e0BKJtSeJioN8ysTUHn4TZaCgYKAXcSARUSFQHGX2Mi9K286fUkMtZwJNhejeJZxg0211","email":"claracouve342@gmail.com","expired":"2026-01-02T00:18:24+01:00","expires_in":3599,"project_id":"lofty-sorter-00fqx","refresh_token":"1//09GZJ6C1n1VwFCgYIARAAGAkSNwF-L9IrM3IOj19bnFTuU99g7NEZh2v-q-_HkHVu0nQzvKii1eNlhPJeaBYo9JlQ0IkGQ1QkwDE","timestamp":1767305905292,"type":"antigravity"}
auth/antigravity-diesmalwichtigsamuel_gmail_com.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"access_token":"ya29.a0Aa7pCA-digf4tFdMayz_Dd9GAZH1hbQauskM7JZvpa6N8VjVXHzr0FHOOxv1Na_wz84RzHHIDpRcpNBYFApievjaEDpxoMGTT0v2Rr_Rq_n9znyEvC1PFCCjQlVmgyXYBgfsTW7J2G51d7gvoYKnr5DiHqyZgaGCFrAQnf9wW5Z-rsa4S1X6xL5bW-RDicAWpOi5FgNc2sQ-aCgYKAWwSARQSFQHGX2MilKC3mz76wZKDL03WjTSQbw0211","email":"diesmalwichtigsamuel@gmail.com","expired":"2026-01-02T00:19:39+01:00","expires_in":3599,"refresh_token":"1//09tvr0tts6qmvCgYIARAAGAkSNwF-L9Ir2Q6uDIlIhVcgzxWHSpvKy4WkxyXvR1NU9LORdLs7bvtbbl7ahF9TvInw__LQEUx6yKQ","timestamp":1767305980210,"type":"antigravity"}
auth/antigravity-hintermaier_pascal_gmail_com.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"access_token":"ya29.a0Aa7pCA9IDNSnhAjLh2PbI7xjiKpF_4rmeq1iep6M0HS80zZtHx8vv3alRfJ9b2HuCsaf-10xI916Bwim9PGH6Opttxrerv3-P9YGfeVVP5J2gjzXPZke1FOkb7WI-dGTRwLdP52MW15nXsXgXiBALXQzS1ZzAAORWGFfnV3hh_341f1vPeObdHCTLaAiR5lO0Ml7fQ3Nob3IaCgYKAWQSARYSFQHGX2MiupVKZOsM2fxyS57yOfc47Q0211","email":"hintermaier.pascal@gmail.com","expired":"2026-01-02T00:17:58+01:00","expires_in":3599,"project_id":"modified-fastness-wlr19","refresh_token":"1//09l9GQlj_VRTFCgYIARAAGAkSNwF-L9IrbS2oCSBRwQBzNzOFIMEqtD8q8dfSTZ8lswoQQ-mUzpXWPLKdoVqCfdYH9z0ilLRoHmI","timestamp":1767305879026,"type":"antigravity"}
auth/antigravity-hintermaierpascal0_gmail_com.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"access_token":"ya29.a0Aa7pCA8J_q9LPSBVRtJ2bIAXxE7FTCwEKmWxa0nESOQMvY0zS6aoS5TMsU6JteMrTHGN_iL9yNYtteOO6BQv2kuJ3k-MuU0M4A2NJ1mkUT1J3Mu8cR_VVK5pN4UTRY9N5l9ujzBrDHC1WMTXmxxjh51Fi78rZ7QWv9t7Ch_DES_te47pFz8x1eDh1jjraLU6NIIXU5pVna4AaCgYKAbgSARYSFQHGX2MiV7V0yJN7Au__melh6T_l_g0211","email":"hintermaierpascal0@gmail.com","expired":"2026-01-02T00:18:32+01:00","expires_in":3599,"project_id":"phonic-pillar-1zftk","refresh_token":"1//09L559Xu1HR65CgYIARAAGAkSNwF-L9IrNRO1A6ybH155Y6Y1TGKmrVCN7-0TsC3tonouMFsKAfnRNxO9TEZ5EhymmK_bnq60q3c","timestamp":1767305913612,"type":"antigravity"}
auth/antigravity-pascal_hintermaier_gmail_com.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"access_token":"ya29.a0Aa7pCA9jRjQOmohIG_pzuvi6PU0TLzxtWziImkHyzrj87Can6-B475kZ2rVFzEjZMEwEjtqsKiZNl4UNCpqkDU5Xg_ajX4SGxocRlTQYltKw8saL9yc0mH5-PsVFzQ10bp8bjH50ZkG9zhGEO3O3FawmeqAZ5zT3vO_dd5LLQopMo5TH0s-SMozZSs6BKInUoAFl23o_BntRaCgYKAacSARYSFQHGX2Mi07efzoG1Wy3HeuazuxUgDQ0211","email":"pascal.hintermaier@gmail.com","expired":"2026-01-02T00:17:41+01:00","expires_in":3599,"project_id":"alert-brace-j1nhr","refresh_token":"1//09zyxez21TBu2CgYIARAAGAkSNwF-L9IrIOs7JCFeBds7LqcJZKMouL7vk40uWA77KJiYvdeV49RQz4SUxhz8rM4SL3B2fZ9INwk","timestamp":1767305862567,"type":"antigravity"}
auth/antigravity-rave_riotofficial_gmail_com.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"access_token":"ya29.a0Aa7pCA8YBU00C_zuB548ozVzlaXES5VhvyrqStyJv38m96lf2g_mJyIr-ywDP63sdlzYZ8Ec8SOtxaj9A7SvWhiw1gvo3CvH_rVvQH8kaQfYSbadtO3RLo3GMYf0L8omuTyZKI7bunOUxYhXJo7nTsmKEo3FZ6wnz02n2L-jYPkyGZTq_ghBv2rOoKHGv8SnOYzSpshg1dVaaCgYKAUoSARISFQHGX2Mi40PKBz2bpbCexj7DzBCevQ0211","email":"rave.riotofficial@gmail.com","expired":"2026-01-02T00:19:57+01:00","expires_in":3599,"project_id":"blissful-age-zww27","refresh_token":"1//093bq-VRNSCPfCgYIARAAGAkSNwF-L9IrQP0RZvGVhhshN7lIHkbsu5zgE4qmDsKdfdx0oWUO6q1DqRUQOjTcepkFnitCNuOLpME","timestamp":1767305998823,"type":"antigravity"}
auth/citrondon666@gmail.com-gen-lang-client-0171616182.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"token":{"access_token":"ya29.a0Aa7pCA9i1naLUPL-0-tftJdh88tAfpQRAqmJLUZbkuu3bfMWqS_0_lenKOtS5Vn1xeVj8BODMH-6jtTkaRkvPW4YugsQEILGOt4yXC4P4GxEFvIsKEE2jw-GMyVIPocbBmPOXeGJ_lWU3RmtMB1oLob1XW2vPjzd-A0CJ6TI0obV0qV9BJ5SWojz-f4Rn-mHc5QXfND1tV28aCgYKAbkSARASFQHGX2Miwo8dM2I97qjOYCvH5-Z6aQ0211","client_id":"681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com","client_secret":"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","expires_in":3599,"expiry":"2026-01-02T00:15:45.829310593+01:00","refresh_token":"1//09Lwiwr528W7JCgYIARAAGAkSNwF-L9Ir5G6OfSE68L5SDtdBaT2-EydTmYcg4XBye_6gkYtNuXVuYlH9aLxEJg4gL3ZEkp3xIhM","scopes":["https://www.googleapis.com/auth/cloud-platform","https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/userinfo.profile"],"token_type":"Bearer","token_uri":"https://oauth2.googleapis.com/token","universe_domain":"googleapis.com"},"project_id":"gen-lang-client-0171616182","email":"citrondon666@gmail.com","auto":false,"checked":true,"type":"gemini"}
auth/claracouve342@gmail.com-bluebirdhub-clara-2025.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"token":{"access_token":"ya29.a0Aa7pCA8YcixUQXmIuzbo7vySb8n8aohMsqWia1_sYitaBPDHcQl50Ikb_8_PvWHIXgDESmaVWBL0-aKG_YDKPxGtq87Mxic9FSJMMqM7MUuvRHRM8rgmdPKI5XggnOkX8kqT66AKfI4OglhI_ojD05JXofRaHlBZBttquTiJLbXsXmwOHu8AC4nZxxaNutOBzzSaVpu_89ABaCgYKARkSARUSFQHGX2MiZmzlC0JJ1Pm3FCmlgU0c1w0211","client_id":"681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com","client_secret":"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","expires_in":3599,"expiry":"2026-01-02T00:11:47.777597698+01:00","refresh_token":"1//09Pe3DLMsnRhFCgYIARAAGAkSNwF-L9IrNg_BGMBsI2AWcZbR8n-1iMi9pmscb3r9T50fG2Ok_Cz4FH_bZGf-oRzmc_Zzi7m-Bf8","scopes":["https://www.googleapis.com/auth/cloud-platform","https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/userinfo.profile"],"token_type":"Bearer","token_uri":"https://oauth2.googleapis.com/token","universe_domain":"googleapis.com"},"project_id":"bluebirdhub-clara-2025","email":"claracouve342@gmail.com","auto":false,"checked":true,"type":"gemini"}
auth/hintermaier.pascal@gmail.com-gen-lang-client-0084172363.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"token":{"access_token":"ya29.a0Aa7pCA-tT7fzxjembWop9gxC6gMoOgECa8rDmrSj18w-ikGPyna08vQZbRnsJ_9RPPWD0N-Ifkb3OkQ1i7CnbZGVlkaxOI8eBEDzDCGqmKvh45z_6smwk_mteAq3HBauYNyeot1ouitgIlcMXDaEHs5igTMjvpOJFSxUKY980yPAEPiv57NAwBXhfTQQlfaZ9qKRDLJ1UfPWaCgYKAdcSARYSFQHGX2Mi_I69sgBKDPmsCHr_2dvJrQ0211","client_id":"681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com","client_secret":"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","expires_in":3599,"expiry":"2026-01-02T00:10:08.911390808+01:00","refresh_token":"1//09ob8pMdbHcbpCgYIARAAGAkSNwF-L9Ir2LnNCRo20RUeAusLILxBDQiwveCJWJFYsayiRGOBbvpzb8-q_KfUZ_P01Yq7p_USp_M","scopes":["https://www.googleapis.com/auth/cloud-platform","https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/userinfo.profile"],"token_type":"Bearer","token_uri":"https://oauth2.googleapis.com/token","universe_domain":"googleapis.com"},"project_id":"gen-lang-client-0084172363","email":"hintermaier.pascal@gmail.com","auto":false,"checked":true,"type":"gemini"}
auth/hintermaierpascal0@gmail.com-gen-lang-client-0476252734.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"token":{"access_token":"ya29.a0Aa7pCA85OQRBB7u8YgcQRfayVnLk8I6dunNZp6oArZ9llWfKj7wLdqiJNAl2U51XIiFNdZpeL1tOgBvm2H8z9eUROJ2qw2D0pT8cOaQv7r-weT2RSSMve7I_2Yk5U2pHZBg4VMFRsd015UhwpACIIHhFl3EBjCc1Iy7xApFjq9Rxkg2yBzxsj1pJ0QSMVIV7e58YUGL2FPjoaCgYKASwSARYSFQHGX2MivWwKs3LijABXANjQ3RqEkg0211","client_id":"681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com","client_secret":"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","expires_in":3599,"expiry":"2026-01-02T00:13:15.204806529+01:00","refresh_token":"1//09AUg0-ZLVaHmCgYIARAAGAkSNwF-L9Ir7-ZgC0mclyGm8A8PpB52zp212A6GTlD8BXnBsvw8fjTcdQ8RdC-z9HSLiv3BjY1AQ5E","scopes":["https://www.googleapis.com/auth/cloud-platform","https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/userinfo.profile"],"token_type":"Bearer","token_uri":"https://oauth2.googleapis.com/token","universe_domain":"googleapis.com"},"project_id":"gen-lang-client-0476252734","email":"hintermaierpascal0@gmail.com","auto":false,"checked":true,"type":"gemini"}
auth/kiro-aws-thewolfofvaalstreet@gmail.com.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"access_token":"aoaAAAAAGlkFKoxVq73tgXDpSo80R0INlcVelAqpmjtG-s4gSyh0SBJg1btQc_NXrkaUPCIFrj2epxXlXbwX_zudkBkc0:MGUCMCc8akLHezKXbx9EQ7Q2qQhHzINnsplvlmkvC0yx3W+vza20l4VuV8kkXlAHqkMHiAIxALPSQYKTKurWy97XJrERxpLkEuKio0731p3LYVQPphi6oktnfL+tZJV6vthmAk8nZA","auth_method":"builder-id","client_id":"5FisoOIBeETVXgV2F7wnqXVzLWVhc3QtMQ","client_secret":"eyJraWQiOiJrZXktMTU2NDAyODA5OSIsImFsZyI6IkhTMzg0In0.eyJzZXJpYWxpemVkIjoie1wiY2xpZW50SWRcIjp7XCJ2YWx1ZVwiOlwiNUZpc29PSUJlRVRWWGdWMkY3d25xWFZ6TFdWaGMzUXRNUVwifSxcImlkZW1wb3RlbnRLZXlcIjpudWxsLFwidGVuYW50SWRcIjpudWxsLFwiY2xpZW50TmFtZVwiOlwiS2lybyBJREVcIixcImJhY2tmaWxsVmVyc2lvblwiOm51bGwsXCJjbGllbnRUeXBlXCI6XCJQVUJMSUNcIixcInRlbXBsYXRlQXJuXCI6bnVsbCxcInRlbXBsYXRlQ29udGV4dFwiOm51bGwsXCJleHBpcmF0aW9uVGltZXN0YW1wXCI6MTc3NTExODU5OC44MTIwNzg4NDcsXCJjcmVhdGVkVGltZXN0YW1wXCI6MTc2NzM0MjU5OC44MTIwNzg4NDcsXCJ1cGRhdGVkVGltZXN0YW1wXCI6MTc2NzM0MjU5OC44MTIwNzg4NDcsXCJjcmVhdGVkQnlcIjpudWxsLFwidXBkYXRlZEJ5XCI6bnVsbCxcInN0YXR1c1wiOm51bGwsXCJpbml0aWF0ZUxvZ2luVXJpXCI6bnVsbCxcImVudGl0bGVkUmVzb3VyY2VJZFwiOm51bGwsXCJlbnRpdGxlZFJlc291cmNlQ29udGFpbmVySWRcIjpudWxsLFwiZXh0ZXJuYWxJZFwiOm51bGwsXCJzb2Z0d2FyZUlkXCI6bnVsbCxcInNjb3Blc1wiOlt7XCJmdWxsU2NvcGVcIjpcImNvZGV3aGlzcGVyZXI6Y29tcGxldGlvbnNcIixcInN0YXR1c1wiOlwiSU5JVElBTFwiLFwiYXBwbGljYXRpb25Bcm5cIjpudWxsLFwiZnJpZW5kbHlJZFwiOlwiY29kZXdoaXNwZXJlclwiLFwidXNlQ2FzZUFjdGlvblwiOlwiY29tcGxldGlvbnNcIixcInR5cGVcIjpcIkltbXV0YWJsZUFjY2Vzc1Njb3BlXCIsXCJzY29wZVR5cGVcIjpcIkFDQ0VTU19TQ09QRVwifSx7XCJmdWxsU2NvcGVcIjpcImNvZGV3aGlzcGVyZXI6YW5hbHlzaXNcIixcInN0YXR1c1wiOlwiSU5JVElBTFwiLFwiYXBwbGljYXRpb25Bcm5cIjpudWxsLFwiZnJpZW5kbHlJZFwiOlwiY29kZXdoaXNwZXJlclwiLFwidXNlQ2FzZUFjdGlvblwiOlwiYW5hbHlzaXNcIixcInR5cGVcIjpcIkltbXV0YWJsZUFjY2Vzc1Njb3BlXCIsXCJzY29wZVR5cGVcIjpcIkFDQ0VTU19TQ09QRVwifSx7XCJmdWxsU2NvcGVcIjpcImNvZGV3aGlzcGVyZXI6Y29udmVyc2F0aW9uc1wiLFwic3RhdHVzXCI6XCJJTklUSUFMXCIsXCJhcHBsaWNhdGlvbkFyblwiOm51bGwsXCJmcmllbmRseUlkXCI6XCJjb2Rld2hpc3BlcmVyXCIsXCJ1c2VDYXNlQWN0aW9uXCI6XCJjb252ZXJzYXRpb25zXCIsXCJ0eXBlXCI6XCJJbW11dGFibGVBY2Nlc3NTY29wZVwiLFwic2NvcGVUeXBlXCI6XCJBQ0NFU1NfU0NPUEVcIn0se1wiZnVsbFNjb3BlXCI6XCJjb2Rld2hpc3BlcmVyOnRyYW5zZm9ybWF0aW9uc1wiLFwic3RhdHVzXCI6XCJJTklUSUFMXCIsXCJhcHBsaWNhdGlvbkFyblwiOm51bGwsXCJmcmllbmRseUlkXCI6XCJjb2Rld2hpc3BlcmVyXCIsXCJ1c2VDYXNlQWN0aW9uXCI6XCJ0cmFuc2Zvcm1hdGlvbnNcIixcInR5cGVcIjpcIkltbXV0YWJsZUFjY2Vzc1Njb3BlXCIsXCJzY29wZVR5cGVcIjpcIkFDQ0VTU19TQ09QRVwifSx7XCJmdWxsU2NvcGVcIjpcImNvZGV3aGlzcGVyZXI6dGFza2Fzc2lzdFwiLFwic3RhdHVzXCI6XCJJTklUSUFMXCIsXCJhcHBsaWNhdGlvbkFyblwiOm51bGwsXCJmcmllbmRseUlkXCI6XCJjb2Rld2hpc3BlcmVyXCIsXCJ1c2VDYXNlQWN0aW9uXCI6XCJ0YXNrYXNzaXN0XCIsXCJ0eXBlXCI6XCJJbW11dGFibGVBY2Nlc3NTY29wZVwiLFwic2NvcGVUeXBlXCI6XCJBQ0NFU1NfU0NPUEVcIn1dLFwiYXV0aGVudGljYXRpb25Db25maWd1cmF0aW9uXCI6bnVsbCxcInNoYWRvd0F1dGhlbnRpY2F0aW9uQ29uZmlndXJhdGlvblwiOm51bGwsXCJlbmFibGVkR3JhbnRzXCI6bnVsbCxcImVuZm9yY2VBdXRoTkNvbmZpZ3VyYXRpb25cIjpudWxsLFwib3duZXJBY2NvdW50SWRcIjpudWxsLFwic3NvSW5zdGFuY2VBY2NvdW50SWRcIjpudWxsLFwidXNlckNvbnNlbnRcIjpudWxsLFwibm9uSW50ZXJhY3RpdmVTZXNzaW9uc0VuYWJsZWRcIjpudWxsLFwiYXNzb2NpYXRlZEluc3RhbmNlQXJuXCI6bnVsbCxcImlzQmFja2ZpbGxlZFwiOmZhbHNlLFwiaGFzSW5pdGlhbFNjb3Blc1wiOnRydWUsXCJhcmVBbGxTY29wZXNDb25zZW50ZWRUb1wiOmZhbHNlLFwiaXNFeHBpcmVkXCI6ZmFsc2UsXCJzc29TY29wZXNcIjpbXSxcImdyb3VwU2NvcGVzQnlGcmllbmRseUlkXCI6e1wiY29kZXdoaXNwZXJlclwiOlt7XCJmdWxsU2NvcGVcIjpcImNvZGV3aGlzcGVyZXI6YW5hbHlzaXNcIixcInN0YXR1c1wiOlwiSU5JVElBTFwiLFwiYXBwbGljYXRpb25Bcm5cIjpudWxsLFwiZnJpZW5kbHlJZFwiOlwiY29kZXdoaXNwZXJlclwiLFwidXNlQ2FzZUFjdGlvblwiOlwiYW5hbHlzaXNcIixcInR5cGVcIjpcIkltbXV0YWJsZUFjY2Vzc1Njb3BlXCIsXCJzY29wZVR5cGVcIjpcIkFDQ0VTU19TQ09QRVwifSx7XCJmdWxsU2NvcGVcIjpcImNvZGV3aGlzcGVyZXI6dHJhbnNmb3JtYXRpb25zXCIsXCJzdGF0dXNcIjpcIklOSVRJQUxcIixcImFwcGxpY2F0aW9uQXJuXCI6bnVsbCxcImZyaWVuZGx5SWRcIjpcImNvZGV3aGlzcGVyZXJcIixcInVzZUNhc2VBY3Rpb25cIjpcInRyYW5zZm9ybWF0aW9uc1wiLFwidHlwZVwiOlwiSW1tdXRhYmxlQWNjZXNzU2NvcGVcIixcInNjb3BlVHlwZVwiOlwiQUNDRVNTX1NDT1BFXCJ9LHtcImZ1bGxTY29wZVwiOlwiY29kZXdoaXNwZXJlcjpjb252ZXJzYXRpb25zXCIsXCJzdGF0dXNcIjpcIklOSVRJQUxcIixcImFwcGxpY2F0aW9uQXJuXCI6bnVsbCxcImZyaWVuZGx5SWRcIjpcImNvZGV3aGlzcGVyZXJcIixcInVzZUNhc2VBY3Rpb25cIjpcImNvbnZlcnNhdGlvbnNcIixcInR5cGVcIjpcIkltbXV0YWJsZUFjY2Vzc1Njb3BlXCIsXCJzY29wZVR5cGVcIjpcIkFDQ0VTU19TQ09QRVwifSx7XCJmdWxsU2NvcGVcIjpcImNvZGV3aGlzcGVyZXI6dGFza2Fzc2lzdFwiLFwic3RhdHVzXCI6XCJJTklUSUFMXCIsXCJhcHBsaWNhdGlvbkFyblwiOm51bGwsXCJmcmllbmRseUlkXCI6XCJjb2Rld2hpc3BlcmVyXCIsXCJ1c2VDYXNlQWN0aW9uXCI6XCJ0YXNrYXNzaXN0XCIsXCJ0eXBlXCI6XCJJbW11dGFibGVBY2Nlc3NTY29wZVwiLFwic2NvcGVUeXBlXCI6XCJBQ0NFU1NfU0NPUEVcIn0se1wiZnVsbFNjb3BlXCI6XCJjb2Rld2hpc3BlcmVyOmNvbXBsZXRpb25zXCIsXCJzdGF0dXNcIjpcIklOSVRJQUxcIixcImFwcGxpY2F0aW9uQXJuXCI6bnVsbCxcImZyaWVuZGx5SWRcIjpcImNvZGV3aGlzcGVyZXJcIixcInVzZUNhc2VBY3Rpb25cIjpcImNvbXBsZXRpb25zXCIsXCJ0eXBlXCI6XCJJbW11dGFibGVBY2Nlc3NTY29wZVwiLFwic2NvcGVUeXBlXCI6XCJBQ0NFU1NfU0NPUEVcIn1dfSxcInNob3VsZEdldFZhbHVlRnJvbVRlbXBsYXRlXCI6dHJ1ZSxcImhhc1JlcXVlc3RlZFNjb3Blc1wiOmZhbHNlLFwiY29udGFpbnNPbmx5U3NvU2NvcGVzXCI6ZmFsc2UsXCJpc1YxQmFja2ZpbGxlZFwiOmZhbHNlLFwiaXNWMkJhY2tmaWxsZWRcIjpmYWxzZSxcImlzVjNCYWNrZmlsbGVkXCI6ZmFsc2UsXCJpc1Y0QmFja2ZpbGxlZFwiOmZhbHNlfSJ9.DiJpx0r9gC_jmCWyCnT1IlZvHeUvMSKJfjPR-DuOI3q4LT7em4LIyxbVoE9WHGJW","email":"thewolfofvaalstreet@gmail.com","expires_at":"2026-01-11T22:22:50+01:00","last_refresh":"2026-01-11T21:22:50+01:00","profile_arn":"","provider":"AWS","refresh_token":"aorAAAAAGnOKY0Am29SYn6By21bOzldZAxR193g2QTyRS6KXX6AK1M4Fma12aZE2TDCPnRsI_uj1HUjJfE2zEydqMBkc0:MGUCMCzzb1rRj5AAhg+kfEk/1qPME44GUly/qn8Oarh3lo1z02Xi/zi0qxlw1ZcV5AgRYwIxAOTwAyJo7mWQ1LekVwkyzguAH4jAipwYrdKVvXtzzdHsyRZn2W98dbT5+lh9au2NDA","type":"kiro"}
auth/kiro-imported.json ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "access_token": "aoaAAAAAGlkDekrMnJSl1YIFYAJ29XEpOETQOyIuBN7i5uNeRSRQToomd8IOdhu2UKhOw2ool4WAy0qNheY6Cye5gBkc0:MGYCMQDTHENT4w0BzqbwDoA/IJwxn1+Ce7c9rX8D1WdwNxzNtHQWva10pYQsXrZ9fO/qXzMCMQDLFUQEnzFh9PK68TSlUFSx/1tghIG96l4ngax8085Pvgz+6dSgp7mPH1ZlRGyOFgc",
3
+ "refresh_token": "aorAAAAAGnaptg1icfwZhyXuM5cBjQtZPs2LQJyOlbSRf6I_AKvtLmtHSgnHOLQf8Gi0emeTbxjwiGwbNZMTLUCQABkc0:MGQCMAVg1bvvEOfPWs/36xo0O++ymfuZV9qbVGVnc44p0mhP6mCaw4mbaWq7P+zxzYr5/AIwXnJ+pFLb/XOz8orjlctjZlINcnxadpPWn7ljEHXH1DHVYFRpBbNP4RCHqeynWgE9",
4
+ "client_id": "5FisoOIBeETVXgV2F7wnqXVzLWVhc3QtMQ",
5
+ "client_secret": "PLACEHOLDER_SECRET_HOPE_IT_WORKS_OR_REAUTH_IS_NEEDED",
6
+ "expires_at": "2026-02-11T20:43:01+01:00",
7
+ "auth_method": "builder-id",
8
+ "email": "imported-session@kiro.dev",
9
+ "provider": "AWS",
10
+ "type": "kiro"
11
+ }
auth/pascal.hintermaier@gmail.com-uniqueuniquesfromuniquewa.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"token":{"access_token":"ya29.a0Aa7pCA-JmhVnLjUMvTDNINUisfjwu7TYAGUEEBB8BkskL4N_EDKHnPiFm5c2CQy4ZXj7qrGFY-GV6xFBoLl5zz1AvCZEEQpOgZqwOJ70mp8Tej7hCeksQSsWsg7T7As11ooVRrcocaJAop0UWrGzvctGNmXkhdzfenWasifGvFs4IeO9H3D4ZfVKvQ33xkv-5ywm-L7z0SnGaCgYKAW4SARYSFQHGX2MiHAUPf_7OlClRr9w2KsuOpA0211","client_id":"681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com","client_secret":"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","expires_in":3599,"expiry":"2026-01-02T00:09:51.395235364+01:00","refresh_token":"1//090htx9bnW3FhCgYIARAAGAkSNwF-L9IrQFx7l8-oZzygHuJZ7qI5YuYr8f0UFpcy1SUKGCvG5MIaiKfAaKy71ipGQSRmVq6DgYE","scopes":["https://www.googleapis.com/auth/cloud-platform","https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/userinfo.profile"],"token_type":"Bearer","token_uri":"https://oauth2.googleapis.com/token","universe_domain":"googleapis.com"},"project_id":"uniqueuniquesfromuniquewa","email":"pascal.hintermaier@gmail.com","auto":false,"checked":true,"type":"gemini"}
auth/qwen-qwen-1767306169376.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"access_token":"0exSDQrcZiCvP-wj7p6HjGaouYiLDfw6dIxnsTnqh9B6CgemJz8vT-BKS1YQhK5tCr07gECe3mibLQ6W826f_g","email":"qwen-1767306169376","expired":"2026-01-04T03:10:33+01:00","last_refresh":"2026-01-03T21:10:33+01:00","refresh_token":"q1j2tXG9fh3YvOQDWbMyVMUf7SIo_mUb87q4iWnzU4WostN8faarjLqkYvJk-J1rLzbofHGouUde2yhZFOksVw","resource_url":"portal.qwen.ai","type":"qwen"}
auth/qwen-qwen-1768083358627.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"access_token":"ekJyQZXCGIyGEYvjJkingGK-7mDjYQ_tJyp45tI72uVRNeCptiHK52xC0tpfg6iMfcUirIAT7JA6-GxGgVivTA","email":"qwen-1768083358627","expired":"2026-01-12T02:27:44+01:00","last_refresh":"2026-01-11T20:27:44+01:00","refresh_token":"R8_pR0ZK7q_i2lmMWVH0in_QuhKzhr0BsjD5fkPYafBIPunPiNU7TC9V5fQnfSO7XP-eDoOIqdlz44qrmc9hNQ","resource_url":"portal.qwen.ai","type":"qwen"}
auth/rave.riotofficial@gmail.com-gen-lang-client-0808033057.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"token":{"access_token":"ya29.a0Aa7pCA99cbhSEpb2VASWH4ve1PT90NXhZlA-Vizvv5jTjZtkCcPsrZiRx0ePQb3RP1jrnVcl3FIcD9vm1Y9qECfxt_pht6ix0NyiVhaomFfllY8x7N8iiQ_84Kbzdtx6ZqDEtTE94I4tezDMnwInYOJ-lgjUTfdaZdCh5pPzdPokeTKpIsva_H6AoxFU4c-64rWXUpZQ_RA0aCgYKAY4SARISFQHGX2Mi0OOAitFV7HIB1eWyuItT7w0211","client_id":"681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com","client_secret":"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","expires_in":3599,"expiry":"2026-01-02T00:14:41.673223313+01:00","refresh_token":"1//09tt-yEwjTCtECgYIARAAGAkSNwF-L9IrMDhY1GirEU2mJDg1J57FOuougJaiCzZEIjIxBr08ewkiqCqOyhhz_qbm0BUfii3Mq-g","scopes":["https://www.googleapis.com/auth/cloud-platform","https://www.googleapis.com/auth/userinfo.email","https://www.googleapis.com/auth/userinfo.profile"],"token_type":"Bearer","token_uri":"https://oauth2.googleapis.com/token","universe_domain":"googleapis.com"},"project_id":"gen-lang-client-0808033057","email":"rave.riotofficial@gmail.com","auto":false,"checked":true,"type":"gemini"}
config.yaml CHANGED
@@ -19,6 +19,7 @@ auth-dir: "./auth"
19
  # Client Keys for YOU to access the API
20
  api-keys:
21
  - "sk-admin-power-1"
 
22
  - "sk-client-key-custom"
23
 
24
  # Performance & Logging
@@ -70,6 +71,44 @@ oauth-model-mappings:
70
  alias: "g-pro"
71
  - name: "gemini-2.5-flash"
72
  alias: "g-flash"
 
 
 
 
73
  claude:
74
  - name: "claude-3-5-sonnet-20241022"
75
- alias: "sonnet"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  # Client Keys for YOU to access the API
20
  api-keys:
21
  - "sk-admin-power-1"
22
+ - "sk-ant-proxy-key-1"
23
  - "sk-client-key-custom"
24
 
25
  # Performance & Logging
 
71
  alias: "g-pro"
72
  - name: "gemini-2.5-flash"
73
  alias: "g-flash"
74
+ - name: "gemini-2.5-pro"
75
+ alias: "gemini-1.5-pro"
76
+ - name: "gemini-2.5-flash"
77
+ alias: "gemini-1.5-flash"
78
  claude:
79
  - name: "claude-3-5-sonnet-20241022"
80
+ alias: "sonnet"
81
+ - name: "claude-3-5-sonnet-20241022"
82
+ alias: "claude-sonnet-4-5-20250929"
83
+ - name: "claude-3-5-sonnet-20241022"
84
+ alias: "claude-haiku-4-5-20251001"
85
+ - name: "claude-3-5-sonnet-20241022"
86
+ alias: "claude-3-5-sonnet-latest"
87
+ - name: "claude-3-5-sonnet-20241022"
88
+ alias: "claude-3-5-sonnet-20241022"
89
+ openrouter:
90
+ - name: "anthropic/claude-3-5-sonnet"
91
+ alias: "claude-3-5-sonnet-20241022"
92
+ - name: "anthropic/claude-3-5-sonnet"
93
+ alias: "claude-3-5-sonnet-latest"
94
+ - name: "anthropic/claude-3-5-haiku"
95
+ alias: "claude-3-5-haiku-20241022"
96
+
97
+ # 5. Amp Integration (Claude Code)
98
+ oauth-excluded-models:
99
+ # Removed kiro exclusion to enable Kiro models
100
+ claude: []
101
+
102
+ ampcode:
103
+ force-model-mappings: true
104
+ model-mappings:
105
+ - from: "gpt-4o"
106
+ to: "gemini-2.5-flash"
107
+ - from: "gpt-4o-mini"
108
+ to: "gemini-2.5-flash"
109
+ - from: "claude-sonnet-4-5-20250929"
110
+ to: "kiro-claude-sonnet-4-5"
111
+ - from: "claude-haiku-4-5-20251001"
112
+ to: "kiro-claude-sonnet-4-5"
113
+
114
+ ws-auth: false
internal/api/handlers/management/config_basic.go CHANGED
@@ -241,3 +241,27 @@ func (h *Handler) DeleteProxyURL(c *gin.Context) {
241
  h.cfg.ProxyURL = ""
242
  h.persist(c)
243
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
  h.cfg.ProxyURL = ""
242
  h.persist(c)
243
  }
244
+
245
+ // Logs max total size
246
+ func (h *Handler) GetLogsMaxTotalSizeMb(c *gin.Context) {
247
+ c.JSON(200, gin.H{"logs-max-total-size-mb": h.cfg.LogsMaxTotalSizeMB})
248
+ }
249
+ func (h *Handler) PutLogsMaxTotalSizeMb(c *gin.Context) {
250
+ h.updateIntField(c, func(v int) { h.cfg.LogsMaxTotalSizeMB = v })
251
+ }
252
+
253
+ // Routing strategy
254
+ func (h *Handler) GetRoutingStrategy(c *gin.Context) {
255
+ c.JSON(200, gin.H{"strategy": h.cfg.Routing.Strategy})
256
+ }
257
+ func (h *Handler) PutRoutingStrategy(c *gin.Context) {
258
+ h.updateStringField(c, func(v string) { h.cfg.Routing.Strategy = v })
259
+ }
260
+
261
+ // Force model prefix
262
+ func (h *Handler) GetForceModelPrefix(c *gin.Context) {
263
+ c.JSON(200, gin.H{"force-model-prefix": h.cfg.ForceModelPrefix})
264
+ }
265
+ func (h *Handler) PutForceModelPrefix(c *gin.Context) {
266
+ h.updateBoolField(c, func(v bool) { h.cfg.ForceModelPrefix = v })
267
+ }
internal/api/modules/amp/routes.go CHANGED
@@ -307,6 +307,7 @@ func (m *AmpModule) registerProviderAliases(engine *gin.Engine, baseHandler *han
307
  provider.POST("/chat/completions", fallbackHandler.WrapHandler(openaiHandlers.ChatCompletions))
308
  provider.POST("/completions", fallbackHandler.WrapHandler(openaiHandlers.Completions))
309
  provider.POST("/responses", fallbackHandler.WrapHandler(openaiResponsesHandlers.Responses))
 
310
 
311
  // /v1 routes (OpenAI/Claude-compatible endpoints)
312
  v1Amp := provider.Group("/v1")
 
307
  provider.POST("/chat/completions", fallbackHandler.WrapHandler(openaiHandlers.ChatCompletions))
308
  provider.POST("/completions", fallbackHandler.WrapHandler(openaiHandlers.Completions))
309
  provider.POST("/responses", fallbackHandler.WrapHandler(openaiResponsesHandlers.Responses))
310
+ provider.POST("/messages", fallbackHandler.WrapHandler(claudeCodeHandlers.ClaudeMessages))
311
 
312
  // /v1 routes (OpenAI/Claude-compatible endpoints)
313
  v1Amp := provider.Group("/v1")
internal/api/server.go CHANGED
@@ -361,6 +361,10 @@ func (s *Server) setupRoutes() {
361
  s.engine.POST("/api/event_logging/batch", func(c *gin.Context) {
362
  c.JSON(http.StatusOK, gin.H{"status": "ok"})
363
  })
 
 
 
 
364
  s.engine.POST("/v1internal:method", geminiCLIHandlers.CLIHandler)
365
 
366
  // OAuth callback endpoints (reuse main server port)
@@ -548,6 +552,18 @@ func (s *Server) registerManagementRoutes() {
548
  mgmt.PATCH("/gemini-api-key", s.mgmt.PatchGeminiKey)
549
  mgmt.DELETE("/gemini-api-key", s.mgmt.DeleteGeminiKey)
550
 
 
 
 
 
 
 
 
 
 
 
 
 
551
  mgmt.GET("/logs", s.mgmt.GetLogs)
552
  mgmt.DELETE("/logs", s.mgmt.DeleteLogs)
553
  mgmt.GET("/request-error-logs", s.mgmt.GetRequestErrorLogs)
@@ -665,25 +681,19 @@ func (s *Server) serveManagementControlPanel(c *gin.Context) {
665
  // Direct fallback: serve management.html from memory if file access fails
666
  c.File(filePath)
667
  }
668
- filePath := managementasset.FilePath(s.configFilePath)
669
- if strings.TrimSpace(filePath) == "" {
670
- c.AbortWithStatus(http.StatusNotFound)
671
- return
 
672
  }
 
673
  if _, err := os.Stat(filePath); err != nil {
674
- if os.IsNotExist(err) {
675
- go managementasset.EnsureLatestManagementHTML(context.Background(), managementasset.StaticDir(s.configFilePath), cfg.ProxyURL, cfg.RemoteManagement.PanelGitHubRepository)
676
- c.AbortWithStatus(http.StatusNotFound)
677
- return
678
- }
679
- log.WithError(err).Error("failed to stat management control panel asset")
680
- c.AbortWithStatus(http.StatusInternalServerError)
681
  return
682
  }
683
- // Direct fallback: serve management.html from memory if file access fails
684
  c.File(filePath)
685
  }
686
- }
687
 
688
  func (s *Server) enableKeepAlive(timeout time.Duration, onTimeout func()) {
689
  if timeout <= 0 || onTimeout == nil {
 
361
  s.engine.POST("/api/event_logging/batch", func(c *gin.Context) {
362
  c.JSON(http.StatusOK, gin.H{"status": "ok"})
363
  })
364
+ // Add catch-all for provider-specific event logging
365
+ s.engine.POST("/api/provider/:provider/api/event_logging/batch", func(c *gin.Context) {
366
+ c.JSON(http.StatusOK, gin.H{"status": "ok"})
367
+ })
368
  s.engine.POST("/v1internal:method", geminiCLIHandlers.CLIHandler)
369
 
370
  // OAuth callback endpoints (reuse main server port)
 
552
  mgmt.PATCH("/gemini-api-key", s.mgmt.PatchGeminiKey)
553
  mgmt.DELETE("/gemini-api-key", s.mgmt.DeleteGeminiKey)
554
 
555
+ mgmt.GET("/logs-max-total-size-mb", s.mgmt.GetLogsMaxTotalSizeMb)
556
+ mgmt.PUT("/logs-max-total-size-mb", s.mgmt.PutLogsMaxTotalSizeMb)
557
+ mgmt.PATCH("/logs-max-total-size-mb", s.mgmt.PutLogsMaxTotalSizeMb)
558
+
559
+ mgmt.GET("/routing/strategy", s.mgmt.GetRoutingStrategy)
560
+ mgmt.PUT("/routing/strategy", s.mgmt.PutRoutingStrategy)
561
+ mgmt.PATCH("/routing/strategy", s.mgmt.PutRoutingStrategy)
562
+
563
+ mgmt.GET("/force-model-prefix", s.mgmt.GetForceModelPrefix)
564
+ mgmt.PUT("/force-model-prefix", s.mgmt.PutForceModelPrefix)
565
+ mgmt.PATCH("/force-model-prefix", s.mgmt.PutForceModelPrefix)
566
+
567
  mgmt.GET("/logs", s.mgmt.GetLogs)
568
  mgmt.DELETE("/logs", s.mgmt.DeleteLogs)
569
  mgmt.GET("/request-error-logs", s.mgmt.GetRequestErrorLogs)
 
681
  // Direct fallback: serve management.html from memory if file access fails
682
  c.File(filePath)
683
  }
684
+
685
+ func (s *Server) serveStatusPage(c *gin.Context) {
686
+ staticPath := os.Getenv("MANAGEMENT_STATIC_PATH")
687
+ if staticPath == "" {
688
+ staticPath = filepath.Join(s.currentPath, "static")
689
  }
690
+ filePath := filepath.Join(staticPath, "status.html")
691
  if _, err := os.Stat(filePath); err != nil {
692
+ c.AbortWithStatus(http.StatusNotFound)
 
 
 
 
 
 
693
  return
694
  }
 
695
  c.File(filePath)
696
  }
 
697
 
698
  func (s *Server) enableKeepAlive(timeout time.Duration, onTimeout func()) {
699
  if timeout <= 0 || onTimeout == nil {
internal/registry/model_definitions.go CHANGED
@@ -85,6 +85,17 @@ func GetClaudeModels() []*ModelInfo {
85
  MaxCompletionTokens: 8192,
86
  Thinking: &ThinkingSupport{Min: 1024, Max: 100000, ZeroAllowed: false, DynamicAllowed: true},
87
  },
 
 
 
 
 
 
 
 
 
 
 
88
  {
89
  ID: "claude-3-5-haiku-20241022",
90
  Object: "model",
@@ -192,6 +203,34 @@ func GetGeminiModels() []*ModelInfo {
192
  SupportedGenerationMethods: []string{"generateContent", "countTokens", "createCachedContent", "batchGenerateContent"},
193
  Thinking: &ThinkingSupport{Min: 128, Max: 32768, ZeroAllowed: false, DynamicAllowed: true, Levels: []string{"low", "high"}},
194
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
  }
196
  }
197
 
@@ -1104,6 +1143,17 @@ func GetKiroModels() []*ModelInfo {
1104
  MaxCompletionTokens: 64000,
1105
  Thinking: &ThinkingSupport{Min: 1024, Max: 32000, ZeroAllowed: true, DynamicAllowed: true},
1106
  },
 
 
 
 
 
 
 
 
 
 
 
1107
  }
1108
  }
1109
 
@@ -1166,5 +1216,15 @@ func GetAmazonQModels() []*ModelInfo {
1166
  ContextLength: 200000,
1167
  MaxCompletionTokens: 64000,
1168
  },
 
 
 
 
 
 
 
 
 
 
1169
  }
1170
  }
 
85
  MaxCompletionTokens: 8192,
86
  Thinking: &ThinkingSupport{Min: 1024, Max: 100000, ZeroAllowed: false, DynamicAllowed: true},
87
  },
88
+ {
89
+ ID: "claude-3-5-sonnet-20241022",
90
+ Object: "model",
91
+ Created: 1729555200, // 2024-10-22
92
+ OwnedBy: "anthropic",
93
+ Type: "claude",
94
+ DisplayName: "Claude 3.5 Sonnet",
95
+ ContextLength: 200000,
96
+ MaxCompletionTokens: 8192,
97
+ Thinking: &ThinkingSupport{Min: 1024, Max: 100000, ZeroAllowed: false, DynamicAllowed: true},
98
+ },
99
  {
100
  ID: "claude-3-5-haiku-20241022",
101
  Object: "model",
 
203
  SupportedGenerationMethods: []string{"generateContent", "countTokens", "createCachedContent", "batchGenerateContent"},
204
  Thinking: &ThinkingSupport{Min: 128, Max: 32768, ZeroAllowed: false, DynamicAllowed: true, Levels: []string{"low", "high"}},
205
  },
206
+ {
207
+ ID: "gemini-1.5-pro",
208
+ Object: "model",
209
+ Created: 1715644800,
210
+ OwnedBy: "google",
211
+ Type: "gemini",
212
+ Name: "models/gemini-1.5-pro",
213
+ Version: "1.5",
214
+ DisplayName: "Gemini 1.5 Pro",
215
+ Description: "Gemini 1.5 Pro reflects our latest research and engineering, including our work on multimodal large-scale training and our work in making models more efficient to serve while maintaining maximum quality.",
216
+ InputTokenLimit: 1048576,
217
+ OutputTokenLimit: 8192,
218
+ SupportedGenerationMethods: []string{"generateContent", "countTokens", "createCachedContent", "batchGenerateContent"},
219
+ },
220
+ {
221
+ ID: "gemini-1.5-flash",
222
+ Object: "model",
223
+ Created: 1715644800,
224
+ OwnedBy: "google",
225
+ Type: "gemini",
226
+ Name: "models/gemini-1.5-flash",
227
+ Version: "1.5",
228
+ DisplayName: "Gemini 1.5 Flash",
229
+ Description: "Fast and versatile multimodal model for scaling across a diverse range of tasks.",
230
+ InputTokenLimit: 1048576,
231
+ OutputTokenLimit: 8192,
232
+ SupportedGenerationMethods: []string{"generateContent", "countTokens", "createCachedContent", "batchGenerateContent"},
233
+ },
234
  }
235
  }
236
 
 
1143
  MaxCompletionTokens: 64000,
1144
  Thinking: &ThinkingSupport{Min: 1024, Max: 32000, ZeroAllowed: true, DynamicAllowed: true},
1145
  },
1146
+ {
1147
+ ID: "claude-3-5-sonnet-20241022",
1148
+ Object: "model",
1149
+ Created: 1729555200, // 2024-10-22
1150
+ OwnedBy: "aws",
1151
+ Type: "kiro",
1152
+ DisplayName: "Claude 3.5 Sonnet (via Kiro)",
1153
+ ContextLength: 200000,
1154
+ MaxCompletionTokens: 8192,
1155
+ Thinking: &ThinkingSupport{Min: 1024, Max: 32000, ZeroAllowed: true, DynamicAllowed: true},
1156
+ },
1157
  }
1158
  }
1159
 
 
1216
  ContextLength: 200000,
1217
  MaxCompletionTokens: 64000,
1218
  },
1219
+ {
1220
+ ID: "claude-3-5-sonnet-20241022",
1221
+ Object: "model",
1222
+ Created: 1729555200,
1223
+ OwnedBy: "aws",
1224
+ Type: "kiro",
1225
+ DisplayName: "Claude 3.5 Sonnet (via Q)",
1226
+ ContextLength: 200000,
1227
+ MaxCompletionTokens: 8192,
1228
+ },
1229
  }
1230
  }
internal/runtime/executor/claude_executor.go CHANGED
@@ -116,7 +116,7 @@ func (e *ClaudeExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, r
116
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
117
  b, _ := io.ReadAll(httpResp.Body)
118
  appendAPIResponseChunk(ctx, e.cfg, b)
119
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
120
  err = statusErr{code: httpResp.StatusCode, msg: string(b)}
121
  if errClose := httpResp.Body.Close(); errClose != nil {
122
  log.Errorf("response body close error: %v", errClose)
@@ -228,7 +228,7 @@ func (e *ClaudeExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.A
228
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
229
  b, _ := io.ReadAll(httpResp.Body)
230
  appendAPIResponseChunk(ctx, e.cfg, b)
231
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
232
  if errClose := httpResp.Body.Close(); errClose != nil {
233
  log.Errorf("response body close error: %v", errClose)
234
  }
 
116
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
117
  b, _ := io.ReadAll(httpResp.Body)
118
  appendAPIResponseChunk(ctx, e.cfg, b)
119
+ log.Warnf("claude executor: upstream API error, status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
120
  err = statusErr{code: httpResp.StatusCode, msg: string(b)}
121
  if errClose := httpResp.Body.Close(); errClose != nil {
122
  log.Errorf("response body close error: %v", errClose)
 
228
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
229
  b, _ := io.ReadAll(httpResp.Body)
230
  appendAPIResponseChunk(ctx, e.cfg, b)
231
+ log.Warnf("claude executor: upstream API error, status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
232
  if errClose := httpResp.Body.Close(); errClose != nil {
233
  log.Errorf("response body close error: %v", errClose)
234
  }
internal/runtime/executor/codex_executor.go CHANGED
@@ -110,7 +110,7 @@ func (e *CodexExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, re
110
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
111
  b, _ := io.ReadAll(httpResp.Body)
112
  appendAPIResponseChunk(ctx, e.cfg, b)
113
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
114
  err = statusErr{code: httpResp.StatusCode, msg: string(b)}
115
  return resp, err
116
  }
@@ -218,7 +218,7 @@ func (e *CodexExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Au
218
  return nil, readErr
219
  }
220
  appendAPIResponseChunk(ctx, e.cfg, data)
221
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), data))
222
  err = statusErr{code: httpResp.StatusCode, msg: string(data)}
223
  return nil, err
224
  }
 
110
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
111
  b, _ := io.ReadAll(httpResp.Body)
112
  appendAPIResponseChunk(ctx, e.cfg, b)
113
+ log.Warnf("codex executor: upstream API error, status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
114
  err = statusErr{code: httpResp.StatusCode, msg: string(b)}
115
  return resp, err
116
  }
 
218
  return nil, readErr
219
  }
220
  appendAPIResponseChunk(ctx, e.cfg, data)
221
+ log.Warnf("codex executor: upstream API error (stream), status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), data))
222
  err = statusErr{code: httpResp.StatusCode, msg: string(data)}
223
  return nil, err
224
  }
internal/runtime/executor/gemini_cli_executor.go CHANGED
@@ -186,7 +186,7 @@ func (e *GeminiCLIExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth
186
 
187
  lastStatus = httpResp.StatusCode
188
  lastBody = append([]byte(nil), data...)
189
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), data))
190
  if httpResp.StatusCode == 429 {
191
  if idx+1 < len(models) {
192
  log.Debugf("gemini cli executor: rate limited, retrying with next model: %s", models[idx+1])
@@ -313,7 +313,7 @@ func (e *GeminiCLIExecutor) ExecuteStream(ctx context.Context, auth *cliproxyaut
313
  appendAPIResponseChunk(ctx, e.cfg, data)
314
  lastStatus = httpResp.StatusCode
315
  lastBody = append([]byte(nil), data...)
316
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), data))
317
  if httpResp.StatusCode == 429 {
318
  if idx+1 < len(models) {
319
  log.Debugf("gemini cli executor: rate limited, retrying with next model: %s", models[idx+1])
 
186
 
187
  lastStatus = httpResp.StatusCode
188
  lastBody = append([]byte(nil), data...)
189
+ log.Warnf("gemini-cli executor: upstream API error, status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), data))
190
  if httpResp.StatusCode == 429 {
191
  if idx+1 < len(models) {
192
  log.Debugf("gemini cli executor: rate limited, retrying with next model: %s", models[idx+1])
 
313
  appendAPIResponseChunk(ctx, e.cfg, data)
314
  lastStatus = httpResp.StatusCode
315
  lastBody = append([]byte(nil), data...)
316
+ log.Warnf("gemini-cli executor: upstream API error, status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), data))
317
  if httpResp.StatusCode == 429 {
318
  if idx+1 < len(models) {
319
  log.Debugf("gemini cli executor: rate limited, retrying with next model: %s", models[idx+1])
internal/runtime/executor/gemini_executor.go CHANGED
@@ -157,7 +157,7 @@ func (e *GeminiExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, r
157
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
158
  b, _ := io.ReadAll(httpResp.Body)
159
  appendAPIResponseChunk(ctx, e.cfg, b)
160
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
161
  err = statusErr{code: httpResp.StatusCode, msg: string(b)}
162
  return resp, err
163
  }
@@ -251,12 +251,8 @@ func (e *GeminiExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.A
251
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
252
  b, _ := io.ReadAll(httpResp.Body)
253
  appendAPIResponseChunk(ctx, e.cfg, b)
254
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
255
- if errClose := httpResp.Body.Close(); errClose != nil {
256
- log.Errorf("gemini executor: close response body error: %v", errClose)
257
- }
258
- err = statusErr{code: httpResp.StatusCode, msg: string(b)}
259
- return nil, err
260
  }
261
  out := make(chan cliproxyexecutor.StreamChunk)
262
  stream = out
@@ -370,7 +366,7 @@ func (e *GeminiExecutor) CountTokens(ctx context.Context, auth *cliproxyauth.Aut
370
  }
371
  appendAPIResponseChunk(ctx, e.cfg, data)
372
  if resp.StatusCode < 200 || resp.StatusCode >= 300 {
373
- log.Debugf("request error, error status: %d, error body: %s", resp.StatusCode, summarizeErrorBody(resp.Header.Get("Content-Type"), data))
374
  return cliproxyexecutor.Response{}, statusErr{code: resp.StatusCode, msg: string(data)}
375
  }
376
 
 
157
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
158
  b, _ := io.ReadAll(httpResp.Body)
159
  appendAPIResponseChunk(ctx, e.cfg, b)
160
+ log.Warnf("gemini executor: upstream API error, status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
161
  err = statusErr{code: httpResp.StatusCode, msg: string(b)}
162
  return resp, err
163
  }
 
251
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
252
  b, _ := io.ReadAll(httpResp.Body)
253
  appendAPIResponseChunk(ctx, e.cfg, b)
254
+ log.Warnf("gemini executor: upstream API error (stream), status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
255
+ return nil, statusErr{code: httpResp.StatusCode, msg: string(b)}
 
 
 
 
256
  }
257
  out := make(chan cliproxyexecutor.StreamChunk)
258
  stream = out
 
366
  }
367
  appendAPIResponseChunk(ctx, e.cfg, data)
368
  if resp.StatusCode < 200 || resp.StatusCode >= 300 {
369
+ log.Warnf("gemini executor: upstream API error, status: %d, body: %s", resp.StatusCode, summarizeErrorBody(resp.Header.Get("Content-Type"), data))
370
  return cliproxyexecutor.Response{}, statusErr{code: resp.StatusCode, msg: string(data)}
371
  }
372
 
internal/runtime/executor/gemini_vertex_executor.go CHANGED
@@ -201,7 +201,7 @@ func (e *GeminiVertexExecutor) executeWithServiceAccount(ctx context.Context, au
201
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
202
  b, _ := io.ReadAll(httpResp.Body)
203
  appendAPIResponseChunk(ctx, e.cfg, b)
204
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
205
  err = statusErr{code: httpResp.StatusCode, msg: string(b)}
206
  return resp, err
207
  }
@@ -310,7 +310,7 @@ func (e *GeminiVertexExecutor) executeWithAPIKey(ctx context.Context, auth *clip
310
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
311
  b, _ := io.ReadAll(httpResp.Body)
312
  appendAPIResponseChunk(ctx, e.cfg, b)
313
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
314
  err = statusErr{code: httpResp.StatusCode, msg: string(b)}
315
  return resp, err
316
  }
@@ -404,7 +404,7 @@ func (e *GeminiVertexExecutor) executeStreamWithServiceAccount(ctx context.Conte
404
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
405
  b, _ := io.ReadAll(httpResp.Body)
406
  appendAPIResponseChunk(ctx, e.cfg, b)
407
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
408
  if errClose := httpResp.Body.Close(); errClose != nil {
409
  log.Errorf("vertex executor: close response body error: %v", errClose)
410
  }
@@ -529,7 +529,7 @@ func (e *GeminiVertexExecutor) executeStreamWithAPIKey(ctx context.Context, auth
529
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
530
  b, _ := io.ReadAll(httpResp.Body)
531
  appendAPIResponseChunk(ctx, e.cfg, b)
532
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
533
  if errClose := httpResp.Body.Close(); errClose != nil {
534
  log.Errorf("vertex executor: close response body error: %v", errClose)
535
  }
@@ -641,7 +641,7 @@ func (e *GeminiVertexExecutor) countTokensWithServiceAccount(ctx context.Context
641
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
642
  b, _ := io.ReadAll(httpResp.Body)
643
  appendAPIResponseChunk(ctx, e.cfg, b)
644
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
645
  return cliproxyexecutor.Response{}, statusErr{code: httpResp.StatusCode, msg: string(b)}
646
  }
647
  data, errRead := io.ReadAll(httpResp.Body)
@@ -651,7 +651,7 @@ func (e *GeminiVertexExecutor) countTokensWithServiceAccount(ctx context.Context
651
  }
652
  appendAPIResponseChunk(ctx, e.cfg, data)
653
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
654
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), data))
655
  return cliproxyexecutor.Response{}, statusErr{code: httpResp.StatusCode, msg: string(data)}
656
  }
657
  count := gjson.GetBytes(data, "totalTokens").Int()
@@ -733,7 +733,7 @@ func (e *GeminiVertexExecutor) countTokensWithAPIKey(ctx context.Context, auth *
733
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
734
  b, _ := io.ReadAll(httpResp.Body)
735
  appendAPIResponseChunk(ctx, e.cfg, b)
736
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
737
  return cliproxyexecutor.Response{}, statusErr{code: httpResp.StatusCode, msg: string(b)}
738
  }
739
  data, errRead := io.ReadAll(httpResp.Body)
@@ -743,7 +743,7 @@ func (e *GeminiVertexExecutor) countTokensWithAPIKey(ctx context.Context, auth *
743
  }
744
  appendAPIResponseChunk(ctx, e.cfg, data)
745
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
746
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), data))
747
  return cliproxyexecutor.Response{}, statusErr{code: httpResp.StatusCode, msg: string(data)}
748
  }
749
  count := gjson.GetBytes(data, "totalTokens").Int()
 
201
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
202
  b, _ := io.ReadAll(httpResp.Body)
203
  appendAPIResponseChunk(ctx, e.cfg, b)
204
+ log.Warnf("gemini-vertex executor: upstream API error, status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
205
  err = statusErr{code: httpResp.StatusCode, msg: string(b)}
206
  return resp, err
207
  }
 
310
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
311
  b, _ := io.ReadAll(httpResp.Body)
312
  appendAPIResponseChunk(ctx, e.cfg, b)
313
+ log.Warnf("gemini-vertex executor: upstream API error, status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
314
  err = statusErr{code: httpResp.StatusCode, msg: string(b)}
315
  return resp, err
316
  }
 
404
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
405
  b, _ := io.ReadAll(httpResp.Body)
406
  appendAPIResponseChunk(ctx, e.cfg, b)
407
+ log.Warnf("gemini-vertex executor: upstream API error, status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
408
  if errClose := httpResp.Body.Close(); errClose != nil {
409
  log.Errorf("vertex executor: close response body error: %v", errClose)
410
  }
 
529
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
530
  b, _ := io.ReadAll(httpResp.Body)
531
  appendAPIResponseChunk(ctx, e.cfg, b)
532
+ log.Warnf("gemini-vertex executor: upstream API error, status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
533
  if errClose := httpResp.Body.Close(); errClose != nil {
534
  log.Errorf("vertex executor: close response body error: %v", errClose)
535
  }
 
641
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
642
  b, _ := io.ReadAll(httpResp.Body)
643
  appendAPIResponseChunk(ctx, e.cfg, b)
644
+ log.Warnf("gemini-vertex executor: upstream API error, status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
645
  return cliproxyexecutor.Response{}, statusErr{code: httpResp.StatusCode, msg: string(b)}
646
  }
647
  data, errRead := io.ReadAll(httpResp.Body)
 
651
  }
652
  appendAPIResponseChunk(ctx, e.cfg, data)
653
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
654
+ log.Warnf("gemini-vertex executor: upstream API error, status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), data))
655
  return cliproxyexecutor.Response{}, statusErr{code: httpResp.StatusCode, msg: string(data)}
656
  }
657
  count := gjson.GetBytes(data, "totalTokens").Int()
 
733
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
734
  b, _ := io.ReadAll(httpResp.Body)
735
  appendAPIResponseChunk(ctx, e.cfg, b)
736
+ log.Warnf("gemini-vertex executor: upstream API error, status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
737
  return cliproxyexecutor.Response{}, statusErr{code: httpResp.StatusCode, msg: string(b)}
738
  }
739
  data, errRead := io.ReadAll(httpResp.Body)
 
743
  }
744
  appendAPIResponseChunk(ctx, e.cfg, data)
745
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
746
+ log.Warnf("gemini-vertex executor: upstream API error, status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), data))
747
  return cliproxyexecutor.Response{}, statusErr{code: httpResp.StatusCode, msg: string(data)}
748
  }
749
  count := gjson.GetBytes(data, "totalTokens").Int()
internal/runtime/executor/openai_compat_executor.go CHANGED
@@ -119,7 +119,7 @@ func (e *OpenAICompatExecutor) Execute(ctx context.Context, auth *cliproxyauth.A
119
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
120
  b, _ := io.ReadAll(httpResp.Body)
121
  appendAPIResponseChunk(ctx, e.cfg, b)
122
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
123
  err = statusErr{code: httpResp.StatusCode, msg: string(b)}
124
  return resp, err
125
  }
@@ -213,7 +213,7 @@ func (e *OpenAICompatExecutor) ExecuteStream(ctx context.Context, auth *cliproxy
213
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
214
  b, _ := io.ReadAll(httpResp.Body)
215
  appendAPIResponseChunk(ctx, e.cfg, b)
216
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
217
  if errClose := httpResp.Body.Close(); errClose != nil {
218
  log.Errorf("openai compat executor: close response body error: %v", errClose)
219
  }
 
119
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
120
  b, _ := io.ReadAll(httpResp.Body)
121
  appendAPIResponseChunk(ctx, e.cfg, b)
122
+ log.Warnf("openai-compat executor: upstream API error, status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
123
  err = statusErr{code: httpResp.StatusCode, msg: string(b)}
124
  return resp, err
125
  }
 
213
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
214
  b, _ := io.ReadAll(httpResp.Body)
215
  appendAPIResponseChunk(ctx, e.cfg, b)
216
+ log.Warnf("openai-compat executor: upstream API error, status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
217
  if errClose := httpResp.Body.Close(); errClose != nil {
218
  log.Errorf("openai compat executor: close response body error: %v", errClose)
219
  }
internal/runtime/executor/qwen_executor.go CHANGED
@@ -102,7 +102,7 @@ func (e *QwenExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, req
102
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
103
  b, _ := io.ReadAll(httpResp.Body)
104
  appendAPIResponseChunk(ctx, e.cfg, b)
105
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
106
  err = statusErr{code: httpResp.StatusCode, msg: string(b)}
107
  return resp, err
108
  }
@@ -186,7 +186,7 @@ func (e *QwenExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Aut
186
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
187
  b, _ := io.ReadAll(httpResp.Body)
188
  appendAPIResponseChunk(ctx, e.cfg, b)
189
- log.Debugf("request error, error status: %d, error body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
190
  if errClose := httpResp.Body.Close(); errClose != nil {
191
  log.Errorf("qwen executor: close response body error: %v", errClose)
192
  }
 
102
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
103
  b, _ := io.ReadAll(httpResp.Body)
104
  appendAPIResponseChunk(ctx, e.cfg, b)
105
+ log.Warnf("qwen executor: upstream API error, status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
106
  err = statusErr{code: httpResp.StatusCode, msg: string(b)}
107
  return resp, err
108
  }
 
186
  if httpResp.StatusCode < 200 || httpResp.StatusCode >= 300 {
187
  b, _ := io.ReadAll(httpResp.Body)
188
  appendAPIResponseChunk(ctx, e.cfg, b)
189
+ log.Warnf("qwen executor: upstream API error, status: %d, body: %s", httpResp.StatusCode, summarizeErrorBody(httpResp.Header.Get("Content-Type"), b))
190
  if errClose := httpResp.Body.Close(); errClose != nil {
191
  log.Errorf("qwen executor: close response body error: %v", errClose)
192
  }
static/management.html CHANGED
The diff for this file is too large to render. See raw diff