provider/openai: - Fix doubled tool call args (argsComplete flag): Ollama sends complete args in the first streaming chunk then repeats them as delta, causing doubled JSON and 400 errors in elfs - Handle fs: prefix (gemma4 uses fs:grep instead of fs.grep) - Add Reasoning field support for Ollama thinking output cmd/gnoma: - Early TTY detection so logger is created with correct destination before any component gets a reference to it (fixes slog WARN bleed into TUI textarea) permission: - Exempt spawn_elfs and agent tools from safety scanner: elf prompt text may legitimately mention .env/.ssh/credentials patterns and should not be blocked tui/app: - /init retry chain: no-tool-calls → spawn_elfs nudge → write nudge (ask for plain text output) → TUI fallback write from streamBuf - looksLikeAgentsMD + extractMarkdownDoc: validate and clean fallback content before writing (reject refusals, strip narrative preambles) - Collapse thinking output to 3 lines; ctrl+o to expand (live stream and committed messages) - Stream-level filter for model pseudo-tool-call blocks: suppresses <<tool_code>>...</tool_code>> and <<function_call>>...<tool_call|> from entering streamBuf across chunk boundaries - sanitizeAssistantText regex covers both block formats - Reset streamFilterClose at every turn start
104 lines
2.6 KiB
Go
104 lines
2.6 KiB
Go
package config
|
|
|
|
import "time"
|
|
|
|
// Config is the top-level configuration.
|
|
type Config struct {
|
|
Provider ProviderSection `toml:"provider"`
|
|
Permission PermissionSection `toml:"permission"`
|
|
Tools ToolsSection `toml:"tools"`
|
|
RateLimits RateLimitSection `toml:"rate_limits"`
|
|
Security SecuritySection `toml:"security"`
|
|
}
|
|
|
|
// SecuritySection configures the secret scanner and firewall.
|
|
//
|
|
// Example config:
|
|
//
|
|
// [security]
|
|
// entropy_threshold = 4.5
|
|
//
|
|
// [[security.patterns]]
|
|
// name = "internal_token"
|
|
// regex = "mycompany_[a-zA-Z0-9]{32}"
|
|
// action = "redact"
|
|
type SecuritySection struct {
|
|
EntropyThreshold float64 `toml:"entropy_threshold"`
|
|
Patterns []PatternConfig `toml:"patterns"`
|
|
}
|
|
|
|
type PatternConfig struct {
|
|
Name string `toml:"name"`
|
|
Regex string `toml:"regex"`
|
|
Action string `toml:"action"` // "redact" (default), "block", "warn"
|
|
}
|
|
|
|
type PermissionSection struct {
|
|
Mode string `toml:"mode"`
|
|
Rules []PermissionRule `toml:"rules"`
|
|
}
|
|
|
|
type PermissionRule struct {
|
|
Tool string `toml:"tool"`
|
|
Pattern string `toml:"pattern"`
|
|
Action string `toml:"action"`
|
|
}
|
|
|
|
type ProviderSection struct {
|
|
Default string `toml:"default"`
|
|
Model string `toml:"model"`
|
|
MaxTokens int64 `toml:"max_tokens"`
|
|
Temperature *float64 `toml:"temperature"` // TODO(M8): wire to provider.Request.Temperature
|
|
APIKeys map[string]string `toml:"api_keys"`
|
|
Endpoints map[string]string `toml:"endpoints"`
|
|
}
|
|
|
|
type ToolsSection struct {
|
|
BashTimeout Duration `toml:"bash_timeout"`
|
|
MaxFileSize int64 `toml:"max_file_size"` // TODO(M8): wire to fs tool WithMaxFileSize option
|
|
}
|
|
|
|
// RateLimitSection allows overriding default rate limits per provider.
|
|
//
|
|
// Example config:
|
|
//
|
|
// [rate_limits.mistral]
|
|
// tier = "starter"
|
|
// rps = 1
|
|
// spend_cap = 20.0
|
|
//
|
|
// [rate_limits.anthropic]
|
|
// tier = "tier2"
|
|
// rpm = 1000
|
|
// itpm = 450000
|
|
// otpm = 90000
|
|
type RateLimitSection map[string]RateLimitOverride
|
|
|
|
type RateLimitOverride struct {
|
|
Tier string `toml:"tier"`
|
|
RPS float64 `toml:"rps"`
|
|
RPM int `toml:"rpm"`
|
|
RPD int `toml:"rpd"`
|
|
TPM int `toml:"tpm"`
|
|
ITPM int `toml:"itpm"`
|
|
OTPM int `toml:"otpm"`
|
|
TokensMonth int64 `toml:"tokens_month"`
|
|
SpendCap float64 `toml:"spend_cap"`
|
|
}
|
|
|
|
// Duration wraps time.Duration for TOML string parsing (e.g. "30s", "5m").
|
|
type Duration time.Duration
|
|
|
|
func (d *Duration) UnmarshalText(text []byte) error {
|
|
parsed, err := time.ParseDuration(string(text))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*d = Duration(parsed)
|
|
return nil
|
|
}
|
|
|
|
func (d Duration) Duration() time.Duration {
|
|
return time.Duration(d)
|
|
}
|