use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct OhMyOpencodeConfig {
#[serde(rename = "$schema", skip_serializing_if = "Option::is_none")]
pub schema: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub new_task_system_enabled: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub default_run_agent: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub agent_order: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub agent_definitions: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub disabled_mcps: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub disabled_agents: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub disabled_skills: Option<Vec<DisabledSkill>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub disabled_hooks: Option<Vec<DisabledHook>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub disabled_commands: Option<Vec<DisabledCommand>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub disabled_tools: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub disabled_providers: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub disabled_categories: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mcp_env_allowlist: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub hashline_edit: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub model_fallback: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub agents: Option<AgentsConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub categories: Option<HashMap<String, CategoryConfig>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub background_task: Option<BackgroundTaskConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tmux: Option<TmuxConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub experimental: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sisyphus_agent: Option<SisyphusAgentConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sisyphus: Option<SisyphusConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub skills: Option<SkillsConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub browser_automation_engine: Option<BrowserAutomationConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub git_master: Option<GitMasterConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub comment_checker: Option<CommentCheckerConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub notification: Option<NotificationConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub lsp: Option<LspConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub runtime_fallback: Option<RuntimeFallbackConfig>,
#[serde(flatten)]
pub extra: HashMap<String, serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct AgentsConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub build: Option<AgentDefinition>,
#[serde(skip_serializing_if = "Option::is_none")]
pub plan: Option<AgentDefinition>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sisyphus: Option<AgentDefinition>,
#[serde(skip_serializing_if = "Option::is_none")]
pub hephaestus: Option<AgentDefinition>,
#[serde(skip_serializing_if = "Option::is_none")]
pub prometheus: Option<AgentDefinition>,
#[serde(skip_serializing_if = "Option::is_none")]
pub oracle: Option<AgentDefinition>,
#[serde(skip_serializing_if = "Option::is_none")]
pub librarian: Option<AgentDefinition>,
#[serde(skip_serializing_if = "Option::is_none")]
pub explore: Option<AgentDefinition>,
#[serde(skip_serializing_if = "Option::is_none")]
pub multimodal_looker: Option<AgentDefinition>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metis: Option<AgentDefinition>,
#[serde(skip_serializing_if = "Option::is_none")]
pub momus: Option<AgentDefinition>,
#[serde(skip_serializing_if = "Option::is_none")]
pub atlas: Option<AgentDefinition>,
#[serde(flatten)]
pub custom: HashMap<String, AgentDefinition>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct AgentDefinition {
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fallback_models: Option<FallbackModels>,
#[serde(skip_serializing_if = "Option::is_none")]
pub variant: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub category: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub skills: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub temperature: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub top_p: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub prompt: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub prompt_append: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tools: Option<HashMap<String, bool>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub disable: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub mode: Option<AgentMode>,
#[serde(skip_serializing_if = "Option::is_none")]
pub color: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub display_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub permission: Option<AgentPermission>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_tokens: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub thinking: Option<AgentThinking>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reasoning_effort: Option<ReasoningEffort>,
#[serde(skip_serializing_if = "Option::is_none")]
pub text_verbosity: Option<TextVerbosity>,
#[serde(skip_serializing_if = "Option::is_none")]
pub provider_options: Option<HashMap<String, serde_json::Value>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ultrawork: Option<AgentUltrawork>,
#[serde(skip_serializing_if = "Option::is_none")]
pub compaction: Option<AgentCompaction>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(untagged)]
pub enum FallbackModels {
Single(String),
StringList(Vec<String>),
DetailedList(Vec<FallbackModelSpec>),
MixedList(Vec<FallbackModelEntry>),
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(untagged)]
pub enum FallbackModelEntry {
String(String),
Detailed(FallbackModelSpec),
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct FallbackModelSpec {
pub model: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub variant: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reasoning_effort: Option<ReasoningEffort>,
#[serde(skip_serializing_if = "Option::is_none")]
pub temperature: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub top_p: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_tokens: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub thinking: Option<AgentThinking>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct AgentThinking {
pub r#type: ThinkingType,
#[serde(skip_serializing_if = "Option::is_none")]
pub budget_tokens: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct AgentPermission {
#[serde(skip_serializing_if = "Option::is_none")]
pub edit: Option<PermissionAction>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bash: Option<BashPermission>,
#[serde(skip_serializing_if = "Option::is_none")]
pub webfetch: Option<PermissionAction>,
#[serde(skip_serializing_if = "Option::is_none")]
pub task: Option<PermissionAction>,
#[serde(skip_serializing_if = "Option::is_none")]
pub doom_loop: Option<PermissionAction>,
#[serde(skip_serializing_if = "Option::is_none")]
pub external_directory: Option<PermissionAction>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(untagged)]
pub enum BashPermission {
Simple(PermissionAction),
Detailed(HashMap<String, PermissionAction>),
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct AgentUltrawork {
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub variant: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct AgentCompaction {
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub variant: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct CategoryConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub variant: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub temperature: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub top_p: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_tokens: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fallback_models: Option<FallbackModels>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct BackgroundTaskConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub provider_concurrency: Option<ConcurrencyConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub model_concurrency: Option<ConcurrencyConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub default_concurrency: Option<ConcurrencyConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub stale_timeout_ms: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct ConcurrencyConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub max: Option<u64>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct TmuxConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub enabled: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct SisyphusAgentConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub variant: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct SisyphusConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub tasks: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct SkillsConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub paths: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub urls: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct BrowserAutomationConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub engine: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub enabled: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct GitMasterConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub max_depth: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_descendants: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub stale_timeout_ms: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub include_co_authored_by: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub git_env_prefix: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct CommentCheckerConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub enabled: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct NotificationConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub enabled: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub provider: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct LspConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub enabled: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub servers: Option<HashMap<String, serde_json::Value>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct RuntimeFallbackConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub enabled: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum AgentMode {
Subagent,
Primary,
All,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum PermissionAction {
Ask,
Allow,
Deny,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum ReasoningEffort {
#[serde(rename = "none")]
None,
#[serde(rename = "minimal")]
Minimal,
#[serde(rename = "low")]
Low,
#[serde(rename = "medium")]
Medium,
#[serde(rename = "high")]
High,
#[serde(rename = "xhigh")]
Xhigh,
#[serde(rename = "max")]
Max,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum TextVerbosity {
Low,
Medium,
High,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum ThinkingType {
Enabled,
Disabled,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum DisabledSkill {
#[serde(rename = "playwright")]
Playwright,
#[serde(rename = "playwright-cli")]
PlaywrightCli,
#[serde(rename = "agent-browser")]
AgentBrowser,
#[serde(rename = "dev-browser")]
DevBrowser,
#[serde(rename = "frontend-ui-ux")]
FrontendUiUx,
#[serde(rename = "git-master")]
GitMaster,
#[serde(rename = "review-work")]
ReviewWork,
#[serde(rename = "ai-slop-remover")]
AiSlopRemover,
#[serde(rename = "team-mode")]
TeamMode,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum DisabledCommand {
#[serde(rename = "init-deep")]
InitDeep,
#[serde(rename = "ralph-loop")]
RalphLoop,
#[serde(rename = "ulw-loop")]
UlwLoop,
#[serde(rename = "cancel-ralph")]
CancelRalph,
#[serde(rename = "refactor")]
Refactor,
#[serde(rename = "start-work")]
StartWork,
#[serde(rename = "stop-continuation")]
StopContinuation,
#[serde(rename = "remove-ai-slops")]
RemoveAiSlops,
#[serde(rename = "hyperplan")]
Hyperplan,
#[serde(rename = "handoff")]
Handoff,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum DisabledHook {
#[serde(rename = "todo-continuation-enforcer")]
TodoContinuationEnforcer,
#[serde(rename = "context-window-monitor")]
ContextWindowMonitor,
#[serde(rename = "session-recovery")]
SessionRecovery,
#[serde(rename = "session-notification")]
SessionNotification,
#[serde(rename = "comment-checker")]
CommentChecker,
#[serde(rename = "grep-output-truncator")]
GrepOutputTruncator,
#[serde(rename = "tool-output-truncator")]
ToolOutputTruncator,
#[serde(rename = "directory-agents-injector")]
DirectoryAgentsInjector,
#[serde(rename = "directory-readme-injector")]
DirectoryReadmeInjector,
#[serde(rename = "empty-task-response-detector")]
EmptyTaskResponseDetector,
#[serde(rename = "think-mode")]
ThinkMode,
#[serde(rename = "anthropic-context-window-limit-recovery")]
AnthropicContextWindowLimitRecovery,
#[serde(rename = "rules-injector")]
RulesInjector,
#[serde(rename = "background-notification")]
BackgroundNotification,
#[serde(rename = "auto-update-checker")]
AutoUpdateChecker,
#[serde(rename = "startup-toast")]
StartupToast,
#[serde(rename = "keyword-detector")]
KeywordDetector,
#[serde(rename = "agent-usage-reminder")]
AgentUsageReminder,
#[serde(rename = "non-interactive-env")]
NonInteractiveEnv,
#[serde(rename = "interactive-bash-session")]
InteractiveBashSession,
#[serde(rename = "compaction-context-injector")]
CompactionContextInjector,
#[serde(rename = "thinking-block-validator")]
ThinkingBlockValidator,
#[serde(rename = "claude-code-hooks")]
ClaudeCodeHooks,
#[serde(rename = "ralph-loop")]
RalphLoop,
#[serde(rename = "preemptive-compaction")]
PreemptiveCompaction,
#[serde(rename = "auto-slash-command")]
AutoSlashCommand,
#[serde(rename = "sisyphus-junior-notepad")]
SisyphusJuniorNotepad,
#[serde(rename = "no-sisyphus-gpt")]
NoSisyphusGpt,
#[serde(rename = "start-work")]
StartWork,
#[serde(rename = "runtime-fallback")]
RuntimeFallback,
}