feat: 飞书官方插件迁移 + 配对审批 + Gateway防卡死 + 微信升级修复 + 更新检测修复

- 飞书渠道从 @openclaw/feishu 迁移到 @larksuite/openclaw-lark 官方插件
- 保存飞书配置时自动禁用旧 feishu 插件,防止新旧插件冲突
- 所有主要渠道(飞书/Telegram/Discord/Slack)启用配对审批UI
- gateway_command 增加20s超时,超时后force-kill+fresh start
- 全平台启动前端口占用检查,防止Guardian无限拉起
- Linux gateway_command 补齐 Duration 导入和 cleanup_zombie 实现
- Guardian自动守护在Tauri桌面端也启用,轮询间隔30s→15s
- 微信渠道:升级操作不再弹出扫码二维码,按钮文案区分安装/升级
- 版本更新检测:CI不再将minAppVersion写死为当前版本
- 部署脚本增强OpenClaw检测,支持已安装的官方版
- 日间/夜间模式圆形扩散切换动画(View Transitions API)
- API错误信息完整展示(429限流等),URL自动转可点击链接
- 第三方API接入引导优化:移除内置密钥,引导式流程
- 修复全平台 Clippy 警告(strip_prefix/dead_code/unnecessary_unwrap等)
- Rust代码格式化修复(cargo fmt)
- toast组件支持HTML内容渲染
- Rust后端test_model返回详细错误信息
This commit is contained in:
晴天
2026-03-23 20:37:48 +08:00
parent dccb4b4dbf
commit 3687e26d5d
50 changed files with 8055 additions and 2715 deletions

View File

@@ -1772,7 +1772,7 @@ const handlers = {
install_qqbot_plugin() {
const bin = findOpenclawBin() || 'openclaw'
try {
execSync(`${bin} plugins install @sliverp/qqbot@latest`, { timeout: 60000, cwd: homedir() })
execSync(`${bin} plugins install @tencent-connect/openclaw-qqbot@latest`, { timeout: 600000, cwd: homedir() })
return '安装成功'
} catch (e) {
throw new Error('QQBot 插件安装失败: ' + (e.message || e))
@@ -3122,6 +3122,75 @@ const handlers = {
return result
},
// Agent 渠道绑定管理
list_all_bindings() {
const cfg = readConfig()
const bindings = cfg.bindings || []
return { bindings }
},
save_agent_binding({ agentId, channel, accountId, bindingConfig }) {
const cfg = readConfig()
if (!cfg.bindings) cfg.bindings = []
const bindings = cfg.bindings
// 构建新绑定
const newBinding = {
type: 'route',
agentId,
match: {
channel,
...(accountId ? { accountId } : {}),
},
}
// 合并 peer 配置到 match
if (bindingConfig && typeof bindingConfig === 'object') {
if (bindingConfig.peer) {
newBinding.match.peer = bindingConfig.peer
}
}
// 查找并更新现有绑定(相同 agentId + channel + accountId
const accountKey = accountId || ''
let found = false
for (let i = 0; i < bindings.length; i++) {
const b = bindings[i]
if (b.agentId === agentId && b.match?.channel === channel) {
const existingAccount = b.match?.accountId || ''
if (existingAccount === accountKey) {
bindings[i] = newBinding
found = true
break
}
}
}
if (!found) {
bindings.push(newBinding)
}
saveConfig(cfg)
return { ok: true }
},
delete_agent_binding({ agentId, channel, accountId }) {
const cfg = readConfig()
if (!cfg.bindings) cfg.bindings = []
const bindings = cfg.bindings
const accountKey = accountId || ''
const before = bindings.length
cfg.bindings = bindings.filter(b => {
if (b.agentId !== agentId) return true
if (b.match?.channel !== channel) return true
const existingAccount = b.match?.accountId || ''
return existingAccount !== accountKey
})
saveConfig(cfg)
return { ok: true, removed: before - cfg.bindings.length }
},
// 记忆文件
list_memory_files({ category, agent_id }) {
const suffix = agent_id && agent_id !== 'main' ? `/agents/${agent_id}` : ''