# HotPlex Worker Gateway - Base Configuration
#
# Sensible defaults for both dev and prod. Override via:
#   1. Inheritance: config-dev.yaml / config-prod.yaml (inherits this file)
#   2. Environment variables: HOTPLEX_* (highest priority, auto-detected if key exists here)
#   3. Secrets provider: JWT secret, admin tokens (never in config files)
#
# Code defaults live in internal/config/config.go:Default().

# ─────────────────────────────────────────────────────────────────────────────
# CORE NETWORK (Gateway)
# ─────────────────────────────────────────────────────────────────────────────

gateway:
  # Bind to localhost by default for security.
  # Change to ":8888" to listen on all interfaces (e.g. behind a reverse proxy).
  addr: "localhost:8888"
  read_buffer_size: 4096
  write_buffer_size: 4096
  ping_interval: 54s
  pong_timeout: 60s
  write_timeout: 10s
  idle_timeout: 5m
  max_frame_size: 32768
  broadcast_queue_size: 256
  
  # Advanced performance tuning for messaging platforms
  platform_write_buffer: 64
  platform_drop_threshold: 56
  delta_coalesce_interval: 120ms
  delta_coalesce_size: 200

# ─────────────────────────────────────────────────────────────────────────────
# ADMIN API
# ─────────────────────────────────────────────────────────────────────────────

admin:
  enabled: true
  # Bind to localhost by default. Change to ":9999" to expose.
  addr: "localhost:9999"
  # Tokens must be provided via HOTPLEX_ADMIN_TOKEN_1..N env vars
  tokens: []
  default_scopes: ["session:read", "stats:read", "health:read", "admin:write"]
  ip_whitelist_enabled: false
  allowed_cidrs: ["127.0.0.0/8", "10.0.0.0/8"]
  rate_limit_enabled: true
  requests_per_sec: 10
  burst: 20

# ─────────────────────────────────────────────────────────────────────────────
# DATA & PERSISTENCE
# ─────────────────────────────────────────────────────────────────────────────

db:
  path: ~/.hotplex/data/hotplex.db
  events_path: ""           # Deprecated: events table lives in hotplex.db
  wal_mode: true
  busy_timeout: 5s
  max_open_conns: 3         # 1 writer + 2 readers for shared session/event store
  vacuum_threshold: 0.2     # VACUUM when 20%+ free pages
  cache_size_kib: 8192
  mmap_size_mib: 64
  wal_autocheckpoint: 2000

# ─────────────────────────────────────────────────────────────────────────────
# SECURITY & AUTH
# ─────────────────────────────────────────────────────────────────────────────

security:
  api_key_header: "X-API-Key"
  # APIKeys must be provided via HOTPLEX_SECURITY_API_KEY_1..N env vars
  api_keys: []
  # api_key_users maps API key values (or env var names) to user identities.
  # When set, the resolved userID flows into session isolation (UUIDv5 key,
  # SEC-008 cross-user rejection, per-user quotas). Without mapping, all keys
  # resolve to "api_user" (shared namespace).
  # Example (env var names resolved at load time):
  #   api_key_users:
  #     HOTPLEX_SECURITY_API_KEY_1: "alice"
  #     HOTPLEX_SECURITY_API_KEY_2: "bob"
  # Or with literal key values:
  #   api_key_users:
  #     "sk-actual-key-value": "alice"
  api_key_users: {}
  # Resolver chain: DB (Admin API CRUD) → YAML config. DB entries override config.
  # No configuration needed — the chain is always active when the table exists.
  tls_enabled: false
  tls_cert_file: "/etc/hotplex/tls/server.crt"
  tls_key_file: "/etc/hotplex/tls/server.key"
  allowed_origins:
    - "*"
  jwt_audience: "hotplex-gateway"

  # Work directory security settings (convention + configuration)
  # Program defaults (convention over configuration):
  #   - ~/.hotplex/workspace (HotPlex convention)
  #   - ~/workspace, ~/projects, ~/work, ~/dev (common developer patterns)
  #   - /var/hotplex/projects (production, if exists)
  #   - Temp directories
  # Config below supplements program defaults (whitelist priority):
  work_dir_allowed_base_patterns:
    # - "~/custom_projects"  # Extra whitelist: supports ~ and ${VAR} expansion
    # - "/opt/projects"       # Absolute path
  work_dir_forbidden_dirs:
    # - "/srv/deployments"    # Extra blacklist: explicitly forbidden

# ─────────────────────────────────────────────────────────────────────────────
# SESSION & RESOURCE POOL
# ─────────────────────────────────────────────────────────────────────────────

session:
  retention_period: 168h    # Data retention for events and logs
  gc_scan_interval: 1m
  max_concurrent: 1000

pool:
  min_size: 0
  max_size: 100
  max_idle_per_user: 5
  max_memory_per_user: 3221225472  # 3GB (bytes)

# ─────────────────────────────────────────────────────────────────────────────
# WORKER RUNTIME
# ─────────────────────────────────────────────────────────────────────────────

worker:
  max_lifetime: 24h
  idle_timeout: 60m
  execution_timeout: 30m
  turn_timeout: 0  # per-turn kill timer; 0=disabled (execution_timeout catches zombies)
  default_work_dir: ~/.hotplex/workspace
  pid_dir: ~/.hotplex/.pids

  # Environment variables to block from workers (prefix match with trailing "_").
  env_blocklist: []

  # Extra environment variables for all worker processes (highest priority).
  # These override all other env sources.
  environment:
    - GH_TOKEN=${HOTPLEX_WORKER_GH_TOKEN}
    - GITHUB_TOKEN=${HOTPLEX_WORKER_GITHUB_TOKEN}
  # - BUN_JSC_useJIT=0  # JIT workaround for Bun SIGILL on broken AVX VPS (severe perf penalty)

  auto_retry:
    enabled: true
    max_retries: 9
    base_delay: 5s
    max_delay: 120s
    retry_input: "继续"
    notify_user: true
    # Regex patterns for retryable errors (appended to system defaults like 429, 500).
    patterns: []

  claude_code:
    # Command to start Claude Code worker. Default: "claude"
    # Override via HOTPLEX_WORKER_CLAUDE_CODE_COMMAND environment variable.
    command: "claude"
    # Enable --permission-prompt-tool stdio for forwarding permission requests
    # to Slack/Feishu interaction UI. When false (default), Claude Code auto-denies
    # permission requests in headless mode (no user interaction).
    permission_prompt: false
    # Tool names to auto-approve without forwarding to user interaction UI.
    # These tools are approved silently when permission_prompt is enabled.
    permission_auto_approve:
      - "ExitPlanMode"

  opencode_server:
    # Command to start OpenCode Server. Default: "opencode"
    # Override via HOTPLEX_WORKER_OPENCODE_SERVER_COMMAND environment variable.
    command: "opencode"
    idle_drain_period: 30m
    ready_timeout: 10s
    ready_poll_interval: 200ms
    http_timeout: 30s

  codex_cli:
    # Command to start Codex CLI worker. Default: "codex"
    command: "codex"
    # Model name. Empty = use Codex default model from ~/.codex/config.toml
    model: ""
    # Sandbox mode: read-only, workspace-write, danger-full-access
    sandbox: "workspace-write"
    # Approval mode: untrusted, on-request, never
    approval_mode: "never"
    # Ephemeral sessions (don't persist to disk)
    ephemeral: true
    # Process startup timeout
    startup_timeout: 30s
    # Use persistent app-server mode (default) instead of one-shot exec
    use_app_server: true
    # Idle drain timeout for app-server mode before killing process
    idle_drain_period: 30m

# ─────────────────────────────────────────────────────────────────────────────
# AGENT PERSONALITY & SKILLS (B/C Channels)
# ─────────────────────────────────────────────────────────────────────────────

agent_config:
  enabled: true
  # Root directory for personality (SOUL.md, AGENTS.md, SKILLS.md)
  # and user context (USER.md, MEMORY.md).
  config_dir: ~/.hotplex/agent-configs

skills:
  cache_ttl: 5m

# ─────────────────────────────────────────────────────────────────────────────
# OBSERVABILITY & UI
# ─────────────────────────────────────────────────────────────────────────────

log:
  level: "info"
  format: "json" # "json" or "text"

webchat:
  addr: ""      # informational: banner display only
  enabled: true  # serve embedded webchat SPA from gateway

# ─────────────────────────────────────────────────────────────────────────────
# MESSAGING PLATFORMS
# ─────────────────────────────────────────────────────────────────────────────

messaging:
  # Send turn summary after each completed turn (default: true).
  turn_summary_enabled: true

  # ── Shared defaults (inherited by all platforms, overridable per-platform) ──
  worker_type: "claude_code"

  # STT (Speech-to-Text)
  stt_provider: "local"
  stt_local_cmd: "python3 ~/.hotplex/scripts/stt_server.py"
  stt_local_idle_ttl: 15m

  # TTS (Text-to-Speech) — voice replies for voice-triggered turns
  tts_enabled: true
  # Provider: edge (Edge TTS, free), moss (MOSS-TTS-Nano local CPU),
  #   edge+moss (Edge primary + MOSS fallback)
  tts_provider: "edge+moss"
  tts_voice: "zh-CN-XiaoxiaoNeural"
  tts_max_chars: 150
  # MOSS-TTS-Nano sidecar settings
  tts_moss_model_dir: "~/.hotplex/models/moss-tts-nano"
  tts_moss_voice: "Xiaoyu"
  tts_moss_port: 18083
  tts_moss_idle_timeout: 30m
  tts_moss_cpu_threads: 0

  # ── Platform-specific configs ──────────────────────────────────────────────
  slack:
    enabled: false
    socket_mode: true
    require_mention: true
    # Override shared defaults here if needed, e.g.:
    # tts_provider: "edge"
    # Multi-bot support (uncomment to use):
    # bots:
    #   - name: tech-support
    #     bot_token: xoxb-xxx
    #     app_token: xapp-xxx
    #     soul: tech-support
    #   - name: hr-bot
    #     bot_token: xoxb-yyy
    #     app_token: xapp-yyy
    #     soul: hr-assistant

  feishu:
    enabled: false
    require_mention: true
    # Override shared defaults here if needed, e.g.:
    # tts_provider: "edge"
    # Multi-bot support (uncomment to use):
    # bots:
    #   - name: tech-support
    #     app_id: cli_xxx
    #     app_secret: xxx
    #     soul: tech-support
    #   - name: hr-bot
    #     app_id: cli_yyy
    #     app_secret: yyy
    #     soul: hr-assistant

# ── Cron Scheduler ─────────────────────────────────────────────────────────
# AI-native cronjob engine: natural language prompt as payload, results
# delivered to the creator's platform (Feishu card / Slack message).
# Docs: https://github.com/hrygo/hotplex/tree/main/internal/cron
cron:
  enabled: true
  # max_concurrent_runs: 3      # Max parallel job executions
  # max_jobs: 50                # Max registered jobs
  # default_timeout_sec: 300    # Per-job timeout (5 min)
  # tick_interval_sec: 60       # Scheduler tick interval
