collet 0.1.0

Relentless agentic coding orchestrator with zero-drop agent loops
Documentation
pub mod file;
pub mod provider;
pub mod rag;
pub mod remote;
pub mod sections;

// ── Re-exports (preserve existing `config::types::*` paths) ──────────────────
pub use file::{ConfigFile, LegacyForkSection, LegacyHiveSection};
pub use provider::{AgentDef, AgentsSection, ModelOverride, ModelRole, ProviderEntry};
pub use rag::{BridgeRagConfig, BridgeRagSection, RagConfig};
#[cfg(test)]
pub use remote::WebSection;
pub use remote::{
    ChannelMappingEntry, DiscordSection, RemotePermissionsSection, SlackSection, TelegramSection,
    WebConfig,
};
pub use sections::ApiSection;

// ---------------------------------------------------------------------------
// Top-level Config (runtime)
// ---------------------------------------------------------------------------

use std::fmt;

use crate::agent::swarm::config::CollaborationConfig;

/// Fully resolved application configuration.
#[derive(Clone)]
pub struct Config {
    // ── API ──
    pub api_key: String,
    pub base_url: String,
    pub model: String,
    pub max_tokens: u32,
    /// Provider-level tool support override (None = use model_profile).
    pub supports_tools: Option<bool>,

    // ── Agent ──
    pub tool_timeout_secs: u64,
    pub task_timeout_secs: u64,
    pub max_iterations: u32,
    pub max_continuations: u32,
    pub circuit_breaker_threshold: u32,
    /// Seconds of no streaming chunk before retrying (default: 120).
    pub stream_idle_timeout_secs: u64,
    /// Max number of stream retry attempts on idle timeout (default: 5).
    pub stream_max_retries: u32,
    /// Milliseconds to pause between agent iterations (default: 50).
    /// The 429 rate-limit retry logic provides its own exponential backoff,
    /// so this only needs to be a minimal courtesy delay.
    pub iteration_delay_ms: u64,
    /// Sampling temperature to include in API requests (None = omit field).
    /// Resolved from active provider override, then global config, then None.
    /// Silently dropped for reasoning models (supports_reasoning = true).
    pub temperature: Option<f32>,
    /// Reasoning/thinking budget tokens (None = omit from request).
    /// Only sent when the active model profile has supports_reasoning = true.
    /// Takes priority over `reasoning_effort`.
    pub thinking_budget_tokens: Option<u32>,
    /// Reasoning effort level: "low", "medium", "high" (None = omit from request).
    /// Ignored if `thinking_budget_tokens` is set.
    pub reasoning_effort: Option<String>,

    // ── Model overrides (global < model < agent resolution chain)
    pub model_overrides: Vec<ModelOverride>,

    // ── Agents (named agent definitions for Tab/Shift+Tab switching)
    pub agents: Vec<AgentDef>,

    // ── Context ──
    pub context_max_tokens: usize,
    pub compaction_threshold: f32,
    /// When true, adaptively adjusts compaction_threshold based on tool density and turn size.
    /// Set to false to use compaction_threshold strictly as-is.
    pub adaptive_compaction: bool,

    // ── Hooks ──
    pub auto_commit: bool,
    pub lint_cmd: Option<String>,
    pub test_cmd: Option<String>,

    // ── UI ──
    pub theme: String,
    /// Show debug monitor panel in sidebar (memory, CPU, tokens, tool calls).
    pub debug_mode: bool,

    // ── Benchmark logging ──
    /// How many days to keep bench.jsonl entries (0 = keep forever).
    pub bench_retain_days: u32,

    // ── Collaboration mode (none | fork | hive | flock) ──
    pub collaboration: CollaborationConfig,

    // ── Paths ──
    /// Root directory for all collet data (config, sessions, worktrees, knowledge).
    /// Defaults to `~/.collet`. Overridable via `[paths] home` in config.toml
    /// or `COLLET_HOME` env var.
    pub collet_home: std::path::PathBuf,

    // ── Debug performance targets ──
    pub debug_targets: DebugTargets,

    // ── Web server ──
    pub web: WebConfig,

    // ── Optimizer ──
    /// Auto-trigger optimization suggestions (ctx≥40%, post-compaction). Default: true.
    pub auto_optimize: bool,

    // ── Model routing ──
    /// Automatically select lighter/heavier model based on task complexity. Default: false.
    pub auto_route: bool,

    // ── Security ──
    /// PII/sensitive data filter (default: true).
    pub pii_filter: bool,
    /// Paths that the agent may never read or write.  See `SecuritySection::deny_paths`.
    pub deny_paths: Vec<String>,
    /// When false, resolve symlinks and re-check against deny_paths. Default: false.
    pub follow_symlinks: bool,

    // ── RAG ──
    pub rag: Option<RagConfig>,

    // ── Soul ──
    /// Enable Soul.md agent personality persistence. Default: false.
    pub soul_enabled: bool,

    // ── Evolution ──
    /// Auto-trigger evolution loop after agent task completes. Default: false.
    pub evolution_enabled: bool,
    /// Evolver model override for auto-evolution (None = use config.model).
    pub evolution_model: Option<String>,
    /// Cycles per auto-evolution trigger. Default: 1.
    pub evolution_cycles: u32,

    // ── Telemetry ──
    /// Master telemetry switch (default: true, override with `COLLET_TELEMETRY=0`).
    pub telemetry_enabled: bool,
    /// Send anonymous crash/error reports (default: true).
    pub telemetry_error_reporting: bool,
    /// Send anonymous usage analytics (default: true).
    pub telemetry_analytics: bool,

    // ── CLI provider ──
    /// When the active provider is a CLI agent (e.g. `claude -p`), this holds
    /// the binary name. The agent loop uses this to bypass HTTP streaming and
    /// spawn the CLI process instead.
    pub cli: Option<String>,
    /// Extra arguments passed before the prompt (e.g. `["-p"]` for claude).
    pub cli_args: Vec<String>,
    /// Extra arguments appended in yolo mode (e.g. `["--dangerously-skip-permissions"]` for claude).
    pub cli_yolo_args: Vec<String>,
    /// If set, passes the model via this environment variable instead of `--model`.
    pub cli_model_env: Option<String>,
    /// If true, model selection is not passed to the CLI at all.
    pub cli_skip_model: bool,
    /// Environment variables to set in yolo mode, as "KEY=VALUE" strings.
    pub cli_yolo_env: Vec<String>,
    /// CLI flag for passing max iterations (e.g. "--max-turns"). None = not supported.
    pub cli_max_turns_flag: Option<String>,

    // ── Provider registry (for rate-limit fallback) ──
    /// All configured providers (API + CLI). Used by the rate limiter
    /// for capability-based fallback and CLI fallback discovery.
    pub providers: Vec<ProviderEntry>,

    // ── Proxy headers ──
    /// Extra HTTP headers injected into every API request.
    /// Useful for routing through a security proxy.
    /// Set via `[proxy_headers]` in config.toml or `COLLET_PROXY_HEADERS` env var.
    pub proxy_headers: std::collections::HashMap<String, String>,

    // ── Runtime-only flags (not persisted to config.toml) ──
    /// Set by `--yolo` CLI flag. Starts the session in Yolo approval mode
    /// (all tool calls auto-approved). Independent of `auto_commit`.
    pub yolo: bool,

    /// Shared iteration budget for external limit adjustment (web UI "extend").
    /// Set by swarm subagent spawning; the agent guard reads this atomically
    /// so external controllers can bump the limit without stopping the agent.
    pub iteration_budget: Option<crate::agent::guard::IterationBudget>,
}

impl fmt::Debug for Config {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Config")
            .field("api_key", &"[REDACTED]")
            .field("base_url", &self.base_url)
            .field("model", &self.model)
            .field("max_tokens", &self.max_tokens)
            .finish_non_exhaustive()
    }
}

/// Performance target thresholds for debug monitor.
/// Metrics exceeding targets are highlighted in the sidebar.
#[derive(Debug, Clone)]
pub struct DebugTargets {
    /// Target: average tool call latency in ms (highlight if exceeded).
    pub tool_latency_avg_ms: u64,
    /// Target: average API call latency in ms (highlight if exceeded).
    pub api_latency_avg_ms: u64,
    /// Target: minimum tool success rate % (highlight if below).
    pub tool_success_rate: f32,
    /// Target: max tokens consumed per iteration (highlight if exceeded).
    pub tokens_per_iteration: u64,
    /// Target: max tool calls per iteration (highlight if exceeded).
    pub tools_per_iteration: u32,
}

impl Default for DebugTargets {
    fn default() -> Self {
        Self {
            tool_latency_avg_ms: 2000,
            api_latency_avg_ms: 5000,
            tool_success_rate: 95.0,
            tokens_per_iteration: 8000,
            tools_per_iteration: 5,
        }
    }
}