Install
openclaw skills install @zhaoyongxiu/subagent-archive安全归档/清理子会话的标准操作流程(跨平台 + workspace 可配置 + 原生清理 + dashboard 父会话分流 + 反向匹配索引清理 + 软删除 + OpenClaw 6.1 适配)
openclaw skills install @zhaoyongxiu/subagent-archive| 功能 | 5.26 | 6.1+ | v3.2 处理 |
|---|---|---|---|
| 会话 lock 释放修复 | ❌ | ✅ | 6.1+ 自动获益 |
--fix-missing 反向匹配 | ❌ | ✅ | v3.2 优先调官方 + 自写补盲区 |
--active-key 保护 | ❌ | ✅ | v3.2 透传 |
--fix-dm-scope 修 DM | ✅ | ✅ | v3.2 透传 |
export-trajectory 脱敏 | ❌ | ✅ | 与 v3.0 无关(语义化归档仍是 v3.0 独家) |
核心设计原则:v3.0+ 永远保留 dashboard 父会话归档、物理文件清理、软删除、归档到 memory/ 等 6.1 没提供的功能。v3.1+ 的升级是"集成"而不是"替换"。
v3.1 → v3.2 升级要点:
-WorkspaceDir 参数(默认自动检测唯一 workspace,多 workspace 时引导用户显式指定)| 平台 | PowerShell | 状态 |
|---|---|---|
| Windows | PowerShell 5.1 (Desktop) | ✅ 已测试 |
| Windows | PowerShell 7+ (Core) | ✅ 代码兼容(测试待办) |
| macOS | PowerShell 7+ (Core) | ✅ 代码兼容(测试待办) |
| Linux | PowerShell 7+ (Core) | ✅ 代码兼容(测试待办) |
路径检测逻辑:
- PS 5.1 on Windows:
$env:USERPROFILE→~/.openclaw- PS 7+ on Win/macOS/Linux:
$HOME→~/.openclaw
当需要清理/归档子会话时,必须按照本技能定义的标准流程执行,确保:
:main 绝对不动):cron:* 活跃任务不动,只清过期)--fix-missing,再用自写补盲区(双保险)| 改进点 | v3.1 行为 | v3.2 行为 |
|---|---|---|
| 跨平台路径 | 硬编码 Windows + 单一用户路径 | 自动检测用户主目录,支持 Win/macOS/Linux + PS 5.1/7+ |
| workspace 检测 | 硬编码单一 workspace 路径 | 新增 -WorkspaceDir 参数;默认扫描 ~/.openclaw/workspace-* 找带 MEMORY.md 的目录 |
| 多 workspace 处理 | 不支持 | 唯一命中自动选中;多重命中报错引导用户用 -WorkspaceDir 显式指定 |
| 作者署名 | 强绑定特定工作区和开发者 | "OpenClaw Community"(中性);原开发者 credit 在 README 致谢区 |
| 示例 agent | -Agent <私有 agent> | -Agent myagent(中性占位) |
| v3.1 独有功能 | 全部保留 | dashboard 父会话归档、软删除、归档到 memory/、--fix-missing/--active-key/--fix-dm-scope 全部保留 |
| 改进点 | v3.0 行为 | v3.1 行为 |
|---|---|---|
| OpenClaw 6.1 兼容 | 不识别 6.1 新参数 | 第 1 步自动加 --fix-missing,第 6 步集成官方反向匹配 |
| orphan 检测覆盖 | 只看 status 字段,漏"无 status + 无 transcript"孤儿 | 6.1 官方 --fix-missing 一步清 + 自写补 status 缺失 |
| active-key 保护 | 硬编码保护 :main / :cron: / :dashboard: | 支持 6.1 --active-key <key> 透传任意 key |
| dm-scope 修复 | 不处理 DM scope | 6.1 --fix-dm-scope 透传 |
| 降级兼容 | 无 | -NoFixMissing 开关:6.1 不可用时降级到 v3.0 行为 |
| v3.0 独有功能 | 全部保留 | dashboard 父会话归档、软删除、归档到 memory/ 全部保留 |
| 改进点 | v1.1.0 行为 | v3.0 行为 |
|---|---|---|
| 物理文件清理 | 只删 .jsonl 单一文件 | 按 sessionId.* 成组删除,覆盖 .jsonl / .trajectory.jsonl / .trajectory-path.json / .jsonl.checkpoint.<id>.jsonl / .jsonl.reset.<ts> / .jsonl.deleted.<ts> |
| sessions.json 索引清理 | 用 :main$ 粗暴过滤,可能误杀其他后缀 | 反向匹配:只清理 sessionFile 已不存在的 key |
| dashboard 父会话处理 | 没有特殊处理,依赖通用规则 | status 分流:status=done 父会话 + 空壳子会话 + 派生子会话可归档;status=running/活跃永远不动 |
| 保护 key | 只保护 :main | 保护 :main、:cron:*(除过期)、:dashboard:*(除 done) |
| 模式支持 | 只有硬删除 | 支持 dry-run(默认)、enforce(真删)、soft(重命名为 .deleted.<timestamp>) |
| 追加写入铁律 | 写在第 3/4 步 | 仍为铁律:第 3/4 步必须 Add-Content,禁止 write/Set-Content |
| dashboard 父会话归档 | 不归档 | 归档到 memory/dashboard-archives/YYYY-MM-DD-dashboard-<sessionId>.md |
第 3 步和第 4 步必须使用追加写入(Add-Content),禁止使用覆盖写入(write/Set-Content)!
理由:
例外:
Set-Content 是允许的(必须用原子重写)New-Item目标:跨平台检测 OpenClaw 根目录、workspace 目录、memory 目录、dashboard 归档目录。
# === 跨平台 OpenClaw 根目录检测 ===
$IsWindowsOS = ($env:OS -eq "Windows_NT")
if ($IsWindowsOS) {
$OpenClawHome = if ($env:USERPROFILE) { $env:USERPROFILE } else { $HOME }
} else {
$OpenClawHome = $HOME
}
$OpenClawDir = Join-Path $OpenClawHome ".openclaw"
$SessionsDir = Join-Path $OpenClawDir "agents/$Agent/sessions"
# === workspace 目录检测(v3.2 新增) ===
# 优先级:-WorkspaceDir 显式指定 > 自动扫描 $OpenClawDir\workspace-*
# 自动扫描规则:找带 MEMORY.md 的目录
# - 唯一命中:自动选中
# - 多重命中:报错引导用户显式指定
# - 零命中:报错引导用户显式指定
if ($WorkspaceDir -ne "") {
# 显式指定,直接用
} else {
$candidates = @()
$wsDirs = Get-ChildItem -Path $OpenClawDir -Directory -Filter "workspace-*"
foreach ($w in $wsDirs) {
if (Test-Path (Join-Path $w.FullName "MEMORY.md")) {
$candidates += $w.FullName
}
}
if ($candidates.Count -eq 0) { Write-Error "未找到 workspace 目录"; exit 2 }
elseif ($candidates.Count -gt 1) { Write-Error "检测到多个 workspace"; exit 2 }
else { $WorkspaceDir = $candidates[0] }
}
$MemoryDir = Join-Path $WorkspaceDir "memory"
$DashboardArchiveDir = Join-Path $MemoryDir "dashboard-archives"
多 workspace 错误信息示例:
[ERR] 检测到多个 workspace:
[ERR] - /home/user/.openclaw/workspace-alpha
[ERR] - /home/user/.openclaw/workspace-beta
[ERR] 请用 -WorkspaceDir <path> 显式指定其中一个。
目标:识别目标会话的类型(direct/cron/dashboard)和状态(running/done/idle)。
v3.1+ 新增:第 1 步优先调 OpenClaw 6.1 官方 --fix-missing(识别"transcript 文件不存在"的孤儿),第 1 步还支持 --active-key / --fix-dm-scope 透传。
# 1.1 构造原生清理命令(v3.1 自动加 --fix-missing)
$nativeArgs = @("sessions", "cleanup", "--agent", $Agent, "--dry-run")
if ($FixMissing -and -not $NoFixMissing) { $nativeArgs += "--fix-missing" }
if ($FixDmScope) { $nativeArgs += "--fix-dm-scope" }
foreach ($key in $ActiveKey) { $nativeArgs += "--active-key"; $nativeArgs += $key }
$nativeOutput = & openclaw @nativeArgs 2>&1 | Out-String
# 1.2 列出所有会话,识别 dashboard 父会话
$allKeys = openclaw sessions --agent <agentId> --json | ConvertFrom-Json
# 1.3 对每个候选会话,读取状态(status 字段)
foreach ($entry in $allKeys) {
$key = $entry.key
$status = $entry.status # running | done | idle | unknown
$kind = $entry.kind # direct | cron | dashboard | ...
# dashboard 父会话的 status=done 才归档,status=running/idle 跳过
if ($key -match ':dashboard:') {
if ($status -ne 'done') {
Write-Host "[跳过] $key - dashboard 父会话非 done 状态 ($status)" -ForegroundColor Yellow
continue
}
}
# cron 任务保护(除非已过期)
if ($key -match ':cron:') {
Write-Host "[跳过] $key - cron 任务受保护" -ForegroundColor Yellow
continue
}
# 主会话保护
if ($key -match ':main$') {
Write-Host "[跳过] $key - 主会话受保护" -ForegroundColor Yellow
continue
}
}
dashboard 父会话识别规则:
:dashboard: 开头status=done(任务结束)v3.1+ --fix-missing 行为说明:
--fix-missing 会绕过 age/count retention 限制,直接清"transcript 文件不存在"的孤儿status 字段,漏掉了"无 status + 无 transcript"的孤儿——这正是 6.1 --fix-missing 补的输出:
--active-key 指定的 key)--fix-missing)对每个待归档会话做内容审查:
输出:安全分析结论(pass / hold / special)
在 <workspace>/memory/YYYY-MM-DD-subagent-archive-v3.md 中追加归档记录:
$archiveFile = Join-Path $MemoryDir "$DateStr-subagent-archive-v3.md"
# 先检查文件是否存在,没有则创建
if (-not (Test-Path $archiveFile)) {
New-Item -Path $archiveFile -ItemType File -Force | Out-Null
Add-Content -Path $archiveFile -Value "# 子会话归档日志 (v3.2)`n"
}
# 检查是否已存在该 sessionId 的归档记录
$sessionId = '<具体 sessionId>'
$existing = Select-String -Path $archiveFile -Pattern $sessionId -SimpleMatch -ErrorAction SilentlyContinue
if ($existing) {
Write-Host "[跳过归档] $sessionId - 已存在归档记录" -ForegroundColor Yellow
} else {
# 追加归档记录
Add-Content -Path $archiveFile -Value @"
## ✅ 安全归档记录($((Get-Date).ToString('yyyy-MM-dd HH:mm'))执行)
| 智能体 | 会话类型 | 归档文件 | 大小 | 归档时间戳 |
|--------|----------|----------|------|-----------|
| $agentId | $kind | $sessionId.jsonl | $size | $((Get-Date).ToString('yyyy-MM-dd HH:mm')) |
### 会话内容摘要
- **用途**:$purpose
- **创建时间**:$createdAt
- **最后活跃**:$lastActive
- **结果**:$result
"@
}
dashboard 父会话特殊处理:归档到 <workspace>/memory/dashboard-archives/YYYY-MM-DD-dashboard-<sessionId>.md:
$dashboardDir = Join-Path $MemoryDir "dashboard-archives"
if (-not (Test-Path $dashboardDir)) {
New-Item -Path $dashboardDir -ItemType Directory -Force | Out-Null
}
$dashboardFile = Join-Path $dashboardDir "$DateStr-dashboard-$sessionId.md"
if (-not (Test-Path $dashboardFile)) {
New-Item -Path $dashboardFile -ItemType File -Force | Out-Null
Add-Content -Path $dashboardFile -Value @"
# Dashboard 父会话归档
**Session ID**: $sessionId
**归档时间**: $((Get-Date).ToString('yyyy-MM-dd HH:mm'))
**归档原因**: status=done,会话已结束
"@
}
关键点:
Add-Content 追加写入write/Set-Content 覆盖将本次 v3.2 执行作为系统管理记录追加到日志文件:
Add-Content -Path $archiveFile -Value @"
## 📋 系统管理操作(v3.2)
### 归档执行
- **时间**:$((Get-Date).ToString('yyyy-MM-dd HH:mm'))
- **模式**:$mode (dry-run / enforce / soft)
- **目标智能体**:$agentId
- **workspace**:$WorkspaceDir
- **归档会话数**:$archivedCount
- **释放空间**:$freedMB MB
- **受保护 key**:$protectedKeys
- **OpenClaw 6.1 兼容**:FixMissing=$FixMissing, FixDmScope=$FixDmScope, ActiveKey=$($ActiveKey -join ',')
- **操作**:v3.2 安全归档完成
"@
关键点:
Add-Content 追加写入write/Set-Content 覆盖⚠️ v3.0 核心改进(v3.2 完整保留):按 sessionId.* 成组删除,覆盖所有变体文件:
# v3.2: SessionsDir 已经从 path 配置阶段计算好
$sessionsDir = $SessionsDir
$sessionId = '<具体 sessionId>'
# 找出该 sessionId 的所有变体文件
# 覆盖:.jsonl, .trajectory.jsonl, .trajectory-path.json,
# .jsonl.checkpoint.<id>.jsonl, .jsonl.reset.<ts>, .jsonl.deleted.<ts>
$patterns = @(
"$sessionId.jsonl",
"$sessionId.trajectory.jsonl",
"$sessionId.trajectory-path.json",
"$sessionId.jsonl.checkpoint.*.jsonl",
"$sessionId.jsonl.reset.*",
"$sessionId.jsonl.deleted.*"
)
$totalFreed = 0
foreach ($pattern in $patterns) {
$files = Get-ChildItem -Path $sessionsDir -Filter $pattern -Force -ErrorAction SilentlyContinue
foreach ($file in $files) {
$size = $file.Length
if ($mode -eq 'soft') {
# 软删除:重命名为 .deleted.<timestamp>
$newName = "$($file.FullName).deleted.$((Get-Date).ToString('yyyy-MM-ddTHH-mm-ss.fffZ'))"
Rename-Item -Path $file.FullName -NewName (Split-Path $newName -Leaf)
Write-Host "[soft-rename] $($file.Name) -> $(Split-Path $newName -Leaf)" -ForegroundColor DarkYellow
} else {
# 硬删除
Remove-Item $file.FullName -Force
Write-Host "[hard-delete] $($file.Name) ($size bytes)" -ForegroundColor Green
}
$totalFreed += $size
}
}
Write-Host "[总计] 释放 $($totalFreed / 1MB) MB" -ForegroundColor Cyan
警告:
<id>.jsonl,会漏掉 .trajectory.jsonl 等sessionId.* 通配符成组清理⚠️ v3.1+ 核心升级:在 v3.0 反向匹配基础上,优先调 OpenClaw 6.1 官方 --fix-missing,再用自写逻辑补盲区(双保险):
$sessionsFile = Join-Path $SessionsDir "sessions.json"
# === v3.1+ 第 6.1 步:优先调官方 --fix-missing(6.1+) ===
# 官方会识别所有"transcript 文件不存在"的孤儿,绕过 age/count retention 限制
if ($FixMissing -and -not $NoFixMissing) {
if ($Mode -eq "enforce") {
$fixArgs = @("sessions", "cleanup", "--agent", $Agent, "--enforce", "--fix-missing")
if ($FixDmScope) { $fixArgs += "--fix-dm-scope" }
foreach ($key in $ActiveKey) { $fixArgs += "--active-key"; $fixArgs += $key }
Write-Action "执行官方 --fix-missing 清理..."
& openclaw @fixArgs 2>&1 | Out-String | Write-Info
} else {
Write-Info "[dry-run] 6.1 --fix-missing 将被调用(实际未执行)"
}
} else {
Write-Warn "跳过官方 --fix-missing(FixMissing=$FixMissing, NoFixMissing=$NoFixMissing)"
}
# === v3.1+ 第 6.2 步:自写逻辑补盲区(仅当 6.1 漏掉时) ===
# 6.1 官方只清"transcript 不存在"的孤儿,漏掉"status 缺失但文件存在"等异常
$json = Get-Content $sessionsFile -Raw | ConvertFrom-Json
$staleKeys = @()
foreach ($prop in $json.PSObject.Properties.Copy) {
$entry = $prop.Value
$keyName = $prop.Name
# 跳过受保护 key
if ($keyName -in $protectedKeys) { continue }
if ($keyName -match ':main$') { continue }
if ($keyName -match ':cron:') { continue }
if ($keyName -match ':dashboard:' -and $entry.status -ne 'done') { continue }
# 检测"status 字段缺失但文件存在"的异常(v3.0 漏的类型)
if (-not $entry.status -and $entry.sessionFile -and (Test-Path $entry.sessionFile)) {
Write-Warn "异常条目:$keyName 缺 status 字段(v3.0 盲区,v3.1+/v3.2 检测但不自动清)"
# 不加入 $staleKeys,留给操作员决定
}
# 检测孤儿条目(v3.0 已有逻辑,官方 --fix-missing 已经在第 1 步清过)
if ($entry.sessionFile -and -not (Test-Path $entry.sessionFile)) {
$staleKeys += $keyName
Write-Action "发现 orphan key: $keyName"
}
}
# === v3.1+ 第 6.3 步:零匹配守卫(v3.0 修复的 bug,不能重蹈覆辙) ===
if ($Mode -eq "enforce") {
if ($staleKeys.Count -gt 0) {
# 强制备份
$backupPath = "$sessionsFile.backup-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
Copy-Item $sessionsFile $backupPath
Write-Success "已备份: $backupPath"
# 删除 stale keys
foreach ($key in $staleKeys) {
$json.PSObject.Properties.Remove($key)
}
# 重写
$json | ConvertTo-Json -Depth 20 | Set-Content $sessionsFile -NoNewline -Encoding UTF8
Write-Success "已清理 $($staleKeys.Count) 个 stale key"
} else {
Write-Info "无需重写 sessions.json(无 stale key)"
}
} else {
Write-Warn "[dry-run] 将清理 $($staleKeys.Count) 个 stale key(未执行)"
foreach ($k in $staleKeys) {
Write-Action " - $k"
}
}
v3.2 vs v3.0 第 6 步关键差异:
--fix-missing(6.1 一步补上"transcript 不存在"孤儿)v3.1+ 第 6 步设计原则:
验证清理结果:
openclaw sessions --agent $agentId
# 应该显示: Sessions listed: N(:main + 活跃 cron + 活跃 dashboard 仍保留)
:main 绝对不能动:cron:* 中正在运行的受保护:dashboard:* 中 status≠done 的受保护:main$ 这种粗暴过滤Add-Content<workspace>/memory/dashboard-archives/ 独立目录-Enforce 才真删.deleted.<timestamp> 后缀代替 Remove-Item--fix-missing / --active-key / --fix-dm-scope;低版本自动降级(用 -NoFixMissing)~/.openclaw(Win/macOS/Linux)-WorkspaceDir-Agent myagent,避免绑定特定私有 agentsessions cleanup 做补强:main 条目.jsonl 不删 .trajectory.jsonl(数据残留)$key -notmatch ':main$' 过滤 sessions.json(粗暴,可能误杀)--dry-run 模式下执行物理删除:cron:* 活跃任务--fix-missing 调用(除非用 -NoFixMissing 显式降级)--agent=foo(必须用 PowerShell 原生 -Agent foo)-WorkspaceDir 显式指定--fix-missing(6.1+ 自动)--active-key 透传(如指定)Add-Content 到 <workspace>/memory/YYYY-MM-DD-subagent-archive-v3.md)<workspace>/memory/dashboard-archives/YYYY-MM-DD-dashboard-<sessionId>.mdAdd-Content)sessionId.* 成组,覆盖 6 种变体)dry-run / soft / enforce 中合适的模式--fix-missing + 自写反向匹配)openclaw sessions --agent $agentId 显示正确的会话数scripts/archive-sessions.ps1(v3.2 实现,跨平台 + workspace 可配置)openclaw sessions cleanup --enforce --fix-missing(v3.1+ 集成)--fix-missing / --active-key / --fix-dm-scopeopenclaw config get session.maintenance(v3.1+ 配合 enforce 模式)-WorkspaceDir 参数(自动检测 + 显式覆盖)、中性化作者署名;完整保留 v3.1 全部功能--fix-missing / --active-key / --fix-dm-scope;第 6 步改为"官方 + 自写"双保险;新增 -NoFixMissing 降级开关