server:
  port: 18080
  shutdown: graceful
  netty:
    connection-timeout: 10s
  error:
    include-message: never
    include-binding-errors: never
    include-stacktrace: never
    include-exception: false

spring:
  application:
    name: ai-novel-server
  data:
    mongodb:
      uri: mongodb://${MONGO_USER:${MONGO_USERNAME:}}:${MONGO_PASSWORD}@${MONGO_HOST:localhost}:${MONGO_PORT:27017}/${MONGO_DATABASE:ainovel}?authSource=${MONGO_AUTH_DB:admin}
      auto-index-creation: true
      database: ${MONGO_DATABASE:ainovel}
      authentication-database: ${MONGO_AUTH_DB:admin}
      map-key-dot-replacement: "#DOT#"
  webflux:
    base-path: /
  lifecycle:
    timeout-per-shutdown-phase: 30s
  rabbitmq:
    host: ${RABBITMQ_HOST:localhost}
    port: ${RABBITMQ_PORT:5672}
    username: ${RABBITMQ_USER:guest}
    password: ${RABBITMQ_PASSWORD:guest}
    virtual-host: ${RABBITMQ_VHOST:/}
    publisher-confirm-type: correlated
    publisher-returns: true
    listener:
      simple:
        acknowledge-mode: manual
        prefetch: 5
        concurrency: 8
        max-concurrency: 16
        retry:
          enabled: true
          max-attempts: 3
    connection-timeout: 10000
    template:
      mandatory: true
      receive-timeout: 60000
      reply-timeout: 60000

logging:
  level:
    root: WARN
    com.ainovel: INFO
    org.springframework.data.mongodb: WARN
    org.springframework.web: WARN
    reactor.netty: WARN
    com.ainovel.server: INFO
    com.ainovel.server.task: WARN
    org.springframework.amqp: WARN
  request: false
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%X{traceId:-}] [%X{userId:-}] [%thread] %logger{36} - %msg%n"
    file: "%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%X{traceId:-}] [%X{userId:-}] [%thread] %logger{36} - %msg%n"
  file:
    name: /var/log/ainoval/application.log
    max-size: 100MB
    max-history: 30
    total-size-cap: 3GB

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
    jmx:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: when-authorized
    jmx:
      enabled: true
  jmx:
    enabled: true
  prometheus:
    metrics:
      export:
        enabled: true
  metrics:
    tags:
      application: ${spring.application.name}
      environment: production
    distribution:
      percentiles-histogram:
        "[tasks.execution.time]": true
        "[http.server.requests]": true
      percentiles:
        "[tasks.execution.time]": [0.5, 0.95, 0.99]
        "[http.server.requests]": [0.5, 0.95, 0.99]
      slo:
        "[tasks.execution.time]": [2000ms, 10000ms, 30000ms]
        "[http.server.requests]": [100ms, 300ms, 1s, 3s, 5s]


# 生产环境配置
ainovel:
  security:
    jwt:
      secret-key: ${JWT_SECRET_KEY}
      expiration-time: 86400000  # 24小时
      refresh-token-expiration: 604800000  # 7天
  performance:
    virtual-threads:
      enabled: true
    monitoring:
      enabled: true
    testing:
      security-disabled: false  # 生产环境启用安全验证
  version-control:
    enabled: true
    auto-save-history: true
    max-history-count: 50
  storage:
    default-provider: ${STORAGE_PROVIDER:alioss}
    covers-path: ${STORAGE_COVERS_PATH:covers}
    test-on-startup: true
    aliyun:
      endpoint: ${ALIYUN_OSS_ENDPOINT}
      access-key-id: ${ALIYUN_OSS_ACCESS_KEY_ID}
      access-key-secret: ${ALIYUN_OSS_ACCESS_KEY_SECRET}
      bucket-name: ${ALIYUN_OSS_BUCKET_NAME}
      base-url: ${ALIYUN_OSS_BASE_URL}
      region: ${ALIYUN_OSS_REGION:cn-shanghai}
  ai:
    default-prompts:
      scene-to-summary: "请根据以下小说场景内容，生成一段简洁的摘要。\n场景内容:\n{input}\n参考信息:\n{context}"
      summary-to-scene: "请根据以下摘要/大纲，结合参考信息，生成一段详细的小说场景。\n摘要/大纲:\n{input}\n参考信息:\n{context}"
    rag:
      retrieval-k: 5
    resilience:
      timeout:
        duration: 60s
      retry:
        max-attempts: 5
        backoff:
          initial-delay: 2s
          multiplier: 2

# 向量存储配置
vectorstore:
  chroma:
    url: ${CHROMA_URL:http://localhost:18000}
    collection: ${CHROMA_COLLECTION:ainovel}
    use-random-collection: true
    reuse-collection: true

# 代理配置（生产环境可能不需要）
proxy:
  enabled: ${PROXY_ENABLED:true}
  host: ${PROXY_HOST:127.0.0.1}
  port: ${PROXY_PORT:6888}
  type: http            # 关键：切换为 socks
  applySystemProperties: true
  applyProxySelector: true
  trustAllCerts: false   # 排障时可临时 true，生产请 false

jwt:
  secret: ${JWT_SECRET}
  expiration: 86400000
  refresh-expiration: 604800000

ai:
  model:
    default: ${AI_DEFAULT_MODEL:gpt-3.5-turbo}
    temperature: ${AI_TEMPERATURE:0.7}
    max-tokens: ${AI_MAX_TOKENS:204800}
  openai:
    api-key: ${OPENAI_API_KEY}
  gemini:
    api-key: ${GEMINI_API_KEY}

jasypt:
  encryptor:
    password: ${JASYPT_PASSWORD:MaliangAI_SecretKey_PleaseChangeThis_2025}
    algorithm: PBEWITHHMACSHA512ANDAES_256
    iv-generator-classname: org.jasypt.iv.RandomIvGenerator

# 生产环境限流配置
task:
  ratelimiter:
    type: ${RATE_LIMITER_TYPE:memory}
    
    dimensions:
      default: USER_PROVIDER_MODEL
      gemini: GLOBAL
      sensitive_tasks: HYBRID
      high_performance: PROVIDER_MODEL
    
    default:
      rate: 20.0
      burstCapacity: 40
      defaultTimeoutMillis: 10000
      dimension: USER_PROVIDER_MODEL
      
    providers:
      gemini:
        strategy: CONSERVATIVE
        dimension: GLOBAL
        rate: 0.2
        burstCapacity: 1
        dailyLimit: 180
        safetyBuffer: 20
        retryStrategy: EXPONENTIAL_BACKOFF
        maxRetryAttempts: 5
        defaultTimeoutMillis: 60000
        
      openai:
        strategy: STANDARD
        dimension: USER_PROVIDER_MODEL
        rate: 10.0
        burstCapacity: 20
        retryStrategy: LINEAR_BACKOFF
        maxRetryAttempts: 3
        defaultTimeoutMillis: 10000
        
      anthropic:
        strategy: STANDARD
        dimension: USER_PROVIDER_MODEL
        rate: 8.0
        burstCapacity: 16
        retryStrategy: LINEAR_BACKOFF
        maxRetryAttempts: 3
        defaultTimeoutMillis: 10000
        
      gpt-4:
        strategy: CONSERVATIVE
        rate: 5.0
        burstCapacity: 10
        retryStrategy: EXPONENTIAL_BACKOFF
        maxRetryAttempts: 4
        defaultTimeoutMillis: 15000
        
      openrouter:
        strategy: STANDARD
        rate: 15.0
        burstCapacity: 30
        retryStrategy: INTELLIGENT_BACKOFF
        maxRetryAttempts: 4
        defaultTimeoutMillis: 10000
        
      siliconflow:
        strategy: STANDARD
        rate: 20.0
        burstCapacity: 40
        retryStrategy: LINEAR_BACKOFF
        maxRetryAttempts: 3
        defaultTimeoutMillis: 10000

  retry:
    maxAttempts: 5
    initialDelayMillis: 2000
    maxDelayMillis: 3600000
    backoffFactor: 2.0
    jitterFactor: 0.1
    delays: 5000,15000,60000
    
  shutdown:
    awaitTerminationTimeout: PT60S

# 安全配置
security:
  jwt:
    disabled: false 