Files
Cyrene_v2/.env.example
T
AskaEth c96a7db7f1
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
feat(gateway,config,web,docs): backthink 实时帧显示打扰原因 + 图片上限可配 + api-reference 端点表补齐
- 前端:`lib/wsParse.ts` 的 `parseBackthinkItem` 现在也读原始 `PushResult` 的 route/detail/bypassed(兼容
  camelCase),与历史 DTO 路径**同名同义**(空串 → undefined、未报告的 bool 不编成 false);
  Backthink 页 Notice 改为如实描述。证据=用后端两条路径的**真实序列化**喂同一个 PushResult 做逐字段比对
- 图片上限可配:`CHAT_IMAGE_MAX_BYTES`(默认 5242880 = 与 /upload 同口径;**未配置/0/负 一律用默认**,
  不存在「禁用上限」);删掉重复的字符常量,换算只留一份 `chatImageCharsFor`;补 3 条用例
  (默认值==upload 预算、配 1 MiB 真生效且只有合法那条驱动回合、非正值回落默认)
- `Docs/api-reference.md`:§1 端点表按 `routes.go` **补齐**(auth refresh/logout、upload、files、三支 audio、
  /admin/plugins/installed、/admin/llm/catalog、observability/logs、notifications、owner-profile、reminders),
  既有编号一律未动(保交叉引用);两张 `historyMessage` 字段表补 `personaId`(+ `clientMsgId`);
  修正 §8.1「主人档案保存仍 501」与实现不符(已真实实现)
- 复核:build/vet 绿 + gateway/config 包测试绿 + 前端 tsc 0 错 + vite build 成功
- 登记:§1 各表的编号跨表重复(不重编号以保交叉引用);`admin_plugins.go:217` 注释写错鉴权档(未改);
  §6.4 的 WS 事件帧表仍未补全
2026-10-04 16:24:36 +08:00

254 lines
16 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ============================================
# Cyrene v2 配置文件 (.env)
# 复制为 .env 后修改。所有配置均从环境变量注入,代码内禁硬编码。
# 注意:.env 仅用于本地开发;生产用 systemd / env_file。
# 敏感信息(API Key / JWT_SECRET)一律不要写进日志。
# ============================================
# ---- 运行环境 ----
ENV=development
LOG_LEVEL=debug
TZ=Asia/Shanghai
# ---- 数据目录(裁决 12.4.2/15.4.1,design/13 §2) ----
# 两种取法都实现:默认 ./data;显式写 platform(保留字哨兵)则走平台标准数据目录
# (Windows %APPDATA%\Cyrene、macOS ~/Library/Application Support/Cyrene、Linux ~/.local/share/cyrene)。
DATA_DIR=./data
# ---- 服务器(网关,唯一对外端口) ----
# HOST 默认 0.0.0.0,暴露面由 .env 决定(本机自托管要收紧就改 127.0.0.1)。
HOST=0.0.0.0
PORT=8080
# 管理面板的安全入口路径(裁决 1.6/16.4.7,design/07 §0.2):
# 管理面板前端挂在这个路径下,默认 admin(即 /admin);想藏起来就自定义,例如
# ADMIN_PATH=my-secret/admin → 面板在 /my-secret/admin,猜 /admin 直接 404。
# 它只影响面板前端路由;REST 仍是 /api/v1/admin/*(API 不藏,安全靠 JWT + 角色门),
# 且该路径串不会出现在用户端页面里。
ADMIN_PATH=admin
# chat.image 的【解码后图像字节】上限(协同文档 G3),默认 5242880(5 MiB,与 POST /api/v1/upload 同口径)。
# 图片有「上传」与「base64 内联」两条入口,两边必须给出同一个「一张图能有多大」的答案,否则内联可绕开上传限制。
# 调大请谨慎:整段 base64 会被落库,并随每页历史(GET /sessions/{id}/messages)与每次 WS history 回放重传一遍。
# ≤0(写 0 或负数)= 用默认值 5 MiB,不是「禁用上限」——一张图能有多大只能有一个答案。
CHAT_IMAGE_MAX_BYTES=5242880
# ---- 认证 / 管理员 ----
# JWT_SECRET 必填,长度 >= 32;缺失或过短会在启动时 panic。
JWT_SECRET=change-me-to-a-random-string-at-least-32-characters
ADMIN_USERNAME=admin
ADMIN_PASSWORD=admin12345
REGISTRATION_ENABLED=true
# 不透明 refresh token 有效期(Go duration,如 720h = 30 天);access token 固定 24h。
AUTH_REFRESH_TTL=720h
# refresh token 单次使用轮换默认开启(用旧换新、防重放);仅当客户端无法保存轮换后的
# 新 token 时才设为 true 关闭轮换。
AUTH_REFRESH_ROTATE_DISABLED=false
# ---- 数据库 ----
# SQLite 为默认(单二进制、无需外部服务)。
DB_SQLITE_PATH=./data/cyrene.db
# PostgreSQL + pgvector 为可选增强;未配置时走 SQLite。相关向量能力在 M4 接入。
# DB_PG_URL=postgres://cyrene:cyrene_pass@localhost:5432/cyrene_ai?sslmode=disable
# ---- LLM 多供应商(LLM_PROVIDER 显式声明协议:openai / anthropic,默认 openai) ----
# ⚠️ 本节是【兜底】:管理面板「LLM 模型」页保存会写入本地 models.json(默认 <DATA_DIR>/models.json,已 gitignore),
# 只要 models.json 存在且有效,运行中的 LLM 就优先用它的多厂商多模型组,并支持面板实时保存→热更新(无需重启)。
# 仅当 models.json 不存在/无效时才回退到下面的 .env。
# Provider = openai:OpenAI 兼容 /chat/completions(含 OpenAI 兼容网关,也可经它承载 Anthropic 模型,但失去原生 tool input 对象优势)
LLM_PROVIDER=openai
LLM_BASE_URL=https://api.openai.com/v1
LLM_API_KEY=sk-xxxxx
LLM_MODEL=gpt-4o
LLM_FALLBACK_MODEL=gpt-4o-mini
# 最后一道回退模型(fallback 链末端)的 token 预算上限。仅当链确有回退模型、
# 且该模型组未在 models.json 设 maxTokens、请求也未显式给 MaxTokens 时生效;
# 0 = 关闭该兜底(改用适配器默认,如 anthropic 8192)。每模型组预算见 models.json 的 maxTokens。
LLM_FALLBACK_MAX_TOKENS=8192
# 推理开关的【提供商形状】声明(裁决 03.4.2 / 08.4.1):auto(默认,= 留空)/ deepseek /
# openai / vllm / dashscope。形状决定把思考开关下发改成哪个字段(如 vllm =
# chat_template_kwargs.enable_thinking、dashscope = 顶层 enable_thinking),必须按端点真实形状
# 声明——发错形状会被上游拒。留空/auto = 按模型名与 base URL 推断厂商,形状有歧义时一个字段都不发。
# ⚠️ 本键只作用于 .env 合成的模型组:存在有效 models.json 时,以该组的 reasoning.kind 为准
# (面板可编辑,见「LLM 模型」页)。
LLM_REASONING_KIND=
# ---- LLM 视觉模型(视觉/OCR 工具用的模型;与「主模型能否收图」无关) ----
# 语义(v0.53 修正):主模型自己能不能收图,看 models.json 生效组的 multimodal 字段(面板可勾选),
# 不是看这里;本节的模型【只供 vision / ocr 工具】调用。都不配置时工具回落用主模型(LLM_MODEL)。
# LLM_VISION_MODEL=gpt-4o-mini
# OCR 工具单独用另一个模型(可选):留空 = 复用 LLM_VISION_MODEL。
# LLM_OCR_MODEL=qwen-vl-ocr
# Provider = anthropic:Anthropic Messages /v1/messages(tool_use.input 为结构化对象,工具循环更稳)
# ANTHROPIC_BASE_URL=https://api.anthropic.com
# ANTHROPIC_API_KEY=sk-ant-xxxxx
# ANTHROPIC_MODEL=claude-sonnet-4-20250514
# ANTHROPIC_FALLBACK_MODEL=claude-haiku-3-5
# ⚠️ 若 ANTHROPIC_BASE_URL 指向 DeepSeek(https://api.deepseek.com/anthropic),模型名须用 DeepSeek 当前名称
# (deepseek-flash / deepseek-v4-pro):不认识的名称(如 claude-*)会被服务端【静默映射成 deepseek-flash】,
# 配置错了不会报错。旧的 deepseek-chat / deepseek-reasoner 已于 2026-07-24 停用。
# ---- LLM 本地第三级(降级链末端;默认关,裁决 03.4.3) ----
# 降级链为「主 → 备 → 本地」;本地这一级默认关闭(当前设备跑本地模型困难),链保持两级。
# 开启需要三个条件同时满足:LLM_LOCAL_ENABLED=true + LLM_LOCAL_BASE_URL + LLM_LOCAL_MODEL;
# 只开开关不配端点/模型会被记 WARN 并跳过(不会半配成一个只会失败的链尾步)。
LLM_LOCAL_ENABLED=false
# 本地端点协议:openai(llama.cpp / ollama / vLLM 兼容)或 anthropic;留空 = openai。
# LLM_LOCAL_PROVIDER=openai
# LLM_LOCAL_BASE_URL=http://127.0.0.1:8080/v1
# 本地服务通常不需要 key;留空即可。
# LLM_LOCAL_API_KEY=
# LLM_LOCAL_MODEL=qwen3-4b-instruct
# ---- 记忆嵌入(可选,真语义) ----
# 不配置时使用内置 n-gram / FTS 向量(dim=256)。配置后必须真实走语义路径。
# EMBEDDING_API_URL 是【完整 /embeddings 端点】(不是 base)——例:Ollama / llama.cpp = http://localhost:11434/v1/embeddings
# EMBEDDING_API_URL=http://localhost:11434/v1/embeddings
# EMBEDDING_API_KEY=
# EMBEDDING_MODEL=Qwen3-Embedding-0.6B # 推荐(Q8_0 ~639MB、dim=1024、ModelScope 国内可下)
# ---- IoT 设备提供者 ----
# mock = 模拟智能家居设备(开发测试用);none = 禁用 IoT。
IOT_PROVIDER=mock
# ---- 语音服务 ----
TTS_PROVIDER=edge-tts
STT_PROVIDER=dashscope
# DASHSCOPE_API_KEY=sk-xxxxx # ⚠️ 必填才能接通阿里百炼语音;未填时走降级链 (silent)。绝不打日志。
# --- 阿里百炼 DashScope 语音(STT + TTS 主链路)---
# DASHSCOPE_BASE_URL=https://dashscope.aliyuncs.com/api/v1
# VOICE_STT_MODEL=qwen-audio-3.0-asr-flash
# VOICE_STT_LANGUAGE=zh
# 已实测:cosyvoice-v3.5-plus / cosyvoice-v2 走 HTTP SpeechSynthesizer 会回 418(引擎拒绝);
# 可用组合为 cosyvoice-v3-flash + 对应 v3 音色(longxiaochun_v3 龙小淳·女助手等)。
# 各模型音色不可混用(v2 名如 longxiaochun 用于 v3 模型会 418)。
# VOICE_TTS_MODEL=cosyvoice-v3-flash
# VOICE_TTS_VOICE_ID=longxiaochun_v3
# VOICE_TTS_FORMAT=wav
# VOICE_TTS_SAMPLE_RATE=24000
# 情绪/语气指令(TTS instruction):只对「复刻/设计音色」生效(可任意指令,如
# "语气开朗俏皮,像女朋友撒娇"),系统音色 longxiaochun_v3 必须用固定格式故不传。
# 长度≤100 字符(汉字记 2)。也可在 POST /api/v1/audio/speech 用 instruction 按请求覆盖。
# VOICE_TTS_INSTRUCTION=语气开朗俏皮,像女朋友撒娇
# 声音复刻前缀(create_voice 的 prefix,≤10 字母/数字,空则用 cyrene)。target_model
# 固定为 VOICE_TTS_MODEL(须与合成模型一致)。
# VOICE_CLONE_PREFIX=cyrene
# 声音复刻(响昔涟音色):先用参考音频(公网 URL)调 POST /api/v1/audio/voice-clone
# 建自定义音色,再把返回的 voice_id 填到 VOICE_TTS_VOICE_ID。
# ⚠️ 建音色必须公网可访问的参考音频 URL(create_voice 只收 input.url,不收 base64);
# 待主人提供参考音频公网 URL 方能真建音色。
# ---- 后台思考 ----
ENABLE_BACKGROUND_THINKING=true
# 自主思考心跳周期(秒)。默认 900(15 分钟一次);数值越小越频繁打扰。
THINK_INTERVAL_SEC=900
THINK_SILENCE_TIMEOUT_SEC=120
# 主动推送频率(design/12 §6):窗口内最多 PushLimit 次;推后冷却 Cooldown 秒;
# 同一风味(问候/提醒/分享/关心)在 KindWindow 秒内最多一次;主人最近消息在
# RecentChatCooldown 秒内则冷避不推。收敛默认值:1 次 / 60 分钟 + 推后 30 分钟冷却。
THINK_PUSH_LIMIT=1
THINK_PUSH_WINDOW_SEC=3600
THINK_PUSH_COOLDOWN_SEC=1800
THINK_RECENT_CHAT_COOLDOWN_SEC=600
THINK_KIND_WINDOW_SEC=7200
# 安静时段(本地时钟小时,默认 23:00-07:00;两端相等且非 0 则关闭)。
# 同时用于 backthink 后台思考与 channelbridge 公共平台安静时段轻思考(design/12 §6 策略五)。
QUIET_START_HOUR=23
QUIET_END_HOUR=7
# ---- 唤醒式能力渐进(capacity 意图判定,design/14 §2.2) ----
# L3 = 模型辅助的意图分类:仅当 L1 启发式与 L2 上下文仍拿不准时介入一次轻量模型调用。
# 默认关闭(纯启发式够日常,且该层要多花一次模型调用);关闭时该层从不运行,
# L1/L2/L4 的行为与接线前逐字节一致。
CAPACITY_L3_ENABLED=false
# L3 判定结果的缓存 TTL(Go duration,如 5m):同一段回合文本在此窗口内复用判定,避免每轮都问模型;
# 留空 = 5m;0 或解析不出 = 不缓存。
CAPACITY_L3_CACHE_TTL=5m
# ---- 子代理(orchestration,design/05 §7) ----
# 单个子代理整次运行的时限(秒)。默认 600 = 10 分钟(裁决 02.4.4:agent_timeout
# 可配置);模型派发时可用 subagent_spawn 的 timeout_seconds 参数按调用覆盖。
SUBAGENT_TIMEOUT_SEC=600
# ---- 护栏与上下文预算(design/04 §1.3 / §5) ----
# 上下文溢出压缩预算(token,离线估算值)。默认启用:会话估算上下文超过它时,
# 更早的轮次被摘要成一条前导摘要消息,近期尾部(含尾部工具结果)原样保留。
# 默认 32768 = loop.DefaultMaxContextTokens:默认模型(gpt-4o)窗口 128K,
# 它只占四分之一,给系统提示词/工具 schema/本轮输出留足余量,且远高于日常对话
# 体量(正常聊天几乎不触发压缩)。设 0(或负数)= 关闭压缩,行为与接线前一致。
CONTEXT_MAX_TOKENS=32768
# 内容策略关键词表(逗号分隔,大小写不敏感的子串匹配)。留空 = 不挂关键词护栏
# (项目不内置任何词表,只有你显式声明过的词才会被拦)。敏感信息(API key /
# bearer token / 密码 / 私钥)为阻断档、请求与响应各有长度上限,这两项是代码
# 内定的安全默认值,不对外开放配置(见 cmd/cyrene/wire_guardrail.go)。
# GUARDRAIL_KEYWORDS=
# ---- 主人身份说明书注入范围(design/11 §0 红线) ----
# 主人身份说明书(owner.yaml identityFile)注入范围:owner_only(默认,仅主人会话) | always(所有会话,含群聊/陌生人,仅自测) | off。
# owner_only 按渠道层强类型 actor 元数据判定;非法值回退 owner_only 并记 WARN(绝不静默放行)。
# 它只决定那段知识进不进该会话的上下文,不参与任何身份/权限判定(身份始终看 actor 元数据 + 白名单)。
OWNER_IDENTITY_INJECTION=owner_only
# ---- 推送出口(D1,主动推送的两级投递)----
# 主动消息在 WS/IM 投递之外,异步镜像到「主人自建统一推送服务」(主通道)。
# 该服务不可达/未配时,日志注明「个推(Getui)回退待接入」——当前无 Getui SDK,不伪造投递。
# 填写自建服务的 webhook 地址并置 ENABLE=true 即启用;token 只走 Authorization 头,不落日志。
PUSH_EXPORTER_ENABLED=false
# PUSH_EXPORTER_URL=https://push.example.com/webhook
# PUSH_EXPORTER_TOKEN=change-me
# PUSH_EXPORTER_TIMEOUT_SEC=5
# 个推(Getui)回退字段:预留占位,SDK 未接入,当前不生效。
# GETUI_APP_ID=
# GETUI_APP_KEY=
# GETUI_MASTER_SECRET=
# GETUI_BASE_URL=
# ---- WebSocket ----
WS_MAX_CONNECTIONS=1000
SESSION_IDLE_TIMEOUT_MIN=30
# ---- MCP 服务器(可选,JSON 数组字符串;每台 server 含 name/command/args/url/enabled) ----
# stdio 子进程示例:
# MCP_SERVERS_JSON=[{"name":"calc","command":"mcp-calc","args":["--stdio"],"enabled":true}]
# SSE 端点示例:
# MCP_SERVERS_JSON=[{"name":"weather","url":"http://localhost:3001/sse","enabled":true}]
# ---- 本地执行沙箱(exec/terminal 工具;默认关闭,授权放权) ----
# 只有 Enabled=true 时 agent 才可执行命令;仍需命令白名单与根目录边界。
# EXEC_SANDBOX_ENABLED=false
# EXEC_SANDBOX_COMMANDS=git,ls,cat,pwd
# EXEC_SANDBOX_ROOTS=./data
# EXEC_SANDBOX_ENV=PATH
# ---- 跨域白名单 ----
ALLOWED_ORIGINS=http://localhost:5173,http://localhost:3000
# ---- KOOK(KaiHeiLa)渠道 ----
# 单账号走环境变量;多账号走下方 CHANNELS_JSON。
# .env 仅提供【必要连接兜底】;接收模式 / webhook 回调路由 / verify_token / encrypt_key 等
# 业务·高级项一律在管理面板「渠道管理」配置(写入 channels.json,热更新),不落 .env。
# CHANNEL_KOOK_TOKEN 为 KOOK 开发者中心机器人 token(敏感,勿写日志/提交)。
# CHANNEL_KOOK_BASE_URL 可选,默认 https://www.kookapp.cn/api/v3。
# CHANNEL_KOOK_TOKEN=
# CHANNEL_KOOK_BASE_URL=
# ---- IM 多账号 / 黑白名单(可选,design/16 §4.6 §5-6) ----
# ⚠️ 本节是【兜底】:管理面板「渠道管理」页保存会写入本地 channels.json(默认 <DATA_DIR>/channels.json,已 gitignore),
# 只要 channels.json 存在且有效,运行中的渠道 adapter 就优先用它的多平台账号配置,并支持面板实时保存→热更新(无需重启)。
# 仅当 channels.json 不存在/无效时才回退到下面的 CHANNELS_JSON 与 CHANNEL_<NAME>_*。
# 业务·高级项(接收模式 receive_mode / webhook 回调路由与 verify_token、encrypt_key / 黑白名单 / 限流)
# 一律在管理面板「渠道管理」配置:写 channels.json、热更新;.env 仅作无文件时的必要连接回退(token/base_url 等)。
# 单账号仍走上面 CHANNEL_<NAME>_* 环境变量;这里提供独立的 JSON 注册表,
# 支持同一平台配多个接入配置(多账号),并配群聊/私聊黑白名单(代码层拦截,
# 被拉黑/不在白名单的群或用户消息不进 LLM,且有审计)。形如:
# CHANNELS_JSON={"telegram":[{"id":"conf0","config":{"bot_token":"..."},"denyUsers":["12345"],"denyGroups":["-100"]}]}
# 每个 account 字段:id(平台内唯一)、config(平台特有凭据 map)、
# allowGroups/denyGroups(群黑白名单,allowGroups 非空则成为白名单)、
# allowUsers/denyUsers(私聊用户黑白名单)。未配置时按单账号 env 路径处理。
# 群/总限流与总上限(可选,design/12 §6 策略三/四,公共平台防刷屏/最小化打扰):
# groupMsgPerMin 群聊每分钟上限(0=用默认6,-1=不限,正整数=该值)
# msgPerMin 非主人消息每分钟总上限(>0 生效,0/-1=不限)
# maxMessages 待处理上限,接近上限时由审查模型剔除低价值消息(0=用默认50,-1=不限,正整数=该值)
# 旧账号不配这些字段默认走「保护性默认/不限」,保持向后兼容。
# CHANNELS_JSON=