feat: add agent-friendly ufile CLI

This commit is contained in:
loveuer
2026-09-21 00:45:35 -07:00
parent f0c29e4832
commit a58990ce66
17 changed files with 1684 additions and 3 deletions
+96
View File
@@ -0,0 +1,96 @@
package main
import (
"encoding/json"
"errors"
"fmt"
"net/url"
"os"
"path/filepath"
"strings"
"time"
)
type configFile struct {
Host string `json:"host,omitempty"`
Session string `json:"session,omitempty"`
ExpiresAt time.Time `json:"expiresAt,omitempty"`
}
func defaultConfigPath() string {
if value := os.Getenv("UFILE_CONFIG"); value != "" {
return value
}
dir, err := os.UserConfigDir()
if err != nil {
return "ufile-cli.json"
}
return filepath.Join(dir, "ufile-cli", "config.json")
}
func loadConfig(path string) (configFile, error) {
data, err := os.ReadFile(path)
if errors.Is(err, os.ErrNotExist) {
return configFile{}, nil
}
if err != nil {
return configFile{}, err
}
var config configFile
if err := json.Unmarshal(data, &config); err != nil {
return configFile{}, fmt.Errorf("配置文件格式错误: %w", err)
}
return config, nil
}
func saveConfig(path string, config configFile) error {
dir := filepath.Dir(path)
if err := os.MkdirAll(dir, 0o700); err != nil {
return err
}
data, err := json.MarshalIndent(config, "", " ")
if err != nil {
return err
}
data = append(data, '\n')
temp, err := os.CreateTemp(dir, ".config-*")
if err != nil {
return err
}
tempName := temp.Name()
defer os.Remove(tempName)
if err := temp.Chmod(0o600); err != nil {
temp.Close()
return err
}
if _, err := temp.Write(data); err != nil {
temp.Close()
return err
}
if err := temp.Close(); err != nil {
return err
}
if err := os.Rename(tempName, path); err == nil {
return nil
}
if err := os.Remove(path); err != nil && !errors.Is(err, os.ErrNotExist) {
return err
}
return os.Rename(tempName, path)
}
func normalizeHost(value string) (string, error) {
value = strings.TrimSpace(value)
parsed, err := url.Parse(value)
if err != nil || parsed.Scheme == "" || parsed.Host == "" {
return "", fmt.Errorf("无效的服务地址 %q,需要包含 http:// 或 https://", value)
}
if parsed.Scheme != "http" && parsed.Scheme != "https" {
return "", fmt.Errorf("服务地址只支持 http 或 https")
}
if parsed.RawQuery != "" || parsed.Fragment != "" {
return "", fmt.Errorf("服务地址不能包含查询参数或片段")
}
parsed.Path = strings.TrimRight(parsed.Path, "/")
return strings.TrimRight(parsed.String(), "/"), nil
}