config

package
v1.35.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 31, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Overview

Package config loads and merges odek configuration from multiple sources.

Priority (lowest to highest):

  1. ~/.odek/config.json — global defaults (shared across projects)
  2. ./odek.json — project-specific overrides
  3. ODEK_* env vars — runtime/environment overrides
  4. CLI flags — explicit invocation overrides (highest)

Both config files are optional. Missing files are silently ignored. String values in config files support ${VAR} environment variable substitution (e.g. "api_key": "${MY_API_KEY}"). Use $$ for a literal dollar sign.

Index

Constants

View Source
const (
	// BudgetInheritOperator gives every sub-agent the operator-configured
	// limits regardless of what the parent has already spent (pre-1.28
	// behavior; the default).
	BudgetInheritOperator = "operator"
	// BudgetInheritShare gives a sub-agent min(operator limits, parent's
	// remaining budget) so a near-exhausted parent cannot spawn children
	// with fresh headroom.
	BudgetInheritShare = "share"

	// DefaultProfileName is the built-in default sub-agent capability
	// profile (P4). Materialized into ResolvedConfig.Profiles by
	// injectBuiltinDefaultProfile unless the operator defines their own
	// profile with this name or opts out via subagent.default_profile="none".
	DefaultProfileName = "default"

	// DefaultProfileDisabled is the subagent.default_profile sentinel that
	// disables the built-in default envelope entirely. Honored only from the
	// operator's config — never from a task file or the --profile flag, so
	// a delegating model cannot strip the operator's envelope.
	DefaultProfileDisabled = "none"
)

Budget inheritance modes for the subagent section.

View Source
const (
	DefaultSandboxNetwork = "none"
)

Variables

This section is empty.

Functions

func GlobalConfigPath

func GlobalConfigPath() string

GlobalConfigPath returns the path to the global config file. Uses $HOME/.odek/config.json.

func ProjectConfigPath

func ProjectConfigPath() string

ProjectConfigPath returns the path to the project-level config file. Uses ./odek.json relative to the current working directory.

func SecretsEnvNames added in v1.26.0

func SecretsEnvNames() []string

SecretsEnvNames returns the environment variable names that were injected from ~/.odek/secrets.env during LoadConfig. Callers spawning child processes strip these from the inherited environment.

Types

type CLIFlags

type CLIFlags struct {
	Model    string
	BaseURL  string
	System   string
	Thinking string
	MaxIter  int   // 0 = not set
	Sandbox  *bool // nil = not set
	NoColor  *bool // nil = not set
	NoAgents *bool // nil = not set
	Learn    *bool // nil = not set
	Task     string

	// ToolsEnabled and ToolsDisabled control which tools are exposed to the LLM.
	// These override file/env config.
	ToolsEnabled  []string
	ToolsDisabled []string

	// PromptCaching enables prompt caching markers for supported providers.
	// Config: prompt_caching, ODEK_PROMPT_CACHING, --prompt-caching.
	PromptCaching *bool // nil = not set

	// Stream enables SSE streaming of LLM responses for the main think
	// step (default: off). Config: stream, ODEK_STREAM, --stream.
	Stream *bool // nil = not set

	// Compaction enables LLM-based rolling compaction of trimmed context
	// (default: on). Config: compaction, ODEK_COMPACTION,
	// --compaction / --no-compaction.
	Compaction *bool // nil = not set

	// Planning enables the built-in plan tool and its protected plan message
	// (default: on). Config: planning.enabled, ODEK_PLANNING,
	// --planning / --no-planning.
	Planning *bool // nil = not set

	// Sandbox-specific
	SandboxImage    string
	SandboxNetwork  string
	SandboxMemory   string
	SandboxCPUs     string
	SandboxUser     string
	SandboxReadonly *bool // nil = not set

	// InteractionMode controls how tool-call progress is surfaced.
	// "engaging" (default) = emoji-rich narration, progress message edited.
	// "enhance" = per-tool narrated messages appended, progress header kept.
	// "verbose" = raw tool names, args, and results.
	// "off" = no intermediate progress output, clean answer only.
	InteractionMode string

	// Extended memory subsystem CLI overrides.
	MemoryExtendedEnabled                     *bool // nil = not set
	MemoryExtendedMaxSizeMB                   int   // 0 = not set
	MemoryExtendedAtomMaxChars                int   // 0 = not set
	MemoryExtendedMemoryBudgetChars           int   // 0 = not set
	MemoryExtendedUserStateTurnInterval       int   // 0 = not set
	MemoryExtendedUserStateMaxPending         int   // 0 = not set
	MemoryExtendedAssociationsEnabled         *bool // nil = not set
	MemoryExtendedAssociationSemanticTopK     int   // 0 = not set
	MemoryExtendedProactiveReturnAfterBreak   *bool // nil = not set
	MemoryExtendedStyleMirroringEnabled       *bool // nil = not set
	MemoryExtendedAnaphoraResolutionEnabled   *bool // nil = not set
	MemoryExtendedFollowUpAnticipationEnabled *bool // nil = not set

	// Guard subsystem CLI overrides.
	GuardProvider         string  // "" = not set
	GuardURL              string  // "" = not set
	GuardBatchURL         string  // "" = not set
	GuardLongURL          string  // "" = not set
	GuardSocketPath       string  // "" = not set
	GuardThreshold        float64 // 0 = not set
	GuardTimeoutSeconds   int     // 0 = not set
	GuardFallbackToLocal  *bool   // nil = not set
	GuardScanMemory       *bool   // nil = not set
	GuardScanSystemPrompt *bool   // nil = not set
	GuardScanMCP          *bool   // nil = not set
	GuardScanSkills       *bool   // nil = not set
	GuardScanToolOutputs  *bool   // nil = not set
	GuardScanTelegram     *bool   // nil = not set

	// TrustedProxies is a list of IP addresses or CIDR ranges of reverse proxies
	// whose X-Forwarded-For / X-Real-Ip headers are trusted. Empty means headers
	// are ignored even from loopback. Only used by `odek serve`.
	TrustedProxies []string

	// Execution-budget CLI overrides (odek-extension/v1). CLI flags are
	// operator intent: they set limits explicitly, 0 = flag not passed.
	MaxRuntimeSeconds int64
	MaxToolCalls      int64
	MaxInputTokens    int64
	MaxOutputTokens   int64
	MaxCostUSD        float64
}

CLIFlags holds values parsed from the CLI. Zero/nil values mean the flag was not explicitly passed — the config loader will look at lower priority layers for these fields.

CLIFlags holds CLI-only configuration. These fields participate in the same merge chain: global file → project file → ODEK_* env → CLI. Fields typed as *bool distinguish "explicitly set to false" from "not set", which matters when the config file says "sandbox_readonly: false" (user explicitly wants writable) vs the field being absent (inherit from lower layer or default).

type FileConfig

type FileConfig struct {
	Model   string `json:"model,omitempty"`
	BaseURL string `json:"base_url,omitempty"`
	APIKey  string `json:"api_key,omitempty"`

	Thinking string `json:"thinking,omitempty"`
	MaxIter  int    `json:"max_iterations,omitempty"`

	Sandbox  *bool `json:"sandbox,omitempty"`
	NoColor  *bool `json:"no_color,omitempty"`
	NoAgents *bool `json:"no_agents,omitempty"`

	// PromptCaching enables prompt caching markers for supported providers.
	PromptCaching *bool `json:"prompt_caching,omitempty"`

	// Stream enables SSE streaming of LLM responses for the main think
	// step (default: off). Config: stream, ODEK_STREAM, --stream.
	Stream *bool `json:"stream,omitempty"`

	// Compaction enables LLM-based rolling compaction of trimmed context
	// (default: on; set false to explicitly disable).
	Compaction *bool `json:"compaction,omitempty"`

	// Planning configures the built-in plan tool (docs/PLANNING.md).
	// The global config may set anything; the project config may set
	// enabled:false and may only LOWER the caps (see clampProjectPlanning).
	Planning *PlanningFileConfig `json:"planning,omitempty"`

	System string `json:"system,omitempty"`

	// Sandbox-specific fields.
	SandboxImage    string            `json:"sandbox_image,omitempty"`
	SandboxNetwork  string            `json:"sandbox_network,omitempty"`
	SandboxReadonly *bool             `json:"sandbox_readonly,omitempty"`
	SandboxMemory   string            `json:"sandbox_memory,omitempty"`
	SandboxCPUs     string            `json:"sandbox_cpus,omitempty"`
	SandboxUser     string            `json:"sandbox_user,omitempty"`
	SandboxEnv      map[string]string `json:"sandbox_env,omitempty"`
	SandboxVolumes  []string          `json:"sandbox_volumes,omitempty"`

	// Dangerous operation approval settings.
	Dangerous *danger.DangerousConfig `json:"dangerous,omitempty"`

	// Skills section (see internal/skills package).
	Skills *SkillsConfig `json:"skills,omitempty"`

	// Memory section controls the persistent memory system.
	Memory *memory.MemoryConfig `json:"memory,omitempty"`

	// Guard configures the prompt-injection guard subsystem.
	// Operator-controlled: rejected from project-level ./odek.json.
	Guard *guard.Config `json:"guard,omitempty"`

	// Embedding is the shared default embedding backend for semantic retrieval.
	// Every subsystem (memory, sessions, skills) uses it unless that subsystem
	// sets its own override (memory.embedding / sessions.embedding /
	// skills.embedding). See internal/embedding.Config.
	Embedding *embedding.Config `json:"embedding,omitempty"`

	// Sessions configures the session subsystem. Currently only an optional
	// embedding override for semantic session_search.
	Sessions *SessionsConfig `json:"sessions,omitempty"`

	// MCPServers maps server names to MCP server configurations.
	// Each server is an external MCP server (e.g., Playwright, database,
	// web scraping) whose tools are exposed to the agent.
	// Format matches Claude Code's mcpServers config:
	//
	//	"mcp_servers": {
	//	  "playwright": {
	//	    "command": "npx",
	//	    "args": ["@playwright/mcp"]
	//\t  }
	//\t}
	MCPServers map[string]mcpclient.ServerConfig `json:"mcp_servers,omitempty"`

	// MaxConcurrency limits how many sub-agent tasks run in parallel.
	// Config: max_concurrency, ODEK_MAX_CONCURRENCY.
	// Default: 3.
	MaxConcurrency int `json:"max_concurrency,omitempty"`

	// MaxToolParallel limits how many tool calls run concurrently per
	// agent iteration. Config: max_tool_parallel.
	// Default: 0 (loop uses default of 4).
	MaxToolParallel int `json:"max_tool_parallel,omitempty"`

	// TrustedProxies lists IP addresses or CIDR ranges of reverse proxies whose
	// X-Forwarded-For / X-Real-Ip headers are trusted. Empty means headers are
	// ignored even from loopback. Config: trusted_proxies, ODEK_TRUSTED_PROXIES.
	// Only used by `odek serve`.
	TrustedProxies []string `json:"trusted_proxies,omitempty"`

	// LLM tunes the shared LLM client (internal/llm). Currently: the SSE
	// stream idle watchdog — time between events (keepalives count) before
	// the stream is dropped and retried. Thinking models can spend minutes
	// before their first event; 0 keeps the built-in default (120s).
	// Config: llm.stream_idle_timeout_seconds, ODEK_STREAM_IDLE_TIMEOUT_SECONDS.
	LLM *LLMConfig `json:"llm,omitempty"`

	// Telegram configures the Telegram bot integration.
	Telegram *telegram.TelegramConfig `json:"telegram,omitempty"`

	// Transcription configures local audio transcription (whisper.cpp).
	Transcription *TranscriptionConfig `json:"transcription,omitempty"`

	// Vision configures local image/video understanding (MiniCPM-V 4.6 via llama-mtmd-cli).
	Vision *VisionConfig `json:"vision,omitempty"`

	// WebSearch configures the web_search tool (self-hosted SearXNG backend).
	WebSearch *WebSearchConfig `json:"web_search,omitempty"`

	// Schedules configures the native in-process task scheduler.
	Schedules *SchedulesConfig `json:"schedules,omitempty"`

	// Maintenance configures the storage-maintenance janitor (retention and
	// deletion of sessions, audit records, plans, logs, skip-list entries).
	// Operator-controlled: rejected from project-level ./odek.json.
	Maintenance *MaintenanceConfig `json:"maintenance,omitempty"`

	// Subagent configures delegate_tasks sub-agent execution (docs/SUBAGENTS.md).
	// Operator-controlled: rejected from project-level ./odek.json.
	Subagent *SubagentConfig `json:"subagent,omitempty"`

	// Profiles are named capability profiles (P4): when a task selects one,
	// its settings OVERRIDE the corresponding operator permissions
	// (max_risk clamp, allowlist, tool filter) for that sub-agent.
	// Operator-controlled: rejected from project-level ./odek.json — a
	// cloned repo must not be able to author its own permission envelope.
	Profiles map[string]ProfileConfig `json:"profiles,omitempty"`

	// Tools controls which tools are exposed to the LLM.
	// Project-level ./odek.json may only disable tools, not enable them.
	Tools *ToolsConfig `json:"tools,omitempty"`

	// InteractionMode controls how the agent communicates tool/progress updates.
	// "engaging" (default) = emoji-rich narration, progress message edited.
	// "enhance" = per-tool narrated messages, progress header kept.
	// "verbose" = raw tool names, args, and results.
	// "off" = no progress output, clean answer only.
	InteractionMode string `json:"interaction_mode,omitempty"`

	// ToolProgress controls per-tool progress messages for the Telegram bot.
	//   "all"     (default) — show every tool call
	//   "new"     — only when the tool name changes (dedup consecutive same-tool)
	//   "verbose" — full tool arguments in progress messages
	//   "off"     — no per-tool progress messages (just thinking + final answer)
	ToolProgress string `json:"tool_progress,omitempty"`

	// ToolProgressCleanup controls whether progress messages are deleted after
	// the final answer. Default: true (delete progress messages).
	ToolProgressCleanup *bool `json:"tool_progress_cleanup,omitempty"`

	// Limits is the "limits" section: hard execution budgets
	// (odek-extension/v1). The global config may set any limit; the project
	// config may only LOWER an existing one (see clampProjectLimits).
	Limits *budget.Limits `json:"limits,omitempty"`
}

FileConfig is the JSON schema used by ~/.odek/config.json and ./odek.json. Pointer booleans distinguish "explicitly set to false" from "not set".

type LLMConfig added in v1.35.3

type LLMConfig struct {
	// StreamIdleTimeoutSeconds caps the time between SSE events (keepalive
	// comment lines count) before the stream is dropped and retried.
	// Thinking models can legitimately spend minutes before their first
	// event, so the built-in default is generous (120s). 0 keeps the
	// default. Config: llm.stream_idle_timeout_seconds,
	// ODEK_STREAM_IDLE_TIMEOUT_SECONDS.
	StreamIdleTimeoutSeconds int `json:"stream_idle_timeout_seconds,omitempty"`
}

LLMConfig tunes the shared LLM client (internal/llm). Nil section = the built-in defaults.

type MaintenanceConfig added in v1.15.0

type MaintenanceConfig struct {
	Enabled              *bool  `json:"enabled,omitempty"`
	IntervalMinutes      *int   `json:"interval_minutes,omitempty"`
	SessionsMaxAgeDays   *int   `json:"sessions_max_age_days,omitempty"`
	AuditMaxAgeDays      *int   `json:"audit_max_age_days,omitempty"`
	LogMaxMB             *int64 `json:"log_max_mb,omitempty"`
	PlansMaxAgeDays      *int   `json:"plans_max_age_days,omitempty"`
	ArtifactsMaxAgeHours *int   `json:"artifacts_max_age_hours,omitempty"`
}

MaintenanceConfig is the file-level "maintenance" section. Pointer fields distinguish "not set" (inherit the default) from an explicit 0, which is meaningful for the retention knobs (0 = keep forever / disable). Operator-controlled: rejected from project-level ./odek.json because it governs DELETION of user data.

type PlanningConfig added in v1.27.0

type PlanningConfig struct {
	// Enabled is the master switch: false removes the plan tool from the
	// registry and skips all plan logic.
	Enabled bool
	// MaxSteps caps plan(create) size; enforced fail-closed.
	MaxSteps int
	// MaxRenderChars caps the rendered plan message; overflow drops the
	// oldest done steps first with an explicit omission marker.
	MaxRenderChars int
}

PlanningConfig is the resolved planning configuration (docs/PLANNING.md).

func DefaultPlanningConfig added in v1.27.0

func DefaultPlanningConfig() PlanningConfig

DefaultPlanningConfig returns the shipped defaults: planning on, 12 steps, 2000-char render cap (~500 estimated tokens at ~4 chars/token).

type PlanningFileConfig added in v1.27.0

type PlanningFileConfig struct {
	Enabled        *bool `json:"enabled,omitempty"`
	MaxSteps       *int  `json:"max_steps,omitempty"`
	MaxRenderChars *int  `json:"max_render_chars,omitempty"`
}

PlanningFileConfig is the "planning" section of odek.json. Pointer fields distinguish "not set" from explicit values so partial sections merge field-by-field across the global/project layers.

type ProfileConfig added in v1.28.0

type ProfileConfig struct {
	// Description is a short human/model-readable summary of what the
	// profile is FOR. It is surfaced by the list_subagent_profiles tool so
	// the delegating model can pick the right profile by intent rather
	// than by guessing at names. Operator-authored only; never parsed for
	// permission semantics.
	Description string      `json:"description,omitempty"`
	MaxRisk     string      `json:"max_risk,omitempty"`
	Allowlist   []string    `json:"allowlist,omitempty"`
	Tools       *ToolConfig `json:"tools,omitempty"`
}

ProfileConfig is one named capability profile (P4). When a task selects the profile, its settings OVERRIDE the corresponding operator config for that sub-agent: max_risk clamps every higher-ranked class to deny, allowlist REPLACES the global allowlist, and the tools filter replaces the global one. Operator-authored only (project config is stripped), so the override is policy rather than escalation — the P2 non-interactive deny and the P3 trust lockdown are applied afterwards and cannot be lifted by selecting a profile.

type ProjectSandboxOverride added in v1.14.0

type ProjectSandboxOverride struct {
	HasEnv              bool
	EnvKeys             []string
	EnvHasInterpolation bool
	HasImage            bool
	Image               string
	HasNetwork          bool
	Network             string
	HasVolumes          bool
	Volumes             []string
}

ProjectSandboxOverride records which sandbox knobs were supplied by the project-level ./odek.json config. These require explicit operator approval before they are applied, because a malicious repo could otherwise exfiltrate host secrets (via ${VAR} interpolation in sandbox_env), pull an attacker-controlled image, or widen the container's network access.

type ResolvedConfig

type ResolvedConfig struct {
	Model           string
	BaseURL         string
	APIKey          string
	Thinking        string
	MaxIter         int
	Sandbox         bool
	SandboxExplicit bool // true when any config layer explicitly set sandbox
	NoColor         bool
	NoAgents        bool
	Stream          bool
	PromptCaching   bool
	Compaction      bool

	// Planning is the resolved planning configuration (docs/PLANNING.md).
	Planning PlanningConfig
	System   string

	// SandboxImage is the Docker image for the sandbox container.
	// Default: "alpine:latest" (applied at call site, not here —
	// set to "alpine:latest" only if Dockerfile.odek doesn't exist).
	// Config: sandbox_image, ODEK_SANDBOX_IMAGE, --sandbox-image.
	SandboxImage string

	// SandboxNetwork is the Docker network mode.
	// Default: "bridge" (internet access by default).
	// Config: sandbox_network, ODEK_SANDBOX_NETWORK, --sandbox-network.
	SandboxNetwork string

	// SandboxReadonly, when true, mounts the working directory read-only
	// in the container. The agent can read /workspace but cannot write to it.
	// Config: sandbox_readonly, ODEK_SANDBOX_READONLY, --sandbox-readonly.
	SandboxReadonly bool

	// SandboxMemory is the container memory limit (e.g. "512m", "2g").
	// Empty string means no limit.
	// Config: sandbox_memory, ODEK_SANDBOX_MEMORY, --sandbox-memory.
	SandboxMemory string

	// SandboxCPUs is the container CPU limit (e.g. "0.5", "2", "4").
	// Empty string means no limit.
	// Config: sandbox_cpus, ODEK_SANDBOX_CPUS, --sandbox-cpus.
	SandboxCPUs string

	// SandboxUser sets the container user (e.g. "1000:1000" or "node").
	// Empty string means root (default Docker behavior).
	// Config: sandbox_user, ODEK_SANDBOX_USER, --sandbox-user.
	SandboxUser string

	// SandboxEnv holds extra environment variables injected into the
	// container. File-only — no env var or CLI mapping.
	// Config: sandbox_env.
	SandboxEnv map[string]string

	// SandboxVolumes holds extra volume mounts in "host:container" format.
	// File-only — no env var or CLI mapping.
	// Config: sandbox_volumes.
	SandboxVolumes []string

	// Dangerous is the resolved dangerous operations config.
	// Uses danger.DangerousConfig defaults for any unset fields.
	Dangerous danger.DangerousConfig

	// Skills is the resolved skills config with default values.
	Skills skills.SkillsConfig

	// Memory is the resolved memory config with default values.
	Memory memory.MemoryConfig

	// Guard is the resolved injection-guard config with default values.
	Guard guard.Config

	// Embedding is the resolved shared embedding backend — the default every
	// subsystem inherits unless it overrides. nil = default RandomProjections.
	Embedding *embedding.Config

	// SessionEmbedding is the embedding backend sessions use for semantic
	// session_search: sessions.embedding when set, else the shared Embedding.
	SessionEmbedding *embedding.Config

	// MCPServers maps server names to external MCP server configurations.
	// Populated from the mcp_servers section of odek.json.
	MCPServers map[string]mcpclient.ServerConfig

	// ProjectMCPServerNames lists the MCP server names that were introduced by
	// the project-level ./odek.json config. These require explicit user approval
	// before their subprocesses are spawned, because a malicious repo could
	// otherwise execute arbitrary code via the mcp_servers section.
	ProjectMCPServerNames []string

	// ProjectSandboxOverride records sandbox knobs supplied by the project-level
	// ./odek.json config. These require explicit operator approval before they
	// are applied, because a malicious repo could otherwise exfiltrate host
	// secrets or pull an attacker-controlled sandbox image.
	ProjectSandboxOverride ProjectSandboxOverride

	// MaxConcurrency limits how many sub-agent tasks run in parallel.
	// Config: max_concurrency, ODEK_MAX_CONCURRENCY.
	// Default: 3.
	MaxConcurrency int

	// MaxToolParallel limits how many tool calls run concurrently per
	// agent iteration. Config: max_tool_parallel.
	// Default: 0 (loop uses default of 4).
	MaxToolParallel int

	// Telegram is the resolved Telegram bot configuration.
	Telegram telegram.TelegramConfig

	// Transcription is the resolved transcription config.
	// Default: auto_transcribe=true, model="tiny", language="", no binary_path.
	Transcription TranscriptionConfig

	// Vision is the resolved vision config.
	// Default: VideoFrames=8, ModelsDir="" (auto-detect), BinaryPath="" (PATH lookup).
	Vision VisionConfig

	// WebSearch is the resolved web_search config.
	// Default: MaxResults=10, Timeout=15, BaseURL="" (tool disabled until set).
	WebSearch WebSearchConfig

	// Schedules is the resolved scheduler config.
	// Default: enabled=true, max_concurrent=2, timezone="UTC", catchup=false.
	Schedules ScheduleConfig

	// Maintenance is the resolved storage-maintenance config.
	// Default: maintenance.DefaultConfig() (enabled, 60min tick, sessions 30d,
	// audit 14d, logs 50MB, plans 30d, skip-list 90d).
	Maintenance maintenance.Config

	// Subagent is the resolved sub-agent execution config.
	// Default: MaxConcurrency=0 (fall back to global), TimeoutSeconds=1800 (30m),
	// MaxIterations=15, MaxDepth=2, AnnounceBudget=true,
	// BudgetInherit="operator".
	Subagent SubagentResolved

	// Profiles is the resolved set of operator-defined capability profiles
	// (P4). nil when none are defined. Selecting an unknown profile name
	// fails closed at the consumer.
	Profiles map[string]ProfileConfig

	// Tools is the resolved tool-list configuration.
	// Empty Enabled/Disabled means "no restriction" for that direction.
	Tools ToolConfig

	// InteractionMode is the resolved interaction style.
	// Values: "engaging" (default), "enhance", "verbose", or "off".
	// "engaging" (default), "enhance", or "verbose".
	InteractionMode string

	// ToolProgress is the resolved tool progress mode for Telegram.
	// Default: "all".
	ToolProgress string

	// ToolProgressCleanup controls whether progress messages are deleted
	// after the final answer. Default: true.
	ToolProgressCleanup bool

	// TrustedProxies lists IP addresses or CIDR ranges of reverse proxies whose
	// X-Forwarded-For / X-Real-Ip headers are trusted by `odek serve`.
	TrustedProxies []string

	// Limits is the resolved execution-budget configuration
	// (odek-extension/v1). Zero fields mean "no limit". Merge rule: the global
	// config may set any limit; the untrusted project ./odek.json may only
	// LOWER an existing limit (never raise, never disable); CLI flags are
	// operator intent and set limits explicitly.
	Limits budget.Limits
}

ResolvedConfig is the fully merged result. Every field has a concrete value — callers can read directly without checking for "not set".

func LoadConfig

func LoadConfig(cli CLIFlags) ResolvedConfig

LoadConfig merges configuration from all four layers and returns the fully resolved result.

Priority (lowest → highest):

global file → project file → ODEK_* env → CLI flags

For each field, the highest-priority layer that provides a value wins. API key has an additional fallback: if none of the four layers provides one, it falls back to DEEPSEEK_API_KEY → OPENAI_API_KEY (legacy env vars).

type ScheduleConfig added in v1.2.0

type ScheduleConfig struct {
	Enabled                 bool
	MaxConcurrent           int
	Timezone                string
	Catchup                 bool
	AllowTelegramManagement bool
	TelegramAdminChats      []int64
	TelegramAdminUsers      []int64
	// Dangerous is the schedule-specific dangerous-operations policy. See
	// SchedulesConfig.Dangerous for semantics.
	Dangerous danger.DangerousConfig
}

ScheduleConfig is the resolved scheduler config (all fields concrete).

type SchedulesConfig added in v1.2.0

type SchedulesConfig struct {
	Enabled       *bool  `json:"enabled,omitempty"`        // run the embedded scheduler inside `odek telegram` (default true)
	MaxConcurrent int    `json:"max_concurrent,omitempty"` // max jobs running at once (default 2)
	Timezone      string `json:"timezone,omitempty"`       // default timezone for jobs with none (default UTC)
	Catchup       *bool  `json:"catchup,omitempty"`        // global default: run a missed fire once on startup (default false)
	// AllowTelegramManagement gates the in-chat `/schedule` management commands.
	// When false, the Telegram bot still lists/previews jobs but refuses to
	// add/remove/enable/disable/run them — manage from the host CLI instead.
	AllowTelegramManagement *bool `json:"allow_telegram_management,omitempty"` // default true
	// TelegramAdminChats restricts mutating `/schedule` commands to the listed
	// chat IDs. When empty, management falls back to telegram.default_chat_id
	// (if set). Read-only commands are not affected.
	TelegramAdminChats []int64 `json:"telegram_admin_chats,omitempty"`
	// TelegramAdminUsers restricts mutating `/schedule` commands to the listed
	// user IDs. Read-only commands are not affected.
	TelegramAdminUsers []int64 `json:"telegram_admin_users,omitempty"`
	// Dangerous overrides the global dangerous-operations policy for scheduled
	// (unattended) runs only. It is applied on top of the global dangerous
	// config, then a non-overrideable safety floor is applied by the scheduler
	// itself: destructive and blocked classes are always denied, and
	// non_interactive is always deny because no human is present to approve.
	// This lets operators allow network_egress/system_write/etc. for cron jobs
	// without widening the policy for interactive CLI/REPL/WebUI use.
	Dangerous *danger.DangerousConfig `json:"dangerous,omitempty"`
}

SchedulesConfig is the file-level scheduler configuration. Tri-state fields use pointers so "unset" is distinguishable from an explicit false.

type SessionsConfig added in v1.6.0

type SessionsConfig struct {
	Embedding *embedding.Config `json:"embedding,omitempty"`
}

SessionsConfig is the "sessions" section of odek.json. It currently only carries an optional embedding override for semantic session_search; when unset, sessions use the shared top-level embedding default.

type SkillsConfig

type SkillsConfig struct {
	MaxAutoLoad  *int                 `json:"max_auto_load,omitempty"`
	MaxLazySlots *int                 `json:"max_lazy_slots,omitempty"`
	Dirs         []string             `json:"dirs,omitempty"`
	Import       *skills.ImportConfig `json:"import,omitempty"`
	Verbose      *bool                `json:"verbose,omitempty"`
	Embedding    *embedding.Config    `json:"embedding,omitempty"`
}

SkillsConfig holds the skills configuration section from JSON files.

type SubagentConfig added in v1.28.0

type SubagentConfig struct {
	MaxConcurrency *int   `json:"max_concurrency,omitempty"`
	TimeoutSeconds *int   `json:"timeout_seconds,omitempty"`
	MaxIterations  *int   `json:"max_iterations,omitempty"`
	MaxDepth       *int   `json:"max_depth,omitempty"`
	AnnounceBudget *bool  `json:"announce_budget,omitempty"`
	BudgetInherit  string `json:"budget_inherit,omitempty"`
	// DefaultProfile selects the capability profile applied when a delegated
	// task omits the profile field: a defined profile name, or "none" to
	// disable the built-in default envelope. Operator-controlled (rejected
	// from project-level ./odek.json like the rest of this section).
	DefaultProfile string `json:"default_profile,omitempty"`
}

SubagentConfig is the file-level "subagent" section (docs/SUBAGENTS.md). Pointer fields distinguish "not set" (inherit the default) from explicit values, mirroring MaintenanceConfig. Operator-controlled: rejected from project-level ./odek.json — a malicious repo must not be able to extend its own sub-agents' runtime/iteration budgets or weaken budget inheritance.

type SubagentResolved added in v1.28.0

type SubagentResolved struct {
	// MaxConcurrency caps parallel sub-agent tasks per delegate_tasks call.
	// 0 = fall back to the global max_concurrency. Clamped to 8.
	MaxConcurrency int
	// TimeoutSeconds is the default per-sub-agent wall-clock budget in
	// seconds. Clamped to 1800.
	TimeoutSeconds int
	// MaxIterations is the default think→act cycle budget per sub-agent.
	// Clamped to 100.
	MaxIterations int
	// MaxDepth caps delegation nesting via ODEK_SUBAGENT_DEPTH (1 = no
	// sub-agent may delegate further). Clamped to 8.
	MaxDepth int
	// AnnounceBudget makes sub-agent engines inject budget-awareness hints
	// (50/75/90% of the iteration or wall-clock budget) and announce the
	// effective limits in the sub-agent system prompt.
	AnnounceBudget bool
	// BudgetInherit is BudgetInheritOperator or BudgetInheritShare.
	BudgetInherit string
	// DefaultProfile is the profile name applied when a delegated task
	// selects none: DefaultProfileName (built-in), an operator-defined
	// name, or DefaultProfileDisabled ("none" = no envelope).
	DefaultProfile string
}

SubagentResolved is the resolved "subagent" configuration.

type ToolConfig added in v1.11.0

type ToolConfig struct {
	Enabled  []string `json:"enabled,omitempty"`
	Disabled []string `json:"disabled,omitempty"`
}

ToolConfig controls which tools are exposed to the LLM. Config: tools.enabled, tools.disabled; ODEK_TOOLS_ENABLED, ODEK_TOOLS_DISABLED; --tool, --no-tool.

type ToolsConfig added in v1.11.0

type ToolsConfig = ToolConfig

ToolsConfig is the "tools" section of odek.json. It is intentionally a pointer in FileConfig so "not set" can be distinguished from an explicit empty list.

type TranscriptionConfig

type TranscriptionConfig struct {
	Model          string `json:"model,omitempty"`
	Language       string `json:"language,omitempty"`
	AutoTranscribe bool   `json:"auto_transcribe,omitempty"`
	ModelsDir      string `json:"models_dir,omitempty"`
	BinaryPath     string `json:"binary_path,omitempty"`
}

TranscriptionConfig controls the transcribe tool (local whisper.cpp). Populated from the "transcription" section of odek.json.

type VisionConfig added in v1.3.0

type VisionConfig struct {
	// ModelsDir is the directory containing model.gguf and mmproj.gguf.
	// Default: /usr/local/share/minicpm-v/models (Docker image path), with
	// fallback to ~/.odek/minicpm-v/models for out-of-container installs.
	ModelsDir string `json:"models_dir,omitempty"`
	// BinaryPath overrides PATH lookup for the llama-mtmd-cli binary.
	BinaryPath string `json:"binary_path,omitempty"`
	// VideoFrames is the number of frames to sample evenly from a video file.
	// Default: 8.
	VideoFrames int `json:"video_frames,omitempty"`
	// AutoDescribe controls whether photos received over Telegram are
	// automatically run through the vision model to extract a description
	// before the agent answers (mirrors transcription.auto_transcribe).
	// Default: true.
	AutoDescribe bool `json:"auto_describe,omitempty"`
}

VisionConfig controls the vision tool (MiniCPM-V 4.6 via llama-mtmd-cli). Populated from the "vision" section of odek.json or ~/.odek/config.json.

type WebSearchConfig added in v1.4.0

type WebSearchConfig struct {
	// BaseURL is the SearXNG instance the tool queries, e.g.
	// "http://searxng:8080" (Docker compose) or "http://127.0.0.1:8888"
	// (host). Empty disables the tool.
	BaseURL string `json:"base_url,omitempty"`
	// Categories optionally restricts the SearXNG categories queried
	// (comma-separated, e.g. "general" or "general,news"). Empty = SearXNG default.
	Categories string `json:"categories,omitempty"`
	// Language optionally sets the SearXNG language code (e.g. "en"). Empty = SearXNG default.
	Language string `json:"language,omitempty"`
	// MaxResults caps how many results are returned to the agent. Default: 10.
	MaxResults int `json:"max_results,omitempty"`
	// Timeout is the per-request timeout in seconds. Default: 15.
	Timeout int `json:"timeout_seconds,omitempty"`
}

WebSearchConfig controls the web_search tool (self-hosted SearXNG backend). Populated from the "web_search" section of odek.json or ~/.odek/config.json. The tool is registered only when BaseURL is non-empty — without a reachable SearXNG instance there is no backend, so the tool stays hidden by default (a plain `go install` has no sidecar; the Docker compose setup sets BaseURL).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL