focusprogram commited on
Commit
de01b62
·
1 Parent(s): b083533
Dockerfile ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM golang:alpine AS builder
2
+
3
+ WORKDIR /app
4
+ COPY . .
5
+
6
+ ENV GO111MODULE=on GOPROXY=https://goproxy.cn,direct
7
+ RUN go mod download
8
+
9
+ RUN CGO_ENABLED=0 go build -ldflags="-w -s" -o override
10
+
11
+ FROM alpine:latest
12
+
13
+ RUN apk --no-cache add ca-certificates
14
+
15
+ COPY --from=builder /app/override /usr/local/bin/
16
+ COPY config.json.example /app/config.json
17
+
18
+ WORKDIR /app
19
+ VOLUME /app
20
+
21
+ EXPOSE 8181
22
+ CMD ["override"]
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2024 LINUX DO
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md CHANGED
@@ -5,6 +5,7 @@ colorFrom: green
5
  colorTo: green
6
  sdk: docker
7
  pinned: false
 
8
  ---
9
 
10
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
5
  colorTo: green
6
  sdk: docker
7
  pinned: false
8
+ app_port: 8181
9
  ---
10
 
11
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
config.json ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bind": "0.0.0.0:8181",
3
+ "proxy_url": "",
4
+ "timeout": 600,
5
+ "codex_api_base": "https://api.deepseek.com/beta/v1",
6
+ "codex_api_key": "",
7
+ "codex_api_organization": "",
8
+ "codex_api_project": "",
9
+ "codex_max_tokens": 500,
10
+ "code_instruct_model": "deepseek-coder",
11
+ "chat_api_base": "https://api.deepseek.com/v1",
12
+ "chat_api_key": "",
13
+ "chat_api_organization": "",
14
+ "chat_api_project": "",
15
+ "chat_max_tokens": 4096,
16
+ "chat_model_default": "deepseek-chat",
17
+ "chat_model_map": {},
18
+ "chat_locale": "zh_CN",
19
+ "auth_token": ""
20
+ }
config.json.example ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bind": "127.0.0.1:8181",
3
+ "proxy_url": "",
4
+ "timeout": 600,
5
+ "codex_api_base": "https://api-proxy.oaipro.com/v1",
6
+ "codex_api_key": "sk-xxx",
7
+ "codex_api_organization": "",
8
+ "codex_api_project": "",
9
+ "codex_max_tokens": 500,
10
+ "code_instruct_model": "gpt-3.5-turbo-instruct",
11
+ "chat_api_base": "https://api-proxy.oaipro.com/v1",
12
+ "chat_api_key": "sk-xxx",
13
+ "chat_api_organization": "",
14
+ "chat_api_project": "",
15
+ "chat_max_tokens": 4096,
16
+ "chat_model_default": "gpt-4o",
17
+ "chat_model_map": {},
18
+ "chat_locale": "zh_CN",
19
+ "auth_token": ""
20
+ }
docker-compose.yml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ services:
2
+ override-app:
3
+ image: linux-do/override:latest
4
+ container_name: override-app
5
+ restart: always
6
+ build:
7
+ context: .
8
+ dockerfile: Dockerfile
9
+ volumes:
10
+ - ./config.json:/app/config.json
11
+ ports:
12
+ - "8181:8181"
go.mod ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ module override
2
+
3
+ go 1.21
4
+
5
+ toolchain go1.21.4
6
+
7
+ require (
8
+ github.com/gin-gonic/gin v1.10.0
9
+ github.com/tidwall/gjson v1.17.1
10
+ github.com/tidwall/sjson v1.2.5
11
+ golang.org/x/net v0.25.0
12
+ )
13
+
14
+ require (
15
+ github.com/bytedance/sonic v1.11.6 // indirect
16
+ github.com/bytedance/sonic/loader v0.1.1 // indirect
17
+ github.com/cloudwego/base64x v0.1.4 // indirect
18
+ github.com/cloudwego/iasm v0.2.0 // indirect
19
+ github.com/gabriel-vasile/mimetype v1.4.3 // indirect
20
+ github.com/gin-contrib/sse v0.1.0 // indirect
21
+ github.com/go-playground/locales v0.14.1 // indirect
22
+ github.com/go-playground/universal-translator v0.18.1 // indirect
23
+ github.com/go-playground/validator/v10 v10.20.0 // indirect
24
+ github.com/goccy/go-json v0.10.2 // indirect
25
+ github.com/google/go-cmp v0.5.9 // indirect
26
+ github.com/json-iterator/go v1.1.12 // indirect
27
+ github.com/klauspost/cpuid/v2 v2.2.7 // indirect
28
+ github.com/kr/pretty v0.3.0 // indirect
29
+ github.com/leodido/go-urn v1.4.0 // indirect
30
+ github.com/mattn/go-isatty v0.0.20 // indirect
31
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
32
+ github.com/modern-go/reflect2 v1.0.2 // indirect
33
+ github.com/pelletier/go-toml/v2 v2.2.2 // indirect
34
+ github.com/rogpeppe/go-internal v1.12.0 // indirect
35
+ github.com/tidwall/match v1.1.1 // indirect
36
+ github.com/tidwall/pretty v1.2.1 // indirect
37
+ github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
38
+ github.com/ugorji/go/codec v1.2.12 // indirect
39
+ golang.org/x/arch v0.8.0 // indirect
40
+ golang.org/x/crypto v0.23.0 // indirect
41
+ golang.org/x/sys v0.20.0 // indirect
42
+ golang.org/x/text v0.15.0 // indirect
43
+ google.golang.org/protobuf v1.34.1 // indirect
44
+ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
45
+ gopkg.in/yaml.v3 v3.0.1 // indirect
46
+ )
go.sum ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
2
+ github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
3
+ github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
4
+ github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
5
+ github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
6
+ github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
7
+ github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
8
+ github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
9
+ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
10
+ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
11
+ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
12
+ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
13
+ github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
14
+ github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
15
+ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
16
+ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
17
+ github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
18
+ github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
19
+ github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
20
+ github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
21
+ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
22
+ github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
23
+ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
24
+ github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
25
+ github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
26
+ github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
27
+ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
28
+ github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
29
+ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
30
+ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
31
+ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
32
+ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
33
+ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
34
+ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
35
+ github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
36
+ github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
37
+ github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
38
+ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
39
+ github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
40
+ github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
41
+ github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
42
+ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
43
+ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
44
+ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
45
+ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
46
+ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
47
+ github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
48
+ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
49
+ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
50
+ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
51
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
52
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
53
+ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
54
+ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
55
+ github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
56
+ github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
57
+ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
58
+ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
59
+ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
60
+ github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
61
+ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
62
+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
63
+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
64
+ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
65
+ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
66
+ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
67
+ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
68
+ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
69
+ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
70
+ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
71
+ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
72
+ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
73
+ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
74
+ github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
75
+ github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
76
+ github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
77
+ github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
78
+ github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
79
+ github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
80
+ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
81
+ github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
82
+ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
83
+ github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
84
+ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
85
+ github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
86
+ github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
87
+ github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
88
+ golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
89
+ golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
90
+ golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
91
+ golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
92
+ golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
93
+ golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
94
+ golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
95
+ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
96
+ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
97
+ golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
98
+ golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
99
+ golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
100
+ golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
101
+ google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
102
+ google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
103
+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
104
+ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
105
+ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
106
+ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
107
+ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
108
+ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
109
+ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
110
+ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
111
+ nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
112
+ rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
main.go ADDED
@@ -0,0 +1,548 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ package main
2
+
3
+ import (
4
+ "bytes"
5
+ "context"
6
+ "encoding/json"
7
+ "errors"
8
+ "fmt"
9
+ "github.com/gin-gonic/gin"
10
+ "github.com/tidwall/gjson"
11
+ "github.com/tidwall/sjson"
12
+ "golang.org/x/net/http2"
13
+ "io"
14
+ "log"
15
+ "net/http"
16
+ "net/url"
17
+ "os"
18
+ "reflect"
19
+ "strconv"
20
+ "strings"
21
+ "time"
22
+ )
23
+
24
+ const DefaultInstructModel = "gpt-3.5-turbo-instruct"
25
+
26
+ const StableCodeModelPrefix = "stable-code"
27
+
28
+ const DeepSeekCoderModel = "deepseek-coder"
29
+
30
+ type config struct {
31
+ Bind string `json:"bind"`
32
+ ProxyUrl string `json:"proxy_url"`
33
+ Timeout int `json:"timeout"`
34
+ CodexApiBase string `json:"codex_api_base"`
35
+ CodexApiKey string `json:"codex_api_key"`
36
+ CodexApiOrganization string `json:"codex_api_organization"`
37
+ CodexApiProject string `json:"codex_api_project"`
38
+ CodexMaxTokens int `json:"codex_max_tokens"`
39
+ CodeInstructModel string `json:"code_instruct_model"`
40
+ ChatApiBase string `json:"chat_api_base"`
41
+ ChatApiKey string `json:"chat_api_key"`
42
+ ChatApiOrganization string `json:"chat_api_organization"`
43
+ ChatApiProject string `json:"chat_api_project"`
44
+ ChatMaxTokens int `json:"chat_max_tokens"`
45
+ ChatModelDefault string `json:"chat_model_default"`
46
+ ChatModelMap map[string]string `json:"chat_model_map"`
47
+ ChatLocale string `json:"chat_locale"`
48
+ AuthToken string `json:"auth_token"`
49
+ }
50
+
51
+ func readConfig() *config {
52
+ content, err := os.ReadFile("config.json")
53
+ if nil != err {
54
+ log.Fatal(err)
55
+ }
56
+
57
+ _cfg := &config{}
58
+ err = json.Unmarshal(content, &_cfg)
59
+ if nil != err {
60
+ log.Fatal(err)
61
+ }
62
+
63
+ v := reflect.ValueOf(_cfg).Elem()
64
+ t := v.Type()
65
+
66
+ for i := 0; i < v.NumField(); i++ {
67
+ field := v.Field(i)
68
+ tag := t.Field(i).Tag.Get("json")
69
+ if tag == "" {
70
+ continue
71
+ }
72
+
73
+ value, exists := os.LookupEnv("OVERRIDE_" + strings.ToUpper(tag))
74
+ if !exists {
75
+ continue
76
+ }
77
+
78
+ switch field.Kind() {
79
+ case reflect.String:
80
+ field.SetString(value)
81
+ case reflect.Bool:
82
+ if boolValue, err := strconv.ParseBool(value); err == nil {
83
+ field.SetBool(boolValue)
84
+ }
85
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
86
+ if intValue, err := strconv.ParseInt(value, 10, 64); err == nil {
87
+ field.SetInt(intValue)
88
+ }
89
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
90
+ if uintValue, err := strconv.ParseUint(value, 10, 64); err == nil {
91
+ field.SetUint(uintValue)
92
+ }
93
+ case reflect.Float32, reflect.Float64:
94
+ if floatValue, err := strconv.ParseFloat(value, field.Type().Bits()); err == nil {
95
+ field.SetFloat(floatValue)
96
+ }
97
+ }
98
+ }
99
+ if _cfg.CodeInstructModel == "" {
100
+ _cfg.CodeInstructModel = DefaultInstructModel
101
+ }
102
+
103
+ if _cfg.CodexMaxTokens == 0 {
104
+ _cfg.CodexMaxTokens = 500
105
+ }
106
+
107
+ if _cfg.ChatMaxTokens == 0 {
108
+ _cfg.ChatMaxTokens = 4096
109
+ }
110
+
111
+ return _cfg
112
+ }
113
+
114
+ func getClient(cfg *config) (*http.Client, error) {
115
+ transport := &http.Transport{
116
+ ForceAttemptHTTP2: true,
117
+ DisableKeepAlives: false,
118
+ }
119
+
120
+ err := http2.ConfigureTransport(transport)
121
+ if nil != err {
122
+ return nil, err
123
+ }
124
+
125
+ if "" != cfg.ProxyUrl {
126
+ proxyUrl, err := url.Parse(cfg.ProxyUrl)
127
+ if nil != err {
128
+ return nil, err
129
+ }
130
+
131
+ transport.Proxy = http.ProxyURL(proxyUrl)
132
+ }
133
+
134
+ client := &http.Client{
135
+ Transport: transport,
136
+ Timeout: time.Duration(cfg.Timeout) * time.Second,
137
+ }
138
+
139
+ return client, nil
140
+ }
141
+
142
+ func abortCodex(c *gin.Context, status int) {
143
+ c.Header("Content-Type", "text/event-stream")
144
+
145
+ c.String(status, "data: [DONE]\n")
146
+ c.Abort()
147
+ }
148
+
149
+ func closeIO(c io.Closer) {
150
+ err := c.Close()
151
+ if nil != err {
152
+ log.Println(err)
153
+ }
154
+ }
155
+
156
+ type ProxyService struct {
157
+ cfg *config
158
+ client *http.Client
159
+ }
160
+
161
+ func NewProxyService(cfg *config) (*ProxyService, error) {
162
+ client, err := getClient(cfg)
163
+ if nil != err {
164
+ return nil, err
165
+ }
166
+
167
+ return &ProxyService{
168
+ cfg: cfg,
169
+ client: client,
170
+ }, nil
171
+ }
172
+ func AuthMiddleware(authToken string) gin.HandlerFunc {
173
+ return func(c *gin.Context) {
174
+ token := c.Param("token")
175
+ if token != authToken {
176
+ c.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
177
+ c.Abort()
178
+ return
179
+ }
180
+ c.Next()
181
+ }
182
+ }
183
+
184
+ func (s *ProxyService) InitRoutes(e *gin.Engine) {
185
+ e.GET("/_ping", s.pong)
186
+ e.GET("/models", s.models)
187
+ e.GET("/v1/models", s.models)
188
+ authToken := s.cfg.AuthToken // replace with your dynamic value as needed
189
+ if authToken != "" {
190
+ // 鉴权
191
+ v1 := e.Group("/:token/v1/", AuthMiddleware(authToken))
192
+ {
193
+ v1.POST("/chat/completions", s.completions)
194
+ v1.POST("/engines/copilot-codex/completions", s.codeCompletions)
195
+
196
+ v1.POST("/v1/chat/completions", s.completions)
197
+ v1.POST("/v1/engines/copilot-codex/completions", s.codeCompletions)
198
+ }
199
+ } else {
200
+ e.POST("/v1/chat/completions", s.completions)
201
+ e.POST("/v1/engines/copilot-codex/completions", s.codeCompletions)
202
+
203
+ e.POST("/v1/v1/chat/completions", s.completions)
204
+ e.POST("/v1/v1/engines/copilot-codex/completions", s.codeCompletions)
205
+ }
206
+ }
207
+
208
+ type Pong struct {
209
+ Now int `json:"now"`
210
+ Status string `json:"status"`
211
+ Ns1 string `json:"ns1"`
212
+ }
213
+
214
+ func (s *ProxyService) pong(c *gin.Context) {
215
+ c.JSON(http.StatusOK, Pong{
216
+ Now: time.Now().Second(),
217
+ Status: "ok",
218
+ Ns1: "200 OK",
219
+ })
220
+ }
221
+
222
+ func (s *ProxyService) models(c *gin.Context) {
223
+ c.JSON(http.StatusOK, gin.H{
224
+ "data": []gin.H{
225
+ {
226
+ "capabilities": gin.H{
227
+ "family": "gpt-3.5-turbo",
228
+ "object": "model_capabilities",
229
+ "type": "chat",
230
+ },
231
+ "id": "gpt-3.5-turbo",
232
+ "name": "GPT 3.5 Turbo",
233
+ "object": "model",
234
+ "version": "gpt-3.5-turbo-0613",
235
+ },
236
+ {
237
+ "capabilities": gin.H{
238
+ "family": "gpt-3.5-turbo",
239
+ "object": "model_capabilities",
240
+ "type": "chat",
241
+ },
242
+ "id": "gpt-3.5-turbo-0613",
243
+ "name": "GPT 3.5 Turbo (2023-06-13)",
244
+ "object": "model",
245
+ "version": "gpt-3.5-turbo-0613",
246
+ },
247
+ {
248
+ "capabilities": gin.H{
249
+ "family": "gpt-4",
250
+ "object": "model_capabilities",
251
+ "type": "chat",
252
+ },
253
+ "id": "gpt-4",
254
+ "name": "GPT 4",
255
+ "object": "model",
256
+ "version": "gpt-4-0613",
257
+ },
258
+ {
259
+ "capabilities": gin.H{
260
+ "family": "gpt-4",
261
+ "object": "model_capabilities",
262
+ "type": "chat",
263
+ },
264
+ "id": "gpt-4-0613",
265
+ "name": "GPT 4 (2023-06-13)",
266
+ "object": "model",
267
+ "version": "gpt-4-0613",
268
+ },
269
+ {
270
+ "capabilities": gin.H{
271
+ "family": "gpt-4-turbo",
272
+ "object": "model_capabilities",
273
+ "type": "chat",
274
+ },
275
+ "id": "gpt-4-0125-preview",
276
+ "name": "GPT 4 Turbo (2024-01-25 Preview)",
277
+ "object": "model",
278
+ "version": "gpt-4-0125-preview",
279
+ },
280
+ {
281
+ "capabilities": gin.H{
282
+ "family": "text-embedding-ada-002",
283
+ "object": "model_capabilities",
284
+ "type": "embeddings",
285
+ },
286
+ "id": "text-embedding-ada-002",
287
+ "name": "Embedding V2 Ada",
288
+ "object": "model",
289
+ "version": "text-embedding-ada-002",
290
+ },
291
+ {
292
+ "capabilities": gin.H{
293
+ "family": "text-embedding-ada-002",
294
+ "object": "model_capabilities",
295
+ "type": "embeddings",
296
+ },
297
+ "id": "text-embedding-ada-002-index",
298
+ "name": "Embedding V2 Ada (Index)",
299
+ "object": "model",
300
+ "version": "text-embedding-ada-002",
301
+ },
302
+ {
303
+ "capabilities": gin.H{
304
+ "family": "text-embedding-3-small",
305
+ "object": "model_capabilities",
306
+ "type": "embeddings",
307
+ },
308
+ "id": "text-embedding-3-small",
309
+ "name": "Embedding V3 small",
310
+ "object": "model",
311
+ "version": "text-embedding-3-small",
312
+ },
313
+ {
314
+ "capabilities": gin.H{
315
+ "family": "text-embedding-3-small",
316
+ "object": "model_capabilities",
317
+ "type": "embeddings",
318
+ },
319
+ "id": "text-embedding-3-small-inference",
320
+ "name": "Embedding V3 small (Inference)",
321
+ "object": "model",
322
+ "version": "text-embedding-3-small",
323
+ },
324
+ },
325
+ "object": "list",
326
+ })
327
+ }
328
+
329
+ func (s *ProxyService) completions(c *gin.Context) {
330
+ ctx := c.Request.Context()
331
+
332
+ body, err := io.ReadAll(c.Request.Body)
333
+ if nil != err {
334
+ c.AbortWithStatus(http.StatusBadRequest)
335
+ return
336
+ }
337
+
338
+ model := gjson.GetBytes(body, "model").String()
339
+ if mapped, ok := s.cfg.ChatModelMap[model]; ok {
340
+ model = mapped
341
+ } else {
342
+ model = s.cfg.ChatModelDefault
343
+ }
344
+ body, _ = sjson.SetBytes(body, "model", model)
345
+
346
+ if !gjson.GetBytes(body, "function_call").Exists() {
347
+ messages := gjson.GetBytes(body, "messages").Array()
348
+ lastIndex := len(messages) - 1
349
+ if !strings.Contains(messages[lastIndex].Get("content").String(), "Respond in the following locale") {
350
+ locale := s.cfg.ChatLocale
351
+ if locale == "" {
352
+ locale = "zh_CN"
353
+ }
354
+ body, _ = sjson.SetBytes(body, "messages."+strconv.Itoa(lastIndex)+".content", messages[lastIndex].Get("content").String()+"Respond in the following locale: "+locale+".")
355
+ }
356
+ }
357
+
358
+ body, _ = sjson.DeleteBytes(body, "intent")
359
+ body, _ = sjson.DeleteBytes(body, "intent_threshold")
360
+ body, _ = sjson.DeleteBytes(body, "intent_content")
361
+
362
+ if int(gjson.GetBytes(body, "max_tokens").Int()) > s.cfg.ChatMaxTokens {
363
+ body, _ = sjson.SetBytes(body, "max_tokens", s.cfg.ChatMaxTokens)
364
+ }
365
+
366
+ proxyUrl := s.cfg.ChatApiBase + "/chat/completions"
367
+ req, err := http.NewRequestWithContext(ctx, http.MethodPost, proxyUrl, io.NopCloser(bytes.NewBuffer(body)))
368
+ if nil != err {
369
+ c.AbortWithStatus(http.StatusInternalServerError)
370
+ return
371
+ }
372
+
373
+ req.Header.Set("Content-Type", "application/json")
374
+ req.Header.Set("Authorization", "Bearer "+s.cfg.ChatApiKey)
375
+ if "" != s.cfg.ChatApiOrganization {
376
+ req.Header.Set("OpenAI-Organization", s.cfg.ChatApiOrganization)
377
+ }
378
+ if "" != s.cfg.ChatApiProject {
379
+ req.Header.Set("OpenAI-Project", s.cfg.ChatApiProject)
380
+ }
381
+
382
+ resp, err := s.client.Do(req)
383
+ if nil != err {
384
+ if errors.Is(err, context.Canceled) {
385
+ c.AbortWithStatus(http.StatusRequestTimeout)
386
+ return
387
+ }
388
+
389
+ log.Println("request conversation failed:", err.Error())
390
+ c.AbortWithStatus(http.StatusInternalServerError)
391
+ return
392
+ }
393
+ defer closeIO(resp.Body)
394
+
395
+ if resp.StatusCode != http.StatusOK { // log
396
+ body, _ := io.ReadAll(resp.Body)
397
+ log.Println("request completions failed:", string(body))
398
+
399
+ resp.Body = io.NopCloser(bytes.NewBuffer(body))
400
+ }
401
+
402
+ c.Status(resp.StatusCode)
403
+
404
+ contentType := resp.Header.Get("Content-Type")
405
+ if "" != contentType {
406
+ c.Header("Content-Type", contentType)
407
+ }
408
+
409
+ _, _ = io.Copy(c.Writer, resp.Body)
410
+ }
411
+
412
+ func (s *ProxyService) codeCompletions(c *gin.Context) {
413
+ ctx := c.Request.Context()
414
+
415
+ time.Sleep(200 * time.Millisecond)
416
+ if ctx.Err() != nil {
417
+ abortCodex(c, http.StatusRequestTimeout)
418
+ return
419
+ }
420
+
421
+ body, err := io.ReadAll(c.Request.Body)
422
+ if nil != err {
423
+ abortCodex(c, http.StatusBadRequest)
424
+ return
425
+ }
426
+
427
+ body = ConstructRequestBody(body, s.cfg)
428
+
429
+ proxyUrl := s.cfg.CodexApiBase + "/completions"
430
+ req, err := http.NewRequestWithContext(ctx, http.MethodPost, proxyUrl, io.NopCloser(bytes.NewBuffer(body)))
431
+ if nil != err {
432
+ abortCodex(c, http.StatusInternalServerError)
433
+ return
434
+ }
435
+
436
+ req.Header.Set("Content-Type", "application/json")
437
+ req.Header.Set("Authorization", "Bearer "+s.cfg.CodexApiKey)
438
+ if "" != s.cfg.CodexApiOrganization {
439
+ req.Header.Set("OpenAI-Organization", s.cfg.CodexApiOrganization)
440
+ }
441
+ if "" != s.cfg.CodexApiProject {
442
+ req.Header.Set("OpenAI-Project", s.cfg.CodexApiProject)
443
+ }
444
+
445
+ resp, err := s.client.Do(req)
446
+ if nil != err {
447
+ if errors.Is(err, context.Canceled) {
448
+ abortCodex(c, http.StatusRequestTimeout)
449
+ return
450
+ }
451
+
452
+ log.Println("request completions failed:", err.Error())
453
+ abortCodex(c, http.StatusInternalServerError)
454
+ return
455
+ }
456
+ defer closeIO(resp.Body)
457
+
458
+ if resp.StatusCode != http.StatusOK {
459
+ body, _ := io.ReadAll(resp.Body)
460
+ log.Println("request completions failed:", string(body))
461
+
462
+ abortCodex(c, resp.StatusCode)
463
+ return
464
+ }
465
+
466
+ c.Status(resp.StatusCode)
467
+
468
+ contentType := resp.Header.Get("Content-Type")
469
+ if "" != contentType {
470
+ c.Header("Content-Type", contentType)
471
+ }
472
+
473
+ _, _ = io.Copy(c.Writer, resp.Body)
474
+ }
475
+
476
+ func ConstructRequestBody(body []byte, cfg *config) []byte {
477
+ body, _ = sjson.DeleteBytes(body, "extra")
478
+ body, _ = sjson.DeleteBytes(body, "nwo")
479
+ body, _ = sjson.SetBytes(body, "model", cfg.CodeInstructModel)
480
+
481
+ if int(gjson.GetBytes(body, "max_tokens").Int()) > cfg.CodexMaxTokens {
482
+ body, _ = sjson.SetBytes(body, "max_tokens", cfg.CodexMaxTokens)
483
+ }
484
+
485
+ if strings.Contains(cfg.CodeInstructModel, StableCodeModelPrefix) {
486
+ return constructWithStableCodeModel(body)
487
+ } else if strings.HasPrefix(cfg.CodeInstructModel, DeepSeekCoderModel) {
488
+ if gjson.GetBytes(body, "n").Int() > 1 {
489
+ body, _ = sjson.SetBytes(body, "n", 1)
490
+ }
491
+ }
492
+
493
+ if strings.HasSuffix(cfg.ChatApiBase, "chat") {
494
+ // @Todo constructWithChatModel
495
+ // 如果code base以chat结尾则构建chatModel,暂时没有好的prompt
496
+ }
497
+
498
+ return body
499
+ }
500
+
501
+ func constructWithStableCodeModel(body []byte) []byte {
502
+ suffix := gjson.GetBytes(body, "suffix")
503
+ prompt := gjson.GetBytes(body, "prompt")
504
+ content := fmt.Sprintf("<fim_prefix>%s<fim_suffix>%s<fim_middle>", prompt, suffix)
505
+
506
+ // 创建新的 JSON 对象并添加到 body 中
507
+ messages := []map[string]string{
508
+ {
509
+ "role": "user",
510
+ "content": content,
511
+ },
512
+ }
513
+ return constructWithChatModel(body, messages)
514
+ }
515
+
516
+ func constructWithChatModel(body []byte, messages interface{}) []byte {
517
+
518
+ body, _ = sjson.SetBytes(body, "messages", messages)
519
+
520
+ // fmt.Printf("Request Body: %s\n", body)
521
+ // 2. 将转义的字符替换回原来的字符
522
+ jsonStr := string(body)
523
+ jsonStr = strings.ReplaceAll(jsonStr, "\\u003c", "<")
524
+ jsonStr = strings.ReplaceAll(jsonStr, "\\u003e", ">")
525
+ return []byte(jsonStr)
526
+ }
527
+
528
+ func main() {
529
+ cfg := readConfig()
530
+
531
+ gin.SetMode(gin.ReleaseMode)
532
+ r := gin.Default()
533
+
534
+ proxyService, err := NewProxyService(cfg)
535
+ if nil != err {
536
+ log.Fatal(err)
537
+ return
538
+ }
539
+
540
+ proxyService.InitRoutes(r)
541
+
542
+ err = r.Run(cfg.Bind)
543
+ if nil != err {
544
+ log.Fatal(err)
545
+ return
546
+ }
547
+
548
+ }
scripts/install-all-users.vbs ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ If Not WScript.Arguments.Named.Exists("elevate") Then
2
+ CreateObject("Shell.Application").ShellExecute WScript.FullName, """" & WScript.ScriptFullName & """ /elevate", "", "runas", 10
3
+ WScript.Quit
4
+ End If
5
+
6
+ Set oShell = CreateObject("WScript.Shell")
7
+ Set oEnvSystem = oShell.Environment("SYSTEM")
8
+ Set oFS = CreateObject("Scripting.FileSystemObject")
9
+
10
+ MsgBox "It may take a few seconds to execute this script." & vbCrLf & vbCrLf & "Click 'OK' button and wait for the prompt of 'Done.' to pop up!"
11
+
12
+ Dim baseUrl
13
+ baseUrl = "http://127.0.0.1:8181"
14
+
15
+ Sub RemoveEnv(env)
16
+ On Error Resume Next
17
+
18
+ env.Remove("AGENT_DEBUG_OVERRIDE_PROXY_URL")
19
+ env.Remove("GITHUB_COPILOT_OVERRIDE_PROXY_URL")
20
+ env.Remove("AGENT_DEBUG_OVERRIDE_CAPI_URL")
21
+ env.Remove("GITHUB_COPILOT_OVERRIDE_CAPI_URL")
22
+ End Sub
23
+
24
+ RemoveEnv oShell.Environment("USER")
25
+
26
+ oEnvSystem("AGENT_DEBUG_OVERRIDE_PROXY_URL") = baseUrl
27
+ oEnvSystem("GITHUB_COPILOT_OVERRIDE_PROXY_URL") = baseUrl
28
+ oEnvSystem("AGENT_DEBUG_OVERRIDE_CAPI_URL") = baseUrl & "/v1"
29
+ oEnvSystem("GITHUB_COPILOT_OVERRIDE_CAPI_URL") = baseUrl & "/v1"
30
+
31
+ MsgBox "Done."
scripts/install-current-user.vbs ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Set oShell = CreateObject("WScript.Shell")
2
+ Set oEnv = oShell.Environment("USER")
3
+ Set oFS = CreateObject("Scripting.FileSystemObject")
4
+
5
+ Dim baseUrl
6
+ baseUrl = "http://127.0.0.1:8181"
7
+
8
+ MsgBox "It may take a few seconds to execute this script." & vbCrLf & vbCrLf & "Click 'OK' button and wait for the prompt of 'Done.' to pop up!"
9
+
10
+ oEnv("AGENT_DEBUG_OVERRIDE_PROXY_URL") = baseUrl
11
+ oEnv("GITHUB_COPILOT_OVERRIDE_PROXY_URL") = baseUrl
12
+ oEnv("AGENT_DEBUG_OVERRIDE_CAPI_URL") = baseUrl & "/v1"
13
+ oEnv("GITHUB_COPILOT_OVERRIDE_CAPI_URL") = baseUrl & "/v1"
14
+
15
+ MsgBox "Done."
scripts/install.sh ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ OS_NAME=$(uname -s)
6
+ BASE_URL="http://127.0.0.1:8181"
7
+
8
+ KDE_ENV_DIR="${HOME}/.config/plasma-workspace/env"
9
+ LAUNCH_AGENTS_DIR="${HOME}/Library/LaunchAgents"
10
+
11
+ PROFILE_PATH="${HOME}/.profile"
12
+ ZSH_PROFILE_PATH="${HOME}/.zshrc"
13
+ PLIST_PATH="${LAUNCH_AGENTS_DIR}/copilot.override.plist"
14
+
15
+ if [ "$OS_NAME" = "Darwin" ]; then
16
+ BASH_PROFILE_PATH="${HOME}/.bash_profile"
17
+
18
+ mkdir -p "${LAUNCH_AGENTS_DIR}"
19
+ echo '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>Label</key><string>copilot.override</string><key>ProgramArguments</key><array><string>sh</string><string>-c</string><string>' >"${PLIST_PATH}"
20
+ else
21
+ BASH_PROFILE_PATH="${HOME}/.bashrc"
22
+ mkdir -p "${KDE_ENV_DIR}"
23
+ fi
24
+
25
+ touch "${PROFILE_PATH}"
26
+ touch "${BASH_PROFILE_PATH}"
27
+ touch "${ZSH_PROFILE_PATH}"
28
+
29
+ GH_OVERRIDE_SHELL_NAME="copilot.override.sh"
30
+ GH_OVERRIDE_SHELL_FILE="${HOME}/.${GH_OVERRIDE_SHELL_NAME}"
31
+ echo '#!/bin/sh' >"${GH_OVERRIDE_SHELL_FILE}"
32
+
33
+ # shellcheck disable=SC2016
34
+ EXEC_LINE='___GH_OVERRIDE_SHELL_FILE="${HOME}/.copilot.override.sh"; if [ -f "${___GH_OVERRIDE_SHELL_FILE}" ]; then . "${___GH_OVERRIDE_SHELL_FILE}"; fi'
35
+
36
+ # shellcheck disable=SC2129
37
+ echo "export AGENT_DEBUG_OVERRIDE_PROXY_URL=\"${BASE_URL}\"" >>"${GH_OVERRIDE_SHELL_FILE}"
38
+ echo "export GITHUB_COPILOT_OVERRIDE_PROXY_URL=\"${BASE_URL}\"" >>"${GH_OVERRIDE_SHELL_FILE}"
39
+ echo "export AGENT_DEBUG_OVERRIDE_CAPI_URL=\"${BASE_URL}/v1\"" >>"${GH_OVERRIDE_SHELL_FILE}"
40
+ echo "export GITHUB_COPILOT_OVERRIDE_CAPI_URL=\"${BASE_URL}/v1\"" >>"${GH_OVERRIDE_SHELL_FILE}"
41
+
42
+ if [ "$OS_NAME" = "Darwin" ]; then
43
+ launchctl setenv "AGENT_DEBUG_OVERRIDE_PROXY_URL" "${BASE_URL}"
44
+ launchctl setenv "GITHUB_COPILOT_OVERRIDE_PROXY_URL" "${BASE_URL}"
45
+ launchctl setenv "AGENT_DEBUG_OVERRIDE_CAPI_URL" "${BASE_URL}/v1"
46
+ launchctl setenv "GITHUB_COPILOT_OVERRIDE_CAPI_URL" "${BASE_URL}/v1"
47
+
48
+ # shellcheck disable=SC2129
49
+ echo "launchctl setenv \"AGENT_DEBUG_OVERRIDE_PROXY_URL\" \"${BASE_URL}\"" >>"${PLIST_PATH}"
50
+ echo "launchctl setenv \"GITHUB_COPILOT_OVERRIDE_PROXY_URL\" \"${BASE_URL}\"" >>"${PLIST_PATH}"
51
+ echo "launchctl setenv \"AGENT_DEBUG_OVERRIDE_CAPI_URL\" \"${BASE_URL}/v1\"" >>"${PLIST_PATH}"
52
+ echo "launchctl setenv \"GITHUB_COPILOT_OVERRIDE_CAPI_URL\" \"${BASE_URL}/v1\"" >>"${PLIST_PATH}"
53
+ fi
54
+
55
+ if [ "$OS_NAME" = "Darwin" ]; then
56
+ # shellcheck disable=SC2016
57
+ sed -i '' '/___GH_OVERRIDE_SHELL_FILE="${HOME}\/\.copilot\.override\.sh"; if /d' "${PROFILE_PATH}" >/dev/null 2>&1
58
+ # shellcheck disable=SC2016
59
+ sed -i '' '/___GH_OVERRIDE_SHELL_FILE="${HOME}\/\.copilot\.override\.sh"; if /d' "${BASH_PROFILE_PATH}" >/dev/null 2>&1
60
+ # shellcheck disable=SC2016
61
+ sed -i '' '/___GH_OVERRIDE_SHELL_FILE="${HOME}\/\.copilot\.override\.sh"; if /d' "${ZSH_PROFILE_PATH}" >/dev/null 2>&1
62
+
63
+ echo '</string></array><key>RunAtLoad</key><true/></dict></plist>' >>"${PLIST_PATH}"
64
+ else
65
+ # shellcheck disable=SC2016
66
+ sed -i '/___GH_OVERRIDE_SHELL_FILE="${HOME}\/\.copilot\.override\.sh"; if /d' "${PROFILE_PATH}" >/dev/null 2>&1
67
+ # shellcheck disable=SC2016
68
+ sed -i '/___GH_OVERRIDE_SHELL_FILE="${HOME}\/\.copilot\.override\.sh"; if /d' "${BASH_PROFILE_PATH}" >/dev/null 2>&1
69
+ # shellcheck disable=SC2016
70
+ sed -i '/___GH_OVERRIDE_SHELL_FILE="${HOME}\/\.copilot\.override\.sh"; if /d' "${ZSH_PROFILE_PATH}" >/dev/null 2>&1
71
+ fi
72
+
73
+ echo "${EXEC_LINE}" >>"${PROFILE_PATH}"
74
+ echo "${EXEC_LINE}" >>"${BASH_PROFILE_PATH}"
75
+ echo "${EXEC_LINE}" >>"${ZSH_PROFILE_PATH}"
76
+
77
+ if [ "$OS_NAME" = "Darwin" ]; then
78
+ echo 'done. the "kill Dock" command can fix the crash issue.'
79
+ else
80
+ ln -sf "${GH_OVERRIDE_SHELL_FILE}" "${KDE_ENV_DIR}/${GH_OVERRIDE_SHELL_NAME}"
81
+ echo "done. you'd better log off first!"
82
+ fi
scripts/replace_max_tokens.vbs ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ' VBScript to change max tokens to 2048
2
+
3
+ MsgBox "It may take a few seconds to execute this script." & vbCrLf & vbCrLf & "Click 'OK' button and wait for the prompt of 'Done.' to pop up!"
4
+
5
+ Const ForReading = 1
6
+ Const ForWriting = 2
7
+
8
+ ' Subpath of the file to be replaced
9
+ subpath = "dist\extension.js"
10
+
11
+ pattern = "\.maxPromptCompletionTokens\(([a-zA-Z0-9_]+),([0-9]+)\)"
12
+ replacement = ".maxPromptCompletionTokens($1,2048)"
13
+
14
+ ' Iterate over all github copilot directories
15
+ Set objFSO = CreateObject("Scripting.FileSystemObject")
16
+ Set objShell = CreateObject("WScript.Shell")
17
+ Set colExtensions = objFSO.GetFolder(objShell.ExpandEnvironmentStrings("%USERPROFILE%") & "\.vscode\extensions").SubFolders
18
+
19
+ For Each objExtension In colExtensions
20
+ extension_path = objExtension.Path & "\" & subpath
21
+ If objFSO.FileExists(extension_path) Then
22
+ backupfile = extension_path & ".bak"
23
+
24
+ ' Delete if backup file exists
25
+ If objFSO.FileExists(backupfile) Then
26
+ objFSO.DeleteFile backupfile, True
27
+ End If
28
+
29
+ ' Backup
30
+ objFSO.CopyFile extension_path, backupfile
31
+
32
+ ' Do search and replace with pattern
33
+ Set objFile = objFSO.OpenTextFile(extension_path, ForReading)
34
+ strContent = objFile.ReadAll
35
+ objFile.Close
36
+
37
+ Set objRegEx = New RegExp
38
+ objRegEx.Global = True
39
+ objRegEx.IgnoreCase = True
40
+ objRegEx.Pattern = pattern
41
+ strContent = objRegEx.Replace(strContent, replacement)
42
+
43
+ Set objFile = objFSO.OpenTextFile(extension_path, ForWriting)
44
+ objFile.Write strContent
45
+ objFile.Close
46
+ End If
47
+ Next
48
+
49
+ MsgBox "Max tokens modification completed"
scripts/restore_max_tokens.vbs ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ' VBScript to recovery max tokens
2
+ MsgBox "It may take a few seconds to execute this script." & vbCrLf & vbCrLf & "Click 'OK' button and wait for the prompt of 'Done.' to pop up!"
3
+
4
+ Const ForReading = 1
5
+ Const ForWriting = 2
6
+
7
+ ' Subpath of the file to be recovery
8
+ subpath = "dist\extension.js"
9
+
10
+ ' Iterate over all github copilot directories
11
+ Set objFSO = CreateObject("Scripting.FileSystemObject")
12
+ Set objShell = CreateObject("WScript.Shell")
13
+ Set colExtensions = objFSO.GetFolder(objShell.ExpandEnvironmentStrings("%USERPROFILE%") & "\.vscode\extensions").SubFolders
14
+
15
+ For Each objExtension In colExtensions
16
+ extension_path = objExtension.Path & "\" & subpath
17
+ backupfile = extension_path & ".bak"
18
+
19
+ If objFSO.FileExists(backupfile) Then
20
+ ' Delete if exist extension file
21
+ If objFSO.FileExists(extension_path) Then
22
+ objFSO.DeleteFile extension_path, True
23
+ End If
24
+
25
+ ' Replace
26
+ objFSO.MoveFile backupfile, extension_path
27
+ End If
28
+ Next
29
+
30
+ MsgBox "Restore max tokens to default successed"
scripts/uninstall-all-users.vbs ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ If Not WScript.Arguments.Named.Exists("elevate") Then
2
+ CreateObject("Shell.Application").ShellExecute WScript.FullName, """" & WScript.ScriptFullName & """ /elevate", "", "runas", 10
3
+ WScript.Quit
4
+ End If
5
+
6
+ MsgBox "It may take a few seconds to execute this script." & vbCrLf & vbCrLf & "Click 'OK' button and wait for the prompt of 'Done.' to pop up!"
7
+
8
+ Sub RemoveEnv(env)
9
+ On Error Resume Next
10
+
11
+ env.Remove("AGENT_DEBUG_OVERRIDE_PROXY_URL")
12
+ env.Remove("GITHUB_COPILOT_OVERRIDE_PROXY_URL")
13
+ env.Remove("AGENT_DEBUG_OVERRIDE_CAPI_URL")
14
+ env.Remove("GITHUB_COPILOT_OVERRIDE_CAPI_URL")
15
+ End Sub
16
+
17
+ Set oShell = CreateObject("WScript.Shell")
18
+
19
+ RemoveEnv oShell.Environment("USER")
20
+ RemoveEnv oShell.Environment("SYSTEM")
21
+
22
+ MsgBox "Done."
scripts/uninstall-current-user.vbs ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Set oShell = CreateObject("WScript.Shell")
2
+ Set oEnv = oShell.Environment("USER")
3
+
4
+ MsgBox "It may take a few seconds to execute this script." & vbCrLf & vbCrLf & "Click 'OK' button and wait for the prompt of 'Done.' to pop up!"
5
+
6
+ oEnv.Remove("AGENT_DEBUG_OVERRIDE_PROXY_URL")
7
+ oEnv.Remove("GITHUB_COPILOT_OVERRIDE_PROXY_URL")
8
+ oEnv.Remove("AGENT_DEBUG_OVERRIDE_CAPI_URL")
9
+ oEnv.Remove("GITHUB_COPILOT_OVERRIDE_CAPI_URL")
10
+
11
+ MsgBox "Done."
scripts/uninstall.sh ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ OS_NAME=$(uname -s)
6
+
7
+ KDE_ENV_DIR="${HOME}/.config/plasma-workspace/env"
8
+
9
+ PROFILE_PATH="${HOME}/.profile"
10
+ ZSH_PROFILE_PATH="${HOME}/.zshrc"
11
+ PLIST_PATH="${HOME}/Library/LaunchAgents/copilot.override.plist"
12
+
13
+ if [ "$OS_NAME" = "Darwin" ]; then
14
+ BASH_PROFILE_PATH="${HOME}/.bash_profile"
15
+ else
16
+ BASH_PROFILE_PATH="${HOME}/.bashrc"
17
+ fi
18
+
19
+ touch "${PROFILE_PATH}"
20
+ touch "${BASH_PROFILE_PATH}"
21
+ touch "${ZSH_PROFILE_PATH}"
22
+
23
+ GH_OVERRIDE_SHELL_NAME="copilot.override.sh"
24
+ GH_OVERRIDE_SHELL_FILE="${HOME}/.${GH_OVERRIDE_SHELL_NAME}"
25
+
26
+ rm -rf "${GH_OVERRIDE_SHELL_FILE}"
27
+
28
+ if [ "$OS_NAME" = "Darwin" ]; then
29
+ launchctl unsetenv "AGENT_DEBUG_OVERRIDE_PROXY_URL"
30
+ launchctl unsetenv "GITHUB_COPILOT_OVERRIDE_PROXY_URL"
31
+ launchctl unsetenv "AGENT_DEBUG_OVERRIDE_CAPI_URL"
32
+ launchctl unsetenv "GITHUB_COPILOT_OVERRIDE_CAPI_URL"
33
+
34
+ rm -rf "${PLIST_PATH}"
35
+
36
+ # shellcheck disable=SC2016
37
+ sed -i '' '/___GH_OVERRIDE_SHELL_FILE="${HOME}\/\.copilot\.override\.sh"; if /d' "${PROFILE_PATH}" >/dev/null 2>&1
38
+ # shellcheck disable=SC2016
39
+ sed -i '' '/___GH_OVERRIDE_SHELL_FILE="${HOME}\/\.copilot\.override\.sh"; if /d' "${BASH_PROFILE_PATH}" >/dev/null 2>&1
40
+ # shellcheck disable=SC2016
41
+ sed -i '' '/___GH_OVERRIDE_SHELL_FILE="${HOME}\/\.copilot\.override\.sh"; if /d' "${ZSH_PROFILE_PATH}" >/dev/null 2>&1
42
+
43
+ echo 'done.'
44
+ else
45
+ # shellcheck disable=SC2016
46
+ sed -i '/___GH_OVERRIDE_SHELL_FILE="${HOME}\/\.copilot\.override\.sh"; if /d' "${PROFILE_PATH}" >/dev/null 2>&1
47
+ # shellcheck disable=SC2016
48
+ sed -i '/___GH_OVERRIDE_SHELL_FILE="${HOME}\/\.copilot\.override\.sh"; if /d' "${BASH_PROFILE_PATH}" >/dev/null 2>&1
49
+ # shellcheck disable=SC2016
50
+ sed -i '/___GH_OVERRIDE_SHELL_FILE="${HOME}\/\.copilot\.override\.sh"; if /d' "${ZSH_PROFILE_PATH}" >/dev/null 2>&1
51
+
52
+ # shellcheck disable=SC2115
53
+ rm -rf "${KDE_ENV_DIR}/${GH_OVERRIDE_SHELL_NAME}"
54
+ echo "done. you'd better log off first!"
55
+ fi