Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
52 lines
2.1 KiB
Bash
Executable File
52 lines
2.1 KiB
Bash
Executable File
#!/usr/bin/env sh
|
||
# lib.sh — jsc hooks 共用函式。所有 hook 腳本 source 此檔。
|
||
# 輸入相容:Claude 式 stdin JSON、或環境變數(codex/copilot/antigravity/kiro 接線時設定)。
|
||
# 缺資料時安靜降級,hook 預設 exit 0,不可中斷宿主 CLI。
|
||
# 唯一例外:sdlc-gate.sh check 在「SDLC 階段鎖存在且模型不符」時會 exit 2 擋下該輪提示;
|
||
# 其餘情況(無鎖、資料不足無法判定)仍照舊 exit 0。
|
||
|
||
JSC_HOME="${JSC_HOME:-$HOME/.jsc}"
|
||
mkdir -p "$JSC_HOME/sessions" "$JSC_HOME/usage" 2>/dev/null || true
|
||
|
||
# 讀完 stdin(可能為空;非阻塞宿主)
|
||
read_stdin() {
|
||
if [ -t 0 ]; then STDIN_JSON=""; else STDIN_JSON=$(cat 2>/dev/null || true); fi
|
||
}
|
||
|
||
# 從 stdin JSON 取字串欄位(naive 但足夠應付各 CLI 的扁平 payload)
|
||
json_str() { # $1=欄位名
|
||
printf '%s' "$STDIN_JSON" | tr -d '\n' \
|
||
| sed -n "s/.*\"$1\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\".*/\1/p" | head -n1
|
||
}
|
||
|
||
# 目前 session id:stdin JSON > 環境變數 > 固定值
|
||
session_id() {
|
||
sid=$(json_str session_id)
|
||
[ -n "$sid" ] || sid="${JSC_SESSION_ID:-${CLAUDE_SESSION_ID:-default}}"
|
||
printf '%s' "$sid"
|
||
}
|
||
|
||
# 目前實際使用的模型 id:讀 transcript 最後一筆帶 model 的訊息。
|
||
# 這是 shell 唯一能「驗證」的模型來源——模型自我回報無法驗證,等同沒有閘門。
|
||
# 取不到(無 transcript_path、檔案不存在、尚無 assistant 訊息)時不輸出,由呼叫端決定如何降級。
|
||
transcript_model() {
|
||
tp=$(json_str transcript_path)
|
||
[ -n "$tp" ] && [ -f "$tp" ] || return 0
|
||
# 只掃尾端若干行即可命中最近一輪;`<...>` 這類佔位模型名(例如 <synthetic>)排除。
|
||
tail -n 500 "$tp" 2>/dev/null \
|
||
| grep -o '"model":"[^"]*"' \
|
||
| sed 's/^"model":"//; s/"$//' \
|
||
| grep -v '^<' \
|
||
| tail -n 1
|
||
}
|
||
|
||
# 目前 CLI 名稱:環境變數 > 依 stdin 特徵猜測 > unknown
|
||
cli_name() {
|
||
if [ -n "${JSC_CLI:-}" ]; then printf '%s' "$JSC_CLI"
|
||
elif [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then printf 'claude'
|
||
else printf 'unknown'; fi
|
||
}
|
||
|
||
now_epoch() { date +%s; }
|
||
now_iso() { date -u +%Y-%m-%dT%H:%M:%SZ; }
|