11363f3b97
Gap 6 (M3): 7 new bash security checks (8-14) - JQ injection, obfuscated flags (Unicode lookalike hyphens), /proc/environ access, brace expansion, Unicode whitespace, zsh dangerous constructs, comment-quote desync - Total: 14 checks (was 7) Gap 7 (M5): Model picker numbered selection - /model shows numbered sorted list, /model 3 picks by number Gap 8 (M5): /config set command - /config set provider.default mistral writes to .gnoma/config.toml - Whitelisted keys: provider.default, provider.model, permission.mode - New config/write.go with TOML round-trip via BurntSushi/toml Gap 9 (M6): Simple token estimator - EstimateTokens (len/4 heuristic), EstimateMessages (content + overhead) - PreEstimate on Tracker for proactive compaction triggering Gap 10 (M7): Router quality feedback from elfs - Router.Outcome + ReportOutcome (logs for now, M9 bandit uses later) - Manager tracks armID/taskType per elf via elfMeta map - Manager.ReportResult called after elf completion in both agent + batch tools
67 lines
1.5 KiB
Go
67 lines
1.5 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/BurntSushi/toml"
|
|
)
|
|
|
|
// SetProjectConfig writes a single key=value to the project config file (.gnoma/config.toml).
|
|
// Only whitelisted keys are supported.
|
|
func SetProjectConfig(key, value string) error {
|
|
allowed := map[string]bool{
|
|
"provider.default": true,
|
|
"provider.model": true,
|
|
"permission.mode": true,
|
|
}
|
|
if !allowed[key] {
|
|
return fmt.Errorf("unknown config key %q (supported: %s)", key, strings.Join(allowedKeys(), ", "))
|
|
}
|
|
|
|
path := filepath.Join(".gnoma", "config.toml")
|
|
|
|
// Load existing config or start fresh
|
|
var cfg Config
|
|
if data, err := os.ReadFile(path); err == nil {
|
|
toml.Decode(string(data), &cfg)
|
|
}
|
|
if cfg.Provider.APIKeys == nil {
|
|
cfg.Provider.APIKeys = make(map[string]string)
|
|
}
|
|
if cfg.Provider.Endpoints == nil {
|
|
cfg.Provider.Endpoints = make(map[string]string)
|
|
}
|
|
|
|
// Apply the change
|
|
switch key {
|
|
case "provider.default":
|
|
cfg.Provider.Default = value
|
|
case "provider.model":
|
|
cfg.Provider.Model = value
|
|
case "permission.mode":
|
|
cfg.Permission.Mode = value
|
|
}
|
|
|
|
// Ensure directory exists
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
return fmt.Errorf("create config dir: %w", err)
|
|
}
|
|
|
|
// Write
|
|
f, err := os.Create(path)
|
|
if err != nil {
|
|
return fmt.Errorf("create config file: %w", err)
|
|
}
|
|
defer f.Close()
|
|
|
|
enc := toml.NewEncoder(f)
|
|
return enc.Encode(cfg)
|
|
}
|
|
|
|
func allowedKeys() []string {
|
|
return []string{"provider.default", "provider.model", "permission.mode"}
|
|
}
|