# === Required setup ===

# Named upstreams. Every model and every *_connection below must name
# one of these. Run `POST /api/admin/sync-models?connection=<name>` to
# populate the models section from a connection's /models endpoint.
connections:
  litellm:
    api_url: "http://localhost:4000/v1"
    api_key: "sk-litellm-local"
  openrouter:
    api_url: "https://openrouter.ai/api/v1"
    api_key: "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"

# First-run admin + invited users. Set `admin_email` and (optionally)
# `password`; the server hashes the plaintext on first start, then
# clears it. New emails added to `users:` get a random temp password
# and must reset on first login.
# `session_secret` and `media_key` are auto-generated — never edit.
auth:
  admin_email: "viviane@follyfeastlab.com"
  password: ""
  password_hash: ""
  users:
    - email: "viviane@follyfeastlab.com"
      is_admin: true
    - email: "yara@follyfeastlab.com"
    - email: "test@follyfeastlab.com"
  session_secret: "A1maTH3vdQ5MAGZ7sldnXgyBGHYn7G0WRhdR2vZelcEVgCHnti63eMVOh6mBFmq1"
  media_key: "a5e2ff6e3c123e25797d720584ab51840b21897fa1960214a48529ecef6354a2"

# Tavily API keys for the `web_search` tool. Add at least one — the
# tool is unavailable without a key. Multiple keys round-robin.
tavily_keys:
  - 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
  - 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
  - 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
web_search_results: 5
web_search_depth: advanced
web_search_timeout: 30

# === Chat defaults ===
# Seed values for a new browser. Once the user changes a setting in
# the UI, that browser uses its own choice and ignores these.
# `default_temperature`: precise | balanced | creative
# `default_reasoning_effort`: "" | low | medium | high

default_model: gpt-5.5
default_temperature: balanced
default_reasoning_effort: ""
# Toggles the model's built-in `:online` web fetch on capable
# connections. Different from the Tavily `web_search` tool.
default_native_web: false
# Whether new projects start with cross-conversation memory enabled.
# The per-project toggle in project settings always wins.
default_memory: false

# === Internal models ===
# Used by RAG / extraction. Not shown in the chat picker.

embedding_model: perplexity/pplx-embed-v1-4b
embedding_connection: openrouter
extraction_model: google/gemini-2.5-flash-lite
extraction_connection: openrouter
rerank_model: cohere/rerank-4-fast
rerank_connection: openrouter
# Provider names to skip during model sync.
excluded_providers:
  - anthropic

# === System prompts ===

system_prompt: |
  You are a helpful, knowledgeable assistant. Current date and time: {{CURRENT_DATETIME}} ({{CURRENT_TIMEZONE}}). User location: {{USER_LOCATION}}. User language: {{USER_LANGUAGE}}.

  Write clear, polished responses. Lead with the answer, then provide context. Use natural prose for explanations, but use bullet points for steps, options, comparisons, or any response with multiple distinct points. Use markdown tables for comparisons, feature matrices, pricing, specs, or any side-by-side data. For any response longer than one short paragraph, use markdown headers to organize it into clear sections. Do not answer multi-part requests as one dense block of plain text.

  Never use em dashes—use commas or periods instead. Cut all filler phrases ('in today's world', 'at the end of the day'). Do not use over-polished, academic, or inspirational clichés. Prioritize simple language and write like a human who knows what they're talking about.

  Format with markdown: Fenced code blocks with language tags for code, and links where relevant. For diagrams, flowcharts, sequence diagrams, or architecture visuals, emit a ```mermaid fenced block inline — the UI renders it directly. Do not write HTML files or use code execution to generate charts. Keep mermaid diagrams clean and minimal: no custom theme overrides, no %%{init: ...}%% blocks, no classDef/class color styling, no emojis in node labels, no HTML tags like <br/> or <i> in labels. Use plain labels and let the UI's own theme style the diagram. Never open with filler phrases like "Great question!" or "I'd be happy to help." When uncertain, say so directly rather than guessing.

  Use tools wisely. Answer directly from knowledge for opinions, explanations, and general knowledge. But always use tools for anything requiring precision: math, counting, data analysis, date calculations, code execution, or verifiable facts you're unsure about. Use web search for current events, live data, or anything past your training cutoff. Never guess at numbers, calculations, or specific facts — run code or search instead.

  IMPORTANT: Any planning or reasoning about tool calls must go in your internal thinking, never in the response text.

image_system_prompt: |
  You are an image generation assistant. Every request is about creating or editing images. Parse the user's request carefully to understand exactly what they want — subject, style, mood, composition, colors, and any specific details. Generate the image directly without unnecessary conversation. If the request is ambiguous, make reasonable creative choices rather than asking for clarification.

audio_system_prompt: |
  You are an audio generation assistant. Produce the requested speech, narration, or sound directly. Match the tone, language, and style the user asks for. Keep responses concise — do not add extra commentary outside the audio itself.

video_system_prompt: |
  You are a video generation assistant. Interpret the prompt into a short, coherent clip. If the request is ambiguous, make reasonable creative choices rather than asking for clarification.

# Defaults applied to any model with `audio_gen: true`.
default_audio_voice: "alloy"
default_audio_format: "wav"

# === RAG ===

chunk_size: 800
chunk_overlap: 80
embed_batch: 64
rag_results: 8
rerank_candidate_multiplier: 5
max_extracted_chars: 2000000
max_chunks_per_conversation: 5000

# === Tools ===

max_tool_rounds: 60
code_timeout: 60
tool_output_preview: 3000
tool_output_max: 25000

# === Deep research ===

research_max_searches: 50
research_max_sources: 50
research_search_concurrency: 6
research_read_concurrency: 5
research_llm_concurrency: 4
research_min_findings_per_subq: 3
research_page_chars_limit: 20000
research_results_per_query: 8
research_max_subagents: 6
research_max_subagent_loops: 3
research_subagent_search_budget: 8
research_subagent_read_budget: 10
research_enable_debate: true
research_enable_review: true

# === Timeouts (seconds) ===

llm_timeout: 120
llm_stream_timeout: 300
extraction_timeout: 300

# === Reliability and performance ===

# Per-turn caps on optional prep work. On timeout the block is skipped
# and the chat turn proceeds without it.
chat_turn:
  auto_retrieval_timeout: 12   # RAG retrieval
  url_fetch_timeout: 15        # fetch URLs in the user message
  mcp_rpc_timeout: 30          # MCP tool calls
  mcp_cache_ttl: 120           # MCP tool list cache
  project_index_cache_ttl: 60  # project index cache

# Concurrency caps per work kind. `0` or missing key disables the cap.
# Requests over the cap return HTTP 429.
limits:
  chat_stream:
    max_active: 32
    max_per_project: 8
  research:
    max_active: 4
    max_per_project: 2
  video_gen:
    max_active: 4
    max_per_project: 2
  file_index:
    max_active: 8
    max_per_project: 4
  rag_index:
    max_active: 8
    max_per_project: 4
  rag_retrieve:
    max_active: 16
    max_per_project: 8

# Per-session limits for live event delivery (SSE).
session_bus:
  queue_capacity: 2000
  ring_capacity: 500
  ring_max_bytes: 524288

# Slow-request thresholds (ms). `verbose: true` logs every span — use
# only while diagnosing.
timing:
  slow_request_ms: 500
  slow_span_ms: 100
  verbose: false

# Connection pool for the shared HTTP client (chat, research, MCP).
http:
  max_connections: 50
  max_keepalive: 20

# === Server ===

port: 5100
cors_origins:
  - http://localhost:5173
  - http://localhost:5174
  - http://localhost:5100
  - https://chat.follyfeastlab.com

# === Models ===
# Auto-populated by `POST /api/admin/sync-models?connection=<name>`.
# Sync is additive: new IDs append under their connection group,
# existing entries are kept. Order = display order in the UI.
# Empty/null = disabled, true = enabled. Every entry must set `connection`.
models:
  gpt-5.5:
    provider: chatgpt
    name: GPT-5.5
    description: $0/M output
    tags: [Chat]
    tools: true
    native_web: null
    vision: true
    audio: null
    video: null
    image_gen: null
    audio_gen: null
    video_gen: null
    context_window: 1.1M
    connection: litellm
  deepseek/deepseek-v4-pro:
    provider: deepseek
    name: DeepSeek V4 Pro
    description: $0.87/M output
    tags: [Chat]
    tools: true
    native_web: null
    vision: null
    audio: null
    video: null
    image_gen: null
    audio_gen: null
    video_gen: null
    context_window: 1.0M
    connection: openrouter
  google/gemini-3.1-flash-lite-preview@preset/main:
    provider: google
    name: Gemini 3.1 Flash Lite
    description: $1.50/M output
    tags: [Chat]
    tools: true
    native_web: true
    vision: true
    audio: true
    video: true
    image_gen: null
    audio_gen: null
    video_gen: null
    context_window: 1.0M
    connection: openrouter
  google/gemini-3.1-pro-preview-customtools@preset/main:
    provider: google
    name: Gemini 3.1 Pro
    description: $12/M output
    tags: [Chat]
    tools: true
    native_web: true
    vision: true
    audio: true
    video: true
    image_gen: null
    audio_gen: null
    video_gen: null
    context_window: 1.0M
    connection: openrouter
  z-ai/glm-5.1@preset/main:
    provider: z-ai
    name: GLM 5.1
    description: $3.50/M output
    tags: [Chat]
    tools: true
    native_web: null
    vision: null
    audio: null
    video: null
    image_gen: null
    audio_gen: null
    video_gen: null
    context_window: 203K
    connection: openrouter
  x-ai/grok-4.3@preset/main:
    provider: grok
    name: Grok 4.3
    description: $2.50/M output
    tags: [Chat]
    tools: true
    native_web: true
    vision: true
    audio: null
    video: null
    image_gen: null
    audio_gen: null
    video_gen: null
    context_window: 1.0M
    connection: openrouter
  moonshotai/kimi-k2.6@preset/main:
    provider: moonshotai
    name: Kimi K2.6
    description: $3.50/M output
    tags: [Chat]
    tools: true
    native_web: null
    vision: true
    audio: null
    video: null
    image_gen: null
    audio_gen: null
    video_gen: null
    context_window: 262K
    connection: openrouter
  qwen/qwen3.6-plus@preset/main:
    provider: qwen
    name: Qwen3.6 Plus
    description: $1.95/M output
    tags: [Chat]
    tools: true
    native_web: null
    vision: true
    audio: null
    video: true
    image_gen: null
    audio_gen: null
    video_gen: null
    context_window: 1.0M
    connection: openrouter
  black-forest-labs/flux.2-klein-4b:
    provider: black-forest-labs
    name: FLUX.2 Klein 4B
    description: $0.014/img
    tags: []
    tools: null
    native_web: null
    vision: true
    audio: null
    video: null
    image_gen: true
    audio_gen: null
    video_gen: null
    context_window: 41K
    connection: openrouter
  black-forest-labs/flux.2-max:
    provider: black-forest-labs
    name: FLUX.2 Max
    description: $0.071/img
    tags: []
    tools: null
    native_web: null
    vision: true
    audio: null
    video: null
    image_gen: true
    audio_gen: null
    video_gen: null
    context_window: 47K
    connection: openrouter
  google/gemini-3-pro-image-preview:
    provider: google
    name: Nano Banana Pro
    description: $0.134/img
    tags: []
    tools: null
    native_web: true
    vision: true
    audio: null
    video: null
    image_gen: true
    audio_gen: null
    video_gen: null
    context_window: 66K
    connection: openrouter
  google/gemini-3.1-flash-image-preview:
    provider: google
    name: Nano Banana 2
    description: $0.067/img
    tags: []
    tools: null
    native_web: true
    vision: true
    audio: null
    video: null
    image_gen: true
    audio_gen: null
    video_gen: null
    context_window: 66K
    connection: openrouter
  openai/gpt-5.4-image-2:
    provider: openai
    name: GPT-5.4 Image 2
    description: $0.034/img
    tags: []
    tools: null
    native_web: true
    vision: true
    audio: null
    video: null
    image_gen: true
    audio_gen: null
    video_gen: null
    context_window: 272K
    connection: openrouter
  openai/gpt-5-image-mini:
    provider: openai
    name: GPT-5 Image Mini
    description: $0.011/img
    tags: []
    tools: null
    native_web: true
    vision: true
    audio: null
    video: null
    image_gen: true
    audio_gen: null
    video_gen: null
    context_window: 400K
    connection: openrouter
  bytedance-seed/seedream-4.5:
    provider: bytedance
    name: Seedream 4.5
    description: $0.04/img
    tags: []
    tools: null
    native_web: null
    vision: true
    audio: null
    video: null
    image_gen: true
    audio_gen: null
    video_gen: null
    context_window: 4K
    connection: openrouter
  google/lyria-3-clip-preview:
    provider: gemini
    name: Lyria 3 Clip
    description: $0.04/clip
    tags: []
    tools: null
    native_web: null
    vision: true
    audio: null
    video: null
    image_gen: null
    audio_gen: true
    video_gen: null
    context_window: 1M
    connection: openrouter
  google/lyria-3-pro-preview:
    provider: gemini
    name: Lyria 3 Pro
    description: $0.08/clip
    tags: []
    tools: null
    native_web: null
    vision: true
    audio: null
    video: null
    image_gen: null
    audio_gen: true
    video_gen: null
    context_window: 1M
    connection: openrouter
  openai/gpt-audio:
    provider: openai
    name: GPT Audio
    description: $0.032/clip
    tags: []
    tools: true
    native_web: null
    vision: null
    audio: true
    video: null
    image_gen: null
    audio_gen: true
    video_gen: null
    context_window: 128K
    connection: openrouter
  openai/gpt-audio-mini:
    provider: openai
    name: GPT Audio Mini
    description: $0.012/clip
    tags: []
    tools: true
    native_web: null
    vision: null
    audio: true
    video: null
    image_gen: null
    audio_gen: true
    video_gen: null
    context_window: 128K
    connection: openrouter
  kwaivgi/kling-video-o1:
    provider: kling
    name: Kling Video O1
    description: $0.09/second
    tags: []
    tools: null
    native_web: null
    vision: true
    audio: null
    video: null
    image_gen: null
    audio_gen: null
    video_gen: true
    context_window: null
    connection: openrouter
  alibaba/wan-2.7:
    provider: alibaba
    name: Wan 2.7
    description: $0.10/second
    tags: []
    tools: null
    native_web: null
    vision: true
    audio: null
    video: null
    image_gen: null
    audio_gen: null
    video_gen: true
    context_window: null
    connection: openrouter
  bytedance/seedance-2.0-fast:
    provider: bytedance
    name: Seedance 2.0 Fast
    description: $0.270/second
    tags: []
    tools: null
    native_web: null
    vision: true
    audio: null
    video: null
    image_gen: null
    audio_gen: null
    video_gen: true
    context_window: null
    connection: openrouter
  openai/sora-2-pro:
    provider: openai
    name: Sora 2 Pro
    description: $0.30/second
    tags: []
    tools: null
    native_web: null
    vision: true
    audio: null
    video: null
    image_gen: null
    audio_gen: null
    video_gen: true
    context_window: null
    connection: openrouter
  google/veo-3.1:
    provider: gemini
    name: Veo 3.1
    description: $0.40/second
    tags: []
    tools: null
    native_web: null
    vision: true
    audio: null
    video: null
    image_gen: null
    audio_gen: null
    video_gen: true
    context_window: null
    connection: openrouter
  google/veo-3.1-fast:
    provider: gemini
    name: Veo 3.1 Fast
    description: $0.10/second
    tags: []
    tools: null
    native_web: null
    vision: true
    audio: null
    video: null
    image_gen: null
    audio_gen: null
    video_gen: true
    context_window: null
    connection: openrouter
