Files
kandev/apps/backend/internal/runtimeflags/config.go
T
João Salavisa 1a3c134f1a feat(plugins): ship the plugin system without a feature flag (#2086)
Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 08:59:34 +01:00

114 lines
3.8 KiB
Go

package runtimeflags
import (
"os"
"strings"
"github.com/kandev/kandev/internal/common/config"
"github.com/kandev/kandev/internal/profiles"
)
const (
featureOfficeKey = "features.office"
featureAppStatusBarKey = "features.appStatusBar"
featureAuthKey = "features.auth"
featureClaudeBackgroundPromptHandoffKey = "features.claudeBackgroundPromptHandoff"
debugDevModeKey = "debug.devMode"
envFeaturesOffice = "KANDEV_FEATURES_OFFICE"
envFeaturesAppStatusBar = "KANDEV_FEATURES_APP_STATUS_BAR"
envFeaturesAuth = "KANDEV_FEATURES_AUTH"
envFeaturesClaudeBackgroundPromptHandoff = "KANDEV_FEATURES_CLAUDE_BACKGROUND_PROMPT_HANDOFF"
envDebugDevMode = "KANDEV_DEBUG_DEV_MODE"
envDebugPprofEnabled = "KANDEV_DEBUG_PPROF_ENABLED"
envDebugAgentMessages = "KANDEV_DEBUG_AGENT_MESSAGES"
)
func OptionsFromConfig(cfg *config.Config) Options {
return Options{
DefaultValues: ValuesFromConfig(cfg),
RuntimeValues: ValuesFromConfig(cfg),
EnvValues: map[string]bool{
envFeaturesOffice: isTruthy(os.Getenv(envFeaturesOffice)),
envFeaturesAppStatusBar: isTruthy(os.Getenv(envFeaturesAppStatusBar)),
envFeaturesAuth: isTruthy(os.Getenv(envFeaturesAuth)),
envFeaturesClaudeBackgroundPromptHandoff: isTruthy(
os.Getenv(envFeaturesClaudeBackgroundPromptHandoff),
),
envDebugDevMode: isTruthy(os.Getenv(envDebugDevMode)),
envDebugPprofEnabled: isTruthy(os.Getenv(envDebugPprofEnabled)),
envDebugAgentMessages: isTruthy(os.Getenv(envDebugAgentMessages)),
},
IsExplicitEnv: func(name string) bool {
_, ok := os.LookupEnv(name)
return ok && !profiles.WasApplied(name)
},
}
}
func ValuesFromConfig(cfg *config.Config) map[string]bool {
debugEnabled := cfg.Debug.DevMode || cfg.Debug.PprofEnabled
return map[string]bool{
featureOfficeKey: cfg.Features.Office,
featureAppStatusBarKey: cfg.Features.AppStatusBar,
featureAuthKey: cfg.Features.Auth,
featureClaudeBackgroundPromptHandoffKey: cfg.Features.ClaudeBackgroundPromptHandoff,
debugDevModeKey: debugEnabled,
}
}
func ApplyStatesToConfig(cfg *config.Config, states []RuntimeFlagState) {
for _, state := range states {
switch state.Key {
case featureOfficeKey:
cfg.Features.Office = state.EffectiveValue
case featureAppStatusBarKey:
cfg.Features.AppStatusBar = state.EffectiveValue
case featureAuthKey:
cfg.Features.Auth = state.EffectiveValue
case featureClaudeBackgroundPromptHandoffKey:
cfg.Features.ClaudeBackgroundPromptHandoff = state.EffectiveValue
case debugDevModeKey:
cfg.Debug.DevMode = state.EffectiveValue
cfg.Debug.PprofEnabled = state.EffectiveValue
if state.EffectiveValue {
setIfNotExplicit(envDebugAgentMessages, "true")
setIfNotExplicit(envDebugPprofEnabled, "true")
} else {
unsetIfNotExplicit(envDebugAgentMessages)
unsetIfNotExplicit(envDebugPprofEnabled)
}
}
}
}
func RuntimeOptionsFromAppliedConfig(defaults map[string]bool, cfg *config.Config) Options {
opts := OptionsFromConfig(cfg)
opts.DefaultValues = defaults
opts.RuntimeValues = ValuesFromConfig(cfg)
return opts
}
func setIfNotExplicit(name, value string) {
if _, ok := os.LookupEnv(name); ok && !profiles.WasApplied(name) {
return
}
_ = os.Setenv(name, value)
profiles.MarkApplied(name)
}
func unsetIfNotExplicit(name string) {
if _, ok := os.LookupEnv(name); ok && !profiles.WasApplied(name) {
return
}
_ = os.Unsetenv(name)
}
func isTruthy(s string) bool {
switch strings.ToLower(s) {
case "true", "1", "yes", "on":
return true
default:
return false
}
}