What:新增 tools/jsc-wrap.sh 包裝啟動器與 tools/scan-logs.sh 離線日誌回填腳本。 Why:copilot、antigravity 沒有 hook 系統,計時與技能用量原本完全缺漏,需要 hook 之外的落地方案。 How:jsc-wrap.sh 匯出 JSC_CLI 與 JSC_SESSION_ID,啟動前後各呼叫一次 session-timer.sh,結束時自動執行 scan-logs.sh 並原樣傳遞子行程退出碼;scan-logs.sh 解析 copilot、antigravity、codex 的原生日誌,把技能用量與階段界線補進 $JSC_HOME,重掃不產生重複記錄。 Who:無 hook 系統的 CLI(copilot、antigravity)與僅有 notify 的 codex,資料供 jsc-log:worklog 與 jsc-log:stats 使用。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
92 lines
3.8 KiB
Bash
Executable File
92 lines
3.8 KiB
Bash
Executable File
#!/usr/bin/env sh
|
||
# scan-logs.sh — 離線回填:解析各 CLI 的原生日誌,把可辨識的技能使用與工作階段界線
|
||
# 補進 $JSC_HOME/usage/skills.jsonl(與 skill-usage.sh 同一種紀錄格式)與 $JSC_HOME/sessions/。
|
||
# 用法: scan-logs.sh --cli {name} [--session {sid}]
|
||
# 支援: copilot(~/.config/copilot/)、antigravity(全域日誌目錄)、codex(~/.codex/sessions/、~/.codex/log/)。
|
||
# 去重: 以 $JSC_HOME/usage/scan-state/ 記住每個日誌檔已掃描的位元組數,重掃只讀新增段落。
|
||
HERE=$(cd "$(dirname "$0")" && pwd); . "$HERE/../hooks/lib.sh"
|
||
|
||
cli=""; sid=""
|
||
while [ $# -gt 0 ]; do
|
||
case "$1" in
|
||
--cli) cli="${2:-}"; shift; shift ;;
|
||
--session) sid="${2:-}"; shift; shift ;;
|
||
*) shift ;;
|
||
esac
|
||
done
|
||
if [ -z "$cli" ]; then
|
||
echo "用法:scan-logs.sh --cli {name} [--session {sid}]" >&2
|
||
exit 2
|
||
fi
|
||
|
||
STATE="$JSC_HOME/usage/scan-state"
|
||
mkdir -p "$STATE" 2>/dev/null || true
|
||
|
||
# 檔案修改時間(epoch),取不到就用現在
|
||
mtime_epoch() {
|
||
stat -c %Y "$1" 2>/dev/null || date -r "$1" +%s 2>/dev/null || now_epoch
|
||
}
|
||
|
||
# 回填工作階段界線:start 只補缺,end 取較新值(不覆蓋較新的即時紀錄)
|
||
record_session() { # $1=sid $2=epoch
|
||
[ -f "$JSC_HOME/sessions/$1.start" ] || echo "$2" > "$JSC_HOME/sessions/$1.start"
|
||
old=$(cat "$JSC_HOME/sessions/$1.end" 2>/dev/null || echo 0)
|
||
if [ "$2" -gt "$old" ] 2>/dev/null; then echo "$2" > "$JSC_HOME/sessions/$1.end"; fi
|
||
}
|
||
|
||
# 印出日誌檔自上次掃描後的新增內容,並更新位移(位移即去重機制)
|
||
new_content() { # $1=file
|
||
key=$(printf '%s' "$1" | cksum | tr ' \t' '--')
|
||
off_f="$STATE/$cli-$key.offset"
|
||
off=$(cat "$off_f" 2>/dev/null || echo 0)
|
||
size=$(wc -c < "$1" 2>/dev/null || echo 0)
|
||
[ "$size" -gt "$off" ] 2>/dev/null || return 0
|
||
tail -c +"$((off + 1))" "$1" 2>/dev/null
|
||
echo "$size" > "$off_f"
|
||
}
|
||
|
||
# 從新增內容萃取 jsc 技能代號,逐筆追加(同一批先去重;格式與 skill-usage.sh 完全相同)
|
||
append_skills() { # stdin=內容 $1=sid
|
||
grep -oE 'jsc-[a-z]+:[a-z0-9][a-z0-9-]*' 2>/dev/null | sort -u | while IFS= read -r sk; do
|
||
printf '{"ts":"%s","cli":"%s","session":"%s","skill":"%s"}\n' \
|
||
"$(now_iso)" "$cli" "$1" "$sk" >> "$JSC_HOME/usage/skills.jsonl"
|
||
done
|
||
}
|
||
|
||
# 掃描一個日誌目錄;$2=預設 sid(空字串時用檔名當 sid);$3=sessions 時回填階段界線
|
||
scan_dir() {
|
||
find "$1" -maxdepth 3 -type f \( -name '*.json' -o -name '*.jsonl' -o -name '*.log' \) 2>/dev/null \
|
||
| while IFS= read -r f; do
|
||
s="$2"
|
||
[ -n "$s" ] || s="$cli-$(basename "$f" | sed 's/\.[^.]*$//')"
|
||
[ "${3:-}" = "sessions" ] && record_session "$s" "$(mtime_epoch "$f")"
|
||
new_content "$f" | append_skills "$s"
|
||
done
|
||
return 0
|
||
}
|
||
|
||
case "$cli" in
|
||
copilot)
|
||
d="$HOME/.config/copilot"
|
||
if [ ! -d "$d" ]; then echo "[jsc] 找不到 copilot 日誌目錄($d),略過回填。"; exit 0; fi
|
||
[ -d "$d/history-session-state" ] && scan_dir "$d/history-session-state" "$sid" sessions
|
||
[ -d "$d/history" ] && scan_dir "$d/history" "$sid" sessions
|
||
[ -d "$d/logs" ] && scan_dir "$d/logs" "$sid" logs ;;
|
||
antigravity)
|
||
found=""
|
||
for d in "$HOME/.antigravity/logs" "$HOME/.config/antigravity/logs" "$HOME/.antigravity"; do
|
||
if [ -d "$d" ]; then found=1; scan_dir "$d" "$sid" sessions; break; fi
|
||
done
|
||
if [ -z "$found" ]; then echo "[jsc] 找不到 antigravity 日誌目錄,略過回填。"; exit 0; fi ;;
|
||
codex)
|
||
d1="$HOME/.codex/sessions"; d2="$HOME/.codex/log"
|
||
if [ ! -d "$d1" ] && [ ! -d "$d2" ]; then
|
||
echo "[jsc] 找不到 codex 日誌目錄($d1、$d2),略過回填。"; exit 0
|
||
fi
|
||
[ -d "$d1" ] && scan_dir "$d1" "$sid" sessions
|
||
[ -d "$d2" ] && scan_dir "$d2" "$sid" logs ;;
|
||
*)
|
||
echo "[jsc] 尚未支援 $cli 的日誌回填,略過。" ;;
|
||
esac
|
||
exit 0
|