Files
Agent-Native/runtime/resources/settings.go
T
weichenandCursor dfd0d23bf3 Add pi tool aliases, context files, and project trust
Why: Headless runs need the pi tool names, walked context files, prompt includes, and a trust gate before project settings are loaded.
Evidence: go test -count=1 ./runtime/tools/ ./runtime/resources/ ./runtime/skills/
Impact: Existing tool names stay registered. Aliases are added only when the underlying tool exists.
Refs: feature/pi-headless N4
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-01 10:12:26 +00:00

103 lines
2.4 KiB
Go

package resources
import (
"encoding/json"
"os"
"path/filepath"
)
// Trust is how a project directory is treated in non-interactive runs.
type Trust string
const (
TrustAsk Trust = "ask"
TrustAlways Trust = "always"
TrustNever Trust = "never"
)
// Settings is the global plus project configuration.
type Settings struct {
Trust Trust `json:"trust,omitempty"`
Model string `json:"model,omitempty"`
Thinking string `json:"thinking,omitempty"`
Tools []string `json:"tools,omitempty"`
Exclude []string `json:"exclude,omitempty"`
Vars map[string]string `json:"vars,omitempty"`
}
// LoadSettings reads global (optional) then project settings.
// Project keys override global keys. A missing file is an empty settings.
func LoadSettings(globalPath, projectPath string) (Settings, error) {
global, err := readSettings(globalPath)
if err != nil {
return Settings{}, err
}
project, err := readSettings(projectPath)
if err != nil {
return Settings{}, err
}
return mergeSettings(global, project), nil
}
// ProjectTrusted reports whether project resources may be loaded.
// ask and never refuse in non-interactive mode. approve forces trust.
func ProjectTrusted(trust Trust, approve, noApprove bool) bool {
if noApprove {
return false
}
if approve {
return true
}
return trust == TrustAlways
}
func readSettings(path string) (Settings, error) {
if path == "" {
return Settings{}, nil
}
raw, err := os.ReadFile(path)
if err != nil {
if os.IsNotExist(err) {
return Settings{}, nil
}
return Settings{}, err
}
var s Settings
if err := json.Unmarshal(raw, &s); err != nil {
return Settings{}, err
}
return s, nil
}
func mergeSettings(base, over Settings) Settings {
if over.Trust != "" {
base.Trust = over.Trust
}
if over.Model != "" {
base.Model = over.Model
}
if over.Thinking != "" {
base.Thinking = over.Thinking
}
if over.Tools != nil {
base.Tools = over.Tools
}
if over.Exclude != nil {
base.Exclude = over.Exclude
}
if len(over.Vars) > 0 {
if base.Vars == nil {
base.Vars = map[string]string{}
}
for k, v := range over.Vars {
base.Vars[k] = v
}
}
return base
}
// DefaultPaths returns the global and project settings paths for a cwd.
func DefaultPaths(home, cwd string) (string, string) {
return filepath.Join(home, ".agent-native", "settings.json"), filepath.Join(cwd, ".agent-native", "settings.json")
}