# Kiro Gateway - Environment Configuration
# Copy this file to .env and fill in your values
# ===========================================
# REQUIRED
# ===========================================
# Password to protect YOUR proxy server
# This is NOT a token from anywhere - YOU make it up!
# Use this same value as api_key when connecting to your gateway
# Example: "my-super-secret-password-123" or any secure string
PROXY_API_KEY="my-super-secret-password-123"
# ===========================================
# OPTION 1: Kiro IDE credentials (JSON file)
# ===========================================
# Path to JSON credentials file from Kiro IDE
# KIRO_CREDS_FILE="~/.aws/sso/cache/kiro-auth-token.json"
# ===========================================
# OPTION 2: Kiro IDE refresh token
# ===========================================
# Your Kiro refresh token obtained from Kiro IDE traffic.
# REFRESH_TOKEN="your_kiro_refresh_token_here"
# ===========================================
# OPTION 3: kiro-cli SQLite database (AWS SSO)
# ===========================================
# Path to kiro-cli SQLite database (for AWS IAM Identity Center users)
# The gateway will auto-detect AWS SSO OIDC and use the correct endpoint
# KIRO_CLI_DB_FILE="~/.local/share/kiro-cli/data.sqlite3"
# Disable SQLite write-back (read-only mode)
# When enabled, gateway will only read from kiro-cli database without modifying it.
# Useful when kiro-cli is actively managing tokens and you don't want gateway to interfere.
# Default: false (write-back enabled - gateway saves refreshed tokens back to SQLite)
# SQLITE_READONLY=false
# ===========================================
# OPTION 4: AWS SSO cache file (kiro-cli)
# ===========================================
# Path to AWS SSO cache file (contains clientId and clientSecret)
# The gateway will auto-detect AWS SSO OIDC and use the correct endpoint
# KIRO_CREDS_FILE="~/.aws/sso/cache/your-sso-cache-file.json"
# ===========================================
# PROFILE ARN (optional)
# ===========================================
# AWS CodeWhisperer profile ARN
# For Kiro IDE: usually auto-detected from credentials file
# For kiro-cli (AWS SSO / Builder ID): not needed, will be ignored
# PROFILE_ARN="arn:aws:codewhisperer:us-east-1:..."
# ===========================================
# OPTIONAL
# ===========================================
# AWS SSO/auth region (default: us-east-1)
# This is where your AWS SSO/IAM Identity Center is configured.
# Used for OIDC token refresh (authentication).
# KIRO_REGION="us-east-1"
# AWS Q API region (optional, auto-detected)
# This is where Q Developer API endpoints are available.
# The gateway automatically detects this from your credentials.
# Only set manually if auto-detection fails or you need to override.
# Example: Your SSO is in eu-west-1 but Q API only works in eu-central-1
# KIRO_API_REGION="eu-central-1"
# ===========================================
# SERVER SETTINGS
# ===========================================
# Server host (default: 0.0.0.0 - listen on all interfaces)
# Use "127.0.0.1" to only allow local connections
# SERVER_HOST="0.0.0.0"
# Server port (default: 8000)
# Useful when port 8000 is already in use by another application
#
# Configuration priority (highest to lowest):
# 1. CLI arguments: python main.py --port 9000
# 2. Environment variables: SERVER_PORT=9000
# 3. Default value: 8000
#
# Note: When using `uvicorn main:app --port 9000` directly,
# uvicorn handles its own CLI arguments (this setting is ignored)
# SERVER_PORT="8000"
# ===========================================
# VPN/PROXY SETTINGS
# ===========================================
# VPN/Proxy URL for accessing Kiro API through a proxy server.
# Leave empty to connect directly (default).
#
# Use cases:
# - China: GFW (Great Firewall) blocks AWS endpoints
# - Corporate networks: Often require mandatory proxy
# - Privacy: Hide your IP address from AWS
#
# Supports HTTP and SOCKS5 protocols.
# Authentication can be embedded in the URL.
#
# Examples:
# VPN_PROXY_URL="http://127.0.0.1:7890"
# VPN_PROXY_URL="socks5://127.0.0.1:1080"
# VPN_PROXY_URL="http://user:password@proxy.company.com:8080"
# VPN_PROXY_URL="192.168.1.100:8080" # defaults to http://
#
# VPN_PROXY_URL=""
# ===========================================
# MULTI-ACCOUNT SETTINGS
# ===========================================
# Enable multi-account system with intelligent failover (default: false)
#
# When false (legacy mode):
# - Uses single account without failover
# - credentials.json is recreated from .env on every startup
# - Simpler for single-account setups
#
# When true (multi-account mode):
# - Enables full failover loop with Circuit Breaker and sticky behavior
# - Works even with single account (unified architecture)
# - On first startup: automatically migrates .env → credentials.json (one-time)
# - After migration: credentials.json takes priority, .env is ignored
# - Manual credential management via credentials.json
#
# ACCOUNT_SYSTEM=false
# Path to credentials configuration file
# Automatically created from .env on first startup (if doesn't exist)
# After creation, edit this file directly to manage accounts
# See credentials.json.example for format
# ACCOUNTS_CONFIG_FILE="credentials.json"
# Path to runtime state file
# Stores account statistics, failure counts, and model mappings
# Automatically created and updated by the gateway
# ACCOUNTS_STATE_FILE="state.json"
# ===========================================
# CIRCUIT BREAKER SETTINGS (Multi-Account)
# ===========================================
# Base recovery timeout in seconds (for exponential backoff)
# Actual timeout = BASE * 2^(failures - 1), capped at BASE * MAX_MULTIPLIER
# Examples with BASE=60s: 1 failure: 1m, 2: 2m, 3: 4m, 4: 8m, ..., 12+: 1d (cap)
# ACCOUNT_RECOVERY_TIMEOUT=60
# Maximum backoff multiplier (cap for exponential backoff)
# With BASE=60s and MAX=1440, maximum cooldown is 60 * 1440 = 86400s = 1 day
# ACCOUNT_MAX_BACKOFF_MULTIPLIER=1440.0
# Probabilistic retry chance for "broken" accounts (0.0 - 1.0)
# Even if account is broken and timeout hasn't passed, try with this probability
# Default: 0.1 (10% chance) - prevents permanent "stuck" state
# ACCOUNT_PROBABILISTIC_RETRY_CHANCE=0.1
# Model cache TTL in seconds (12 hours)
# Cache is refreshed only when account is used (not in background)
# ACCOUNT_CACHE_TTL=43200
# Interval for periodic state.json saving in seconds
# STATE_SAVE_INTERVAL_SECONDS=10
# ===========================================
# FIRST TOKEN TIMEOUT (Streaming Retry)
# ===========================================
# Timeout for waiting for the first token from the model (in seconds).
# If the model doesn't respond within this time, the request will be cancelled and retried.
# This helps handle "stuck" requests when the model takes too long to start responding.
# Default: 15 seconds (recommended for production)
# Set a lower value (e.g., 5-10) for more aggressive retry behavior.
# FIRST_TOKEN_TIMEOUT="15"
# Maximum number of retry attempts when first token timeout occurs.
# After exhausting all attempts, a 504 Gateway Timeout error will be returned.
# Default: 3 attempts
# FIRST_TOKEN_MAX_RETRIES="3"
# Read timeout for streaming responses (in seconds).
# This is the maximum time to wait for data between chunks during streaming.
# Should be longer than FIRST_TOKEN_TIMEOUT since the model may pause between chunks
# while "thinking" (especially for tool calls or complex reasoning).
# Default: 300 seconds (5 minutes) - generous timeout to avoid premature disconnects.
# STREAMING_READ_TIMEOUT="300"
# ===========================================
# FAKE REASONING (Extended Thinking via Tag Injection)
# ===========================================
# Enable fake reasoning - injects special tags into requests to enable model reasoning.
# When enabled, the model will include its reasoning process in the response.
# The response is then parsed and converted to OpenAI-compatible reasoning_content format.
#
# WHY "FAKE"? This is NOT native extended thinking API support. Instead, we inject
# enabled tags into the prompt, and the model responds
# with ... blocks that we parse and convert to reasoning_content.
# It works great, but it's a hack - hence "fake" reasoning.
#
# Default: true (ENABLED by default for premium experience out of the box)
# To disable, set to false:
# FAKE_REASONING=false
# Maximum thinking length in tokens (default budget when client doesn't specify).
# This value is injected into the request as {value}
# Higher values allow for more detailed reasoning but increase response time and token usage.
# Default: 4000 tokens
# FAKE_REASONING_MAX_TOKENS=4000
# Maximum budget cap for client thinking budget requests.
# Caps client's thinking budget to prevent consuming all output tokens on reasoning.
# WHY CAP? Fake reasoning uses output tokens (not separate thinking tokens like native API).
# Large budgets can cause the model to spend ALL output tokens on reasoning with NOTHING
# left for actual content. This cap prevents that.
# Default: 10000 tokens (2.5x default budget) - allows deeper reasoning while leaving room for response
# Set to 0 to disable capping (not recommended for production)
# FAKE_REASONING_BUDGET_CAP=10000
# How to handle the thinking block in responses:
# - "as_reasoning_content": Extract to reasoning_content field (OpenAI-compatible, recommended)
# - "remove": Remove thinking block completely, return only final answer
# - "pass": Pass through as-is with original tags in content
# - "strip_tags": Remove tags but keep thinking content in regular content
#
# Default: "as_reasoning_content"
# FAKE_REASONING_HANDLING=as_reasoning_content
# Maximum size of initial buffer for tag detection (characters).
# The parser buffers this many characters before deciding if response contains thinking tags.
# Lower values = faster first token appearance, but may miss tags with leading whitespace.
# Default: 20 characters (enough for longest tag = 11 chars + some whitespace)
# FAKE_REASONING_INITIAL_BUFFER_SIZE=20
# ===========================================
# WEBSEARCH (MCP Tool Emulation)
# ===========================================
# Enable web_search tool auto-injection (default: true)
# When enabled, web_search is automatically added as a tool for MCP emulation (Path B)
# Model decides whether to use it or not
#
# Note: Native Anthropic server-side tools (Path A with "type" field) work ALWAYS,
# regardless of this setting
# WEB_SEARCH_ENABLED=true
# ===========================================
# PAYLOAD SIZE GUARD
# ===========================================
# Auto-trim conversation history when payload exceeds limit.
# When enabled, oldest history pairs are removed until payload fits.
# When disabled, returns clear error message instead.
# Default: false (DISABLED by default - enable only if you use many tools and hit payload errors)
# Enable if you use Claude Code or similar with 30+ tools and get "Improperly formed request" errors
# AUTO_TRIM_PAYLOAD=false
# Maximum payload size in bytes before auto-trim kicks in.
# Kiro API rejects payloads over ~615KB with "Improperly formed request" error.
# Default: 600000 (600KB) - leaves 15KB safety margin
# KIRO_MAX_PAYLOAD_BYTES=600000
# ===========================================
# TRUNCATION RECOVERY
# ===========================================
# Enable automatic truncation recovery when Kiro API cuts off large responses.
# When the model generates large tool calls or content, the upstream API may truncate
# the response mid-stream. This feature automatically notifies the model about truncation,
# allowing it to adapt its approach (e.g., write smaller files, split operations).
#
# Default: true (ENABLED by default for better out-of-the-box experience)
# TRUNCATION_RECOVERY=true
# ===========================================
# LOGGING
# ===========================================
# Log level: TRACE, DEBUG, INFO, WARNING, ERROR, CRITICAL
# Default: INFO (recommended for production)
# Set to DEBUG for detailed troubleshooting
# LOG_LEVEL="INFO"
# ===========================================
# DEBUG (for development only)
# ===========================================
# Debug logging mode:
# - off: disabled (default)
# - errors: save logs only for failed requests (4xx, 5xx) - recommended for troubleshooting
# - all: save logs for every request (overwrites on each request)
# DEBUG_MODE=off
# Directory for debug log files
# DEBUG_DIR="debug_logs"