Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/bei666qi-pan_versecraft.json
T

1 line
293 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "bei666qi-pan/versecraft", "files": {".env.example": {"7ef2bfcabda0995ae4253e0841a4770c6a1bf9fd": {"t": 1785747112.9233446, "n": 15398, "h": "c9c5c9ea3d35c33f", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Static asset CDN (images) — optional, unset falls back to local /assets --\n# NEXT_PUBLIC_ASSET_CDN_BASE_URL=\"https://assets.versecraft.cn\"\n\n# --- Canonical app URLs / preview environment guard ---------------------------\n# Local default can stay unset. Preview Coolify should set these explicitly.\n# ENVIRONMENT_NAME=\"preview\"\n# APP_URL=\"https://preview.versecraft.cn\"\n# NEXT_PUBLIC_APP_URL=\"https://preview.versecraft.cn\"\n# Optional SHA-256 hex fingerprints of normalized database URLs.\n# PRODUCTION_DATABASE_URL_FINGERPRINT=\"\"\n# PREVIEW_DATABASE_URL_FINGERPRINT=\"\"\n\n# --- Preview access gate (default closed unless enabled and host matches) -----\nPREVIEW_ACCESS_ENABLED=\"false\"\nPREVIEW_ACCESS_HOSTS=\"preview.versecraft.cn\"\nPREVIEW_ACCESS_PASSWORD=\"\"\nPREVIEW_ACCESS_COOKIE_SECRET=\"\"\nPREVIEW_ACCESS_COOKIE_NAME=\"vc_preview_access\"\nPREVIEW_ACCESS_MAX_AGE_SECONDS=\"604800\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-enhance\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# --- Embeddings (T4, 2026-07: world knowledge vector retrieval) --------------\n# Default path (AI_EMBEDDING_PROVIDER unset / \"openai_compatible\"): reuses\n# AI_GATEWAY_BASE_URL + AI_GATEWAY_API_KEY above (same credentials as chat\n# completions) — point the one-api channel behind AI_MODEL_EMBEDDING at whatever\n# embedding-capable model/vendor you've configured. Do NOT hardcode a vendor\n# model id in app code — this is an opaque string resolved by one-api, same\n# convention as AI_MODEL_MAIN etc.\n# AI_MODEL_EMBEDDING=\"vc-embedding\"\n# Must match world_knowledge_chunks.embedding_vector's pgvector column width\n# (1024 by default — see src/db/ensureSchema.ts). If your embedding model\n# outputs a different dimension, either configure a projection/truncation step in\n# one-api, or change this value AND the schema's vector() width together.\n# AI_EMBEDDING_DIMENSION=\"1024\"\n# Only set if embeddings must go through a different base URL than chat completions.\n# AI_EMBEDDING_GATEWAY_BASE_URL=\"\"\n# AI_EMBEDDING_TIMEOUT_MS=\"20000\"\n#\n# Architectural exception (2026-07): Volcengine Ark's only non-retired embedding\n# model on this account (doubao-embedding-vision / Seed-1.6-Embedding) is a\n# multimodal model that lives on Ark's own /api/v3/embeddings/multimodal route,\n# not the standard OpenAI-compatible /v1/embeddings that one-api proxies (confirmed\n# empirically: one-api returns a route-level 404 for this path, not an auth error).\n# Setting AI_EMBEDDING_PROVIDER=\"ark_multimodal\" makes embedText.ts bypass the\n# one-api gateway and call Ark directly for this ONE offline path only (never\n# /api/chat) — it needs its own dedicated key, which cannot reuse AI_GATEWAY_API_KEY\n# (different auth domain). This intentionally sits outside one-api's unified\n# rate-limiting/billing/observability; keep the exception scoped to embeddings.\n# AI_EMBEDDING_PROVIDER=\"ark_multimodal\"\n# ARK_EMBEDDING_BASE_URL=\"https://ark.cn-beijing.volces.com\"\n# ARK_EMBEDDING_API_KEY=\"\"\n# Enabled by default: adds one online embeddings HTTP call per /api/chat turn (to\n# embed the player's current input for similarity search), under a strict\n# AI_WORLD_VECTOR_QUERY_EMBED_TIMEOUT_MS budget with fail-open behavior (falls back\n# to exact/tag/FTS layers on any error/timeout — see CLAUDE.md 5.4 performance\n# budget). Verify real gateway latency + embedding dimension with\n# `pnpm embeddings:verify-dimension` BEFORE shipping — set AI_ENABLE_WORLD_VECTOR_RETRIEVAL=\"false\"\n# to disable if latency is unacceptable or AI_MODEL_EMBEDDING isn't configured yet.\n# AI_ENABLE_WORLD_VECTOR_RETRIEVAL=\"true\"\n# AI_WORLD_VECTOR_QUERY_EMBED_TIMEOUT_MS=\"300\"\n\n# World Director / offline reasoner loop.\n# Default soft + hint_injection=true: the worker generates agenda via vc-reasoner,\n# and the next-turn DM prompt receives a director hint block (still 100% async to\n# the player SSE; PLAYER_CHAT itself never routes to reasoner).\n#\n# IMPORTANT: For these defaults to actually take effect, the background worker\n# must be running (`pnpm worker:kg`) and AI_MODEL_REASONER must be reachable\n# through the gateway. If the worker is offline, no agenda is produced and the\n# director hint block degrades to empty—no impact on the main SSE.\n# 生产部署可启用 docker-compose `--profile production` 自动起 vc-worker。\nAI_ENABLE_WORLD_DIRECTOR=\"true\"\nAI_DIRECTOR_MODE=\"soft\" # off | shadow | soft\n# AI_ENABLE_DIRECTOR_HINT_INJECTION=\"true\"\n# AI_ENABLE_DIRECTOR_CRITIC=\"false\"\n# AI_DIRECTOR_MAX_DUE_HINTS=\"2\"\n# AI_DIRECTOR_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_DIRECTOR_MAX_PENDING_AGENDA_PER_SESSION=\"12\"\n# AI_DIRECTOR_AGENDA_DEFAULT_TTL_TURNS=\"6\"\n# AI_DIRECTOR_AGENDA_QUERY_TIMEOUT_MS=\"80\"\n\n# Social World / NPC-agent background loop. Default shadow lets vc-reasoner\n# plan NPC social events in workers; PLAYER_CHAT still never routes to reasoner.\nAI_ENABLE_SOCIAL_WORLD=\"true\"\nAI_SOCIAL_WORLD_MODE=\"shadow\" # off | shadow | soft\n# AI_SOCIAL_MAX_ACTIVE_NPCS=\"5\"\n# AI_SOCIAL_MAX_EVENTS_PER_TICK=\"3\"\n# AI_SOCIAL_MAX_PROMPT_EVENTS=\"2\"\n# AI_SOCIAL_PROMPT_MAX_CHARS=\"900\"\n# AI_SOCIAL_QUERY_TIMEOUT_MS=\"80\"\n# AI_SOCIAL_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_SOCIAL_MAX_PENDING_EVENTS_PER_SESSION=\"12\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"4500\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# Bump to \"5\" after separating playable options from main-turn narrative JSON (stable prefix text changed).\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"v3-20260708\"\n# Phase-2/5: enable narrative directive packet (beat + register + dialogue + dueForeshadow); default OFF\n# VERSECRAFT_ENABLE_NARRATIVE_DIRECTIVE=\"1\"\n# Defer playable options to a follow-up options_regen_only request from /play (default ON); set \"0\"/false to rollback.\n# VERSECRAFT_DEFER_MAIN_TURN_OPTIONS_TO_CLIENT=\"1\"\n# NEXT_PUBLIC_VERSECRAFT_DEFER_MAIN_TURN_OPTIONS_TO_CLIENT=\"1\"\n# Phase 7: /play 叙事系统调试浮层(客户端);服务端变更集控制台日志\n# NEXT_PUBLIC_VERSECRAFT_SYSTEMS_DEBUG=\"1\"\n# VERSECRAFT_DM_CHANGESET_DEBUG=\"1\"\n# Phase 6: 叙事咬合读档修复日志\n# NEXT_PUBLIC_VERSECRAFT_NARRATIVE_DEBUG=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (default: enabled as post-stream optional enhancement; set 0 to disable)\nAI_ENABLE_NARRATIVE_ENHANCEMENT=\"1\"\nAI_NARRATIVE_EXPANSION_ENABLED=\"true\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# --- Local dev-ops tooling (scripts/autoops/ only — NOT read by the app itself) -\n# DeepSeek backend for `pnpm autoops:start:deepseek` / the Coolify deploy self-heal\n# script (scripts/autoops/lib/agent-runner.mjs). Also used by eval tools:\n# - `pnpm test:playthrough:run --live` — Playthrough 模拟器 live 模式\n# - `pnpm dlx tsx scripts/run-deepeval.ts --mode live` — DeepEval 叙事裁判 live 模式\n# Put the real value in .env.local, never here. See .ops/autoops/CONFIG.md.\n# DEEPSEEK_API_KEY=\"\"\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "37a2b09e3c5c5f2482bf612d50f8ba7538331575": {"t": 1785770489.2603526, "n": 15398, "h": "c9c5c9ea3d35c33f", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Static asset CDN (images) — optional, unset falls back to local /assets --\n# NEXT_PUBLIC_ASSET_CDN_BASE_URL=\"https://assets.versecraft.cn\"\n\n# --- Canonical app URLs / preview environment guard ---------------------------\n# Local default can stay unset. Preview Coolify should set these explicitly.\n# ENVIRONMENT_NAME=\"preview\"\n# APP_URL=\"https://preview.versecraft.cn\"\n# NEXT_PUBLIC_APP_URL=\"https://preview.versecraft.cn\"\n# Optional SHA-256 hex fingerprints of normalized database URLs.\n# PRODUCTION_DATABASE_URL_FINGERPRINT=\"\"\n# PREVIEW_DATABASE_URL_FINGERPRINT=\"\"\n\n# --- Preview access gate (default closed unless enabled and host matches) -----\nPREVIEW_ACCESS_ENABLED=\"false\"\nPREVIEW_ACCESS_HOSTS=\"preview.versecraft.cn\"\nPREVIEW_ACCESS_PASSWORD=\"\"\nPREVIEW_ACCESS_COOKIE_SECRET=\"\"\nPREVIEW_ACCESS_COOKIE_NAME=\"vc_preview_access\"\nPREVIEW_ACCESS_MAX_AGE_SECONDS=\"604800\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-enhance\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# --- Embeddings (T4, 2026-07: world knowledge vector retrieval) --------------\n# Default path (AI_EMBEDDING_PROVIDER unset / \"openai_compatible\"): reuses\n# AI_GATEWAY_BASE_URL + AI_GATEWAY_API_KEY above (same credentials as chat\n# completions) — point the one-api channel behind AI_MODEL_EMBEDDING at whatever\n# embedding-capable model/vendor you've configured. Do NOT hardcode a vendor\n# model id in app code — this is an opaque string resolved by one-api, same\n# convention as AI_MODEL_MAIN etc.\n# AI_MODEL_EMBEDDING=\"vc-embedding\"\n# Must match world_knowledge_chunks.embedding_vector's pgvector column width\n# (1024 by default — see src/db/ensureSchema.ts). If your embedding model\n# outputs a different dimension, either configure a projection/truncation step in\n# one-api, or change this value AND the schema's vector() width together.\n# AI_EMBEDDING_DIMENSION=\"1024\"\n# Only set if embeddings must go through a different base URL than chat completions.\n# AI_EMBEDDING_GATEWAY_BASE_URL=\"\"\n# AI_EMBEDDING_TIMEOUT_MS=\"20000\"\n#\n# Architectural exception (2026-07): Volcengine Ark's only non-retired embedding\n# model on this account (doubao-embedding-vision / Seed-1.6-Embedding) is a\n# multimodal model that lives on Ark's own /api/v3/embeddings/multimodal route,\n# not the standard OpenAI-compatible /v1/embeddings that one-api proxies (confirmed\n# empirically: one-api returns a route-level 404 for this path, not an auth error).\n# Setting AI_EMBEDDING_PROVIDER=\"ark_multimodal\" makes embedText.ts bypass the\n# one-api gateway and call Ark directly for this ONE offline path only (never\n# /api/chat) — it needs its own dedicated key, which cannot reuse AI_GATEWAY_API_KEY\n# (different auth domain). This intentionally sits outside one-api's unified\n# rate-limiting/billing/observability; keep the exception scoped to embeddings.\n# AI_EMBEDDING_PROVIDER=\"ark_multimodal\"\n# ARK_EMBEDDING_BASE_URL=\"https://ark.cn-beijing.volces.com\"\n# ARK_EMBEDDING_API_KEY=\"\"\n# Enabled by default: adds one online embeddings HTTP call per /api/chat turn (to\n# embed the player's current input for similarity search), under a strict\n# AI_WORLD_VECTOR_QUERY_EMBED_TIMEOUT_MS budget with fail-open behavior (falls back\n# to exact/tag/FTS layers on any error/timeout — see CLAUDE.md 5.4 performance\n# budget). Verify real gateway latency + embedding dimension with\n# `pnpm embeddings:verify-dimension` BEFORE shipping — set AI_ENABLE_WORLD_VECTOR_RETRIEVAL=\"false\"\n# to disable if latency is unacceptable or AI_MODEL_EMBEDDING isn't configured yet.\n# AI_ENABLE_WORLD_VECTOR_RETRIEVAL=\"true\"\n# AI_WORLD_VECTOR_QUERY_EMBED_TIMEOUT_MS=\"300\"\n\n# World Director / offline reasoner loop.\n# Default soft + hint_injection=true: the worker generates agenda via vc-reasoner,\n# and the next-turn DM prompt receives a director hint block (still 100% async to\n# the player SSE; PLAYER_CHAT itself never routes to reasoner).\n#\n# IMPORTANT: For these defaults to actually take effect, the background worker\n# must be running (`pnpm worker:kg`) and AI_MODEL_REASONER must be reachable\n# through the gateway. If the worker is offline, no agenda is produced and the\n# director hint block degrades to empty—no impact on the main SSE.\n# 生产部署可启用 docker-compose `--profile production` 自动起 vc-worker。\nAI_ENABLE_WORLD_DIRECTOR=\"true\"\nAI_DIRECTOR_MODE=\"soft\" # off | shadow | soft\n# AI_ENABLE_DIRECTOR_HINT_INJECTION=\"true\"\n# AI_ENABLE_DIRECTOR_CRITIC=\"false\"\n# AI_DIRECTOR_MAX_DUE_HINTS=\"2\"\n# AI_DIRECTOR_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_DIRECTOR_MAX_PENDING_AGENDA_PER_SESSION=\"12\"\n# AI_DIRECTOR_AGENDA_DEFAULT_TTL_TURNS=\"6\"\n# AI_DIRECTOR_AGENDA_QUERY_TIMEOUT_MS=\"80\"\n\n# Social World / NPC-agent background loop. Default shadow lets vc-reasoner\n# plan NPC social events in workers; PLAYER_CHAT still never routes to reasoner.\nAI_ENABLE_SOCIAL_WORLD=\"true\"\nAI_SOCIAL_WORLD_MODE=\"shadow\" # off | shadow | soft\n# AI_SOCIAL_MAX_ACTIVE_NPCS=\"5\"\n# AI_SOCIAL_MAX_EVENTS_PER_TICK=\"3\"\n# AI_SOCIAL_MAX_PROMPT_EVENTS=\"2\"\n# AI_SOCIAL_PROMPT_MAX_CHARS=\"900\"\n# AI_SOCIAL_QUERY_TIMEOUT_MS=\"80\"\n# AI_SOCIAL_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_SOCIAL_MAX_PENDING_EVENTS_PER_SESSION=\"12\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"4500\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# Bump to \"5\" after separating playable options from main-turn narrative JSON (stable prefix text changed).\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"v3-20260708\"\n# Phase-2/5: enable narrative directive packet (beat + register + dialogue + dueForeshadow); default OFF\n# VERSECRAFT_ENABLE_NARRATIVE_DIRECTIVE=\"1\"\n# Defer playable options to a follow-up options_regen_only request from /play (default ON); set \"0\"/false to rollback.\n# VERSECRAFT_DEFER_MAIN_TURN_OPTIONS_TO_CLIENT=\"1\"\n# NEXT_PUBLIC_VERSECRAFT_DEFER_MAIN_TURN_OPTIONS_TO_CLIENT=\"1\"\n# Phase 7: /play 叙事系统调试浮层(客户端);服务端变更集控制台日志\n# NEXT_PUBLIC_VERSECRAFT_SYSTEMS_DEBUG=\"1\"\n# VERSECRAFT_DM_CHANGESET_DEBUG=\"1\"\n# Phase 6: 叙事咬合读档修复日志\n# NEXT_PUBLIC_VERSECRAFT_NARRATIVE_DEBUG=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (default: enabled as post-stream optional enhancement; set 0 to disable)\nAI_ENABLE_NARRATIVE_ENHANCEMENT=\"1\"\nAI_NARRATIVE_EXPANSION_ENABLED=\"true\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# --- Local dev-ops tooling (scripts/autoops/ only — NOT read by the app itself) -\n# DeepSeek backend for `pnpm autoops:start:deepseek` / the Coolify deploy self-heal\n# script (scripts/autoops/lib/agent-runner.mjs). Also used by eval tools:\n# - `pnpm test:playthrough:run --live` — Playthrough 模拟器 live 模式\n# - `pnpm dlx tsx scripts/run-deepeval.ts --mode live` — DeepEval 叙事裁判 live 模式\n# Put the real value in .env.local, never here. See .ops/autoops/CONFIG.md.\n# DEEPSEEK_API_KEY=\"\"\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "be603006171a214d66e0ff28c1fdc3aa507e4075": {"t": 1785770490.595908, "n": 15240, "h": "61c821f63e93a0a5", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Static asset CDN (images) — optional, unset falls back to local /assets --\n# NEXT_PUBLIC_ASSET_CDN_BASE_URL=\"https://assets.versecraft.cn\"\n\n# --- Canonical app URLs / preview environment guard ---------------------------\n# Local default can stay unset. Preview Coolify should set these explicitly.\n# ENVIRONMENT_NAME=\"preview\"\n# APP_URL=\"https://preview.versecraft.cn\"\n# NEXT_PUBLIC_APP_URL=\"https://preview.versecraft.cn\"\n# Optional SHA-256 hex fingerprints of normalized database URLs.\n# PRODUCTION_DATABASE_URL_FINGERPRINT=\"\"\n# PREVIEW_DATABASE_URL_FINGERPRINT=\"\"\n\n# --- Preview access gate (default closed unless enabled and host matches) -----\nPREVIEW_ACCESS_ENABLED=\"false\"\nPREVIEW_ACCESS_HOSTS=\"preview.versecraft.cn\"\nPREVIEW_ACCESS_PASSWORD=\"\"\nPREVIEW_ACCESS_COOKIE_SECRET=\"\"\nPREVIEW_ACCESS_COOKIE_NAME=\"vc_preview_access\"\nPREVIEW_ACCESS_MAX_AGE_SECONDS=\"604800\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-enhance\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# --- Embeddings (T4, 2026-07: world knowledge vector retrieval) --------------\n# Default path (AI_EMBEDDING_PROVIDER unset / \"openai_compatible\"): reuses\n# AI_GATEWAY_BASE_URL + AI_GATEWAY_API_KEY above (same credentials as chat\n# completions) — point the one-api channel behind AI_MODEL_EMBEDDING at whatever\n# embedding-capable model/vendor you've configured. Do NOT hardcode a vendor\n# model id in app code — this is an opaque string resolved by one-api, same\n# convention as AI_MODEL_MAIN etc.\n# AI_MODEL_EMBEDDING=\"vc-embedding\"\n# Must match world_knowledge_chunks.embedding_vector's pgvector column width\n# (1024 by default — see src/db/ensureSchema.ts). If your embedding model\n# outputs a different dimension, either configure a projection/truncation step in\n# one-api, or change this value AND the schema's vector() width together.\n# AI_EMBEDDING_DIMENSION=\"1024\"\n# Only set if embeddings must go through a different base URL than chat completions.\n# AI_EMBEDDING_GATEWAY_BASE_URL=\"\"\n# AI_EMBEDDING_TIMEOUT_MS=\"20000\"\n#\n# Architectural exception (2026-07): Volcengine Ark's only non-retired embedding\n# model on this account (doubao-embedding-vision / Seed-1.6-Embedding) is a\n# multimodal model that lives on Ark's own /api/v3/embeddings/multimodal route,\n# not the standard OpenAI-compatible /v1/embeddings that one-api proxies (confirmed\n# empirically: one-api returns a route-level 404 for this path, not an auth error).\n# Setting AI_EMBEDDING_PROVIDER=\"ark_multimodal\" makes embedText.ts bypass the\n# one-api gateway and call Ark directly for this ONE offline path only (never\n# /api/chat) — it needs its own dedicated key, which cannot reuse AI_GATEWAY_API_KEY\n# (different auth domain). This intentionally sits outside one-api's unified\n# rate-limiting/billing/observability; keep the exception scoped to embeddings.\n# AI_EMBEDDING_PROVIDER=\"ark_multimodal\"\n# ARK_EMBEDDING_BASE_URL=\"https://ark.cn-beijing.volces.com\"\n# ARK_EMBEDDING_API_KEY=\"\"\n# Enabled by default: adds one online embeddings HTTP call per /api/chat turn (to\n# embed the player's current input for similarity search), under a strict\n# AI_WORLD_VECTOR_QUERY_EMBED_TIMEOUT_MS budget with fail-open behavior (falls back\n# to exact/tag/FTS layers on any error/timeout — see CLAUDE.md 5.4 performance\n# budget). Verify real gateway latency + embedding dimension with\n# `pnpm embeddings:verify-dimension` BEFORE shipping — set AI_ENABLE_WORLD_VECTOR_RETRIEVAL=\"false\"\n# to disable if latency is unacceptable or AI_MODEL_EMBEDDING isn't configured yet.\n# AI_ENABLE_WORLD_VECTOR_RETRIEVAL=\"true\"\n# AI_WORLD_VECTOR_QUERY_EMBED_TIMEOUT_MS=\"300\"\n\n# World Director / offline reasoner loop.\n# Default soft + hint_injection=true: the worker generates agenda via vc-reasoner,\n# and the next-turn DM prompt receives a director hint block (still 100% async to\n# the player SSE; PLAYER_CHAT itself never routes to reasoner).\n#\n# IMPORTANT: For these defaults to actually take effect, the background worker\n# must be running (`pnpm worker:kg`) and AI_MODEL_REASONER must be reachable\n# through the gateway. If the worker is offline, no agenda is produced and the\n# director hint block degrades to empty—no impact on the main SSE.\n# 生产部署可启用 docker-compose `--profile production` 自动起 vc-worker。\nAI_ENABLE_WORLD_DIRECTOR=\"true\"\nAI_DIRECTOR_MODE=\"soft\" # off | shadow | soft\n# AI_ENABLE_DIRECTOR_HINT_INJECTION=\"true\"\n# AI_ENABLE_DIRECTOR_CRITIC=\"false\"\n# AI_DIRECTOR_MAX_DUE_HINTS=\"2\"\n# AI_DIRECTOR_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_DIRECTOR_MAX_PENDING_AGENDA_PER_SESSION=\"12\"\n# AI_DIRECTOR_AGENDA_DEFAULT_TTL_TURNS=\"6\"\n# AI_DIRECTOR_AGENDA_QUERY_TIMEOUT_MS=\"80\"\n\n# Social World / NPC-agent background loop. Default shadow lets vc-reasoner\n# plan NPC social events in workers; PLAYER_CHAT still never routes to reasoner.\nAI_ENABLE_SOCIAL_WORLD=\"true\"\nAI_SOCIAL_WORLD_MODE=\"shadow\" # off | shadow | soft\n# AI_SOCIAL_MAX_ACTIVE_NPCS=\"5\"\n# AI_SOCIAL_MAX_EVENTS_PER_TICK=\"3\"\n# AI_SOCIAL_MAX_PROMPT_EVENTS=\"2\"\n# AI_SOCIAL_PROMPT_MAX_CHARS=\"900\"\n# AI_SOCIAL_QUERY_TIMEOUT_MS=\"80\"\n# AI_SOCIAL_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_SOCIAL_MAX_PENDING_EVENTS_PER_SESSION=\"12\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"4500\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# Bump to \"5\" after separating playable options from main-turn narrative JSON (stable prefix text changed).\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"5\"\n# Defer playable options to a follow-up options_regen_only request from /play (default ON); set \"0\"/false to rollback.\n# VERSECRAFT_DEFER_MAIN_TURN_OPTIONS_TO_CLIENT=\"1\"\n# NEXT_PUBLIC_VERSECRAFT_DEFER_MAIN_TURN_OPTIONS_TO_CLIENT=\"1\"\n# Phase 7: /play 叙事系统调试浮层(客户端);服务端变更集控制台日志\n# NEXT_PUBLIC_VERSECRAFT_SYSTEMS_DEBUG=\"1\"\n# VERSECRAFT_DM_CHANGESET_DEBUG=\"1\"\n# Phase 6: 叙事咬合读档修复日志\n# NEXT_PUBLIC_VERSECRAFT_NARRATIVE_DEBUG=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (default: enabled as post-stream optional enhancement; set 0 to disable)\nAI_ENABLE_NARRATIVE_ENHANCEMENT=\"1\"\nAI_NARRATIVE_EXPANSION_ENABLED=\"true\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# --- Local dev-ops tooling (scripts/autoops/ only — NOT read by the app itself) -\n# DeepSeek backend for `pnpm autoops:start:deepseek` / the Coolify deploy self-heal\n# script (scripts/autoops/lib/agent-runner.mjs). Also used by eval tools:\n# - `pnpm test:playthrough:run --live` — Playthrough 模拟器 live 模式\n# - `pnpm dlx tsx scripts/eval-deepeval.ts --mode live` — DeepEval 叙事裁判 live 模式\n# Put the real value in .env.local, never here. See .ops/autoops/CONFIG.md.\n# DEEPSEEK_API_KEY=\"\"\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "d01d0334cd18e61a40b95b24a230decd88245c5a": {"t": 1785770492.3794544, "n": 15070, "h": "bddfb305c79e9e67", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Static asset CDN (images) — optional, unset falls back to local /assets --\n# NEXT_PUBLIC_ASSET_CDN_BASE_URL=\"https://assets.versecraft.cn\"\n\n# --- Canonical app URLs / preview environment guard ---------------------------\n# Local default can stay unset. Preview Coolify should set these explicitly.\n# ENVIRONMENT_NAME=\"preview\"\n# APP_URL=\"https://preview.versecraft.cn\"\n# NEXT_PUBLIC_APP_URL=\"https://preview.versecraft.cn\"\n# Optional SHA-256 hex fingerprints of normalized database URLs.\n# PRODUCTION_DATABASE_URL_FINGERPRINT=\"\"\n# PREVIEW_DATABASE_URL_FINGERPRINT=\"\"\n\n# --- Preview access gate (default closed unless enabled and host matches) -----\nPREVIEW_ACCESS_ENABLED=\"false\"\nPREVIEW_ACCESS_HOSTS=\"preview.versecraft.cn\"\nPREVIEW_ACCESS_PASSWORD=\"\"\nPREVIEW_ACCESS_COOKIE_SECRET=\"\"\nPREVIEW_ACCESS_COOKIE_NAME=\"vc_preview_access\"\nPREVIEW_ACCESS_MAX_AGE_SECONDS=\"604800\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-enhance\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# --- Embeddings (T4, 2026-07: world knowledge vector retrieval) --------------\n# Default path (AI_EMBEDDING_PROVIDER unset / \"openai_compatible\"): reuses\n# AI_GATEWAY_BASE_URL + AI_GATEWAY_API_KEY above (same credentials as chat\n# completions) — point the one-api channel behind AI_MODEL_EMBEDDING at whatever\n# embedding-capable model/vendor you've configured. Do NOT hardcode a vendor\n# model id in app code — this is an opaque string resolved by one-api, same\n# convention as AI_MODEL_MAIN etc.\n# AI_MODEL_EMBEDDING=\"vc-embedding\"\n# Must match world_knowledge_chunks.embedding_vector's pgvector column width\n# (1024 by default — see src/db/ensureSchema.ts). If your embedding model\n# outputs a different dimension, either configure a projection/truncation step in\n# one-api, or change this value AND the schema's vector() width together.\n# AI_EMBEDDING_DIMENSION=\"1024\"\n# Only set if embeddings must go through a different base URL than chat completions.\n# AI_EMBEDDING_GATEWAY_BASE_URL=\"\"\n# AI_EMBEDDING_TIMEOUT_MS=\"20000\"\n#\n# Architectural exception (2026-07): Volcengine Ark's only non-retired embedding\n# model on this account (doubao-embedding-vision / Seed-1.6-Embedding) is a\n# multimodal model that lives on Ark's own /api/v3/embeddings/multimodal route,\n# not the standard OpenAI-compatible /v1/embeddings that one-api proxies (confirmed\n# empirically: one-api returns a route-level 404 for this path, not an auth error).\n# Setting AI_EMBEDDING_PROVIDER=\"ark_multimodal\" makes embedText.ts bypass the\n# one-api gateway and call Ark directly for this ONE offline path only (never\n# /api/chat) — it needs its own dedicated key, which cannot reuse AI_GATEWAY_API_KEY\n# (different auth domain). This intentionally sits outside one-api's unified\n# rate-limiting/billing/observability; keep the exception scoped to embeddings.\n# AI_EMBEDDING_PROVIDER=\"ark_multimodal\"\n# ARK_EMBEDDING_BASE_URL=\"https://ark.cn-beijing.volces.com\"\n# ARK_EMBEDDING_API_KEY=\"\"\n# Enabled by default: adds one online embeddings HTTP call per /api/chat turn (to\n# embed the player's current input for similarity search), under a strict\n# AI_WORLD_VECTOR_QUERY_EMBED_TIMEOUT_MS budget with fail-open behavior (falls back\n# to exact/tag/FTS layers on any error/timeout — see CLAUDE.md 5.4 performance\n# budget). Verify real gateway latency + embedding dimension with\n# `pnpm embeddings:verify-dimension` BEFORE shipping — set AI_ENABLE_WORLD_VECTOR_RETRIEVAL=\"false\"\n# to disable if latency is unacceptable or AI_MODEL_EMBEDDING isn't configured yet.\n# AI_ENABLE_WORLD_VECTOR_RETRIEVAL=\"true\"\n# AI_WORLD_VECTOR_QUERY_EMBED_TIMEOUT_MS=\"300\"\n\n# World Director / offline reasoner loop.\n# Default soft + hint_injection=true: the worker generates agenda via vc-reasoner,\n# and the next-turn DM prompt receives a director hint block (still 100% async to\n# the player SSE; PLAYER_CHAT itself never routes to reasoner).\n#\n# IMPORTANT: For these defaults to actually take effect, the background worker\n# must be running (`pnpm worker:kg`) and AI_MODEL_REASONER must be reachable\n# through the gateway. If the worker is offline, no agenda is produced and the\n# director hint block degrades to empty—no impact on the main SSE.\n# 生产部署可启用 docker-compose `--profile production` 自动起 vc-worker。\nAI_ENABLE_WORLD_DIRECTOR=\"true\"\nAI_DIRECTOR_MODE=\"soft\" # off | shadow | soft\n# AI_ENABLE_DIRECTOR_HINT_INJECTION=\"true\"\n# AI_ENABLE_DIRECTOR_CRITIC=\"false\"\n# AI_DIRECTOR_MAX_DUE_HINTS=\"2\"\n# AI_DIRECTOR_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_DIRECTOR_MAX_PENDING_AGENDA_PER_SESSION=\"12\"\n# AI_DIRECTOR_AGENDA_DEFAULT_TTL_TURNS=\"6\"\n# AI_DIRECTOR_AGENDA_QUERY_TIMEOUT_MS=\"80\"\n\n# Social World / NPC-agent background loop. Default shadow lets vc-reasoner\n# plan NPC social events in workers; PLAYER_CHAT still never routes to reasoner.\nAI_ENABLE_SOCIAL_WORLD=\"true\"\nAI_SOCIAL_WORLD_MODE=\"shadow\" # off | shadow | soft\n# AI_SOCIAL_MAX_ACTIVE_NPCS=\"5\"\n# AI_SOCIAL_MAX_EVENTS_PER_TICK=\"3\"\n# AI_SOCIAL_MAX_PROMPT_EVENTS=\"2\"\n# AI_SOCIAL_PROMPT_MAX_CHARS=\"900\"\n# AI_SOCIAL_QUERY_TIMEOUT_MS=\"80\"\n# AI_SOCIAL_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_SOCIAL_MAX_PENDING_EVENTS_PER_SESSION=\"12\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"4500\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# Bump to \"5\" after separating playable options from main-turn narrative JSON (stable prefix text changed).\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"5\"\n# Defer playable options to a follow-up options_regen_only request from /play (default ON); set \"0\"/false to rollback.\n# VERSECRAFT_DEFER_MAIN_TURN_OPTIONS_TO_CLIENT=\"1\"\n# NEXT_PUBLIC_VERSECRAFT_DEFER_MAIN_TURN_OPTIONS_TO_CLIENT=\"1\"\n# Phase 7: /play 叙事系统调试浮层(客户端);服务端变更集控制台日志\n# NEXT_PUBLIC_VERSECRAFT_SYSTEMS_DEBUG=\"1\"\n# VERSECRAFT_DM_CHANGESET_DEBUG=\"1\"\n# Phase 6: 叙事咬合读档修复日志\n# NEXT_PUBLIC_VERSECRAFT_NARRATIVE_DEBUG=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (default: enabled as post-stream optional enhancement; set 0 to disable)\nAI_ENABLE_NARRATIVE_ENHANCEMENT=\"1\"\nAI_NARRATIVE_EXPANSION_ENABLED=\"true\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# --- Local dev-ops tooling (scripts/autoops/ only — NOT read by the app itself) -\n# DeepSeek backend for `pnpm autoops:start:deepseek` / the Coolify deploy self-heal\n# script (scripts/autoops/lib/agent-runner.mjs). Put the real value in .env.local,\n# never here. See .ops/autoops/CONFIG.md.\n# DEEPSEEK_API_KEY=\"\"\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "cdeaefe39431f31d98418787999860831f9f5eb9": {"t": 1785770494.0837612, "n": 14114, "h": "85aff576ae6b335a", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Static asset CDN (images) — optional, unset falls back to local /assets --\n# NEXT_PUBLIC_ASSET_CDN_BASE_URL=\"https://assets.versecraft.cn\"\n\n# --- Canonical app URLs / preview environment guard ---------------------------\n# Local default can stay unset. Preview Coolify should set these explicitly.\n# ENVIRONMENT_NAME=\"preview\"\n# APP_URL=\"https://preview.versecraft.cn\"\n# NEXT_PUBLIC_APP_URL=\"https://preview.versecraft.cn\"\n# Optional SHA-256 hex fingerprints of normalized database URLs.\n# PRODUCTION_DATABASE_URL_FINGERPRINT=\"\"\n# PREVIEW_DATABASE_URL_FINGERPRINT=\"\"\n\n# --- Preview access gate (default closed unless enabled and host matches) -----\nPREVIEW_ACCESS_ENABLED=\"false\"\nPREVIEW_ACCESS_HOSTS=\"preview.versecraft.cn\"\nPREVIEW_ACCESS_PASSWORD=\"\"\nPREVIEW_ACCESS_COOKIE_SECRET=\"\"\nPREVIEW_ACCESS_COOKIE_NAME=\"vc_preview_access\"\nPREVIEW_ACCESS_MAX_AGE_SECONDS=\"604800\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-enhance\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# --- Embeddings (T4, 2026-07: world knowledge vector retrieval) --------------\n# Reuses AI_GATEWAY_BASE_URL + AI_GATEWAY_API_KEY above (same credentials as chat\n# completions) — point the one-api channel behind AI_MODEL_EMBEDDING at whatever\n# embedding-capable model/vendor you've configured (e.g. Volcengine Ark 豆包\n# embedding model). Do NOT hardcode a vendor model id in app code — this is an\n# opaque string resolved by one-api, same convention as AI_MODEL_MAIN etc.\n# AI_MODEL_EMBEDDING=\"vc-embedding\"\n# Must match world_knowledge_chunks.embedding_vector's pgvector column width\n# (vector(256) by default — see src/db/ensureSchema.ts). If your embedding model\n# outputs a different dimension, either configure a projection/truncation step in\n# one-api, or change this value AND the schema's vector() width together.\n# AI_EMBEDDING_DIMENSION=\"256\"\n# Only set if embeddings must go through a different base URL than chat completions.\n# AI_EMBEDDING_GATEWAY_BASE_URL=\"\"\n# AI_EMBEDDING_TIMEOUT_MS=\"20000\"\n# Enabled by default: adds one online embeddings HTTP call per /api/chat turn (to\n# embed the player's current input for similarity search), under a strict\n# AI_WORLD_VECTOR_QUERY_EMBED_TIMEOUT_MS budget with fail-open behavior (falls back\n# to exact/tag/FTS layers on any error/timeout — see CLAUDE.md 5.4 performance\n# budget). Verify real gateway latency + embedding dimension with\n# `pnpm embeddings:verify-dimension` BEFORE shipping — set AI_ENABLE_WORLD_VECTOR_RETRIEVAL=\"false\"\n# to disable if latency is unacceptable or AI_MODEL_EMBEDDING isn't configured yet.\n# AI_ENABLE_WORLD_VECTOR_RETRIEVAL=\"true\"\n# AI_WORLD_VECTOR_QUERY_EMBED_TIMEOUT_MS=\"300\"\n\n# World Director / offline reasoner loop.\n# Default soft + hint_injection=true: the worker generates agenda via vc-reasoner,\n# and the next-turn DM prompt receives a director hint block (still 100% async to\n# the player SSE; PLAYER_CHAT itself never routes to reasoner).\n#\n# IMPORTANT: For these defaults to actually take effect, the background worker\n# must be running (`pnpm worker:kg`) and AI_MODEL_REASONER must be reachable\n# through the gateway. If the worker is offline, no agenda is produced and the\n# director hint block degrades to empty—no impact on the main SSE.\n# 生产部署可启用 docker-compose `--profile production` 自动起 vc-worker。\nAI_ENABLE_WORLD_DIRECTOR=\"true\"\nAI_DIRECTOR_MODE=\"soft\" # off | shadow | soft\n# AI_ENABLE_DIRECTOR_HINT_INJECTION=\"true\"\n# AI_ENABLE_DIRECTOR_CRITIC=\"false\"\n# AI_DIRECTOR_MAX_DUE_HINTS=\"2\"\n# AI_DIRECTOR_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_DIRECTOR_MAX_PENDING_AGENDA_PER_SESSION=\"12\"\n# AI_DIRECTOR_AGENDA_DEFAULT_TTL_TURNS=\"6\"\n# AI_DIRECTOR_AGENDA_QUERY_TIMEOUT_MS=\"80\"\n\n# Social World / NPC-agent background loop. Default shadow lets vc-reasoner\n# plan NPC social events in workers; PLAYER_CHAT still never routes to reasoner.\nAI_ENABLE_SOCIAL_WORLD=\"true\"\nAI_SOCIAL_WORLD_MODE=\"shadow\" # off | shadow | soft\n# AI_SOCIAL_MAX_ACTIVE_NPCS=\"5\"\n# AI_SOCIAL_MAX_EVENTS_PER_TICK=\"3\"\n# AI_SOCIAL_MAX_PROMPT_EVENTS=\"2\"\n# AI_SOCIAL_PROMPT_MAX_CHARS=\"900\"\n# AI_SOCIAL_QUERY_TIMEOUT_MS=\"80\"\n# AI_SOCIAL_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_SOCIAL_MAX_PENDING_EVENTS_PER_SESSION=\"12\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"4500\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# Bump to \"5\" after separating playable options from main-turn narrative JSON (stable prefix text changed).\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"5\"\n# Defer playable options to a follow-up options_regen_only request from /play (default ON); set \"0\"/false to rollback.\n# VERSECRAFT_DEFER_MAIN_TURN_OPTIONS_TO_CLIENT=\"1\"\n# NEXT_PUBLIC_VERSECRAFT_DEFER_MAIN_TURN_OPTIONS_TO_CLIENT=\"1\"\n# Phase 7: /play 叙事系统调试浮层(客户端);服务端变更集控制台日志\n# NEXT_PUBLIC_VERSECRAFT_SYSTEMS_DEBUG=\"1\"\n# VERSECRAFT_DM_CHANGESET_DEBUG=\"1\"\n# Phase 6: 叙事咬合读档修复日志\n# NEXT_PUBLIC_VERSECRAFT_NARRATIVE_DEBUG=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (default: enabled as post-stream optional enhancement; set 0 to disable)\nAI_ENABLE_NARRATIVE_ENHANCEMENT=\"1\"\nAI_NARRATIVE_EXPANSION_ENABLED=\"true\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# --- Local dev-ops tooling (scripts/autoops/ only — NOT read by the app itself) -\n# DeepSeek backend for `pnpm autoops:start:deepseek` / the Coolify deploy self-heal\n# script (scripts/autoops/lib/agent-runner.mjs). Put the real value in .env.local,\n# never here. See .ops/autoops/CONFIG.md.\n# DEEPSEEK_API_KEY=\"\"\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "ab2d9adbddd7b4cbab8a187417c194461e723af2": {"t": 1785770495.3566902, "n": 13799, "h": "f4dc87fbb0622065", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Static asset CDN (images) — optional, unset falls back to local /assets --\n# NEXT_PUBLIC_ASSET_CDN_BASE_URL=\"https://assets.versecraft.cn\"\n\n# --- Canonical app URLs / preview environment guard ---------------------------\n# Local default can stay unset. Preview Coolify should set these explicitly.\n# ENVIRONMENT_NAME=\"preview\"\n# APP_URL=\"https://preview.versecraft.cn\"\n# NEXT_PUBLIC_APP_URL=\"https://preview.versecraft.cn\"\n# Optional SHA-256 hex fingerprints of normalized database URLs.\n# PRODUCTION_DATABASE_URL_FINGERPRINT=\"\"\n# PREVIEW_DATABASE_URL_FINGERPRINT=\"\"\n\n# --- Preview access gate (default closed unless enabled and host matches) -----\nPREVIEW_ACCESS_ENABLED=\"false\"\nPREVIEW_ACCESS_HOSTS=\"preview.versecraft.cn\"\nPREVIEW_ACCESS_PASSWORD=\"\"\nPREVIEW_ACCESS_COOKIE_SECRET=\"\"\nPREVIEW_ACCESS_COOKIE_NAME=\"vc_preview_access\"\nPREVIEW_ACCESS_MAX_AGE_SECONDS=\"604800\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-enhance\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# --- Embeddings (T4, 2026-07: world knowledge vector retrieval) --------------\n# Reuses AI_GATEWAY_BASE_URL + AI_GATEWAY_API_KEY above (same credentials as chat\n# completions) — point the one-api channel behind AI_MODEL_EMBEDDING at whatever\n# embedding-capable model/vendor you've configured (e.g. Volcengine Ark 豆包\n# embedding model). Do NOT hardcode a vendor model id in app code — this is an\n# opaque string resolved by one-api, same convention as AI_MODEL_MAIN etc.\n# AI_MODEL_EMBEDDING=\"vc-embedding\"\n# Must match world_knowledge_chunks.embedding_vector's pgvector column width\n# (vector(256) by default — see src/db/ensureSchema.ts). If your embedding model\n# outputs a different dimension, either configure a projection/truncation step in\n# one-api, or change this value AND the schema's vector() width together.\n# AI_EMBEDDING_DIMENSION=\"256\"\n# Only set if embeddings must go through a different base URL than chat completions.\n# AI_EMBEDDING_GATEWAY_BASE_URL=\"\"\n# AI_EMBEDDING_TIMEOUT_MS=\"20000\"\n# Enabled by default: adds one online embeddings HTTP call per /api/chat turn (to\n# embed the player's current input for similarity search), under a strict\n# AI_WORLD_VECTOR_QUERY_EMBED_TIMEOUT_MS budget with fail-open behavior (falls back\n# to exact/tag/FTS layers on any error/timeout — see CLAUDE.md 5.4 performance\n# budget). Verify real gateway latency + embedding dimension with\n# `pnpm embeddings:verify-dimension` BEFORE shipping — set AI_ENABLE_WORLD_VECTOR_RETRIEVAL=\"false\"\n# to disable if latency is unacceptable or AI_MODEL_EMBEDDING isn't configured yet.\n# AI_ENABLE_WORLD_VECTOR_RETRIEVAL=\"true\"\n# AI_WORLD_VECTOR_QUERY_EMBED_TIMEOUT_MS=\"300\"\n\n# World Director / offline reasoner loop.\n# Default soft + hint_injection=true: the worker generates agenda via vc-reasoner,\n# and the next-turn DM prompt receives a director hint block (still 100% async to\n# the player SSE; PLAYER_CHAT itself never routes to reasoner).\n#\n# IMPORTANT: For these defaults to actually take effect, the background worker\n# must be running (`pnpm worker:kg`) and AI_MODEL_REASONER must be reachable\n# through the gateway. If the worker is offline, no agenda is produced and the\n# director hint block degrades to empty—no impact on the main SSE.\n# 生产部署可启用 docker-compose `--profile production` 自动起 vc-worker。\nAI_ENABLE_WORLD_DIRECTOR=\"true\"\nAI_DIRECTOR_MODE=\"soft\" # off | shadow | soft\n# AI_ENABLE_DIRECTOR_HINT_INJECTION=\"true\"\n# AI_ENABLE_DIRECTOR_CRITIC=\"false\"\n# AI_DIRECTOR_MAX_DUE_HINTS=\"2\"\n# AI_DIRECTOR_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_DIRECTOR_MAX_PENDING_AGENDA_PER_SESSION=\"12\"\n# AI_DIRECTOR_AGENDA_DEFAULT_TTL_TURNS=\"6\"\n# AI_DIRECTOR_AGENDA_QUERY_TIMEOUT_MS=\"80\"\n\n# Social World / NPC-agent background loop. Default shadow lets vc-reasoner\n# plan NPC social events in workers; PLAYER_CHAT still never routes to reasoner.\nAI_ENABLE_SOCIAL_WORLD=\"true\"\nAI_SOCIAL_WORLD_MODE=\"shadow\" # off | shadow | soft\n# AI_SOCIAL_MAX_ACTIVE_NPCS=\"5\"\n# AI_SOCIAL_MAX_EVENTS_PER_TICK=\"3\"\n# AI_SOCIAL_MAX_PROMPT_EVENTS=\"2\"\n# AI_SOCIAL_PROMPT_MAX_CHARS=\"900\"\n# AI_SOCIAL_QUERY_TIMEOUT_MS=\"80\"\n# AI_SOCIAL_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_SOCIAL_MAX_PENDING_EVENTS_PER_SESSION=\"12\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"4500\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# Bump to \"5\" after separating playable options from main-turn narrative JSON (stable prefix text changed).\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"5\"\n# Defer playable options to a follow-up options_regen_only request from /play (default ON); set \"0\"/false to rollback.\n# VERSECRAFT_DEFER_MAIN_TURN_OPTIONS_TO_CLIENT=\"1\"\n# NEXT_PUBLIC_VERSECRAFT_DEFER_MAIN_TURN_OPTIONS_TO_CLIENT=\"1\"\n# Phase 7: /play 叙事系统调试浮层(客户端);服务端变更集控制台日志\n# NEXT_PUBLIC_VERSECRAFT_SYSTEMS_DEBUG=\"1\"\n# VERSECRAFT_DM_CHANGESET_DEBUG=\"1\"\n# Phase 6: 叙事咬合读档修复日志\n# NEXT_PUBLIC_VERSECRAFT_NARRATIVE_DEBUG=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (default: enabled as post-stream optional enhancement; set 0 to disable)\nAI_ENABLE_NARRATIVE_ENHANCEMENT=\"1\"\nAI_NARRATIVE_EXPANSION_ENABLED=\"true\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "adb8a29d24a9745d3fbe66b149601300bea9c16f": {"t": 1785770497.1437316, "n": 13653, "h": "6523e48e2f02322c", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Canonical app URLs / preview environment guard ---------------------------\n# Local default can stay unset. Preview Coolify should set these explicitly.\n# ENVIRONMENT_NAME=\"preview\"\n# APP_URL=\"https://preview.versecraft.cn\"\n# NEXT_PUBLIC_APP_URL=\"https://preview.versecraft.cn\"\n# Optional SHA-256 hex fingerprints of normalized database URLs.\n# PRODUCTION_DATABASE_URL_FINGERPRINT=\"\"\n# PREVIEW_DATABASE_URL_FINGERPRINT=\"\"\n\n# --- Preview access gate (default closed unless enabled and host matches) -----\nPREVIEW_ACCESS_ENABLED=\"false\"\nPREVIEW_ACCESS_HOSTS=\"preview.versecraft.cn\"\nPREVIEW_ACCESS_PASSWORD=\"\"\nPREVIEW_ACCESS_COOKIE_SECRET=\"\"\nPREVIEW_ACCESS_COOKIE_NAME=\"vc_preview_access\"\nPREVIEW_ACCESS_MAX_AGE_SECONDS=\"604800\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-enhance\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# --- Embeddings (T4, 2026-07: world knowledge vector retrieval) --------------\n# Reuses AI_GATEWAY_BASE_URL + AI_GATEWAY_API_KEY above (same credentials as chat\n# completions) — point the one-api channel behind AI_MODEL_EMBEDDING at whatever\n# embedding-capable model/vendor you've configured (e.g. Volcengine Ark 豆包\n# embedding model). Do NOT hardcode a vendor model id in app code — this is an\n# opaque string resolved by one-api, same convention as AI_MODEL_MAIN etc.\n# AI_MODEL_EMBEDDING=\"vc-embedding\"\n# Must match world_knowledge_chunks.embedding_vector's pgvector column width\n# (vector(256) by default — see src/db/ensureSchema.ts). If your embedding model\n# outputs a different dimension, either configure a projection/truncation step in\n# one-api, or change this value AND the schema's vector() width together.\n# AI_EMBEDDING_DIMENSION=\"256\"\n# Only set if embeddings must go through a different base URL than chat completions.\n# AI_EMBEDDING_GATEWAY_BASE_URL=\"\"\n# AI_EMBEDDING_TIMEOUT_MS=\"20000\"\n# Enabled by default: adds one online embeddings HTTP call per /api/chat turn (to\n# embed the player's current input for similarity search), under a strict\n# AI_WORLD_VECTOR_QUERY_EMBED_TIMEOUT_MS budget with fail-open behavior (falls back\n# to exact/tag/FTS layers on any error/timeout — see CLAUDE.md 5.4 performance\n# budget). Verify real gateway latency + embedding dimension with\n# `pnpm embeddings:verify-dimension` BEFORE shipping — set AI_ENABLE_WORLD_VECTOR_RETRIEVAL=\"false\"\n# to disable if latency is unacceptable or AI_MODEL_EMBEDDING isn't configured yet.\n# AI_ENABLE_WORLD_VECTOR_RETRIEVAL=\"true\"\n# AI_WORLD_VECTOR_QUERY_EMBED_TIMEOUT_MS=\"300\"\n\n# World Director / offline reasoner loop.\n# Default soft + hint_injection=true: the worker generates agenda via vc-reasoner,\n# and the next-turn DM prompt receives a director hint block (still 100% async to\n# the player SSE; PLAYER_CHAT itself never routes to reasoner).\n#\n# IMPORTANT: For these defaults to actually take effect, the background worker\n# must be running (`pnpm worker:kg`) and AI_MODEL_REASONER must be reachable\n# through the gateway. If the worker is offline, no agenda is produced and the\n# director hint block degrades to empty—no impact on the main SSE.\n# 生产部署可启用 docker-compose `--profile production` 自动起 vc-worker。\nAI_ENABLE_WORLD_DIRECTOR=\"true\"\nAI_DIRECTOR_MODE=\"soft\" # off | shadow | soft\n# AI_ENABLE_DIRECTOR_HINT_INJECTION=\"true\"\n# AI_ENABLE_DIRECTOR_CRITIC=\"false\"\n# AI_DIRECTOR_MAX_DUE_HINTS=\"2\"\n# AI_DIRECTOR_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_DIRECTOR_MAX_PENDING_AGENDA_PER_SESSION=\"12\"\n# AI_DIRECTOR_AGENDA_DEFAULT_TTL_TURNS=\"6\"\n# AI_DIRECTOR_AGENDA_QUERY_TIMEOUT_MS=\"80\"\n\n# Social World / NPC-agent background loop. Default shadow lets vc-reasoner\n# plan NPC social events in workers; PLAYER_CHAT still never routes to reasoner.\nAI_ENABLE_SOCIAL_WORLD=\"true\"\nAI_SOCIAL_WORLD_MODE=\"shadow\" # off | shadow | soft\n# AI_SOCIAL_MAX_ACTIVE_NPCS=\"5\"\n# AI_SOCIAL_MAX_EVENTS_PER_TICK=\"3\"\n# AI_SOCIAL_MAX_PROMPT_EVENTS=\"2\"\n# AI_SOCIAL_PROMPT_MAX_CHARS=\"900\"\n# AI_SOCIAL_QUERY_TIMEOUT_MS=\"80\"\n# AI_SOCIAL_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_SOCIAL_MAX_PENDING_EVENTS_PER_SESSION=\"12\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"4500\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# Bump to \"5\" after separating playable options from main-turn narrative JSON (stable prefix text changed).\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"5\"\n# Defer playable options to a follow-up options_regen_only request from /play (default ON); set \"0\"/false to rollback.\n# VERSECRAFT_DEFER_MAIN_TURN_OPTIONS_TO_CLIENT=\"1\"\n# NEXT_PUBLIC_VERSECRAFT_DEFER_MAIN_TURN_OPTIONS_TO_CLIENT=\"1\"\n# Phase 7: /play 叙事系统调试浮层(客户端);服务端变更集控制台日志\n# NEXT_PUBLIC_VERSECRAFT_SYSTEMS_DEBUG=\"1\"\n# VERSECRAFT_DM_CHANGESET_DEBUG=\"1\"\n# Phase 6: 叙事咬合读档修复日志\n# NEXT_PUBLIC_VERSECRAFT_NARRATIVE_DEBUG=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (default: enabled as post-stream optional enhancement; set 0 to disable)\nAI_ENABLE_NARRATIVE_ENHANCEMENT=\"1\"\nAI_NARRATIVE_EXPANSION_ENABLED=\"true\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "08cfab5bebd22ed743c44e0b36b746585d61e423": {"t": 1785770498.4680824, "n": 11987, "h": "8358c830a75376d4", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Canonical app URLs / preview environment guard ---------------------------\n# Local default can stay unset. Preview Coolify should set these explicitly.\n# ENVIRONMENT_NAME=\"preview\"\n# APP_URL=\"https://preview.versecraft.cn\"\n# NEXT_PUBLIC_APP_URL=\"https://preview.versecraft.cn\"\n# Optional SHA-256 hex fingerprints of normalized database URLs.\n# PRODUCTION_DATABASE_URL_FINGERPRINT=\"\"\n# PREVIEW_DATABASE_URL_FINGERPRINT=\"\"\n\n# --- Preview access gate (default closed unless enabled and host matches) -----\nPREVIEW_ACCESS_ENABLED=\"false\"\nPREVIEW_ACCESS_HOSTS=\"preview.versecraft.cn\"\nPREVIEW_ACCESS_PASSWORD=\"\"\nPREVIEW_ACCESS_COOKIE_SECRET=\"\"\nPREVIEW_ACCESS_COOKIE_NAME=\"vc_preview_access\"\nPREVIEW_ACCESS_MAX_AGE_SECONDS=\"604800\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-enhance\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# World Director / offline reasoner loop.\n# Default soft + hint_injection=true: the worker generates agenda via vc-reasoner,\n# and the next-turn DM prompt receives a director hint block (still 100% async to\n# the player SSE; PLAYER_CHAT itself never routes to reasoner).\n#\n# IMPORTANT: For these defaults to actually take effect, the background worker\n# must be running (`pnpm worker:kg`) and AI_MODEL_REASONER must be reachable\n# through the gateway. If the worker is offline, no agenda is produced and the\n# director hint block degrades to empty—no impact on the main SSE.\n# 生产部署可启用 docker-compose `--profile production` 自动起 vc-worker。\nAI_ENABLE_WORLD_DIRECTOR=\"true\"\nAI_DIRECTOR_MODE=\"soft\" # off | shadow | soft\n# AI_ENABLE_DIRECTOR_HINT_INJECTION=\"true\"\n# AI_ENABLE_DIRECTOR_CRITIC=\"false\"\n# AI_DIRECTOR_MAX_DUE_HINTS=\"2\"\n# AI_DIRECTOR_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_DIRECTOR_MAX_PENDING_AGENDA_PER_SESSION=\"12\"\n# AI_DIRECTOR_AGENDA_DEFAULT_TTL_TURNS=\"6\"\n# AI_DIRECTOR_AGENDA_QUERY_TIMEOUT_MS=\"80\"\n\n# Social World / NPC-agent background loop. Default shadow lets vc-reasoner\n# plan NPC social events in workers; PLAYER_CHAT still never routes to reasoner.\nAI_ENABLE_SOCIAL_WORLD=\"true\"\nAI_SOCIAL_WORLD_MODE=\"shadow\" # off | shadow | soft\n# AI_SOCIAL_MAX_ACTIVE_NPCS=\"5\"\n# AI_SOCIAL_MAX_EVENTS_PER_TICK=\"3\"\n# AI_SOCIAL_MAX_PROMPT_EVENTS=\"2\"\n# AI_SOCIAL_PROMPT_MAX_CHARS=\"900\"\n# AI_SOCIAL_QUERY_TIMEOUT_MS=\"80\"\n# AI_SOCIAL_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_SOCIAL_MAX_PENDING_EVENTS_PER_SESSION=\"12\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"4500\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# Bump to \"5\" after separating playable options from main-turn narrative JSON (stable prefix text changed).\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"5\"\n# Defer playable options to a follow-up options_regen_only request from /play (default ON); set \"0\"/false to rollback.\n# VERSECRAFT_DEFER_MAIN_TURN_OPTIONS_TO_CLIENT=\"1\"\n# NEXT_PUBLIC_VERSECRAFT_DEFER_MAIN_TURN_OPTIONS_TO_CLIENT=\"1\"\n# Phase 7: /play 叙事系统调试浮层(客户端);服务端变更集控制台日志\n# NEXT_PUBLIC_VERSECRAFT_SYSTEMS_DEBUG=\"1\"\n# VERSECRAFT_DM_CHANGESET_DEBUG=\"1\"\n# Phase 6: 叙事咬合读档修复日志\n# NEXT_PUBLIC_VERSECRAFT_NARRATIVE_DEBUG=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (default: enabled as post-stream optional enhancement; set 0 to disable)\nAI_ENABLE_NARRATIVE_ENHANCEMENT=\"1\"\nAI_NARRATIVE_EXPANSION_ENABLED=\"true\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "a3f0092d3035d2879c459210351a97b0580c46c0": {"t": 1785770499.849452, "n": 11735, "h": "0615bb505b5921f2", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Canonical app URLs / preview environment guard ---------------------------\n# Local default can stay unset. Preview Coolify should set these explicitly.\n# ENVIRONMENT_NAME=\"preview\"\n# APP_URL=\"https://preview.versecraft.cn\"\n# NEXT_PUBLIC_APP_URL=\"https://preview.versecraft.cn\"\n# Optional SHA-256 hex fingerprints of normalized database URLs.\n# PRODUCTION_DATABASE_URL_FINGERPRINT=\"\"\n# PREVIEW_DATABASE_URL_FINGERPRINT=\"\"\n\n# --- Preview access gate (default closed unless enabled and host matches) -----\nPREVIEW_ACCESS_ENABLED=\"false\"\nPREVIEW_ACCESS_HOSTS=\"preview.versecraft.cn\"\nPREVIEW_ACCESS_PASSWORD=\"\"\nPREVIEW_ACCESS_COOKIE_SECRET=\"\"\nPREVIEW_ACCESS_COOKIE_NAME=\"vc_preview_access\"\nPREVIEW_ACCESS_MAX_AGE_SECONDS=\"604800\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-enhance\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# World Director / offline reasoner loop.\n# Default soft + hint_injection=true: the worker generates agenda via vc-reasoner,\n# and the next-turn DM prompt receives a director hint block (still 100% async to\n# the player SSE; PLAYER_CHAT itself never routes to reasoner).\n#\n# IMPORTANT: For these defaults to actually take effect, the background worker\n# must be running (`pnpm worker:kg`) and AI_MODEL_REASONER must be reachable\n# through the gateway. If the worker is offline, no agenda is produced and the\n# director hint block degrades to empty—no impact on the main SSE.\n# 生产部署可启用 docker-compose `--profile production` 自动起 vc-worker。\nAI_ENABLE_WORLD_DIRECTOR=\"true\"\nAI_DIRECTOR_MODE=\"soft\" # off | shadow | soft\n# AI_ENABLE_DIRECTOR_HINT_INJECTION=\"true\"\n# AI_ENABLE_DIRECTOR_CRITIC=\"false\"\n# AI_DIRECTOR_MAX_DUE_HINTS=\"2\"\n# AI_DIRECTOR_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_DIRECTOR_MAX_PENDING_AGENDA_PER_SESSION=\"12\"\n# AI_DIRECTOR_AGENDA_DEFAULT_TTL_TURNS=\"6\"\n# AI_DIRECTOR_AGENDA_QUERY_TIMEOUT_MS=\"80\"\n\n# Social World / NPC-agent background loop. Default shadow lets vc-reasoner\n# plan NPC social events in workers; PLAYER_CHAT still never routes to reasoner.\nAI_ENABLE_SOCIAL_WORLD=\"true\"\nAI_SOCIAL_WORLD_MODE=\"shadow\" # off | shadow | soft\n# AI_SOCIAL_MAX_ACTIVE_NPCS=\"5\"\n# AI_SOCIAL_MAX_EVENTS_PER_TICK=\"3\"\n# AI_SOCIAL_MAX_PROMPT_EVENTS=\"2\"\n# AI_SOCIAL_PROMPT_MAX_CHARS=\"900\"\n# AI_SOCIAL_QUERY_TIMEOUT_MS=\"80\"\n# AI_SOCIAL_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_SOCIAL_MAX_PENDING_EVENTS_PER_SESSION=\"12\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"4500\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# Bump to \"4\" after the 情景自适应·动态裁决 narrative-length rework (stable prefix text changed).\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"4\"\n# Phase 7: /play 叙事系统调试浮层(客户端);服务端变更集控制台日志\n# NEXT_PUBLIC_VERSECRAFT_SYSTEMS_DEBUG=\"1\"\n# VERSECRAFT_DM_CHANGESET_DEBUG=\"1\"\n# Phase 6: 叙事咬合读档修复日志\n# NEXT_PUBLIC_VERSECRAFT_NARRATIVE_DEBUG=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (default: enabled as post-stream optional enhancement; set 0 to disable)\nAI_ENABLE_NARRATIVE_ENHANCEMENT=\"1\"\nAI_NARRATIVE_EXPANSION_ENABLED=\"true\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "f20ef9e7b6ecbc24d4004537743e0ed16ee14479": {"t": 1785770501.130664, "n": 11672, "h": "fed05461f051d948", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Canonical app URLs / preview environment guard ---------------------------\n# Local default can stay unset. Preview Coolify should set these explicitly.\n# ENVIRONMENT_NAME=\"preview\"\n# APP_URL=\"https://preview.versecraft.cn\"\n# NEXT_PUBLIC_APP_URL=\"https://preview.versecraft.cn\"\n# Optional SHA-256 hex fingerprints of normalized database URLs.\n# PRODUCTION_DATABASE_URL_FINGERPRINT=\"\"\n# PREVIEW_DATABASE_URL_FINGERPRINT=\"\"\n\n# --- Preview access gate (default closed unless enabled and host matches) -----\nPREVIEW_ACCESS_ENABLED=\"false\"\nPREVIEW_ACCESS_HOSTS=\"preview.versecraft.cn\"\nPREVIEW_ACCESS_PASSWORD=\"\"\nPREVIEW_ACCESS_COOKIE_SECRET=\"\"\nPREVIEW_ACCESS_COOKIE_NAME=\"vc_preview_access\"\nPREVIEW_ACCESS_MAX_AGE_SECONDS=\"604800\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-enhance\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# World Director / offline reasoner loop.\n# Default soft + hint_injection=true: the worker generates agenda via vc-reasoner,\n# and the next-turn DM prompt receives a director hint block (still 100% async to\n# the player SSE; PLAYER_CHAT itself never routes to reasoner).\n#\n# IMPORTANT: For these defaults to actually take effect, the background worker\n# must be running (`pnpm vc:worker`) and AI_MODEL_REASONER must be reachable\n# through the gateway. If the worker is offline, no agenda is produced and the\n# director hint block degrades to empty—no impact on the main SSE.\nAI_ENABLE_WORLD_DIRECTOR=\"true\"\nAI_DIRECTOR_MODE=\"soft\" # off | shadow | soft\n# AI_ENABLE_DIRECTOR_HINT_INJECTION=\"true\"\n# AI_ENABLE_DIRECTOR_CRITIC=\"false\"\n# AI_DIRECTOR_MAX_DUE_HINTS=\"2\"\n# AI_DIRECTOR_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_DIRECTOR_MAX_PENDING_AGENDA_PER_SESSION=\"12\"\n# AI_DIRECTOR_AGENDA_DEFAULT_TTL_TURNS=\"6\"\n# AI_DIRECTOR_AGENDA_QUERY_TIMEOUT_MS=\"80\"\n\n# Social World / NPC-agent background loop. Default shadow lets vc-reasoner\n# plan NPC social events in workers; PLAYER_CHAT still never routes to reasoner.\nAI_ENABLE_SOCIAL_WORLD=\"true\"\nAI_SOCIAL_WORLD_MODE=\"shadow\" # off | shadow | soft\n# AI_SOCIAL_MAX_ACTIVE_NPCS=\"5\"\n# AI_SOCIAL_MAX_EVENTS_PER_TICK=\"3\"\n# AI_SOCIAL_MAX_PROMPT_EVENTS=\"2\"\n# AI_SOCIAL_PROMPT_MAX_CHARS=\"900\"\n# AI_SOCIAL_QUERY_TIMEOUT_MS=\"80\"\n# AI_SOCIAL_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_SOCIAL_MAX_PENDING_EVENTS_PER_SESSION=\"12\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"4500\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# Bump to \"4\" after the 情景自适应·动态裁决 narrative-length rework (stable prefix text changed).\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"4\"\n# Phase 7: /play 叙事系统调试浮层(客户端);服务端变更集控制台日志\n# NEXT_PUBLIC_VERSECRAFT_SYSTEMS_DEBUG=\"1\"\n# VERSECRAFT_DM_CHANGESET_DEBUG=\"1\"\n# Phase 6: 叙事咬合读档修复日志\n# NEXT_PUBLIC_VERSECRAFT_NARRATIVE_DEBUG=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (default: enabled as post-stream optional enhancement; set 0 to disable)\nAI_ENABLE_NARRATIVE_ENHANCEMENT=\"1\"\nAI_NARRATIVE_EXPANSION_ENABLED=\"true\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "e17a3f8011be07be5b9dadbf920623f663882417": {"t": 1785770502.3983479, "n": 11335, "h": "5ad2a62460b3cd07", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Canonical app URLs / preview environment guard ---------------------------\n# Local default can stay unset. Preview Coolify should set these explicitly.\n# ENVIRONMENT_NAME=\"preview\"\n# APP_URL=\"https://preview.versecraft.cn\"\n# NEXT_PUBLIC_APP_URL=\"https://preview.versecraft.cn\"\n# Optional SHA-256 hex fingerprints of normalized database URLs.\n# PRODUCTION_DATABASE_URL_FINGERPRINT=\"\"\n# PREVIEW_DATABASE_URL_FINGERPRINT=\"\"\n\n# --- Preview access gate (default closed unless enabled and host matches) -----\nPREVIEW_ACCESS_ENABLED=\"false\"\nPREVIEW_ACCESS_HOSTS=\"preview.versecraft.cn\"\nPREVIEW_ACCESS_PASSWORD=\"\"\nPREVIEW_ACCESS_COOKIE_SECRET=\"\"\nPREVIEW_ACCESS_COOKIE_NAME=\"vc_preview_access\"\nPREVIEW_ACCESS_MAX_AGE_SECONDS=\"604800\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-enhance\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# World Director / offline reasoner loop. Default shadow means the worker may\n# generate and validate agenda, but PLAYER_CHAT never routes to reasoner and\n# prompts are not affected unless soft mode + hint injection are explicitly on.\nAI_ENABLE_WORLD_DIRECTOR=\"true\"\nAI_DIRECTOR_MODE=\"shadow\" # off | shadow | soft\n# AI_ENABLE_DIRECTOR_HINT_INJECTION=\"false\"\n# AI_ENABLE_DIRECTOR_CRITIC=\"false\"\n# AI_DIRECTOR_MAX_DUE_HINTS=\"2\"\n# AI_DIRECTOR_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_DIRECTOR_MAX_PENDING_AGENDA_PER_SESSION=\"12\"\n# AI_DIRECTOR_AGENDA_DEFAULT_TTL_TURNS=\"6\"\n# AI_DIRECTOR_AGENDA_QUERY_TIMEOUT_MS=\"80\"\n\n# Social World / NPC-agent background loop. Default shadow lets vc-reasoner\n# plan NPC social events in workers; PLAYER_CHAT still never routes to reasoner.\nAI_ENABLE_SOCIAL_WORLD=\"true\"\nAI_SOCIAL_WORLD_MODE=\"shadow\" # off | shadow | soft\n# AI_SOCIAL_MAX_ACTIVE_NPCS=\"5\"\n# AI_SOCIAL_MAX_EVENTS_PER_TICK=\"3\"\n# AI_SOCIAL_MAX_PROMPT_EVENTS=\"2\"\n# AI_SOCIAL_PROMPT_MAX_CHARS=\"900\"\n# AI_SOCIAL_QUERY_TIMEOUT_MS=\"80\"\n# AI_SOCIAL_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_SOCIAL_MAX_PENDING_EVENTS_PER_SESSION=\"12\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"4500\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# Bump to \"4\" after the 情景自适应·动态裁决 narrative-length rework (stable prefix text changed).\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"4\"\n# Phase 7: /play 叙事系统调试浮层(客户端);服务端变更集控制台日志\n# NEXT_PUBLIC_VERSECRAFT_SYSTEMS_DEBUG=\"1\"\n# VERSECRAFT_DM_CHANGESET_DEBUG=\"1\"\n# Phase 6: 叙事咬合读档修复日志\n# NEXT_PUBLIC_VERSECRAFT_NARRATIVE_DEBUG=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (default: enabled as post-stream optional enhancement; set 0 to disable)\nAI_ENABLE_NARRATIVE_ENHANCEMENT=\"1\"\nAI_NARRATIVE_EXPANSION_ENABLED=\"true\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "f00e4f6f72866dbd891d60c4c521badf01154b47": {"t": 1785770503.6560743, "n": 10838, "h": "93490177d1207837", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Canonical app URLs / preview environment guard ---------------------------\n# Local default can stay unset. Preview Coolify should set these explicitly.\n# ENVIRONMENT_NAME=\"preview\"\n# APP_URL=\"https://preview.versecraft.cn\"\n# NEXT_PUBLIC_APP_URL=\"https://preview.versecraft.cn\"\n# Optional SHA-256 hex fingerprints of normalized database URLs.\n# PRODUCTION_DATABASE_URL_FINGERPRINT=\"\"\n# PREVIEW_DATABASE_URL_FINGERPRINT=\"\"\n\n# --- Preview access gate (default closed unless enabled and host matches) -----\nPREVIEW_ACCESS_ENABLED=\"false\"\nPREVIEW_ACCESS_HOSTS=\"preview.versecraft.cn\"\nPREVIEW_ACCESS_PASSWORD=\"\"\nPREVIEW_ACCESS_COOKIE_SECRET=\"\"\nPREVIEW_ACCESS_COOKIE_NAME=\"vc_preview_access\"\nPREVIEW_ACCESS_MAX_AGE_SECONDS=\"604800\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-enhance\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# World Director / offline reasoner loop. Default shadow means the worker may\n# generate and validate agenda, but PLAYER_CHAT never routes to reasoner and\n# prompts are not affected unless soft mode + hint injection are explicitly on.\nAI_ENABLE_WORLD_DIRECTOR=\"true\"\nAI_DIRECTOR_MODE=\"shadow\" # off | shadow | soft\n# AI_ENABLE_DIRECTOR_HINT_INJECTION=\"false\"\n# AI_ENABLE_DIRECTOR_CRITIC=\"false\"\n# AI_DIRECTOR_MAX_DUE_HINTS=\"2\"\n# AI_DIRECTOR_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_DIRECTOR_MAX_PENDING_AGENDA_PER_SESSION=\"12\"\n# AI_DIRECTOR_AGENDA_DEFAULT_TTL_TURNS=\"6\"\n# AI_DIRECTOR_AGENDA_QUERY_TIMEOUT_MS=\"80\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"4500\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# Bump to \"4\" after the 情景自适应·动态裁决 narrative-length rework (stable prefix text changed).\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"4\"\n# Phase 7: /play 叙事系统调试浮层(客户端);服务端变更集控制台日志\n# NEXT_PUBLIC_VERSECRAFT_SYSTEMS_DEBUG=\"1\"\n# VERSECRAFT_DM_CHANGESET_DEBUG=\"1\"\n# Phase 6: 叙事咬合读档修复日志\n# NEXT_PUBLIC_VERSECRAFT_NARRATIVE_DEBUG=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (default: enabled as post-stream optional enhancement; set 0 to disable)\nAI_ENABLE_NARRATIVE_ENHANCEMENT=\"1\"\nAI_NARRATIVE_EXPANSION_ENABLED=\"true\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "4aac940226f1d0800e8e72be0a9dc4c3849bd6e6": {"t": 1785770504.870115, "n": 10803, "h": "5fd853274f109265", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Canonical app URLs / preview environment guard ---------------------------\n# Local default can stay unset. Preview Coolify should set these explicitly.\n# ENVIRONMENT_NAME=\"preview\"\n# APP_URL=\"https://preview.versecraft.cn\"\n# NEXT_PUBLIC_APP_URL=\"https://preview.versecraft.cn\"\n# Optional SHA-256 hex fingerprints of normalized database URLs.\n# PRODUCTION_DATABASE_URL_FINGERPRINT=\"\"\n# PREVIEW_DATABASE_URL_FINGERPRINT=\"\"\n\n# --- Preview access gate (default closed unless enabled and host matches) -----\nPREVIEW_ACCESS_ENABLED=\"false\"\nPREVIEW_ACCESS_HOSTS=\"preview.versecraft.cn\"\nPREVIEW_ACCESS_PASSWORD=\"\"\nPREVIEW_ACCESS_COOKIE_SECRET=\"\"\nPREVIEW_ACCESS_COOKIE_NAME=\"vc_preview_access\"\nPREVIEW_ACCESS_MAX_AGE_SECONDS=\"604800\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-main\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# World Director / offline reasoner loop. Default shadow means the worker may\n# generate and validate agenda, but PLAYER_CHAT never routes to reasoner and\n# prompts are not affected unless soft mode + hint injection are explicitly on.\n# AI_ENABLE_WORLD_DIRECTOR=\"true\"\n# AI_DIRECTOR_MODE=\"shadow\" # off | shadow | soft\n# AI_ENABLE_DIRECTOR_HINT_INJECTION=\"false\"\n# AI_ENABLE_DIRECTOR_CRITIC=\"false\"\n# AI_DIRECTOR_MAX_DUE_HINTS=\"2\"\n# AI_DIRECTOR_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_DIRECTOR_MAX_PENDING_AGENDA_PER_SESSION=\"12\"\n# AI_DIRECTOR_AGENDA_DEFAULT_TTL_TURNS=\"6\"\n# AI_DIRECTOR_AGENDA_QUERY_TIMEOUT_MS=\"80\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"4500\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# Bump to \"4\" after the 情景自适应·动态裁决 narrative-length rework (stable prefix text changed).\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"4\"\n# Phase 7: /play 叙事系统调试浮层(客户端);服务端变更集控制台日志\n# NEXT_PUBLIC_VERSECRAFT_SYSTEMS_DEBUG=\"1\"\n# VERSECRAFT_DM_CHANGESET_DEBUG=\"1\"\n# Phase 6: 叙事咬合读档修复日志\n# NEXT_PUBLIC_VERSECRAFT_NARRATIVE_DEBUG=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (default: enabled as post-stream optional enhancement; set 0 to disable)\n# AI_ENABLE_NARRATIVE_ENHANCEMENT=\"1\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "5f36d88e070075b262686fad1b0c8d20a0ce5a99": {"t": 1785770506.2921517, "n": 10788, "h": "6af9d6275fa731a8", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Canonical app URLs / preview environment guard ---------------------------\n# Local default can stay unset. Preview Coolify should set these explicitly.\n# ENVIRONMENT_NAME=\"preview\"\n# APP_URL=\"https://preview.versecraft.cn\"\n# NEXT_PUBLIC_APP_URL=\"https://preview.versecraft.cn\"\n# Optional SHA-256 hex fingerprints of normalized database URLs.\n# PRODUCTION_DATABASE_URL_FINGERPRINT=\"\"\n# PREVIEW_DATABASE_URL_FINGERPRINT=\"\"\n\n# --- Preview access gate (default closed unless enabled and host matches) -----\nPREVIEW_ACCESS_ENABLED=\"false\"\nPREVIEW_ACCESS_HOSTS=\"preview.versecraft.cn\"\nPREVIEW_ACCESS_PASSWORD=\"\"\nPREVIEW_ACCESS_COOKIE_SECRET=\"\"\nPREVIEW_ACCESS_COOKIE_NAME=\"vc_preview_access\"\nPREVIEW_ACCESS_MAX_AGE_SECONDS=\"604800\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-main\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# World Director / offline reasoner loop. Default shadow means the worker may\n# generate and validate agenda, but PLAYER_CHAT never routes to reasoner and\n# prompts are not affected unless soft mode + hint injection are explicitly on.\n# AI_ENABLE_WORLD_DIRECTOR=\"true\"\n# AI_DIRECTOR_MODE=\"shadow\" # off | shadow | soft\n# AI_ENABLE_DIRECTOR_HINT_INJECTION=\"false\"\n# AI_ENABLE_DIRECTOR_CRITIC=\"false\"\n# AI_DIRECTOR_MAX_DUE_HINTS=\"2\"\n# AI_DIRECTOR_MIN_TRIGGER_GAP_TURNS=\"4\"\n# AI_DIRECTOR_MAX_PENDING_AGENDA_PER_SESSION=\"12\"\n# AI_DIRECTOR_AGENDA_DEFAULT_TTL_TURNS=\"6\"\n# AI_DIRECTOR_AGENDA_QUERY_TIMEOUT_MS=\"80\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"2800\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# Bump to \"4\" after the 情景自适应·动态裁决 narrative-length rework (stable prefix text changed).\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"4\"\n# Phase 7: /play 叙事系统调试浮层(客户端);服务端变更集控制台日志\n# NEXT_PUBLIC_VERSECRAFT_SYSTEMS_DEBUG=\"1\"\n# VERSECRAFT_DM_CHANGESET_DEBUG=\"1\"\n# Phase 6: 叙事咬合读档修复日志\n# NEXT_PUBLIC_VERSECRAFT_NARRATIVE_DEBUG=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (Phase 1 default: disabled, logic kept for compatibility)\n# AI_ENABLE_NARRATIVE_ENHANCEMENT=\"0\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "1916a7ac01a6874c3efd96aac55c60e5fb33aba8": {"t": 1785770507.6983347, "n": 10180, "h": "47a0b7d3d20bbd01", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Canonical app URLs / preview environment guard ---------------------------\n# Local default can stay unset. Preview Coolify should set these explicitly.\n# ENVIRONMENT_NAME=\"preview\"\n# APP_URL=\"https://preview.versecraft.cn\"\n# NEXT_PUBLIC_APP_URL=\"https://preview.versecraft.cn\"\n# Optional SHA-256 hex fingerprints of normalized database URLs.\n# PRODUCTION_DATABASE_URL_FINGERPRINT=\"\"\n# PREVIEW_DATABASE_URL_FINGERPRINT=\"\"\n\n# --- Preview access gate (default closed unless enabled and host matches) -----\nPREVIEW_ACCESS_ENABLED=\"false\"\nPREVIEW_ACCESS_HOSTS=\"preview.versecraft.cn\"\nPREVIEW_ACCESS_PASSWORD=\"\"\nPREVIEW_ACCESS_COOKIE_SECRET=\"\"\nPREVIEW_ACCESS_COOKIE_NAME=\"vc_preview_access\"\nPREVIEW_ACCESS_MAX_AGE_SECONDS=\"604800\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-main\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"2800\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# Bump to \"4\" after the 情景自适应·动态裁决 narrative-length rework (stable prefix text changed).\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"4\"\n# Phase 7: /play 叙事系统调试浮层(客户端);服务端变更集控制台日志\n# NEXT_PUBLIC_VERSECRAFT_SYSTEMS_DEBUG=\"1\"\n# VERSECRAFT_DM_CHANGESET_DEBUG=\"1\"\n# Phase 6: 叙事咬合读档修复日志\n# NEXT_PUBLIC_VERSECRAFT_NARRATIVE_DEBUG=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (Phase 1 default: disabled, logic kept for compatibility)\n# AI_ENABLE_NARRATIVE_ENHANCEMENT=\"0\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "56eb041fb5d3c32d8173b2cab8b0c509620a55d0": {"t": 1785770508.8859487, "n": 9448, "h": "160e38645c497acc", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-main\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"2800\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# Bump to \"4\" after the 情景自适应·动态裁决 narrative-length rework (stable prefix text changed).\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"4\"\n# Phase 7: /play 叙事系统调试浮层(客户端);服务端变更集控制台日志\n# NEXT_PUBLIC_VERSECRAFT_SYSTEMS_DEBUG=\"1\"\n# VERSECRAFT_DM_CHANGESET_DEBUG=\"1\"\n# Phase 6: 叙事咬合读档修复日志\n# NEXT_PUBLIC_VERSECRAFT_NARRATIVE_DEBUG=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (Phase 1 default: disabled, logic kept for compatibility)\n# AI_ENABLE_NARRATIVE_ENHANCEMENT=\"0\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "5a32cfa4445a52863aaf9958b7fc9b6272f49c97": {"t": 1785770512.7551446, "n": 9359, "h": "b487120ded80a978", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-main\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"2800\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"3\"\n# Phase 7: /play 叙事系统调试浮层(客户端);服务端变更集控制台日志\n# NEXT_PUBLIC_VERSECRAFT_SYSTEMS_DEBUG=\"1\"\n# VERSECRAFT_DM_CHANGESET_DEBUG=\"1\"\n# Phase 6: 叙事咬合读档修复日志\n# NEXT_PUBLIC_VERSECRAFT_NARRATIVE_DEBUG=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (Phase 1 default: disabled, logic kept for compatibility)\n# AI_ENABLE_NARRATIVE_ENHANCEMENT=\"0\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "4e86367d983f88d1d377c87bc4f9f19e3e039146": {"t": 1785770514.4244514, "n": 9359, "h": "ffb903a8363b977e", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-main\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"2800\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"1\"\n# Phase 7: /play 叙事系统调试浮层(客户端);服务端变更集控制台日志\n# NEXT_PUBLIC_VERSECRAFT_SYSTEMS_DEBUG=\"1\"\n# VERSECRAFT_DM_CHANGESET_DEBUG=\"1\"\n# Phase 6: 叙事咬合读档修复日志\n# NEXT_PUBLIC_VERSECRAFT_NARRATIVE_DEBUG=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (Phase 1 default: disabled, logic kept for compatibility)\n# AI_ENABLE_NARRATIVE_ENHANCEMENT=\"0\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "a28fbcb46a681639de5628da953ac4b578be1a37": {"t": 1785770515.6759365, "n": 9170, "h": "e6d0f6cbea659df0", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-main\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"2800\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n# AI_CHAT_ENABLE_DIAGNOSTICS=\"1\"\n# AI_CHAT_ENABLE_STATUS_FRAMES=\"1\"\n# AI_CHAT_ENABLE_RISK_LANE_SPLIT=\"1\"\n# AI_CHAT_ENABLE_LIGHTWEIGHT_FAST_PATH=\"1\"\n# AI_CHAT_ENABLE_PROMPT_SLIMMING=\"1\"\n# AI_CHAT_FASTLANE_SKIP_RUNTIME_PACKETS=\"1\"\n# AI_CHAT_TIERED_CONTEXT_BUILD=\"1\"\n# AI_CHAT_CONTROL_PREFLIGHT_BUDGET_MS_CAP=\"260\"\n# AI_CHAT_LORE_RETRIEVAL_BUDGET_MS_CAP=\"220\"\n\n# Router / online task hardening\n# AI_PLAYER_CHAT_STREAM_INCLUDE_USAGE=\"1\"\n# AI_PLAYER_CHAT_MAX_ROLE_CANDIDATES=\"2\"\n# AI_PLAYER_CHAT_MAX_RETRIES=\"1\"\n# AI_ONLINE_SHORT_JSON_MAX_RETRIES=\"0\"\n# AI_ONLINE_SHORT_JSON_RELAX_RESPONSE_FORMAT=\"1\"\n# AI_ONLINE_SHORT_JSON_DISABLE_MAIN_FALLBACK=\"1\"\n\n# Frontend waiting UX / smoothing (A/B ready). 0 = 关闭节流主文案 + 副文案(回退旧「语义等待」行)\n# NEXT_PUBLIC_CHAT_WAITING_UX=\"1\"\n# NEXT_PUBLIC_CHAT_STREAM_SMOOTHING_V2=\"1\"\n# NEXT_PUBLIC_CHAT_DIAGNOSTICS=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH=\"1\"\n# NEXT_PUBLIC_CHAT_AUTO_PARAGRAPH_MIN_CHARS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (Phase 1 default: disabled, logic kept for compatibility)\n# AI_ENABLE_NARRATIVE_ENHANCEMENT=\"0\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "23176b74e8f26b3d4984a6b3ff9626edf44edeb0": {"t": 1785770517.2338305, "n": 8248, "h": "35e4911c458e7112", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-main\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"2800\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (Phase 1 default: disabled, logic kept for compatibility)\n# AI_ENABLE_NARRATIVE_ENHANCEMENT=\"0\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# --- Baidu Sinan / 文本审核(服务端-only,禁止前端导出) --------------\n# 本地 `.env.example` 只放占位;生产环境请在 Coolify 配置真实值(且只能注入到服务端运行环境)。\n# 不允许使用 NEXT_PUBLIC_* 暴露任何 AK/SK 或鉴权信息。\nBAIDU_SINAN_ENABLED=\"false\"\nBAIDU_SINAN_PROVIDER=\"baidu_text_censor\"\n\n# 仅用于服务端:AK/SK -> OAuth access_token(由代码自动换取并缓存,access_token 不落盘)\nBAIDU_SINAN_API_KEY=\"your_baidu_api_key\"\nBAIDU_SINAN_SECRET_KEY=\"your_baidu_secret_key\"\nBAIDU_SINAN_AUTH_MODE=\"oauth_access_token\"\n\n# OAuth / 审核接口地址(可通过 env 切换以支持未来策略)\nBAIDU_SINAN_TOKEN_URL=\"https://aip.baidubce.com/oauth/2.0/token\"\nBAIDU_SINAN_TEXT_CENSOR_URL=\"https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined\"\n\n# 网络保护(用于 AbortController 超时)\nBAIDU_SINAN_TIMEOUT_MS=\"2500\"\nBAIDU_SINAN_CONNECT_TIMEOUT_MS=\"1200\"\n\n# 熔断(circuit breaker)\n# 当外部文本审核连续失败达到阈值时,短时间内跳过外部调用,避免并发故障时拖垮整体服务。\n# 私密场景建议 fail_soft;公开展示建议 fail_closed。\nBAIDU_SINAN_CIRCUIT_FAILURE_THRESHOLD=\"3\"\nBAIDU_SINAN_CIRCUIT_WINDOW_MS=\"60000\"\nBAIDU_SINAN_CIRCUIT_COOLDOWN_MS=\"60000\"\n\n# stage gating(input/output/public)\nBAIDU_SINAN_INPUT_ENABLED=\"true\"\nBAIDU_SINAN_OUTPUT_ENABLED=\"true\"\nBAIDU_SINAN_PUBLIC_CONTENT_ENABLED=\"true\"\n\n# 失败模式(失败时不合规处理策略:private=软失败,public=闭失败)\nBAIDU_SINAN_FAIL_MODE_PRIVATE=\"fail_soft\"\nBAIDU_SINAN_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# 证据留痕/隐私\nBAIDU_SINAN_LOG_RAW_TEXT=\"false\"\nBAIDU_SINAN_HASH_SALT=\"replace_me\"\n\n# 审核策略强度(实现中默认 balanced 不传 strategyId;strict/loose 可作为策略中心映射占位)\nBAIDU_SINAN_STRICTNESS_PROFILE=\"balanced\"\n\n# --- VerseCraft Safety Engine (server-only) -----------------------------------\n# Default: do NOT log raw user text. Enable only for emergency incident debugging.\nVC_SAFETY_LOG_RAW_TEXT=\"false\"\n# Salt for hashing/fingerprinting user text in logs (do not reuse public salts).\nVC_SAFETY_HASH_SALT=\"replace_me\"\n\n# --- Output safety (server-only) ------------------------------------------\n# 外部文本审核不可用时的降级策略(私密输出更偏软降级;公开展示必须更严格)。\nVC_OUTPUT_FAIL_MODE_PRIVATE=\"fail_soft\"\nVC_OUTPUT_FAIL_MODE_PUBLIC=\"fail_closed\"\n\n# Optional: persist safety audit events into DB (append-only). Default OFF.\n# Recommended ON for production operations / investigations; still does NOT store raw user text by default.\nVC_SAFETY_AUDIT_DB_ENABLED=\"false\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "5367a380b2dfe7b1d494a45b3a666d28d83ba203": {"t": 1785770519.502869, "n": 6100, "h": "0dfdd892d87710a3", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Public compliance / legal footer (browser; optional overrides) ----------\n# Defaults in code: domain versecraft.cn, ICP 湘ICP备2025143231号-2, MIIT 查询入口链接\n# NEXT_PUBLIC_PRODUCT_NAME=\"VerseCraft(文界工坊)\"\n# NEXT_PUBLIC_OPERATING_SUBJECT=\"(填写营业执照名称)\"\n# NEXT_PUBLIC_CONTACT_EMAIL=\"support@versecraft.cn\"\n# NEXT_PUBLIC_CONTACT_PHONE=\"18163616407\"\n# NEXT_PUBLIC_CUSTOMER_WECHAT=\"\"\n# NEXT_PUBLIC_CUSTOMER_PUBLIC_ACCOUNT=\"\"\n# NEXT_PUBLIC_OFFICIAL_DOMAIN=\"versecraft.cn\"\n# NEXT_PUBLIC_OFFICIAL_SITE_URL=\"https://versecraft.cn\"\n# NEXT_PUBLIC_BEIAN_NUMBER=\"湘ICP备2025143231号-2\"\n# NEXT_PUBLIC_BEIAN_URL=\"https://beian.miit.gov.cn\"\n# NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE=\"2025-03-25\"\n# NEXT_PUBLIC_IS_TEST_PERIOD=\"true\"\n# NEXT_PUBLIC_SHOW_MINORS=\"true\"\n# NEXT_PUBLIC_SHOW_AI_DISCLAIMER=\"true\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-main\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"2800\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (Phase 1 default: disabled, logic kept for compatibility)\n# AI_ENABLE_NARRATIVE_ENHANCEMENT=\"0\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "7e7986e2c4994724d3c9be006f7fafc1aab50a20": {"t": 1785770521.1078854, "n": 5323, "h": "41f37d5d723b58a9", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-main\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_LORE_RETRIEVAL_BUDGET_MS=\"600\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"2800\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Narrative enhancement pipeline switch (Phase 1 default: disabled, logic kept for compatibility)\n# AI_ENABLE_NARRATIVE_ENHANCEMENT=\"0\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "7617fc6d635e6c3d0fd76237a8e1f8d83bced584": {"t": 1785770522.6470141, "n": 5154, "h": "8f88f4a658ef3907", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-enhance\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# Latency / streaming (see docs/ai-gateway.md §7) — 0 = legacy behavior (no wall-clock cap / no throttle)\n# AI_CONTROL_PREFLIGHT_BUDGET_MS=\"400\"\n# AI_NARRATIVE_ENHANCE_BUDGET_MS=\"2800\"\n# AI_STREAM_MODERATION_THROTTLE_MS=\"100\"\n\n# Player DM: stable system prefix memo invalidation (bump when static lore/rules change)\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"1\"\n# Optional: two system messages (stable + dynamic) for PLAYER_CHAT — default single concatenated system\n# AI_PLAYER_CHAT_SPLIT_SYSTEM=\"0\"\n# Optional: merge JSON into chat-completions body for vendor-specific fields (user, cache hints, etc.)\n# AI_GATEWAY_MERGE_EXTRA_BODY=\"0\"\n# AI_GATEWAY_EXTRA_BODY_JSON=\"{\\\"user\\\":\\\"versecraft-dm-v1\\\"}\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n# Optional: raise to tighten narrative enhancement gate (default 32 = historical)\n# AI_ENHANCE_GATE_MIN_SCORE=\"32\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "4c91e0b52f1de16ebbe2749d982d39dc3ffe6ae5": {"t": 1785770524.3959177, "n": 4342, "h": "7fb5f5393483db8a", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-enhance\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n\n# =============================================================================\n# 附录:旧版 AI 环境变量(迁移用,不推荐新部署)\n# -----------------------------------------------------------------------------\n# 见 docs/ai-gateway.md#legacy-migration — 未来将移除代码内 id→角色 映射,请改用 AI_PLAYER_ROLE_CHAIN。\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n"}, "f0dca8f825dd393f0cc1e25df7e45840c815af92": {"t": 1785770525.9653323, "n": 4183, "h": "7283e5c328dbafac", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI (one-api / OpenAI-compatible gateway) ---------------------------------\n# All LLM traffic goes through one gateway URL + key. Map upstream vendors in one-api, not in app code.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: e.g. https://your-one-api.example.com (app appends /v1/chat/completions) or paste full .../chat/completions\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_oneapi_token\"\n# Logical roles → model names as registered in one-api (opaque strings here)\nAI_MODEL_MAIN=\"vc-main\"\nAI_MODEL_CONTROL=\"vc-control\"\nAI_MODEL_ENHANCE=\"vc-enhance\"\nAI_MODEL_REASONER=\"vc-reasoner\"\n# Player SSE fallback order (comma-separated): main, control, enhance, reasoner\n# AI_PLAYER_ROLE_CHAIN=\"main,control\"\n# Legacy: AI_PLAYER_MODEL_CHAIN with old ids (deepseek-v3.2, glm-5-air, …) is mapped to roles when ROLE_CHAIN unset\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# Optional overrides for task chains (defaults: memory→main, dev assist→reasoner)\n# AI_MEMORY_PRIMARY_ROLE=\"main\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_DEV_ASSIST_PRIMARY_ROLE=\"reasoner\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n# AI_REQUEST_TIMEOUT_MS=\"60000\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_ENABLE_STREAM=\"true\"\n# AI_LOG_LEVEL=\"info\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n"}, "a0beec410d02ee81aac6ff66ac015d7888e96596": {"t": 1785770528.2114189, "n": 4348, "h": "2c8300105a76d2f5", "c": "# =============================================================================\n# VerseCraft — environment template\n# -----------------------------------------------------------------------------\n# Local: copy to `.env.local` and fill values (`.env.local` is gitignored).\n# Coolify: add the same keys under Environment Variables (no file upload needed).\n# Next.js loads `.env.local` automatically in dev/production Node runtime.\n# =============================================================================\n\n# --- Required (server fails fast on boot if missing) --------------------------\nDATABASE_URL=\"postgresql://postgres:change_me@127.0.0.1:5432/versecraft\"\nAUTH_SECRET=\"replace_with_at_least_32_chars_random_secret\"\n\n# --- Auth / admin -------------------------------------------------------------\nAUTH_TRUST_HOST=\"true\"\n# Local dev on port 666: set if NextAuth redirects break\n# AUTH_URL=\"http://localhost:666\"\nADMIN_PASSWORD=\"replace_with_strong_admin_password\"\nALTCHA_HMAC_KEY=\"replace_with_random_hmac_key\"\n\n# Optional: HMAC for `/api/audit` client signatures (defaults to AUTH_SECRET if unset)\n# AUDIT_HMAC_SECRET=\"\"\n\n# --- Redis (optional; rate limits fall back to in-memory if unset) ------------\nREDIS_URL=\"redis://127.0.0.1:6379\"\n\n# --- Public build stamp (safe for browser; optional) --------------------------\n# NEXT_PUBLIC_BUILD_ID=\"local-dev\"\n# BUILD_ID=\"coolify-build-123\"\n\n# --- Next.js dev --------------------------------------------------------------\n# Comma-separated hosts for `allowedDevOrigins` (VPN/LAN IPs, etc.)\n# NEXT_DEV_ALLOWED_ORIGINS=198.18.0.1\n\n# --- AI providers (at least one key recommended for gameplay) ---------------\n# Keys are SERVER-ONLY — do not use NEXT_PUBLIC_* (exposes key to the browser bundle).\n# Code reads (first non-empty): DEEPSEEK_API_KEY | DEEPSEEK_KEY | DEEPSEEK_API_TOKEN\n# (and NEXT_PUBLIC_DEEPSEEK_API_KEY only as a mistaken-name fallback — rename if you use it).\n# ZHIPU: ZHIPU_API_KEY | BIGMODEL_API_KEY | GLM_API_KEY | ZHIPU_KEY\n# MINIMAX: MINIMAX_API_KEY | MINIMAX_KEY\n# If .env.local sets e.g. DEEPSEEK_API_KEY=\"\" it overrides a non-empty value from .env — leave the line out or fill it.\nDEEPSEEK_API_KEY=\"\"\n# Logical model id (whitelist). Alias: AI_DEFAULT_MODEL (e.g. deepseek-chat → maps to deepseek-v3.2).\nDEEPSEEK_MODEL=\"deepseek-v3.2\"\n# Full chat-completions URL, OR set DEEPSEEK_BASE_URL=https://api.deepseek.com and omit API_URL.\nDEEPSEEK_API_URL=\"https://api.deepseek.com/chat/completions\"\n# DEEPSEEK_BASE_URL=\"https://api.deepseek.com\"\n\nZHIPU_API_KEY=\"\"\n# Legacy alias for ZHIPU_API_KEY (same value)\n# BIGMODEL_API_KEY=\"\"\nZHIPU_MODEL=\"glm-5-air\"\nZHIPU_API_URL=\"https://open.bigmodel.cn/api/paas/v4/chat/completions\"\n\nMINIMAX_API_KEY=\"\"\nMINIMAX_MODEL=\"MiniMax-M2.7-highspeed\"\nMINIMAX_API_URL=\"https://api.minimax.io/v1/text/chatcompletion_v2\"\n\n# AI_DEFAULT_MODEL=\"deepseek-chat\"\n# AI_PLAYER_MODEL_CHAIN=\"deepseek-v3.2,glm-5-air\"\n# AI_MEMORY_MODEL=\"deepseek-v3.2\"\n# AI_ADMIN_MODEL=\"deepseek-reasoner\"\n# AI_TIMEOUT_MS=\"60000\"\n# AI_REQUEST_TIMEOUT_MS=\"15000\"\n# AI_MAX_RETRIES=\"2\"\n# AI_RETRY_COUNT=\"2\"\n# AI_CIRCUIT_FAILURE_THRESHOLD=\"4\"\n# AI_CIRCUIT_COOLDOWN_MS=\"60000\"\n# AI_OPERATION_MODE=\"full\"\n# AI_EXPOSE_ROUTING_HEADER=\"0\"\n\n# AI governance (cost / gate / cache) — see docs/ai-governance.md\n# AI_RESPONSE_CACHE_ENABLED=\"1\"\n# VERSECRAFT_AI_CACHE_VERSION=\"1\"\n# AI_CACHE_TTL_CONTROL_SEC=\"50\"\n# AI_PREFLIGHT_MAX_PER_MINUTE=\"48\"\n# AI_ENHANCE_COOLDOWN_SEC=\"90\"\n# AI_ENHANCE_MAX_PER_HOUR=\"10\"\n\n# --- Runtime / quotas ---------------------------------------------------------\nMIGRATE_ON_BOOT=\"1\"\nRUNTIME_SCHEMA_ENSURE=\"1\"\nDAILY_TOKEN_LIMIT=\"50000\"\nDAILY_ACTION_LIMIT=\"200\"\n\n# --- Content safety (canonical names) -----------------------------------------\nMODERATION_ENABLED=\"true\"\nMODERATION_PROVIDER=\"auto\"\nMODERATION_TIMEOUT_MS=\"3000\"\nMODERATION_FAIL_OPEN=\"true\"\nSECURITY_LOG_LEVEL=\"warn\"\n\nSECURITY_IP_LIMIT_PER_MINUTE=\"30\"\nSECURITY_SESSION_LIMIT_PER_MINUTE=\"24\"\nSECURITY_USER_LIMIT_PER_MINUTE=\"20\"\nSECURITY_HIGH_RISK_STRIKE_THRESHOLD=\"3\"\nSECURITY_TEMP_BLOCK_SECONDS=\"600\"\n\n# Renamed / removed (do not use — set the MODERATION_* / SECURITY_LOG_LEVEL keys above instead):\n# SECURITY_MODERATION_ENABLED, SECURITY_MODERATION_PROVIDER, SECURITY_MODERATION_TIMEOUT_MS,\n# SECURITY_MODERATION_FAIL_OPEN, SECURITY_AUDIT_LOG_LEVEL, SECRET_KEY (use AUDIT_HMAC_SECRET or AUTH_SECRET)\n"}}}}