Skip to content

Commit c930f6b

Browse files
Merge upstream/main (auto-sync feat/copilot)
- 96a8b0c feat(executor): normalize reasoning text events and enhance handling logic - 644ba74 feat(videos): implement auth binding for video requests and enhance proxy handling - f23fb12 feat(translator): ensure tool uses stay adjacent to tool results in message generation - acaf250 feat(management): add test to validate priority preservation in auth file uploads - cde5081 test(translator): add tests to validate omission of top-level `output_text` in OpenAI responses - dd49a52 feat(translator): add tests to validate trailing assistant prefill stripping and sanitize tool call IDs
2 parents 36f4f3c + dd49a52 commit c930f6b

17 files changed

Lines changed: 1123 additions & 111 deletions

internal/api/handlers/management/auth_files.go

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"github.com/router-for-me/CLIProxyAPI/v7/internal/misc"
3333
"github.com/router-for-me/CLIProxyAPI/v7/internal/registry"
3434
"github.com/router-for-me/CLIProxyAPI/v7/internal/util"
35+
"github.com/router-for-me/CLIProxyAPI/v7/internal/watcher/synthesizer"
3536
sdkAuth "github.com/router-for-me/CLIProxyAPI/v7/sdk/auth"
3637
coreauth "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/auth"
3738
"github.com/router-for-me/CLIProxyAPI/v7/sdk/pluginapi"
@@ -1161,21 +1162,35 @@ func (h *Handler) buildAuthFromFileData(path string, data []byte) (*coreauth.Aut
11611162
if authID == "" {
11621163
authID = path
11631164
}
1164-
attr := map[string]string{
1165-
"path": path,
1166-
"source": path,
1167-
}
1168-
auth := &coreauth.Auth{
1169-
ID: authID,
1170-
Provider: provider,
1171-
FileName: filepath.Base(path),
1172-
Label: label,
1173-
Status: coreauth.StatusActive,
1174-
Attributes: attr,
1175-
Metadata: metadata,
1176-
CreatedAt: time.Now(),
1177-
UpdatedAt: time.Now(),
1165+
auth := (*coreauth.Auth)(nil)
1166+
if h != nil && h.cfg != nil {
1167+
sctx := &synthesizer.SynthesisContext{
1168+
Config: h.cfg,
1169+
AuthDir: h.cfg.AuthDir,
1170+
Now: time.Now(),
1171+
IDGenerator: synthesizer.NewStableIDGenerator(),
1172+
}
1173+
if generated := synthesizer.SynthesizeAuthFile(sctx, path, data); len(generated) > 0 && generated[0] != nil {
1174+
auth = generated[0].Clone()
1175+
}
1176+
}
1177+
if auth == nil {
1178+
auth = &coreauth.Auth{
1179+
ID: authID,
1180+
Provider: provider,
1181+
Label: label,
1182+
Status: coreauth.StatusActive,
1183+
Attributes: map[string]string{
1184+
"path": path,
1185+
"source": path,
1186+
},
1187+
Metadata: metadata,
1188+
CreatedAt: time.Now(),
1189+
UpdatedAt: time.Now(),
1190+
}
11781191
}
1192+
auth.ID = authID
1193+
auth.FileName = filepath.Base(path)
11791194
if hasLastRefresh {
11801195
auth.LastRefreshedAt = lastRefresh
11811196
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package management
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"mime/multipart"
7+
"net/http"
8+
"net/http/httptest"
9+
"testing"
10+
11+
"github.com/gin-gonic/gin"
12+
"github.com/router-for-me/CLIProxyAPI/v7/internal/config"
13+
coreauth "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/auth"
14+
)
15+
16+
func TestUploadAuthFile_PreservesPriorityAttributes(t *testing.T) {
17+
t.Setenv("MANAGEMENT_PASSWORD", "")
18+
gin.SetMode(gin.TestMode)
19+
20+
authDir := t.TempDir()
21+
manager := coreauth.NewManager(nil, nil, nil)
22+
h := NewHandlerWithoutConfigFilePath(&config.Config{AuthDir: authDir}, manager)
23+
24+
content := `{"type":"codex","email":"midai0530@gmail.com","priority":98}`
25+
26+
var body bytes.Buffer
27+
writer := multipart.NewWriter(&body)
28+
part, err := writer.CreateFormFile("file", "codex-midai0530@gmail.com-plus.json")
29+
if err != nil {
30+
t.Fatalf("failed to create multipart file: %v", err)
31+
}
32+
if _, err = part.Write([]byte(content)); err != nil {
33+
t.Fatalf("failed to write multipart content: %v", err)
34+
}
35+
if err = writer.Close(); err != nil {
36+
t.Fatalf("failed to close multipart writer: %v", err)
37+
}
38+
39+
rec := httptest.NewRecorder()
40+
ctx, _ := gin.CreateTestContext(rec)
41+
req := httptest.NewRequest(http.MethodPost, "/v0/management/auth-files", &body)
42+
req.Header.Set("Content-Type", writer.FormDataContentType())
43+
ctx.Request = req
44+
45+
h.UploadAuthFile(ctx)
46+
47+
if rec.Code != http.StatusOK {
48+
t.Fatalf("expected upload status %d, got %d with body %s", http.StatusOK, rec.Code, rec.Body.String())
49+
}
50+
51+
var payload map[string]any
52+
if err = json.Unmarshal(rec.Body.Bytes(), &payload); err != nil {
53+
t.Fatalf("failed to decode response: %v", err)
54+
}
55+
if status, _ := payload["status"].(string); status != "ok" {
56+
t.Fatalf("expected status ok, got %#v", payload["status"])
57+
}
58+
59+
auth, ok := manager.GetByID("codex-midai0530@gmail.com-plus.json")
60+
if !ok || auth == nil {
61+
t.Fatalf("expected uploaded auth record to exist")
62+
}
63+
if got := auth.Attributes["priority"]; got != "98" {
64+
t.Fatalf("priority attribute = %q, want %q", got, "98")
65+
}
66+
if got := auth.Metadata["priority"]; got != float64(98) {
67+
t.Fatalf("priority metadata = %#v, want 98", got)
68+
}
69+
}

0 commit comments

Comments
 (0)