Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ remote-management:
# Authentication directory (supports ~ for home directory)
auth-dir: "~/.cli-proxy-api"

# Uploaded files directory (supports ~ for home directory).
# Leave empty to use the default location: <auth-dir>/files
files-dir: ""

# API keys for authentication
api-keys:
- "your-api-key-1"
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ require (
golang.org/x/sync v0.18.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/yaml.v3 v3.0.1
rsc.io/pdf v0.1.1
)

require (
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,5 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
2 changes: 1 addition & 1 deletion internal/api/modules/amp/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ func (m *AmpModule) registerProviderAliases(engine *gin.Engine, baseHandler *han
openaiHandlers := openai.NewOpenAIAPIHandler(baseHandler)
geminiHandlers := gemini.NewGeminiAPIHandler(baseHandler)
claudeCodeHandlers := claude.NewClaudeCodeAPIHandler(baseHandler)
openaiResponsesHandlers := openai.NewOpenAIResponsesAPIHandler(baseHandler)
openaiResponsesHandlers := openai.NewOpenAIResponsesAPIHandler(baseHandler, nil)

// Create fallback handler wrapper that forwards to ampcode.com when provider not found
// Uses m.getProxy() for hot-reload support (proxy can be updated at runtime)
Expand Down
12 changes: 11 additions & 1 deletion internal/api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/router-for-me/CLIProxyAPI/v6/internal/api/modules"
ampmodule "github.com/router-for-me/CLIProxyAPI/v6/internal/api/modules/amp"
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
cliproxyfiles "github.com/router-for-me/CLIProxyAPI/v6/internal/files"
"github.com/router-for-me/CLIProxyAPI/v6/internal/logging"
"github.com/router-for-me/CLIProxyAPI/v6/internal/managementasset"
"github.com/router-for-me/CLIProxyAPI/v6/internal/usage"
Expand Down Expand Up @@ -322,7 +323,12 @@ func (s *Server) setupRoutes() {
geminiHandlers := gemini.NewGeminiAPIHandler(s.handlers)
geminiCLIHandlers := gemini.NewGeminiCLIAPIHandler(s.handlers)
claudeCodeHandlers := claude.NewClaudeCodeAPIHandler(s.handlers)
openaiResponsesHandlers := openai.NewOpenAIResponsesAPIHandler(s.handlers)
fileStore, err := cliproxyfiles.NewStoreWithDir(s.cfg.AuthDir, s.cfg.FilesDir)
if err != nil {
log.WithError(err).Warn("failed to initialize local file store")
}
Comment on lines +327 to +329
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The error from cliproxyfiles.NewStoreWithDir is only logged as a warning. While this allows the server to start, it might not be obvious to the operator that the file upload functionality is unavailable, especially if this error occurs due to a misconfiguration. Consider making the log message more explicit about the consequences.

Suggested change
if err != nil {
log.WithError(err).Warn("failed to initialize local file store")
}
if err != nil {
log.WithError(err).Warn("failed to initialize local file store; file upload functionality will be unavailable")
}

openaiResponsesHandlers := openai.NewOpenAIResponsesAPIHandler(s.handlers, fileStore)
openaiFilesHandlers := openai.NewOpenAIFilesAPIHandler(fileStore)

// OpenAI compatible API routes
v1 := s.engine.Group("/v1")
Expand All @@ -333,6 +339,10 @@ func (s *Server) setupRoutes() {
v1.POST("/completions", openaiHandlers.Completions)
v1.POST("/messages", claudeCodeHandlers.ClaudeMessages)
v1.POST("/messages/count_tokens", claudeCodeHandlers.ClaudeCountTokens)
v1.GET("/files", openaiFilesHandlers.List)
v1.POST("/files", openaiFilesHandlers.Create)
v1.GET("/files/:id", openaiFilesHandlers.Get)
v1.DELETE("/files/:id", openaiFilesHandlers.Delete)
v1.GET("/responses", openaiResponsesHandlers.ResponsesWebsocket)
v1.POST("/responses", openaiResponsesHandlers.Responses)
v1.POST("/responses/compact", openaiResponsesHandlers.Compact)
Expand Down
6 changes: 6 additions & 0 deletions internal/api/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ func TestAmpProviderModelRoutes(t *testing.T) {
wantStatus: http.StatusOK,
wantContains: `"models"`,
},
{
name: "files list",
path: "/v1/files",
wantStatus: http.StatusOK,
wantContains: `"object":"list"`,
},
}

for _, tc := range testCases {
Expand Down
4 changes: 4 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ type Config struct {
// AuthDir is the directory where authentication token files are stored.
AuthDir string `yaml:"auth-dir" json:"-"`

// FilesDir overrides the directory where uploaded files are stored.
// When empty, uploads are stored under <auth-dir>/files.
FilesDir string `yaml:"files-dir" json:"-"`

// Debug enables or disables debug-level logging and other debug features.
Debug bool `yaml:"debug" json:"debug"`

Expand Down
28 changes: 28 additions & 0 deletions internal/config/files_dir_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package config

import (
"os"
"path/filepath"
"testing"
)

func TestLoadConfigOptional_FilesDir(t *testing.T) {
dir := t.TempDir()
configPath := filepath.Join(dir, "config.yaml")
configYAML := []byte("\nauth-dir: ~/.cli-proxy-api\nfiles-dir: ~/custom-uploads\n")
if err := os.WriteFile(configPath, configYAML, 0o600); err != nil {
t.Fatalf("failed to write config: %v", err)
}

cfg, err := LoadConfigOptional(configPath, false)
if err != nil {
t.Fatalf("LoadConfigOptional() error = %v", err)
}

if got := cfg.AuthDir; got != "~/.cli-proxy-api" {
t.Fatalf("AuthDir = %q, want %q", got, "~/.cli-proxy-api")
}
if got := cfg.FilesDir; got != "~/custom-uploads" {
t.Fatalf("FilesDir = %q, want %q", got, "~/custom-uploads")
}
}
Loading
Loading