diff --git a/docs/09-问题排查/飞书通道WS假活探活无自愈-2026-10-11.md b/docs/09-问题排查/飞书通道WS假活探活无自愈-2026-10-11.md new file mode 100644 index 0000000..0bbdfb9 --- /dev/null +++ b/docs/09-问题排查/飞书通道WS假活探活无自愈-2026-10-11.md @@ -0,0 +1,30 @@ +# 飞书通道 WS 假活:探活只告警不自愈 + +> 登记: AI-Ops 2026-10-11 22:15 · 来源: 用户 @ bot 零回应事故排查 · 实施归 devflow agent + +## 现象 + +用户 20:07 后在飞书 @ bot 发消息,零回应。feishu-channel.log 尾部停在 20:07 「打包换装」watcher 终版,其后 2h+ 零「收到消息」事件——消息根本未达应用,非模型/会话层问题。 + +## 证据 + +- 日志: `~/AppData/Roaming/top.1216.devflow/feishu-channel.log` +- 累计 90 条探活告警「660s 无任何事件且无在途会话(疑似假活,持续出现请重启应用重建连接)」,跨 10-05~10-11 多日分布,连接时好时坏 +- 时间线: 14:00 前持续告警 → 20:04-20:07 恢复(收到 4 条消息正常受理+终版) → 20:07 起再断,至 22:12 仍零入站,进程未重启(devflow.exe PID 14172 同前) +- 应用本身健康: trace.log 持续输出, B5 引擎「🟢 健康,空闲」 +- 对照: u-claw 曾有同款(热重建不关旧连接致僵尸 WS,closeGraceful 须显式 Close),见 u-claw 记忆 uclaw-zombie-ws-connection + +## 根因方向 + +WS 长连接假活: 探活任务已检测到「无事件+无在途」但仅打日志,无自动重建连接动作,恢复依赖新消息触发或人工重启。为何 20:04 能自愈一次、20:07 后不能,需读 SDK 连接层确认(是否依赖入站流量触发重连)。 + +## 修复建议 + +1. 探活告警连续 N 次(如 2 次,约 20 分钟)→ 主动断开并重建 WS 连接(显式 Close 旧连接防僵尸),重建结果写日志 +2. 重建失败退避重试,持续失败升级通知(桌面通知/卡片) +3. 复核 90 条告警的历史分布,确认是否存在更早未被用户察觉的静默窗口 + +## 排除项 + +- 97「收到消息」vs 47「受理返回」差值: 新旧版本日志口径混杂(受理返回为后加日志),受理守卫拒绝仅 2 条且走旧「AI 正在生成中」路径,无消息丢失 +- watcher 终版无「回复」行: 新版投递走卡片原地更新(edit_card),非回复消息,属正常 diff --git a/scripts/finish-release.ps1 b/scripts/finish-release.ps1 new file mode 100644 index 0000000..d0eb3cb --- /dev/null +++ b/scripts/finish-release.ps1 @@ -0,0 +1,58 @@ +# 发布收尾:杀挂起脚本 -> 手动签名 0.1.3 -> latest.json -> 上传 -> 远端验证 +$ErrorActionPreference = "Stop" +$repo = "E:\wk-lab\devflow" +$nsis = "$repo\target\release\bundle\nsis" +$exe = "$nsis\devflow_0.1.3_x64-setup.exe" +$key = "$env:USERPROFILE\.tauri\devflow.key" +$site = "suke-dev" +$remoteDir = "/var/www/app-site/download/devflow" +$baseUrl = "https://app.1216.top/download/devflow" +$notes = "版本更新与自动升级全链路上线:设置页新增「关于」,支持应用内检查/下载/安装更新" + +# 1. 杀挂起的发布脚本与构建残留 +Get-Process -Id 14328,2008,26208,28276,19412 -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue +Write-Host "[1/5] 挂起进程已清理" + +# 2. 手动签名(key 文件内容经 env 传入——-k/ev 传路径会被当 base64 解码,报 Invalid symbol 58) +Set-Location $repo +$env:TAURI_SIGNING_PRIVATE_KEY = (Get-Content $key -Raw).Trim() +$env:TAURI_SIGNING_PRIVATE_KEY_PASSWORD = "" +cmd /c "cargo tauri signer sign -p `"`" --app-version 0.1.3 `"$exe`" < NUL 2>&1" +if ($LASTEXITCODE -ne 0) { Write-Host "[失败] 签名"; exit 1 } +$sigPath = "$exe.sig" +if (-not (Test-Path $sigPath)) { Write-Host "[失败] .sig 未生成"; exit 1 } +Write-Host "[2/5] 签名完成: $sigPath" + +# 3. 生成 latest.json(UTF-8 无 BOM,防 PS5.1 BOM 坑) +$sig = (Get-Content $sigPath -Raw).Trim() +$pubDate = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") +$latestJson = [ordered]@{ + version = "0.1.3" + notes = $notes + pub_date = $pubDate + platforms = [ordered]@{ + "windows-x86_64" = [ordered]@{ + signature = $sig + url = "$baseUrl/devflow_0.1.3_x64-setup.exe" + } + } +} | ConvertTo-Json -Depth 5 +$latestPath = "$nsis\latest.json" +[System.IO.File]::WriteAllText($latestPath, $latestJson, (New-Object System.Text.UTF8Encoding($false))) +Write-Host "[3/5] latest.json 已生成 (version=0.1.3)" + +# 4. 上传三件套 +$env:MSYS_NO_PATHCONV = "1" +ssh-proxy exec -n $site -c "mkdir -p $remoteDir" +foreach ($f in @($exe, $sigPath, $latestPath)) { + $name = Split-Path $f -Leaf + Write-Host "[4/5] 上传 $name ..." + ssh-proxy upload --name $site --src $f --dst "$remoteDir/$name" + if ($LASTEXITCODE -ne 0) { Write-Host "[失败] 上传 $name"; exit 1 } +} + +# 5. 远端验证 +Write-Host "[5/5] 远端清单验证:" +ssh-proxy exec -n $site -c "ls -la $remoteDir | grep 0.1.3; head -c 200 $remoteDir/latest.json" +Write-Host "" +Write-Host "[发布完成] v0.1.3 清单地址: $baseUrl/latest.json" diff --git a/scripts/kick-release-bg.ps1 b/scripts/kick-release-bg.ps1 new file mode 100644 index 0000000..88c6fdd --- /dev/null +++ b/scripts/kick-release-bg.ps1 @@ -0,0 +1,25 @@ +# 后台启动 publish-release.ps1(tauri build 10 分钟级,run_command 600s 上限装不下) +# 用法: run_command 执行本文件 -> 立即返回 pid -> 之后轮询 release-out.log +$repo = 'E:\wk-lab\devflow' +$log = "$repo\target\release-out.log" +$errl = "$repo\target\release-err.log" + +# 清掉上次 600s 超时可能残留的构建进程,防 cargo 构建锁互等 +$killed = Get-Process cargo,cargo-tauri,rustc -ErrorAction SilentlyContinue +if ($killed) { + $killed | Stop-Process -Force + Write-Host ("清理残留构建进程: " + (($killed | Select-Object -ExpandProperty Id) -join ',')) +} else { + Write-Host "无残留构建进程" +} + +Remove-Item $log,$errl -ErrorAction SilentlyContinue +$p = Start-Process -FilePath 'powershell.exe' ` + -ArgumentList @('-NoProfile','-ExecutionPolicy','Bypass','-File',"$repo\scripts\publish-release.ps1") ` + -WorkingDirectory $repo ` + -NoNewWindow ` + -RedirectStandardOutput $log ` + -RedirectStandardError $errl ` + -PassThru +Set-Content -Path "$repo\target\release-pid.txt" -Value $p.Id -Encoding ascii +Write-Host "release started, pid=$($p.Id), log=$log" diff --git a/src/components/ai/ConversationSidebar.vue b/src/components/ai/ConversationSidebar.vue index 4483a60..6a97527 100644 --- a/src/components/ai/ConversationSidebar.vue +++ b/src/components/ai/ConversationSidebar.vue @@ -773,8 +773,8 @@ body.ai-sidebar-resizing * { border-bottom: 0.5px solid var(--df-border); } .ai-conv-sidebar-title { - font-size: 12px; - font-weight: 500; + font-size: 13px; + font-weight: 600; color: var(--df-text); } @@ -823,7 +823,7 @@ body.ai-sidebar-resizing * { } .ai-conv-group-title { padding: 8px 8px 3px; - font-size: 10px; + font-size: 11px; font-weight: 600; color: var(--df-text-dim); user-select: none; @@ -892,7 +892,8 @@ body.ai-sidebar-resizing * { gap: 2px; } .ai-conv-item-title { - font-size: 11px; + font-size: 13px; + font-weight: 500; color: var(--df-text); white-space: nowrap; overflow: hidden;