Compare commits

...

7 Commits

Author SHA1 Message Date
Luis Pater 599986495b feat(translator): enhance OpenAI Gemini request handling for mixed content
docker-image / docker (push) Has been cancelled
goreleaser / goreleaser (push) Has been cancelled
- Replaced `contentParts` with `aggregatedParts` to support mixed content (text and inline data).
- Introduced `textBuilder` for efficient text concatenation.
- Added support for inline data processing, including base64-encoded image URLs.
- Updated `msg["content"]` logic to handle both plain text and mixed content scenarios.
2025-10-13 02:15:55 +08:00
Luis Pater cb83985cc7 chore(server): remove debug println statement from server.go
docker-image / docker (push) Has been cancelled
goreleaser / goreleaser (push) Has been cancelled
2025-10-12 23:58:50 +08:00
Luis Pater 6ec028808f docs(readme): add MANAGEMENT_PASSWORD environment variable documentation
- Updated environment variable table in both English (README.md) and Chinese (README_CN.md) to include `MANAGEMENT_PASSWORD`.
2025-10-12 23:06:20 +08:00
Luis Pater 71faa19bb4 Merge pull request #114 from router-for-me/management
docker-image / docker (push) Has been cancelled
goreleaser / goreleaser (push) Has been cancelled
feat(managementasset): Authenticate GitHub API requests
2025-10-12 21:40:42 +08:00
hkfires b5ad978d44 feat(managementasset): Authenticate GitHub API requests 2025-10-12 21:21:51 +08:00
Luis Pater 0508c9fbce Merge pull request #113 from sususu98/main
chore: update .gitignore include .env
2025-10-12 18:21:59 +08:00
sususu af82855bed chore: update .gitignore include .env 2025-10-12 07:16:11 +02:00
6 changed files with 57 additions and 18 deletions
+1
View File
@@ -15,3 +15,4 @@ GEMINI.md
temp/*
cli-proxy-api
static/*
.env
+4 -1
View File
@@ -422,12 +422,15 @@ To enable this feature, set the `GITSTORE_GIT_URL` environment variable to the U
**Environment Variables**
| Variable | Required | Default | Description |
| ----------------------- | -------- | ------------------------- | -------------------------------------------------------------------------------------------------------- |
|-------------------------|----------|---------------------------|---------------------------------------------------------------------------------------------------------|
| `MANAGEMENT_PASSWORD` | Yes | | The password for management webui. |
| `GITSTORE_GIT_URL` | Yes | | The HTTPS URL of the Git repository to use. |
| `GITSTORE_LOCAL_PATH` | No | Current working directory | The local path where the Git repository will be cloned. Inside Docker, this defaults to `/CLIProxyAPI`. |
| `GITSTORE_GIT_USERNAME` | No | | The username for Git authentication. |
| `GITSTORE_GIT_TOKEN` | No | | The personal access token (or password) for Git authentication. |
**How it Works**
1. **Cloning:** On startup, the application clones the remote Git repository to the `GITSTORE_LOCAL_PATH`.
+2 -1
View File
@@ -435,7 +435,8 @@ openai-compatibility:
**环境变量**
| 变量 | 必需 | 默认值 | 描述 |
| ----------------------- | ---- | --------------------- | ------------------------------------------------------------------------------------------------------ |
|-------------------------|----|--------|----------------------------------------------------|
| `MANAGEMENT_PASSWORD` | 是 | | 控制面板密码 |
| `GITSTORE_GIT_URL` | 是 | | 要使用的 Git 仓库的 HTTPS URL。 |
| `GITSTORE_LOCAL_PATH` | 否 | 当前工作目录 | 将克隆 Git 仓库的本地路径。在 Docker 内部,此路径默认为 `/CLIProxyAPI`。 |
| `GITSTORE_GIT_USERNAME` | 否 | | 用于 Git 身份验证的用户名。 |
-1
View File
@@ -457,7 +457,6 @@ func (s *Server) serveManagementControlPanel(c *gin.Context) {
c.AbortWithStatus(http.StatusNotFound)
return
}
println(s.currentPath)
filePath := managementasset.FilePath(s.currentPath)
if strings.TrimSpace(filePath) == "" {
c.AbortWithStatus(http.StatusNotFound)
+4
View File
@@ -159,6 +159,10 @@ func fetchLatestAsset(ctx context.Context, client *http.Client) (*releaseAsset,
}
req.Header.Set("Accept", "application/vnd.github+json")
req.Header.Set("User-Agent", httpUserAgent)
gitURL := strings.ToLower(strings.TrimSpace(os.Getenv("GITSTORE_GIT_URL")))
if tok := strings.TrimSpace(os.Getenv("GITSTORE_GIT_TOKEN")); tok != "" && strings.Contains(gitURL, "github.com") {
req.Header.Set("Authorization", "Bearer "+tok)
}
resp, err := client.Do(req)
if err != nil {
@@ -9,6 +9,7 @@ import (
"bytes"
"crypto/rand"
"encoding/json"
"fmt"
"math/big"
"strings"
@@ -100,14 +101,40 @@ func ConvertGeminiRequestToOpenAI(modelName string, inputRawJSON []byte, stream
"content": "",
}
var contentParts []string
var textBuilder strings.Builder
var aggregatedParts []interface{}
onlyTextContent := true
var toolCalls []interface{}
if parts.Exists() && parts.IsArray() {
parts.ForEach(func(_, part gjson.Result) bool {
// Handle text parts
if text := part.Get("text"); text.Exists() {
contentParts = append(contentParts, text.String())
formattedText := text.String()
textBuilder.WriteString(formattedText)
aggregatedParts = append(aggregatedParts, map[string]interface{}{
"type": "text",
"text": formattedText,
})
}
// Handle inline data (e.g., images)
if inlineData := part.Get("inlineData"); inlineData.Exists() {
onlyTextContent = false
mimeType := inlineData.Get("mimeType").String()
if mimeType == "" {
mimeType = "application/octet-stream"
}
data := inlineData.Get("data").String()
imageURL := fmt.Sprintf("data:%s;base64,%s", mimeType, data)
aggregatedParts = append(aggregatedParts, map[string]interface{}{
"type": "image_url",
"image_url": map[string]interface{}{
"url": imageURL,
},
})
}
// Handle function calls (Gemini) -> tool calls (OpenAI)
@@ -175,8 +202,12 @@ func ConvertGeminiRequestToOpenAI(modelName string, inputRawJSON []byte, stream
}
// Set content
if len(contentParts) > 0 {
msg["content"] = strings.Join(contentParts, "")
if len(aggregatedParts) > 0 {
if onlyTextContent {
msg["content"] = textBuilder.String()
} else {
msg["content"] = aggregatedParts
}
}
// Set tool calls if any