# MAESTRO 設定ファイル (v2 layout)
#
# このファイルを config.yaml にコピーして編集してください:
#   cp config.yaml.example config.yaml
#
# ─── v2 への移行 (v1 → v2) ─────────────────────────────────────
# 旧構造 (provider.* / 平置きの worktree_dir 等) は 1 リリース分だけ
# 読み取り互換が残っています。手元の config.yaml が旧形式の場合は:
#
#   scripts/migrate-config.sh --dry-run     # 変換後を確認
#   scripts/migrate-config.sh               # in-place で書き換え (.bak を自動保存)
#
# v3.0 で v1 形式は起動 fatal になる予定です。

# v2 schema バージョン (必須)。
#   - 2          : このリリースの正規形 (= 本ファイル)
#   - 1 / 未指定 : v1 互換読み取り + 起動 warning
#   - その他     : 起動 fatal (typo / 未来形式の混入防止)
config_version: 2

# ─── LLM ─────────────────────────────────────────────────────
# ジョブ実行時に LLM 呼び出し先として使う接続群と、retry / timeout / metrics。
llm:
  timeout_minutes: 10                     # 1 リクエスト全体の上限 (分)。default 10

  retry:
    max_attempts: 3
    backoff_ms: [2000, 5000, 15000]       # 429 / 5xx / 一時的接続失敗時の待機 ms
    retryable_status: [429, 500, 502, 503, 504]

  # workers[] — この AAO がジョブ実行時に呼ぶ接続先。
  #
  # connection_type:
  #   direct       — Ollama / llama.cpp / vLLM 等の OpenAI 互換 backend に直接接続
  #   aao_gateway  — 別 AAO Gateway 経由で接続 (Gateway Key 必須)
  #
  # トップレベル `gateway.*` (この AAO 自身が gateway として動く設定) と
  # 単語衝突を避けるため、worker 側は `aao_gateway` と prefix 付き。
  #
  # model はワーカーごとに明示。`default_model` は廃止された。
  # roles: 用途別 (auto / fast / quality / title / reflection 等) のフィルタ。
  # max_concurrency: 1ワーカーが同時実行するジョブ数 (A1スロット方式)。デフォルト1。
  #                  >1 はオプトイン。注意: shutdown drain は粗く、fairness は低下し、
  #                  LLM provider 側の rate limit は別途。browser を使うワーカーで >1 にする場合は
  #                  セッション作成は mutex 済みだが本番投入前に dogfooding すること。
  # vlm: true で画像入力に対応 (ReadImage は VLM ワーカーを優先)。
  workers:
    - id: local-ollama
      connection_type: direct
      endpoint: http://localhost:11434/v1
      model: qwen3:32b
      roles: [auto, fast, quality]
      max_concurrency: 1
      enabled: true
      vlm: false

    # 例: 別 AAO Gateway 越しに共有 GPU プールを使う
    # - id: team-gateway
    #   connection_type: aao_gateway
    #   endpoint: http://gateway.example.com:9876/v1
    #   api_key: ${TEAM_AAO_GATEWAY_KEY}       # gateway 発行の sk-aao-*** virtual key
    #   model: qwen3:32b
    #   roles: [quality]
    #   max_concurrency: 2
    #   enabled: true

    # 例: タイトル生成専用ワーカー (chat ジョブは受け付けない)
    # - id: title-worker
    #   connection_type: direct
    #   endpoint: http://localhost:11434/v1
    #   model: qwen3:8b
    #   roles: [title]
    #   max_concurrency: 4
    #   enabled: true

    # 例: Reflection 専用ワーカー (cheap モデルで memory 更新を回す)
    # - id: reflector
    #   connection_type: direct
    #   endpoint: http://localhost:11434/v1
    #   model: qwen3:8b
    #   roles: [reflection]
    #   max_concurrency: 1
    #   enabled: true

  # Prometheus exporter (worker side). default で enabled。
  # /metrics が bridge HTTP server (PORT, default 9876) に mount される。
  # access control: default では localhost (127.0.0.1 / ::1) のみ通る。
  # 本番では (a) bearer_token を設定するか、(b) allowed_hosts で前段 IP を許可。
  # env: AAO_WORKER_METRICS_BEARER_TOKEN / AAO_WORKER_METRICS_ALLOWED_HOSTS (CSV) でも上書き可。
  metrics:
    enabled: true
    prefix: aao_worker                      # /^[a-z][a-z0-9_]*$/
    # bearer_token: env:AAO_WORKER_METRICS_BEARER_TOKEN
    # allowed_hosts:
    #   - 127.0.0.1
    #   - ::1
    #   - localhost
    #   # - 0.0.0.0                            # 全許可。前段で firewall を必ず使う運用前提

# ─── AAO Gateway Server ──────────────────────────────────────
# この AAO 自身を OpenAI 互換 LLM Gateway として公開する設定。
# 有効化すると `/v1/chat/completions` などが同 process で立ち上がる。
#
# Virtual Keys (sk-aao-*** 形式) は **admin REST API での発行を推奨**:
#   POST /api/admin/gateway/keys
# config.yaml の virtual_keys[] は bootstrap / backup 用途のみで、
# DB に自動 import される (source='config-import')。rotation は admin API 経由でのみ。
#
# 同 process / separate process の deploy 方法は docs/aao-gateway-overview.md を参照。
# UI からは Settings → LLM → Gateway Server で全て編集可能。
# gateway:
#   enabled: false                           # true で同 process gateway が即時起動
#                                            # (ConfigManager hot reload 対応、再起動不要)
#   listen_port: 4000                        # separate-deploy 時のみ有効 (default LiteLLM 互換)
#   request_timeout_sec: 600                 # 1 リクエスト全体 (streaming 込み)
#   upstream_timeout_sec: 30                 # 各 upstream fetch の TTFB 上限
#   shutdown_graceful_sec: 30                # SIGTERM 後、in-flight SSE の drain 上限秒
#
#   backends:
#     - id: gpu-a                            # `x-aao-backend-id` / `/v1/models` に出る ID
#       endpoint: http://gpu-a:11434/v1
#       model: qwen3:32b                     # 厳密一致 routing
#       max_slots: 2                         # llama-server -np と合わせる
#       api_key: ${GPU_A_API_KEY}            # backend が bearer 必須な場合のみ
#     - id: gpu-b
#       endpoint: http://gpu-b:11434/v1
#       model: qwen3:32b
#       max_slots: 2
#
#   # Bootstrap / Backup 専用 virtual_keys (新規発行は admin API 経由を推奨)。
#   # virtual_keys:
#   #   - key: ${TEAM_ALPHA_KEY}             # 起動時に DB へ idempotent import
#   #     team: alpha
#   #     allowed_models: [qwen3:32b]
#   #     # tokens_budget: 1000000          # 月次 token 上限 (UTC 月初に reset)
#   #     # rate_limit_rpm: 60              # 1 分あたり最大リクエスト数
#
#   # Prometheus exporter (gateway side)。default enabled。
#   # team / key_prefix / backend ラベルが出るので auth 必須運用 (default localhost のみ)。
#   # env: AAO_GATEWAY_METRICS_BEARER_TOKEN / AAO_GATEWAY_METRICS_ALLOWED_HOSTS (CSV) で上書き可。
#   # metrics:
#   #   enabled: true
#   #   prefix: aao_gateway
#   #   bearer_token: env:AAO_GATEWAY_METRICS_BEARER_TOKEN
#   #   allowed_hosts:
#   #     - 127.0.0.1
#   #     - ::1
#   #     # - 0.0.0.0                        # 前段 firewall 必須

# ─── Storage / Paths ─────────────────────────────────────────
# 旧 worktree_dir / custom_pieces_dir / user_folder_root /
#    tools.task_upload_max_size_mb / tools.trash_retention_days
# は normalizer により storage.* に集約された。
storage:
  worktree_dir: ./data/workspaces            # ジョブ実行時の作業ディレクトリのベース
  # custom_pieces_dir: ./custom-pieces      # リポジトリ内の pieces/ に加えて読みに行く Piece dir (任意)
  user_folder_root: ./data/users             # {root}/{userId}/ 配下に AGENTS.md/scripts/notes 等を保存
  task_upload_max_size_mb: 50                # /api/local/tasks と /comments の body 上限 (MB)
                                             # base64 で乗るので実ファイル目安は値 × 0.75。範囲 [1, 1000]
  trash_retention_days: 30                   # data/users/{userId}/trash/ の自動 sweep (起動時 + 24h 周期)
                                             # 0 で sweep 毎に全削除

# ─── Execution ───────────────────────────────────────────────
# ジョブ全体の並列度・movement 上限・ジョブ retry。
concurrency: 4                                # 全 worker 合算の最大並列ジョブ数 (env: CONCURRENCY)
max_movements: 200                            # 1 ジョブ内の最大 movement 数 (loop 防止)
retry:
  max_attempts: 3                             # ジョブ失敗時の最大再試行回数
  backoff_seconds: [60, 300, 900]             # 各 attempt 間の待機秒

# ASK (ユーザーへの質問) 制御
ask:
  max_per_job: 2                              # 1 Job あたりの ASK 上限

# Subtask 制御
subtasks:
  max_depth: 2                                # SpawnSubTask のネスト最大深度
  max_per_parent: 10                          # 1 ジョブが生成できるサブタスクの最大数

# ─── Context (LLM コンテキスト管理) ───────────────────────────
# context:
#   limit_tokens: 128000                      # 省略時は Ollama API で自動取得、それも失敗なら 128000
#   thresholds:
#     - ratio: 0.7
#       action: warn
#     - ratio: 0.85
#       action: prompt
#     - ratio: 0.95
#       action: force_transition

# ─── Safety (エージェント自爆防止) ────────────────────────────
# safety:
#   max_iterations: 200                       # 1 movement 内の最大イテレーション
#   max_revisits: 3                           # 同一 movement の最大再訪問
#   max_tool_loop_repeats: 5                   # 全く同じツール呼び出し(名前+引数)を連続で繰り返した回数がこの値に達したらループとみなし強制中断 (2以上)
#   prompt_guard_ratio: 0.8                   # コンテキスト上限の何 % まで prompt を許容するか (0.5–0.95)
#   history_summarization:                    # 古い turn を構造化要約に置換して粘る (Opencode 方式)
#     enabled: true                           # default true
#     tail_turns: 2                           # 末尾何 turn を必ず保護するか
#     preserve_recent_budget: 8000            # 末尾保護の最大トークン数
#   bash_unrestricted: false                  # true: コマンドホワイトリストを撤廃し任意コマンド実行可。
#                                             # 代わりに bwrap サンドボックスで workspace 単位の
#                                             # ファイルシステム隔離を強制 (タスク間の横断アクセス防止)。
#                                             # 前提: コンテナで user namespace が有効 (nesting=1)。
#                                             # 起動時に bwrap の動作確認を行い、失敗時はエラー終了。
#   # Bash サンドボックス機構:
#   #   auto   (既定) bwrap があれば sandbox、無ければ hardened-whitelist にフォールバック
#   #   always sandbox を強制。bwrap 不在なら起動失敗（本番推奨）
#   #   off    bwrap を使わない（env スクラブは維持）。デバッグ用、非推奨
#   bash_sandbox: auto

# ─── Search Filter (WebSearch の機密情報漏洩防止) ─────────────
# search_filter:
#   blocked_patterns:                         # カスタムブロックパターン (完全一致で除去)
#     - secret-project
#     - internal-codename
#   auto_block:                               # 自動検出 (default: 全 true)
#     private_ip: true                        # 10.* / 172.16-31.* / 192.168.* / 127.*
#     internal_domain: true                   # .local / .internal / .lan / .intranet / .corp / .home
#     email: true
#     phone: true                             # 日本の電話番号

# ─── Browser Runtime (BrowseWeb / BrowserAction) ──────────────
# browser:
#   page_timeout: 60000                       # ms
#   action_timeout: 30000                     # ms
#   captcha_solve: novnc                      # 'skip' (default) / 'novnc'
#   max_captcha_pages: 5
#   channel: chrome                           # 'chromium' (default) / 'chrome' / 'msedge'
#   executable_path: /usr/bin/google-chrome   # channel と排他

# ─── Tools (Web & Search / Media / External / Legacy) ────────
# UI 上は 5 カテゴリに分かれて編集可能 (Web & Search / Browser Runtime /
# Media & Documents / External Services / Legacy Knowledge)。YAML は
# 互換のため `tools` 1 ブロックで管理。
tools:
  # Web & Search
  searxng_url: http://localhost:8080          # WebSearch フォールバック先 (通常は Playwright + Google)
  webfetch_timeout: 30                        # WebFetch / DownloadFile timeout (sec)
  # websearch_timeout: 15
  # webfetch_allowed_hosts:                   # SSRF 例外 (private IP / .local 等を許可する場合)
  #   - my-internal-host.local

  # Media & Documents
  # vision_model: qwen2-vl:8b-instruct        # ReadImage 用 VLM (provider と別エンドポイントなら vision_base_url)
  # vision_base_url: http://localhost:11434/v1
  # vision_timeout: 60
  # vision_max_tokens: 1024
  # ocr_model: glm-ocr                        # OCR 用モデル (vision_base_url の server に問い合わせる)
  # office_excel_max_size_mb: 10              # ReadExcel 上限 (default 10)
  # office_docx_max_size_mb: 10               # ReadDocx 上限
  # office_pdf_max_size_mb: 10                # ReadPdf 上限
  # office_pptx_max_size_mb: 50               # ReadPPTX 上限
  # office_pptx_max_uncompressed_mb: 200      # PPTX ZIP 展開後上限 (zip-bomb 検知)
  # speech_server_url: http://localhost:8000/v1
  # speech_timeout: 300
  # speech_language: ja

  # External Services
  # x_cli_command: ["twitter"]                # twitter-cli 実行コマンド
  # x_timeout: 90
  # x_auth_token: "..."                       # 任意: auth_token cookie
  # x_ct0: "..."                              # 任意: ct0 cookie
  # x_proxy: http://127.0.0.1:7890            # 任意: twitter-cli 用 proxy
  # x_chrome_profile: "Profile 2"             # Chrome cookie 抽出 profile
  # x_download_media: auto                    # 'auto' (default) / 'never'
  # x_download_video: thumbnail               # 'thumbnail' (default) / 'full' / 'never'
  # x_media_max_mb: 25
  # x_media_fetch_timeout_seconds: 15
  # google_maps_api_key: "..."                # 未設定なら Nominatim / OSRM
  # maps_timeout: 30
  # amazon_affiliate_tag: "your-tag-22"
  # keepa_api_key: "..."

  # User scripts (RunUserScript)
  # user_scripts_enabled: false               # true で許可。plain runtime は Node --permission で sandbox 化
  # user_scripts_allow_userids:               # 未指定 = 全ユーザー許可 (user_scripts_enabled に従う)
  #   - alice-id
  #   - bob-id

  # Legacy Knowledge (DKS) — 新規 namespace 追加は MCP 経由を推奨
  # knowledge_service_url: http://dks-server:8100  # 未設定で knowledge ツール無効
  # knowledge_namespaces:
  #   product-a-support:
  #     api_key: "sk-product-a-xxx"
  #   contract-review:
  #     api_key: "sk-contract-yyy"

# ── Shared Knowledge Notes ───────────────────────────────────
# data/users/{userId}/notes/ のノートをシステムプロンプトに自動注入する設定。
# notes:
#   inject:
#     per_note_max_kb: 8                      # 日本語コンテンツは 4 推奨
#     total_max_kb: 32
#     over_budget_strategy: skip_remaining    # truncate_last / skip_remaining (default) / degrade_to_search

# ─── 認証 (オプション) ────────────────────────────────────────
# 未設定なら認証なしで動作 (従来互換)。
# auth:
#   session_secret: "ランダムな文字列を設定してください"
#   session_max_age: 86400000                 # 24h (ms)
#   secure_cookie: false                      # HTTPS 環境では true
#   admin_emails:
#     - "admin@example.com"
#   # primary_provider: gitea                 # 'google' | 'gitea'。両方有効時に明示
#   providers:
#     google:
#       client_id: ""
#       client_secret: ""
#       callback_url: "http://localhost:3000/auth/google/callback"
#     gitea:
#       client_id: ""
#       client_secret: ""
#       base_url: "https://gitea.example.com"
#       callback_url: "http://localhost:3000/auth/gitea/callback"

# ─── Branding (オプション) ────────────────────────────────────
# config.yaml / data/branding/ は .gitignore 済みで git pull 影響なし。
# Settings → System → Branding で GUI 編集可 (admin)。
# branding:
#   app_name: "My Team AI"
#   primary_color: "#2563eb"
#   login_page_title: "My Team AI"
#   logo_url: "/branding/logo-abc123.svg"
#   favicon_url: "/branding/favicon-def456.png"
#   footer_text: "© 2026 Your Team"

# ─── Secrets ─────────────────────────────────────────────────
# secrets:
#   master_key_path: ./data/secrets/master.key    # 32-byte key, auto-generated on first start (mode 0600)

# ─── Reflection ("Hermes" mode) ──────────────────────────────
# default OFF。ON にすると毎ジョブ完了後に user memory を LLM が自動更新する。
# snapshot は data/users/{userId}/.reflection-history/ に残り UI から revert 可。
# reflection:
#   enabled: false
#   max_memory_changes_per_job: 3
#   piece_edit_cooldown_hours: 24
#   snapshot_retention_days: 90
#   per_user_daily_budget_tokens: 200000

# ─── MCP (Model Context Protocol) ────────────────────────────
# Individual servers は admin UI (global) または各ユーザー (self-hosted) で管理。
# MCP_ENCRYPTION_KEY env (64 hex chars) が必須。
# mcp:
#   call_timeout_seconds: 60
#   max_binary_size_mb: 20
#   max_output_files_per_job: 10
#   max_output_size_mb_per_job: 200
#   tool_cache_ttl_seconds: 600
#   oauth_pending_ttl_minutes: 10
#   # allow_private_addresses: false          # 自前 MCP server を private 網に置く場合 true

# ─── SSH (off by default) ────────────────────────────────────
# 有効化手順は docs/ssh.md / config.yaml.example のコメント (旧版) を参照。
# Operator runbook: docs/ssh.md
# Sample piece:     pieces/ssh-ops.yaml
#
# ssh:
#   enabled: false
#
#   # allow_private_addresses: false          # global default。admin は per-connection で grant 可
#   # call_timeout_seconds: 30
#   # max_output_bytes: 32768
#   # max_upload_size_mb: 100
#   # max_download_size_mb: 100
#   # audit_retention_days: 90
#   # admin_bypasses_grants: true
#   # abuse_window_minutes: 10
#   # abuse_failure_threshold: 5
#   # abuse_lock_minutes: 30
#
#   # ── Interactive SSH Console (live PTY-backed shell) ──
#   console:
#     enabled: false                          # true で SshConsole* tools + UI Terminal タブを公開
#     idle_timeout_seconds: 1800              # 30min I/O-less = auto close
#     max_session_duration_seconds: 14400     # 4h hard cap
#     scrollback_bytes: 524288                # 512KB scrollback / session
#     max_sessions_per_connection: 3
#     max_input_bytes_per_send: 16384
#     auto_inject_screen_lines: 24
#     default_cols: 120
#     default_rows: 32


# ── Browser Notifications V2 (Web Push) ───────────────────────────────
# Requires HTTPS hosting + (for iOS) PWA installation on the client side.
# notifications:
#   push:
#     enabled: false                                   # true で V2 を有効化
#     vapid_subject: "https://maestro.example.com/"     # RFC 8292 — operations URL preferred
#     vapid_current_path: "./data/secrets/vapid.json"  # 自動生成 (mode 0600)
#     vapid_history_dir: "./data/secrets/vapid-history"
#     payload_max_bytes: 3072                          # JSON byte length cap (上限 4096)
#     queue_concurrency: 8
#     per_send_timeout_ms: 10000
#
# 起動時に vapid_current_path に鍵が無ければ自動生成、mode 0600 で保存。
# 鍵をローテーションする場合:  npm run vapid-rotate
