<?php

return [
    /*
    |--------------------------------------------------------------------------
    | Bash Sandbox Mode
    |--------------------------------------------------------------------------
    | 'php'       — Commands run in-process with CommandSecurityPolicy allowlist (default, dev-friendly)
    | 'docker'    — Commands run inside a Docker container with --network none, --read-only, workspace mount
    | 'just_bash' — Commands run inside a persistent just-bash Node.js sidecar (recommended for cloud)
    */
    'bash_sandbox_mode' => env('AGENT_BASH_SANDBOX_MODE', 'php'),

    /*
    |--------------------------------------------------------------------------
    | just-bash Sidecar URL
    |--------------------------------------------------------------------------
    | Base URL of the bash-sidecar Docker container. Only used when
    | bash_sandbox_mode is 'just_bash'.
    */
    'bash_sidecar_url' => env('BASH_SIDECAR_URL', 'http://bash_sidecar:3001'),

    /*
    |--------------------------------------------------------------------------
    | just-bash Sidecar Secret
    |--------------------------------------------------------------------------
    | Bearer token required by the sidecar HTTP API. Must match the
    | BASH_SIDECAR_SECRET env var set in the sidecar container.
    */
    'bash_sidecar_secret' => env('BASH_SIDECAR_SECRET', ''),

    /*
    |--------------------------------------------------------------------------
    | Browser Sandbox Mode
    |--------------------------------------------------------------------------
    | 'disabled' — Browser tool returns a plan-upgrade prompt (default)
    | 'cloud'    — Tasks delegated to browser-use Cloud REST API (api.browser-use.com)
    | 'sidecar'  — Tasks run in a self-hosted Python Docker sidecar (Phase 2)
    */
    'browser_sandbox_mode' => env('AGENT_BROWSER_SANDBOX_MODE', 'disabled'),

    /*
    |--------------------------------------------------------------------------
    | browser-use Cloud API Key
    |--------------------------------------------------------------------------
    | Used when browser_sandbox_mode is 'cloud'. Can also be stored per-team
    | in Tool.credentials['api_key'] (encrypted via TeamEncryptedArray).
    | Get your key at: https://cloud.browser-use.com/settings
    */
    'browser_use_cloud_api_key' => env('BROWSER_USE_CLOUD_API_KEY', ''),

    /*
    |--------------------------------------------------------------------------
    | Browser Sidecar URL & Secret
    |--------------------------------------------------------------------------
    | Base URL and bearer token for the browser-use Python sidecar container.
    | Only used when browser_sandbox_mode is 'sidecar' (Phase 2).
    */
    'browser_sidecar_url' => env('BROWSER_SIDECAR_URL', 'http://browser_sidecar:8090'),
    'browser_sidecar_secret' => env('BROWSER_SIDECAR_SECRET', ''),

    /*
    |--------------------------------------------------------------------------
    | Docker Sandbox Image
    |--------------------------------------------------------------------------
    | The Docker image used when bash_sandbox_mode is 'docker'.
    */
    'sandbox_image' => env('AGENT_SANDBOX_IMAGE', 'python:3.12-alpine'),

    /*
    |--------------------------------------------------------------------------
    | Sandbox Root Directory
    |--------------------------------------------------------------------------
    | Base directory for per-execution sandbox directories.
    | Must be writable by the application process.
    */
    'sandbox_root' => storage_path('app/sandboxes'),

    /*
    |--------------------------------------------------------------------------
    | Sandbox Max Size (MB)
    |--------------------------------------------------------------------------
    | Soft limit for per-execution sandbox disk usage (for future quota enforcement).
    */
    'sandbox_max_size_mb' => (int) env('AGENT_SANDBOX_MAX_SIZE_MB', 100),

    /*
    |--------------------------------------------------------------------------
    | MCP Stdio Binary Allowlist
    |--------------------------------------------------------------------------
    | Comma-separated list of absolute paths to binaries that may be spawned
    | by McpStdioClient. When non-empty, only listed binaries are permitted.
    |
    | When EMPTY (default):
    |   - If MCP_STDIO_ALLOW_ANY_BINARY=true  → allow all (local dev opt-in)
    |   - If MCP_STDIO_ALLOW_ANY_BINARY=false → deny all (fail-close, safe default)
    |
    | Production: always set an explicit list.
    |   MCP_STDIO_BINARY_ALLOWLIST=/usr/local/bin/boruna,/usr/local/bin/my-mcp-server
    */
    'mcp_stdio_binary_allowlist' => array_filter(
        explode(',', env('MCP_STDIO_BINARY_ALLOWLIST', '')),
        fn ($v) => $v !== '',
    ),

    /*
    |--------------------------------------------------------------------------
    | MCP Stdio Allow Any Binary (Dev Opt-In)
    |--------------------------------------------------------------------------
    | When true AND mcp_stdio_binary_allowlist is empty, McpStdioClient will
    | allow any binary path. Only for local development. NEVER enable in production.
    */
    'mcp_stdio_allow_any_binary' => (bool) env('MCP_STDIO_ALLOW_ANY_BINARY', false),

    /*
    |--------------------------------------------------------------------------
    | Boruna Binary Path
    |--------------------------------------------------------------------------
    | Absolute path to the Boruna binary on the host / inside the container.
    | Used by the PopularToolsSeeder and install wizard to auto-configure the
    | default Boruna mcp_stdio Tool.
    */
    'boruna_binary_path' => env('BORUNA_BINARY_PATH', '/usr/local/bin/boruna'),

    /*
    |--------------------------------------------------------------------------
    | Agent-as-Tool Max Nesting Depth
    |--------------------------------------------------------------------------
    | Maximum recursion depth when agents call other agents as tools.
    | Prevents infinite loops in agent-to-agent delegation chains.
    */
    'max_agent_tool_depth' => (int) env('AGENT_MAX_TOOL_DEPTH', 3),

    /*
    |--------------------------------------------------------------------------
    | Tool Loop Circuit Breaker Thresholds
    |--------------------------------------------------------------------------
    | Warning  — log a warning when an agent uses this many LLM steps.
    | Critical — throw ToolLoopCriticalException and fail the execution.
    | Global   — rolling 1-hour per-team step count that pauses all agents.
    |
    | Inspired by BroodMind's BROODMIND_TOOL_LOOP_* env vars.
    */
    'tool_loop' => [
        'warning_threshold' => (int) env('AGENT_TOOL_LOOP_WARNING', 8),
        'critical_threshold' => (int) env('AGENT_TOOL_LOOP_CRITICAL', 12),
        'global_breaker' => (int) env('AGENT_TOOL_LOOP_GLOBAL', 30),
        // Semantic loop detection: fires when the exact same tool call set repeats
        'semantic_warn_threshold' => (int) env('AGENT_TOOL_LOOP_SEMANTIC_WARN', 3),
        'semantic_critical_threshold' => (int) env('AGENT_TOOL_LOOP_SEMANTIC_CRITICAL', 5),
    ],

    /*
    |--------------------------------------------------------------------------
    | Memory Capacity Limits
    |--------------------------------------------------------------------------
    | Per-team memory capacity cap. When a team exceeds max_per_team, the
    | memory:prune command removes the lowest effective_importance records
    | in batches of prune_batch_size to avoid lock contention.
    |
    | Formula: effective_importance = min(importance + ln(1 + retrieval_count) * 0.15, 1.0)
    */
    'memory' => [
        'max_per_team' => (int) env('AGENT_MEMORY_MAX_PER_TEAM', 10000),
        'prune_batch_size' => (int) env('AGENT_MEMORY_PRUNE_BATCH_SIZE', 500),
    ],

    /*
    |--------------------------------------------------------------------------
    | Pre-Execution Scout Phase
    |--------------------------------------------------------------------------
    | When enabled, a cheap Haiku call runs before memory/KG injection to
    | identify what specific knowledge the agent needs. The resulting queries
    | are used to focus semantic retrieval on what matters for the task.
    |
    | Off by default. Enable globally here or per-agent via
    | agent.config['enable_scout_phase'] = true.
    */
    'scout_phase' => [
        'enabled' => (bool) env('AGENT_SCOUT_PHASE_ENABLED', false),
    ],

    /*
    |--------------------------------------------------------------------------
    | Output Schema Retry
    |--------------------------------------------------------------------------
    | When an agent has `output_schema` set and the LLM response fails
    | validation, the gateway is re-called with an error-feedback hint so
    | the model can self-correct. Each retry is a full LLM call — keep
    | max_retries_default conservative to bound worst-case cost.
    |
    | Per-agent override: agents.output_schema_max_retries (nullable).
    | 0 = validation only, no retry (Sprint 8 behavior).
    */
    'output_schema' => [
        'max_retries_default' => (int) env('AGENT_OUTPUT_SCHEMA_MAX_RETRIES', 2),
    ],

    /*
    |--------------------------------------------------------------------------
    | Charter-as-contract (Squad borrow)
    |--------------------------------------------------------------------------
    | When enabled, an agent's structured `charter` (owns / refuses /
    | escalate-to / escalate-when) is rendered into the system prompt as an
    | explicit boundary + escalation contract. Off by default — a null charter
    | is byte-for-byte legacy regardless of this flag.
    */
    'charter' => [
        'enabled' => (bool) env('AGENT_CHARTER_ENABLED', false),
    ],

    /*
    |--------------------------------------------------------------------------
    | Eval gate on config change (eve borrow)
    |--------------------------------------------------------------------------
    | When enabled, a config change to an agent that has an eval dataset
    | configured (config.eval_gate_dataset_id) is first replayed against that
    | dataset BEFORE being applied. If the candidate config's aggregate score
    | falls below `threshold`, the change is held (not promoted) and surfaced
    | to the caller. Off by default; with no dataset configured the path is a
    | passthrough. Fail-open: an infra error in the gate lets the change
    | proceed (logged) rather than locking out config edits.
    */
    'eval_gate' => [
        'enabled' => (bool) env('AGENT_EVAL_GATE_ENABLED', false),
        'threshold' => (float) env('AGENT_EVAL_GATE_THRESHOLD', 7.0),
    ],

    /*
    |--------------------------------------------------------------------------
    | Agent prompt optimizer (EvoAgentX / GEPA borrow)
    |--------------------------------------------------------------------------
    | When enabled, OptimizeAgentPromptAction generates candidate goal/backstory
    | variants for an agent, scores EACH against the agent's eval dataset
    | (config.eval_gate_dataset_id) via ReplayEvaluationDatasetAction, and emits
    | an EvolutionProposal for the best variant ONLY if it beats the current
    | config's baseline by `min_improvement`. Proposal-only (human applies).
    | Off by default; requires a configured eval dataset.
    */
    'prompt_optimizer' => [
        'enabled' => (bool) env('AGENT_PROMPT_OPTIMIZER_ENABLED', false),
        'population_size' => (int) env('AGENT_PROMPT_OPTIMIZER_POPULATION', 3),
        'min_improvement' => (float) env('AGENT_PROMPT_OPTIMIZER_MIN_IMPROVEMENT', 0.0),
    ],

    /*
    |--------------------------------------------------------------------------
    | Per-tool-call governance (Squad borrow)
    |--------------------------------------------------------------------------
    | When enabled, mutating built-in tool calls (bash_execute, file_write,
    | ssh_execute) pass through ToolCallGovernor before running: active
    | reviewer-lockouts and OnToolCall guardrail hooks can block the call.
    | Off by default — the governor is a hard no-op when disabled.
    */
    'tool_governance' => [
        'enabled' => (bool) env('AGENT_TOOL_GOVERNANCE_ENABLED', false),

        /*
        | Input-conditioned argument predicates (eve borrow). When enabled (and
        | tool_governance.enabled is on), a tool call's arguments are evaluated
        | against per-argument predicates declared on OnToolCall guardrail hooks
        | (config.arg_predicates). A match can `block` the call or
        | `require_approval` (block + raise an ActionProposal). Off by default;
        | with no arg_predicates configured the governor path is unchanged.
        */
        'argument_predicates' => (bool) env('AGENT_TOOL_ARG_PREDICATES', false),
    ],

    /*
    |--------------------------------------------------------------------------
    | Planning tool (deepagents write_todos borrow)
    |--------------------------------------------------------------------------
    | When enabled, the built-in `plan` tool kind exposes an `update_plan`
    | tool that lets a solo agent maintain a live, self-authored to-do list
    | (replace-semantics) during a long-horizon run — distinct from the
    | system-authored feature-list.json and the append-only progress.md.
    | Off by default: the `plan` kind translates to no tool while disabled,
    | so no agent gains the capability until both the flag is on AND the
    | tool is explicitly attached.
    */
    'planning_tool' => [
        'enabled' => (bool) env('AGENT_PLANNING_TOOL_ENABLED', false),
    ],
];
