sync: HP_BOWEI 2026-10-20
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env bash
|
||||
# claude-brain 巡检:列出本会话每个子 agent 的最近活动时间、空闲时长与最后动作,
|
||||
# 标出空闲超过阈值的 worker,供调度员每 30 分钟打印并决定是否唤醒。
|
||||
#
|
||||
# 原理:Claude Code 把每个 subagent 的转录写在
|
||||
# ~/.claude/projects/<项目slug>/<会话ID>/subagents/agent-<id>.jsonl
|
||||
# 旁边的 agent-<id>.meta.json 带 description(派出时的 description 参数)与 model。
|
||||
# 转录文件的 mtime 就是该 agent 最近一次活动;最后几 KB 能看出它停在什么动作上。
|
||||
#
|
||||
# 用法(在 claude-brain 运行时所在的工程根目录执行):
|
||||
# check_agents.sh [运行目录] [--threshold 30] [--hours 24] [--session <会话ID>] [--ids id1,id2]
|
||||
# 运行目录给出时,末尾顺带打印其中的 agents.md 名册。
|
||||
# --ids 只看这些 agent(前缀即可,逗号分隔);不给则列出时间窗内所有有转录的 agent。
|
||||
# 输出:先一行 "巡检 HH:MM",然后 markdown 表。判定列:
|
||||
# 正常 / 空闲超限 / 正常(大脑等待不计) / 已结束?(回合结束且空闲超限,需对照名册)
|
||||
|
||||
threshold=30
|
||||
hours=24
|
||||
session=""
|
||||
ids=""
|
||||
rundir=""
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--threshold) threshold="$2"; shift 2 ;;
|
||||
--hours) hours="$2"; shift 2 ;;
|
||||
--session) session="$2"; shift 2 ;;
|
||||
--ids) ids="$2"; shift 2 ;;
|
||||
*) rundir="$1"; shift ;;
|
||||
esac
|
||||
done
|
||||
|
||||
cwd="$(pwd -W 2>/dev/null || pwd)"
|
||||
slug="$(printf '%s' "$cwd" | sed -e 's#[:/\\_]#-#g')"
|
||||
proj="$HOME/.claude/projects/$slug"
|
||||
if [ ! -d "$proj" ]; then
|
||||
echo "找不到项目转录目录: $proj" >&2
|
||||
echo "请在 claude-brain 运行时所在的工程根目录执行本脚本。" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mins=$((hours * 60))
|
||||
if [ -n "$session" ]; then
|
||||
files=$(find "$proj/$session/subagents" -name 'agent-*.jsonl' 2>/dev/null)
|
||||
else
|
||||
files=$(find "$proj" -path '*/subagents/agent-*.jsonl' -mmin "-$mins" 2>/dev/null)
|
||||
fi
|
||||
|
||||
now=$(date +%s)
|
||||
echo "巡检 $(date +%H:%M)(阈值 ${threshold} min,时间窗 ${hours} h)"
|
||||
echo
|
||||
echo "| agent | 角色/任务 | 模型 | 最近活动 | 空闲 | 最后动作 | 判定 |"
|
||||
echo "|---|---|---|---|---|---|---|"
|
||||
|
||||
over=0
|
||||
# 按 mtime 新→旧排序
|
||||
for f in $(ls -t $files 2>/dev/null); do
|
||||
id=$(basename "$f" .jsonl | sed 's/^agent-//')
|
||||
if [ -n "$ids" ]; then
|
||||
hit=0
|
||||
for p in $(printf '%s' "$ids" | tr ',' ' '); do
|
||||
case "$id" in "$p"*) hit=1 ;; esac
|
||||
done
|
||||
[ $hit -eq 1 ] || continue
|
||||
fi
|
||||
meta="${f%.jsonl}.meta.json"
|
||||
desc="?"; model="?"
|
||||
if [ -f "$meta" ]; then
|
||||
desc=$(grep -o '"description":"[^"]*"' "$meta" | head -n1 | sed 's/"description":"//;s/"$//')
|
||||
model=$(grep -o '"model":"[^"]*"' "$meta" | head -n1 | sed 's/"model":"//;s/"$//')
|
||||
fi
|
||||
mt=$(stat -c %Y "$f")
|
||||
idle=$(( (now - mt) / 60 ))
|
||||
last=$(date -d "@$mt" +%H:%M)
|
||||
tailtxt=$(tail -c 6000 "$f")
|
||||
if printf '%s' "$tailtxt" | grep -q '"name":"Monitor"'; then
|
||||
act="等待 Monitor"
|
||||
elif printf '%s' "$tailtxt" | grep -q '"run_in_background":true'; then
|
||||
act="等待后台命令"
|
||||
elif printf '%s' "$tailtxt" | grep -q 'Monitor expired\|Monitor event'; then
|
||||
act="收到 Monitor 事件后停住"
|
||||
elif printf '%s' "$tailtxt" | tail -c 1500 | grep -q '"stop_reason":"end_turn"'; then
|
||||
act="回合结束"
|
||||
elif printf '%s' "$tailtxt" | grep -q '"type":"tool_use"'; then
|
||||
act="工具调用中"
|
||||
else
|
||||
act="活动中"
|
||||
fi
|
||||
isbrain=0
|
||||
case "$desc" in *大脑*|*brain*|*Brain*) isbrain=1 ;; esac
|
||||
if [ $isbrain -eq 1 ]; then
|
||||
verdict="正常(大脑等待不计)"
|
||||
elif [ "$idle" -ge "$threshold" ]; then
|
||||
if [ "$act" = "回合结束" ]; then verdict="已结束?(对照名册;运行中则为空闲超限)"; else verdict="**空闲超限**"; fi
|
||||
over=$((over + 1))
|
||||
else
|
||||
verdict="正常"
|
||||
fi
|
||||
printf '| %s… | %s | %s | %s | %s min | %s | %s |\n' "${id:0:5}" "$desc" "$model" "$last" "$idle" "$act" "$verdict"
|
||||
done
|
||||
|
||||
echo
|
||||
if [ "$over" -gt 0 ]; then
|
||||
echo "有 $over 个 agent 空闲 ≥ ${threshold} min。对照 agents.md:状态为「运行中」且报告文件不存在的,按 SKILL.md「30 分钟巡检」第 4 步介入。"
|
||||
else
|
||||
echo "无空闲超限的 agent。"
|
||||
fi
|
||||
|
||||
if [ -n "$rundir" ] && [ -f "$rundir/agents.md" ]; then
|
||||
echo
|
||||
cat "$rundir/agents.md"
|
||||
fi
|
||||
Reference in New Issue
Block a user