tmuxclihook 0.3.6 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -112,6 +112,52 @@ _clear_pane_id() {
|
|
|
112
112
|
[ -n "$SESSION_ID" ] && rm -f "$(_pane_dir)/pane-${SESSION_ID}"
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
# --- cc-switch provider 标签 ---
|
|
116
|
+
# cc-switch(switch 命令)launch 时向 CLI 注入 CC_SWITCH_PROVIDER / CC_SWITCH_PROVIDER_ID,
|
|
117
|
+
# CLI 的 hooks 进程继承之;tmux-ai-status 入口把它们捕获进 pane option
|
|
118
|
+
# @ai_provider / @ai_provider_id。聚合侧在此读取并渲染彩色 provider 段。
|
|
119
|
+
# 颜色真源:~/.cc-switch/statusline-preferences.json(colors.claude / colors.codex
|
|
120
|
+
# 按 providerId 分桶)——与 cc-switch wrapper 状态栏标签同一真源,TUI `o` 改色
|
|
121
|
+
# 下一次 rebuild 即生效。显式值是 ANSI SGI 码(30-37/90-97),映射 tmux colourN
|
|
122
|
+
# (30-37 → 0-7,90-97 → 8-15);缺省 auto = FNV-1a(name)落在 cc-switch wrapper
|
|
123
|
+
# 同款 6 色 bright 调色板上。JS Math.imul 是 32 位截断乘;64 位精确积 & 0xFFFFFFFF
|
|
124
|
+
# 与之同余,纯 bash 可复刻(非 ASCII 名按字节遍历,与 JS 码点遍历 hash 可能不同,
|
|
125
|
+
# 只影响 auto 落点,非错误)。
|
|
126
|
+
_PROVIDER_PREFS_LINES=""
|
|
127
|
+
_PROVIDER_PREFS_LOADED=""
|
|
128
|
+
_provider_prefs_lines() {
|
|
129
|
+
if [ -z "$_PROVIDER_PREFS_LINES" ] && [ -z "$_PROVIDER_PREFS_LOADED" ]; then
|
|
130
|
+
_PROVIDER_PREFS_LOADED=1
|
|
131
|
+
local f="${HOME}/.cc-switch/statusline-preferences.json"
|
|
132
|
+
if [ -f "$f" ]; then
|
|
133
|
+
# claude/codex 两桶浅合并:providerId 是 uuid,跨桶不冲突
|
|
134
|
+
_PROVIDER_PREFS_LINES=$(jq -r '((.colors.claude // {}) + (.colors.codex // {})) | to_entries[] | "\(.key)=\(.value)"' "$f" 2>/dev/null)
|
|
135
|
+
fi
|
|
136
|
+
fi
|
|
137
|
+
printf '%s' "$_PROVIDER_PREFS_LINES"
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
_provider_tag_colour() {
|
|
141
|
+
local id="$1" name="$2" v=""
|
|
142
|
+
if [ -n "$id" ]; then
|
|
143
|
+
v=$(printf '%s\n' "$(_provider_prefs_lines)" | awk -F= -v id="$id" '$1==id{print $2; exit}')
|
|
144
|
+
fi
|
|
145
|
+
case "$v" in
|
|
146
|
+
3[0-7]) echo $(( v - 30 )); return ;;
|
|
147
|
+
9[0-7]) echo $(( v - 82 )); return ;;
|
|
148
|
+
esac
|
|
149
|
+
# auto: FNV-1a 32 位
|
|
150
|
+
local hash=2166136261 i ch cp
|
|
151
|
+
for ((i=0; i<${#name}; i++)); do
|
|
152
|
+
ch="${name:$i:1}"
|
|
153
|
+
printf -v cp '%d' "'$ch"
|
|
154
|
+
hash=$(( (hash ^ cp) * 16777619 & 4294967295 ))
|
|
155
|
+
done
|
|
156
|
+
case $(( hash % 6 )) in
|
|
157
|
+
0) echo 96 ;; 1) echo 92 ;; 2) echo 93 ;; 3) echo 95 ;; 4) echo 94 ;; 5) echo 91 ;;
|
|
158
|
+
esac
|
|
159
|
+
}
|
|
160
|
+
|
|
115
161
|
# --- 状态聚合 ---
|
|
116
162
|
# 扫描所有 attached session 的 pane,读取 @ai_pane_status,写入 @ai_all_status
|
|
117
163
|
#
|
|
@@ -124,7 +170,7 @@ build_all_status() {
|
|
|
124
170
|
cur_sess=""
|
|
125
171
|
local _ai_names
|
|
126
172
|
_ai_names=$(_collect_ai_process_names)
|
|
127
|
-
while IFS='|' read -r pane_id session_name win_idx pane_idx claude_status _attached _created _entered cur_cmd; do
|
|
173
|
+
while IFS='|' read -r pane_id session_name win_idx pane_idx claude_status _attached _created _entered cur_cmd prov_name prov_id; do
|
|
128
174
|
local pane_status="$claude_status"
|
|
129
175
|
if [ -z "$pane_status" ]; then
|
|
130
176
|
# 无显式状态:若前台是 AI 进程(codex 首个 turn 前空窗期),补 idle。
|
|
@@ -149,6 +195,12 @@ build_all_status() {
|
|
|
149
195
|
status_block="#[bg=${STATUS_COLOR},fg=#282A36] ${pane_status} #[bg=default,fg=default]"
|
|
150
196
|
fi
|
|
151
197
|
local seg="${panel_block}${status_block}"
|
|
198
|
+
# cc-switch provider 段:有 @ai_provider 才显示(非 switch 启动的 pane 无此 option)
|
|
199
|
+
if [ -n "$prov_name" ]; then
|
|
200
|
+
local prov_colour
|
|
201
|
+
prov_colour=$(_provider_tag_colour "$prov_id" "$prov_name")
|
|
202
|
+
seg="${seg}#[fg=colour${prov_colour}][${prov_name}] #[fg=default]"
|
|
203
|
+
fi
|
|
152
204
|
if [ "$session_name" != "$cur_sess" ]; then
|
|
153
205
|
ALL="${ALL:+$ALL }${session_block}${seg}"
|
|
154
206
|
cur_sess="$session_name"
|
|
@@ -160,7 +212,7 @@ build_all_status() {
|
|
|
160
212
|
# 自指 switch 由 handler 的 per-client prev 对比滤除)
|
|
161
213
|
# ② session_created(无进入记录时回退创建序)。不用 session_last_attached——
|
|
162
214
|
# tmux 的 server_client_set_session 无条件刷新该时间戳(自指 switch 也算),污染排序。
|
|
163
|
-
done < <(tmux list-panes -a -F "#{pane_id}|#{session_name}|#{window_index}|#{pane_index}|#{@ai_pane_status}|#{session_attached}|#{session_created}|#{@ai_entered_time}|#{pane_current_command}" 2>/dev/null | awk -F'|' -v OFS='|' '$6>0{if($8=="")$8=$7; print}' | sort -t'|' -k8,8n -k7,7n -k2,2 -k3,3n -k4,4n)
|
|
215
|
+
done < <(tmux list-panes -a -F "#{pane_id}|#{session_name}|#{window_index}|#{pane_index}|#{@ai_pane_status}|#{session_attached}|#{session_created}|#{@ai_entered_time}|#{pane_current_command}|#{@ai_provider}|#{@ai_provider_id}" 2>/dev/null | awk -F'|' -v OFS='|' '$6>0{if($8=="")$8=$7; print}' | sort -t'|' -k8,8n -k7,7n -k2,2 -k3,3n -k4,4n)
|
|
164
216
|
}
|
|
165
217
|
|
|
166
218
|
# --- Pending 集合管理(PreToolUse / PermissionRequest 配对)---
|
package/scripts/tmux-ai-status
CHANGED
|
@@ -28,6 +28,22 @@ fi
|
|
|
28
28
|
_save_pane_id
|
|
29
29
|
_maybe_cleanup_stale
|
|
30
30
|
|
|
31
|
+
# cc-switch 注入的 provider 标签(launch env,CLI 的 hooks 进程继承)→
|
|
32
|
+
# per-pane option,供 build_all_status 聚合渲染。env 随 CLI 进程定死,幂等
|
|
33
|
+
# 重写无害;非 switch 启动(env 缺失)时显式清除残留,避免换 AI 进程后 pane
|
|
34
|
+
# 显示上一个 provider。
|
|
35
|
+
if [ -n "$TMUX_PANE" ]; then
|
|
36
|
+
if [ -n "$CC_SWITCH_PROVIDER" ]; then
|
|
37
|
+
tmux set-option -pt "$TMUX_PANE" @ai_provider "$CC_SWITCH_PROVIDER" 2>/dev/null || true
|
|
38
|
+
if [ -n "$CC_SWITCH_PROVIDER_ID" ]; then
|
|
39
|
+
tmux set-option -pt "$TMUX_PANE" @ai_provider_id "$CC_SWITCH_PROVIDER_ID" 2>/dev/null || true
|
|
40
|
+
fi
|
|
41
|
+
else
|
|
42
|
+
tmux set-option -pt "$TMUX_PANE" -u @ai_provider 2>/dev/null || true
|
|
43
|
+
tmux set-option -pt "$TMUX_PANE" -u @ai_provider_id 2>/dev/null || true
|
|
44
|
+
fi
|
|
45
|
+
fi
|
|
46
|
+
|
|
31
47
|
_pane_loc=""
|
|
32
48
|
if [ -n "$TMUX_PANE" ]; then
|
|
33
49
|
_pane_loc=$(tmux display-message -pt "$TMUX_PANE" -p "#{session_name}:#{window_index}.#{pane_index}" 2>/dev/null)
|
|
@@ -211,7 +227,8 @@ case "$EVENT" in
|
|
|
211
227
|
exit 0
|
|
212
228
|
;;
|
|
213
229
|
_session-switched)
|
|
214
|
-
# client-session-changed hook(入口传 #{
|
|
230
|
+
# client-session-changed hook(入口传 #{hook_client},3.7c/3.8 均为触发
|
|
231
|
+
# client 名;注意不存在 #{hook_client_name} 变量,误用恒为空):attach 与 switch-client
|
|
215
232
|
# 的共同汇聚点(tmux server_client_set_session),两种「进入」都能捕获。
|
|
216
233
|
# 该 hook 自指 switch 也触发(源码无 old != s 守卫)→ 用 per-client 自维护的
|
|
217
234
|
# 上次 session 对比过滤:cur != prev 才算「真进入」,自指(cur == prev)跳过。
|
|
@@ -75,7 +75,10 @@ fi
|
|
|
75
75
|
# client-session-changed: attach 与 switch-client 的共同汇聚点 = 「进入」→ 记
|
|
76
76
|
# @ai_entered_time(排序用:刚进入的 session 排最后;handler 内以 per-client
|
|
77
77
|
# 上次 session 对比过滤自指 switch)+ 刷新聚合
|
|
78
|
-
|
|
78
|
+
# 变量必须用 #{hook_client}(3.7c/3.8 均展开为触发 client 名)。不存在
|
|
79
|
+
# #{hook_client_name} 这个 format 变量——误用它恒展开为空,handler 的
|
|
80
|
+
# [ -n "$3" ] 守卫静默跳过,entered_time 从不写入,排序退化为 created 序。
|
|
81
|
+
tmux set-hook -g client-session-changed "run-shell '${CURRENT_DIR}/scripts/tmux-ai-status claude _session-switched #{hook_client}'" 2>/dev/null || true
|
|
79
82
|
# 注:_refresh 与 TOOL_ID 无关(仅重建聚合 + 自修复 claude hooks),统一传 claude。
|
|
80
83
|
tmux set-hook -g session-closed "run-shell '${CURRENT_DIR}/scripts/tmux-ai-status claude _refresh'"
|
|
81
84
|
tmux set-hook -g client-detached "run-shell '${CURRENT_DIR}/scripts/tmux-ai-status claude _refresh'"
|