Files
OpenCode 68a9071cf1 feat: reconcile local master with origin (exa/hot-platform hunters, leaks ledger, latest results)
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.
2026-08-07 12:53:47 +08:00

1 line
330 KiB
JSON
Raw Permalink Blame History

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