优化: 会话侧栏字体层级收敛+v0.1.3发布收尾脚本入库,归档飞书WS假活排查文档
This commit is contained in:
@@ -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),非回复消息,属正常
|
||||||
@@ -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"
|
||||||
@@ -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"
|
||||||
@@ -773,8 +773,8 @@ body.ai-sidebar-resizing * {
|
|||||||
border-bottom: 0.5px solid var(--df-border);
|
border-bottom: 0.5px solid var(--df-border);
|
||||||
}
|
}
|
||||||
.ai-conv-sidebar-title {
|
.ai-conv-sidebar-title {
|
||||||
font-size: 12px;
|
font-size: 13px;
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
color: var(--df-text);
|
color: var(--df-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -823,7 +823,7 @@ body.ai-sidebar-resizing * {
|
|||||||
}
|
}
|
||||||
.ai-conv-group-title {
|
.ai-conv-group-title {
|
||||||
padding: 8px 8px 3px;
|
padding: 8px 8px 3px;
|
||||||
font-size: 10px;
|
font-size: 11px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--df-text-dim);
|
color: var(--df-text-dim);
|
||||||
user-select: none;
|
user-select: none;
|
||||||
@@ -892,7 +892,8 @@ body.ai-sidebar-resizing * {
|
|||||||
gap: 2px;
|
gap: 2px;
|
||||||
}
|
}
|
||||||
.ai-conv-item-title {
|
.ai-conv-item-title {
|
||||||
font-size: 11px;
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
color: var(--df-text);
|
color: var(--df-text);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
Reference in New Issue
Block a user