源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
package defaults
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type generatedDefaultsSpec struct {
|
||||
State generatedStateDefaults
|
||||
}
|
||||
|
||||
type generatedStateDefaults struct {
|
||||
ProductionDirName string
|
||||
DevelopmentDirName string
|
||||
RunDirName string
|
||||
ListenerInfoFileName string
|
||||
}
|
||||
|
||||
type ResolvedDefaults struct {
|
||||
Runtime RuntimeDefaults
|
||||
State StateDefaults
|
||||
}
|
||||
|
||||
type RuntimeDefaults struct {
|
||||
Env string
|
||||
}
|
||||
|
||||
type StateDefaults struct {
|
||||
RootDir string
|
||||
RunDir string
|
||||
TuttidListenerInfoPath string
|
||||
}
|
||||
|
||||
func ResolveDefaultsFromEnv() ResolvedDefaults {
|
||||
env := resolveTuttiEnv()
|
||||
stateRootDir := resolveStateRootDir(env)
|
||||
runDir := resolveRunDir(stateRootDir)
|
||||
|
||||
return ResolvedDefaults{
|
||||
Runtime: RuntimeDefaults{
|
||||
Env: env,
|
||||
},
|
||||
State: StateDefaults{
|
||||
RootDir: stateRootDir,
|
||||
RunDir: runDir,
|
||||
TuttidListenerInfoPath: resolveListenerInfoPath(runDir),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resolveTuttiEnv() string {
|
||||
value := strings.ToLower(resolveStringOverride("TUTTI_ENV", ""))
|
||||
switch value {
|
||||
case "dev", "development", "local":
|
||||
return "development"
|
||||
default:
|
||||
return "production"
|
||||
}
|
||||
}
|
||||
|
||||
func resolveStateRootDir(env string) string {
|
||||
override := resolveStringOverride("TUTTI_STATE_DIR", "")
|
||||
if override != "" {
|
||||
return override
|
||||
}
|
||||
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil || strings.TrimSpace(homeDir) == "" {
|
||||
if env == "development" {
|
||||
return generatedDefaults.State.DevelopmentDirName
|
||||
}
|
||||
return generatedDefaults.State.ProductionDirName
|
||||
}
|
||||
|
||||
dirName := generatedDefaults.State.ProductionDirName
|
||||
if env == "development" {
|
||||
dirName = generatedDefaults.State.DevelopmentDirName
|
||||
}
|
||||
|
||||
return filepath.Join(homeDir, dirName)
|
||||
}
|
||||
|
||||
func resolveRunDir(stateRootDir string) string {
|
||||
override := resolveStringOverride("TUTTID_RUN_DIR", "")
|
||||
if override != "" {
|
||||
return override
|
||||
}
|
||||
|
||||
return filepath.Join(stateRootDir, generatedDefaults.State.RunDirName)
|
||||
}
|
||||
|
||||
func resolveListenerInfoPath(runDir string) string {
|
||||
override := resolveStringOverride("TUTTID_LISTENER_INFO_PATH", "")
|
||||
if override != "" {
|
||||
return override
|
||||
}
|
||||
|
||||
return filepath.Join(runDir, generatedDefaults.State.ListenerInfoFileName)
|
||||
}
|
||||
|
||||
func resolveStringOverride(name string, fallback string) string {
|
||||
override := strings.TrimSpace(os.Getenv(name))
|
||||
if override != "" {
|
||||
return override
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package defaults
|
||||
|
||||
// Code generated by tools/scripts/generate-defaults.mjs. DO NOT EDIT.
|
||||
|
||||
var generatedDefaults = generatedDefaultsSpec{
|
||||
State: generatedStateDefaults{
|
||||
ProductionDirName: ".tutti",
|
||||
DevelopmentDirName: ".tutti-dev",
|
||||
RunDirName: "run",
|
||||
ListenerInfoFileName: "tuttid.listener.json",
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package defaults
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestResolveDefaultsFromEnvUsesGeneratedStateDefaults(t *testing.T) {
|
||||
t.Setenv("HOME", "/tmp/tutti-cli-home")
|
||||
t.Setenv("TUTTI_ENV", "development")
|
||||
t.Setenv("TUTTI_STATE_DIR", "")
|
||||
t.Setenv("TUTTID_RUN_DIR", "")
|
||||
t.Setenv("TUTTID_LISTENER_INFO_PATH", "")
|
||||
|
||||
got := ResolveDefaultsFromEnv()
|
||||
|
||||
if got.Runtime.Env != "development" {
|
||||
t.Fatalf("env = %q, want development", got.Runtime.Env)
|
||||
}
|
||||
wantRoot := filepath.Join("/tmp/tutti-cli-home", ".tutti-dev")
|
||||
if got.State.RootDir != wantRoot {
|
||||
t.Fatalf("root dir = %q, want %q", got.State.RootDir, wantRoot)
|
||||
}
|
||||
wantListenerInfo := filepath.Join(wantRoot, "run", "tuttid.listener.json")
|
||||
if got.State.TuttidListenerInfoPath != wantListenerInfo {
|
||||
t.Fatalf("listener info path = %q, want %q", got.State.TuttidListenerInfoPath, wantListenerInfo)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveDefaultsFromEnvHonorsListenerInfoOverride(t *testing.T) {
|
||||
t.Setenv("TUTTID_LISTENER_INFO_PATH", "/tmp/tuttid.listener.json")
|
||||
|
||||
got := ResolveDefaultsFromEnv()
|
||||
|
||||
if got.State.TuttidListenerInfoPath != "/tmp/tuttid.listener.json" {
|
||||
t.Fatalf("listener info path = %q", got.State.TuttidListenerInfoPath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveDefaultsFromEnvAppliesOverrides(t *testing.T) {
|
||||
t.Setenv("TUTTI_ENV", "development")
|
||||
t.Setenv("TUTTI_STATE_DIR", "/tmp/tutti-state")
|
||||
t.Setenv("TUTTID_LISTENER_INFO_PATH", "/tmp/tuttid.listener.json")
|
||||
|
||||
got := ResolveDefaultsFromEnv()
|
||||
|
||||
if got.Runtime.Env != "development" {
|
||||
t.Fatalf("env = %q, want development", got.Runtime.Env)
|
||||
}
|
||||
if got.State.RootDir != "/tmp/tutti-state" {
|
||||
t.Fatalf("root dir = %q", got.State.RootDir)
|
||||
}
|
||||
if got.State.TuttidListenerInfoPath != "/tmp/tuttid.listener.json" {
|
||||
t.Fatalf("listener info path = %q", got.State.TuttidListenerInfoPath)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user