Skip to content

修复: Profile clone 时智能清理独占平台凭据 + 平台设置独占警告#283

Merged
EKKOLearnAI merged 2 commits into
EKKOLearnAI:mainfrom
wufloor:fix/profile-loading
Apr 29, 2026
Merged

修复: Profile clone 时智能清理独占平台凭据 + 平台设置独占警告#283
EKKOLearnAI merged 2 commits into
EKKOLearnAI:mainfrom
wufloor:fix/profile-loading

Conversation

@wufloor

@wufloor wufloor commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

问题 / Problem

hermes profile create <name> --clone 完整复制源 profile 的 .env + config.yaml(含独占型平台凭据如 WEIXIN_TOKEN / TELEGRAM_BOT_TOKEN),导致多个 profile 共享同一身份 token。hermes-agent 在 platform adapter 初始化或 scoped lock 获取阶段失败,gateway 健康检查持续 15s 超时:

hermes profile create <name> --clone copies the source profile's .env + config.yaml verbatim (including exclusive platform credentials like WEIXIN_TOKEN / TELEGRAM_BOT_TOKEN), causing multiple profiles to share the same identity token. hermes-agent fails during platform adapter initialization or scoped lock acquisition, and the gateway health check times out after 15s:

API Error 500: Gateway health check timed out after 15000ms

根因 / Root Cause

hermes-agent 的 acquire_scoped_lock() 实现了 token 级别的互斥锁(gateway/status.py),防止同一 bot token 被多个 gateway 实例同时使用。--clone 完整复制凭据后,新旧 profile 持有完全相同的 token → 后启动的 gateway 必然 lock 失败。

hermes-agent's acquire_scoped_lock() implements token-level mutual exclusion (gateway/status.py), preventing the same bot token from being used by multiple gateway instances simultaneously. After --clone copies credentials verbatim, both profiles hold the exact same token → the later gateway inevitably fails the lock.

受影响的 7 个平台 / Affected platforms (all call _acquire_platform_lock in gateway/platforms/*.py):
telegram, discord, slack, whatsapp, signal, weixin, feishu

修复方案 / Fix

1. 后端:智能克隆清理 / Backend: Smart Clone Cleanup (profile-credentials.ts)

clone 完成后自动 / Automatically after clone:

  1. <profile>/.env 删除匹配独占平台的环境变量(写 .env.bak.* 备份)/ Strip exclusive platform env vars from .env (backup to .env.bak.*)
  2. <profile>/config.yaml 中把 platforms.<exclusive>.enabled 置为 false / Set platforms.<exclusive>.enabled to false in config.yaml
  3. 清理节点直挂 + extra 子节点下的敏感字段(token / app_secret / account_id 等)/ Strip sensitive credential fields from platform nodes and their extra sub-nodes

2. 前端 toast 通知 / Frontend Toast Notification

clone 完成后 toast 显示清理摘要 / Toast displays cleanup summary after clone:

  • 被剥离的 .env 变量 / Stripped env vars
  • 被禁用的平台 / Disabled platforms
  • 被剥离的 config 内嵌凭据 / Stripped config credentials

3. 平台设置独占警告 / Platform Settings Exclusive Warning

在 PlatformSettings 中为 6 个独占平台卡片顶部添加 NAlert 警告 / Added NAlert warning at top of 6 exclusive platform cards in PlatformSettings:

"此平台使用独占 token 锁。每个 profile 必须使用不同的身份 token,否则会与其他 profile 冲突。"
"This platform uses exclusive token locking. Each profile must use a different identity token to avoid conflicts with other profiles."

EXCLUSIVE_PLATFORMS 列表来源 / List Source

精确对齐 hermes-agent 源码 gateway/platforms/*.py 中调用 _acquire_platform_lock 的 7 个 adapter。
Precisely aligned with the 7 adapters in hermes-agent's gateway/platforms/*.py that call _acquire_platform_lock.

验证方法 / Verification: grep -l _acquire_platform_lock ~/.hermes/hermes-agent/gateway/platforms/*.py

测试 / Tests

新增 tests/server/profile-credentials.test.ts(12 用例全过)/ Added 12 test cases (all passing):

  • isExclusivePlatformKey 命中 / 未命中边界 / hit/miss boundary cases (including removed aliases wechat/lark/line)
  • .env 文件剥离 + 备份 / .env stripping + backup
  • config.yaml 平台禁用 + 节点凭据清理 / config.yaml platform disable + credential stripping
  • 已 disabled 平台仍清理残留凭据 / Still strips credentials from already-disabled platforms (prevents identity reuse on re-enable)

复现步骤 / Reproduction Steps (before fix)

  1. 在 default profile .env 配置 WEIXIN_TOKEN 等独占凭据并启动 gateway / Configure WEIXIN_TOKEN etc. in default profile .env and start gateway
  2. web-ui → Profiles → New Profile → 勾选 Clone from current → 提交 / Check "Clone from current" → Submit
  3. 切换到新 profile 触发 gateway 启动 / Switch to new profile, triggering gateway start
  4. 报错 / Error: API Error 500: Gateway health check timed out after 15000ms

相关 / Related

文件变更 / File Changes

文件 / File 变更 / Change
packages/server/src/services/hermes/profile-credentials.ts 新增 / New - 智能克隆核心逻辑 / Smart clone core logic
packages/server/src/controllers/hermes/profiles.ts clone 后调用 smartCloneCleanup / Call smartCloneCleanup after clone
packages/client/src/api/hermes/profiles.ts CreateProfileResult 透传清理结果 / Pass through cleanup result
packages/client/src/stores/hermes/profiles.ts store 透传 / Store passthrough
packages/client/src/components/hermes/profiles/ProfileCreateModal.vue toast 显示清理摘要 / Toast cleanup summary
packages/client/src/components/hermes/settings/PlatformCard.vue 新增 exclusive prop + NAlert / New exclusive prop + NAlert
packages/client/src/components/hermes/settings/PlatformSettings.vue 6 个独占平台标记 exclusive / Mark 6 exclusive platforms
packages/client/src/i18n/locales/*.ts 8 个 locale 新增 i18n key / 8 locales with new i18n keys
tests/server/profile-credentials.test.ts 新增 / New - 12 个测试用例 / 12 test cases

wufloor and others added 2 commits April 28, 2026 23:18
# 问题
`hermes profile create <name> --clone` 完整复制 .env + config.yaml(含独占型平台凭据
如 WEIXIN_TOKEN / TELEGRAM_BOT_TOKEN 等),导致多个 profile 共享同一身份 token。
hermes-agent 在 platform adapter 初始化或 scoped lock 获取阶段失败,gateway 健康检查
持续 15s 超时,前端报 'API Error 500: Gateway health check timed out'。

# 修复
在 web-ui 后端 clone 完成后自动:
1. 从 <profile>/.env 删除匹配独占平台的环境变量(写 .env.bak.* 备份)
2. 在 <profile>/config.yaml 中把 platforms.<exclusive>.enabled 置为 false
3. 清理节点直挂 + extra 子节点下的敏感字段(token / app_secret / account_id 等)

前端 toast 提示被剥离的凭据、被禁用的平台、被剥离的 config 字段,便于用户后续手动
重新填入新身份再启用。

# EXCLUSIVE_PLATFORMS 列表来源
精确对齐 hermes-agent gateway/platforms/*.py 中调用 _acquire_platform_lock 的 7 个
adapter: telegram, discord, slack, whatsapp, signal, weixin, feishu。
未来上游加新独占平台时用 `grep -l _acquire_platform_lock gateway/platforms/*.py` 验证。

# 测试
新增 tests/server/profile-credentials.test.ts(12 用例全过),覆盖:
- isExclusivePlatformKey 命中/未命中边界
- env 文件剥离 + 备份
- config.yaml 平台禁用 + 节点凭据清理
- 已 disabled 平台仍清理残留凭据(防止后续 re-enable 复用旧身份)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
在 PlatformSettings 中为使用 token 互斥锁的 6 个平台 (telegram, discord, slack,
whatsapp, feishu, weixin) 添加视觉警告,提示用户每个 profile 必须使用不同的身份
token,避免与其他 profile 冲突。

# 背景
hermes-agent 的 acquire_scoped_lock 是 token-level(不是 platform-level),所以
设计上支持多 profile 各自配不同身份的同一平台(如 default 用个人微信、staging
用公司微信)。但用户从 UI 配置时容易误填同一 token,导致 gateway 启动失败。

# 实现
- PlatformCard 新增 exclusive 可选 prop,开启时 body 顶部用 NAlert (warning)
  展示提示
- PlatformSettings 在 6 个独占平台数组项标记 exclusive: true 并传给 PlatformCard
- 8 个 i18n locale 新增 platform.exclusiveTokenWarning 翻译

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@EKKOLearnAI EKKOLearnAI merged commit 2ae7e7a into EKKOLearnAI:main Apr 29, 2026
1 check passed
xinke666 pushed a commit to xinke666/hermes-web-ui that referenced this pull request May 23, 2026
ifsherlock pushed a commit to ifsherlock/hermes-web-ui that referenced this pull request Jun 10, 2026
* 修复: profile clone 时智能清理独占平台凭据,避免 gateway 健康检查超时

# 问题
`hermes profile create <name> --clone` 完整复制 .env + config.yaml(含独占型平台凭据
如 WEIXIN_TOKEN / TELEGRAM_BOT_TOKEN 等),导致多个 profile 共享同一身份 token。
hermes-agent 在 platform adapter 初始化或 scoped lock 获取阶段失败,gateway 健康检查
持续 15s 超时,前端报 'API Error 500: Gateway health check timed out'。

# 修复
在 web-ui 后端 clone 完成后自动:
1. 从 <profile>/.env 删除匹配独占平台的环境变量(写 .env.bak.* 备份)
2. 在 <profile>/config.yaml 中把 platforms.<exclusive>.enabled 置为 false
3. 清理节点直挂 + extra 子节点下的敏感字段(token / app_secret / account_id 等)

前端 toast 提示被剥离的凭据、被禁用的平台、被剥离的 config 字段,便于用户后续手动
重新填入新身份再启用。

# EXCLUSIVE_PLATFORMS 列表来源
精确对齐 hermes-agent gateway/platforms/*.py 中调用 _acquire_platform_lock 的 7 个
adapter: telegram, discord, slack, whatsapp, signal, weixin, feishu。
未来上游加新独占平台时用 `grep -l _acquire_platform_lock gateway/platforms/*.py` 验证。

# 测试
新增 tests/server/profile-credentials.test.ts(12 用例全过),覆盖:
- isExclusivePlatformKey 命中/未命中边界
- env 文件剥离 + 备份
- config.yaml 平台禁用 + 节点凭据清理
- 已 disabled 平台仍清理残留凭据(防止后续 re-enable 复用旧身份)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(平台设置): 独占平台显示 token 隔离警告

在 PlatformSettings 中为使用 token 互斥锁的 6 个平台 (telegram, discord, slack,
whatsapp, feishu, weixin) 添加视觉警告,提示用户每个 profile 必须使用不同的身份
token,避免与其他 profile 冲突。

# 背景
hermes-agent 的 acquire_scoped_lock 是 token-level(不是 platform-level),所以
设计上支持多 profile 各自配不同身份的同一平台(如 default 用个人微信、staging
用公司微信)。但用户从 UI 配置时容易误填同一 token,导致 gateway 启动失败。

# 实现
- PlatformCard 新增 exclusive 可选 prop,开启时 body 顶部用 NAlert (warning)
  展示提示
- PlatformSettings 在 6 个独占平台数组项标记 exclusive: true 并传给 PlatformCard
- 8 个 i18n locale 新增 platform.exclusiveTokenWarning 翻译

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants