2026-07-09 · chore/env-cleanup 分支
.env.example 的完整审计过程、发现的问题、以及每个分组的整理决策。
对项目中所有 Python / Go / TypeScript 源码进行全量搜索,与 .env.example 交叉比对,发现三类问题:
| 变量 | 状态 | 说明 |
|---|---|---|
AGENT_STREAM_DEBUG |
已删除 | 源码中已无引用,仅残留在 docs/specs |
AGENT_EVENT_LOG |
已删除 | 同上 |
SKILL_REGISTRY_URL
已被 BLADE_HUB_URL 取代,
代码中仅作 fallback。在 .env.example 中注释掉并标注"旧名兼容"。
FAST_MODEL
FAST_BASE_URL
FAST_API_KEY
DROP_PARAMS
AGENT_MAX_TURNS
COMPACTION_RATIO
BLADE_ENV
BLADE_ADMIN_EMAILS
DISABLE_PASSWORD_AUTH
BLADE_OAUTH_URL
BLADE_AGENT_LICENSE_SERVICE_TOKEN
BLADE_HUB_URL
SKILL_REGISTRY_SERVICE_TOKEN
GITEA_URL
GIT_PASSWORD
GIT_ACCESS_TOKEN
GITEA_TOKEN
BLADE_SANDBOX_GITEA_URL
BLADE_PUBLIC_API_URL
BLADE_PUBLIC_SHARING
BLADE_BO_INTERNAL_URL
BLADE_BO_INTERNAL_SECRET
BLADE_SOCKETIO_TRACE
VIBE_CODING_SANDBOX_IMAGE
BLADE_EXAMPLE_SESSION_PATHS
BLADE_ENFORCE_NO_SPACE_PATHS
观测相关环境变量约 15+ 个(Langfuse、Helicone、Sentry、PostHog、OTEL、Pyroscope...), 配置复杂,普通运维难以理解,且大部分部署场景用不到。
思路:像 OAuth 一样,用 YAML 文件统一管理观测配置。
否决原因:观测变量大多是行业标准 env var,外部 SDK 直接从 os.environ 读取:
LANGFUSE_* — Langfuse SDK 自动读取OTEL_* — OpenTelemetry 标准规范SENTRY_DSN — Sentry SDK 自动读取PYROSCOPE_* — Pyroscope SDK 自动读取如果放进 YAML,要么需要"读 YAML → 回写 os.environ"的桥接(两个 source of truth),要么放弃 SDK 自动初始化改手动传参(fragile)。OAuth 能用 YAML 是因为它完全是自己的逻辑,没有外部 SDK 按固定名字读取。
在 configs/ 下放两个 .env 片段文件作为参考模板:
configs/observability.server.env.example
Langfuse + Helicone + Sentry + PostHog + OTEL + Pyroscope 全开
configs/observability.box.env.example
仅 JSONL 本地诊断日志,无外网依赖
.env.example 中观测部分从 ~20 行缩减为 5 行引导注释,指向这两个模板。运维按场景复制粘贴即可。
SSL_VERIFY=false — 代码默认值已经是 false,写在这里等于重复API_KEY、BASE_URL)容易冲突,但改名影响面大LLM_BACKEND、DROP_PARAMS、AGENT_MAX_TURNS、COMPACTION_RATIO、TOOL_RESULT_IMAGE_MODE、SSL_VERIFY)和快速模型一起归到"LLM 高级配置"区块SSL_VERIFY=false 改为注释两个独立 section 各只有 1 个变量(BLADE_ENABLE_HTML_RENDER_TOOL 和 BLADE_CHECKPOINTS_ENABLED)。建议合并为一个"功能开关"分组。
内联的 YAML 示例有 10 行,和 configs/memory.example.yaml 完全重复。建议删掉内联示例,只留一行指向 yaml 文件的引导——与观测的处理方式一致。
以下变量散在各 section 之间没有归属:
| 变量 | 问题 | 建议归组 |
|---|---|---|
BLADE_SKILL_PATHS |
空值 = 不设置 | Skill Registry / Hub |
BLADE_GIS_MAP_URL |
空值 = 不设置 | 功能开关 或 Blade OS 集成 |
BLADE_AGENT_MCP_ENABLED |
总开关,逻辑上属功能开关 | 功能开关 |
BLADE_OS_PATH |
和 BLADE_OS_BASE_URL 容易混淆 | Blade OS 集成(加注释区分) |
BLADE_SKILL_DOWNLOAD_CACHE |
空值 = 不设置 | Skill Registry / Hub |
| 变量 | 当前值 | 代码默认 |
|---|---|---|
SSL_VERIFY=false | false | false |
DOCUMENT_READER=light | light | light |
BLADE_HUB_URL= | 空 | 空 |
BLADE_SKILL_PATHS= | 空 | 空 |
BLADE_GIS_MAP_URL= | 空 | 空 |
BLADE_SKILL_DOWNLOAD_CACHE= | 空 | 空 |
复制 .env.example 的人会以为这些是"必须填写"的,实际效果和不写一样。
MULTICA_SERVER_URL=http://localhost:8080 是 uncommented 且带默认值,意味着复制 .env.example 就会连 Multica。如果 Multica 不是默认必须的,应该注释掉。
两个名字很像,但用途不同:
BLADE_OS_PATH — 前端跳转地址("安装到 BladeOS"按钮的目标 URL)BLADE_OS_BASE_URL — 后端 API 地址(服务间调用,推送桌面图标)改名影响面大,这次至少在注释里说清楚区别。
| 变量 | 原因 |
|---|---|
BLADE_ENFORCE_NO_SPACE_PATHS |
路径空格检查,极其冷门 |
BROWSER_EXTENSION_OAUTH_* |
有内置默认值,几乎没人需要改 |
PUBLISHED_APP_RECONCILE_INTERVAL_SECONDS |
运维也不需要改这个定时间隔 |
BLADE_OBSERVABILITY_SERVICE_NAME |
已在 observability 模板文件中 |
BLADE_DEPLOYMENT |
同上 |
按优先级排序: