Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
1 line
330 KiB
JSON
1 line
330 KiB
JSON
{"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"}, "f1c5468fde3a3d15e0b89122c57090e725fad914": {"t": 1786068065.9291086, "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"}, "e865371a6fd9c38068b8e6eea7a2b3e53d6a81cb": {"t": 1786068548.175784, "n": 17562, "h": "06fb31d6e51689dd", "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 / direct OpenAI-compatible gateway) --------------------------\n# oneapi = an actual one-api deployment; openai_compatible = a direct compatible endpoint.\n# Keys are SERVER-ONLY — never NEXT_PUBLIC_*.\nAI_GATEWAY_PROVIDER=\"oneapi\"\n# Base URL: one-api or any compatible endpoint; the app appends /v1/chat/completions.\nAI_GATEWAY_BASE_URL=\"https://your-one-api.example.com\"\nAI_GATEWAY_API_KEY=\"replace_with_gateway_token\"\n# Logical roles → model names accepted by the selected gateway (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# v6-20260806: Major stable prompt compression (~12k→~4.5k chars). Sections removed because code\n# enforces them via resolveDmTurn/validateNarrative/commitTurn/b1Safety/actorEpistemicFilter/\n# post-generation validators / dynamic runtime packets.\n# VERSECRAFT_DM_STABLE_PROMPT_VERSION=\"v6-20260806\"\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\n# =============================================================================\n# Langfuse — LLM Observability, Prompt Management & Evaluation\n# -----------------------------------------------------------------------------\n# 默认关闭。启用需要同时设置 VERSECRAFT_ENABLE_LANGFUSE=1 和有效的密钥。\n# 详见 docs/observability/langfuse.md\n#\n# --- 本地观测台(推荐开发时使用) ---\n# 1. 启动本地 Langfuse:docker compose --profile local up -d langfuse-server\n# 2. 打开 http://localhost:3001 → 注册账号(首个用户自动成为管理员)\n# 3. Settings → API Keys → Create API Key → 复制 pk-lf-... 和 sk-lf-...\n# 4. 填入下方的 LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEY\n# 5. 设置 LANGFUSE_BASE_URL=\"http://localhost:3001\"\n# 6. 设置 VERSECRAFT_ENABLE_LANGFUSE=\"true\"\n# 7. 启动 VerseCraft:pnpm dev\n# -----------------------------------------------------------------------------\n\n# 总开关(默认 false)\n# VERSECRAFT_ENABLE_LANGFUSE=\"false\"\n\n# Langfuse 认证(必须同时提供 public key 和 secret key 才有效)\n# 此为 SERVER-ONLY 变量,禁止使用 NEXT_PUBLIC_* 暴露。\n# 本地:http://localhost:3001 → Settings → API Keys\n# 云端:https://cloud.langfuse.com → Settings → API Keys\n# LANGFUSE_PUBLIC_KEY=\"pk-lf-...\"\n# LANGFUSE_SECRET_KEY=\"sk-lf-...\"\n# LANGFUSE_BASE_URL=\"https://cloud.langfuse.com\" # 🇪🇺 EU 默认;本地用 http://localhost:3001\n\n# 采样率(0-1,基于 requestId 确定性计算)\n# - 本地(development):默认 0(关闭)\n# - 预发布(staging):默认 1(100%)\n# - 生产(production):默认 0.1(10%)\n# VERSECRAFT_LANGFUSE_SAMPLE_RATE=\"0.1\"\n\n# 内容采集(默认 false — 生产环境需要额外显式开关才可能启用)\n# 警告:启用后会上传 metadata-only 内容到 Langfuse,仍需经过统一 redaction 和字段白名单。\n# VERSECRAFT_LANGFUSE_CAPTURE_CONTENT=\"false\"\n\n# Prompt 管理(local | shadow | remote,默认 local)\n# - local:代码内 prompt 为唯一来源\n# - shadow:使用本地 prompt,异步比较 Langfuse 版本和 hash\n# - remote:显式开启后使用远程稳定模板,有进程内缓存、超时和本地 fallback\n# VERSECRAFT_LANGFUSE_PROMPT_SOURCE=\"local\"\n\n# Flush 超时(ms,默认 5000)\n# VERSECRAFT_LANGFUSE_FLUSH_TIMEOUT_MS=\"5000\"\n\n# 身份脱敏盐值(HMAC-SHA256,用户/会话标识不可逆散列)\n# 生产环境必须使用独立随机值,不能复用 AUTH_SECRET 或其他公开值。\n# VERSECRAFT_LANGFUSE_HASH_SALT=\"replace_with_random_salt\"\n\n# 环境标识(默认读取 NODE_ENV,可覆盖)\n# LANGFUSE_TRACING_ENVIRONMENT=\"staging\"\n\n# Release 标识(默认读取 BUILD_ID,可覆盖)\n# LANGFUSE_RELEASE=\"build-2024-001\"\n"}}}} |