修复: Profile clone 时智能清理独占平台凭据 + 平台设置独占警告 (#283)
* 修复: 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>
This commit is contained in:
@@ -43,9 +43,9 @@ export const useProfilesStore = defineStore('profiles', () => {
|
||||
}
|
||||
|
||||
async function createProfile(name: string, clone?: boolean) {
|
||||
const ok = await profilesApi.createProfile(name, clone)
|
||||
if (ok) await fetchProfiles()
|
||||
return ok
|
||||
const res = await profilesApi.createProfile(name, clone)
|
||||
if (res.success) await fetchProfiles()
|
||||
return res
|
||||
}
|
||||
|
||||
async function deleteProfile(name: string) {
|
||||
|
||||
Reference in New Issue
Block a user