package main import ( "encoding/json" "os" "path/filepath" ) type Profile struct { Meta ProfileMeta `json:"meta"` Groups ProfileGroups `json:"groups"` Commands ProfileCommands `json:"commands"` Workdir ProfileWorkdir `json:"workdir"` FS ProfileFS `json:"filesystem"` Network ProfileNetwork `json:"network"` Env ProfileEnv `json:"environment"` } type ProfileMeta struct { Name string `json:"name"` Description string `json:"description"` } type ProfileGroups struct { Include []string `json:"include"` } type ProfileCommands struct { Allow []string `json:"allow"` Deny []string `json:"deny"` } type ProfileWorkdir struct { Access string `json:"access"` } type ProfileFS struct { Allow []string `json:"allow"` Read []string `json:"read"` Write []string `json:"write"` Deny []string `json:"deny"` } type ProfileNetwork struct { Block bool `json:"block"` AllowDomain []string `json:"allow_domain"` } type ProfileEnv struct { SetVars map[string]string `json:"set_vars"` DenyVars []string `json:"deny_vars"` } func DefaultProfilePath() (string, error) { home, err := os.UserHomeDir() if err != nil { return "", err } return filepath.Join(home, ".config", "nono", "profiles", "opencode-tinfoil.json"), nil } func LoadProfile(path string) (*Profile, error) { raw, err := os.ReadFile(path) if err != nil { return nil, err } clean := stripJSONCComments(raw) var p Profile if err := json.Unmarshal(clean, &p); err != nil { return nil, err } return &p, nil } func SaveProfile(path string, p *Profile) error { data, err := json.MarshalIndent(p, "", " ") if err != nil { return err } return os.WriteFile(path, data, 0644) } func stripJSONCComments(data []byte) []byte { var result []byte inString := false escaped := false i := 0 for i < len(data) { c := data[i] if inString { result = append(result, c) if escaped { escaped = false } else if c == '\\' { escaped = true } else if c == '"' { inString = false } i++ continue } if c == '"' { inString = true result = append(result, c) i++ continue } if c == '/' && i+1 < len(data) { if data[i+1] == '/' { for i < len(data) && data[i] != '\n' { i++ } continue } if data[i+1] == '*' { i += 2 for i+1 < len(data) && !(data[i] == '*' && data[i+1] == '/') { i++ } i += 2 continue } } result = append(result, c) i++ } return result }