Files
sproutclaw-web/backend/internal/config/config.go
2026-06-14 20:31:10 +08:00

108 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package config
import (
"flag"
"os"
"path/filepath"
"runtime"
"strings"
)
type Config struct {
Port int
AgentDir string
RepoRoot string // pi 仓库根目录pi CLI 子进程的工作目录)
DataDir string // sproutclaw-web 自己的数据目录SQLite 等)
PiCmd string // pi CLI 启动命令(完整路径)
PiArgs []string
// 派生路径(从 AgentDir 推导)
SessionsDir string
SystemPromptFile string
ModelsConfigFile string
McpConfigFile string
McpCacheFile string
SettingsFile string
SkillsDir string
SkillsDisabledDir string
ExtensionsDir string
FrontendDist string // ../frontend/dist 相对于可执行文件
}
func New() *Config {
port := flag.Int("port", 19133, "HTTP port")
agentDir := flag.String("agent-dir", "", "pi agent directory (e.g. /path/to/.pi/agent)")
repoRoot := flag.String("repo-root", "", "pi repo root (pi CLI cwd); defaults to two levels above agent-dir")
dataDir := flag.String("data-dir", "", "sproutclaw-web data dir for SQLite (defaults to ./data)")
piCmd := flag.String("pi-cmd", "", "pi CLI command (may include args, e.g. \"node /path/tsx.mjs /path/cli.ts\")")
frontendDist := flag.String("frontend-dist", "", "path to frontend/dist (defaults to ../frontend/dist relative to binary)")
flag.Parse()
if *agentDir == "" {
cwd, _ := os.Getwd()
*agentDir = filepath.Join(cwd, ".pi", "agent")
}
cfg := &Config{
Port: *port,
AgentDir: *agentDir,
RepoRoot: *repoRoot,
DataDir: *dataDir,
}
// repoRoot defaults to the directory two levels above agentDir (.pi/agent -> repo root)
if cfg.RepoRoot == "" {
cfg.RepoRoot = filepath.Dir(filepath.Dir(*agentDir))
}
// dataDir defaults to ./data relative to cwd (run-backend.bat cd's into backend/)
if cfg.DataDir == "" {
cwd, _ := os.Getwd()
cfg.DataDir = filepath.Join(cwd, "data")
}
if abs, err := filepath.Abs(cfg.DataDir); err == nil {
cfg.DataDir = abs
}
// --pi-cmd may include arguments separated by spaces, e.g.
// "node /path/to/tsx/dist/cli.mjs /path/to/pi/cli.ts"
// Split into executable + args so exec.Command receives them correctly.
if parts := strings.Fields(*piCmd); len(parts) > 0 {
cfg.PiCmd = parts[0]
cfg.PiArgs = parts[1:]
}
cfg.derivePaths()
// Override frontend dist if explicitly specified
if *frontendDist != "" {
cfg.FrontendDist = *frontendDist
}
return cfg
}
func (c *Config) derivePaths() {
a := c.AgentDir
c.SessionsDir = filepath.Join(a, "sessions")
c.SystemPromptFile = filepath.Join(a, "AGENTS.md")
c.ModelsConfigFile = filepath.Join(a, "models.json")
c.McpConfigFile = filepath.Join(a, "mcp.json")
c.McpCacheFile = filepath.Join(a, "mcp-cache.json")
c.SettingsFile = filepath.Join(a, "settings.json")
c.SkillsDir = filepath.Join(a, "skills")
c.SkillsDisabledDir = filepath.Join(a, "skills-disabled")
c.ExtensionsDir = filepath.Join(a, "extensions")
// frontend/dist 相对于二进制所在目录的上级
exe, err := os.Executable()
if err != nil {
exe, _ = os.Getwd()
}
exeDir := filepath.Dir(exe)
c.FrontendDist = filepath.Join(exeDir, "..", "frontend", "dist")
}
func Platform() string {
return runtime.GOOS
}
func Arch() string {
return runtime.GOARCH
}