tmuxclihook 0.3.0 → 0.3.1

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tmuxclihook",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "交互式 TUI 安装器:环境侦测、AI CLI 侦测、tmux-ai-status hooks 装/卸/修、TPM 软链校验",
5
5
  "type": "module",
6
6
  "bin": {
@@ -122,7 +122,7 @@ build_all_status() {
122
122
  cur_sess=""
123
123
  local _ai_names
124
124
  _ai_names=$(_collect_ai_process_names)
125
- while IFS='|' read -r pane_id session_name win_idx pane_idx claude_status _attached _last cur_cmd; do
125
+ while IFS='|' read -r pane_id session_name win_idx pane_idx claude_status _attached _created _entered cur_cmd; do
126
126
  local pane_status="$claude_status"
127
127
  if [ -z "$pane_status" ]; then
128
128
  # 无显式状态:若前台是 AI 进程(codex 首个 turn 前空窗期),补 idle。
@@ -153,7 +153,12 @@ build_all_status() {
153
153
  else
154
154
  ALL="${ALL}${seg}"
155
155
  fi
156
- done < <(tmux list-panes -a -F "#{pane_id}|#{session_name}|#{window_index}|#{pane_index}|#{@ai_pane_status}|#{session_attached}|#{session_last_attached}|#{pane_current_command}" 2>/dev/null | awk -F'|' '$6>0' | sort -t'|' -k7,7n -k2,2 -k3,3n -k4,4n)
156
+ # 排序两级键:① @ai_entered_time(client-session-changed 时由 _session-switched
157
+ # 写入的「真进入」时间,刚进入的 session 排最后;attach 与 switch-client 都触发,
158
+ # 自指 switch 由 handler 的 per-client prev 对比滤除)
159
+ # ② session_created(无进入记录时回退创建序)。不用 session_last_attached——
160
+ # tmux 的 server_client_set_session 无条件刷新该时间戳(自指 switch 也算),污染排序。
161
+ 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)
157
162
  }
158
163
 
159
164
  # --- Pending 集合管理(PreToolUse / PermissionRequest 配对)---
@@ -39,6 +39,14 @@ _current_pane_status() {
39
39
  tmux display-message -pt "$TMUX_PANE" -p "#{@ai_pane_status}" 2>/dev/null
40
40
  }
41
41
 
42
+ # 重建聚合状态(_refresh / _entered 共用)
43
+ _run_refresh() {
44
+ _maybe_repair_hooks
45
+ _cleanup_stale_panes
46
+ build_all_status
47
+ tmux set-option -g @ai_all_status "$ALL" 2>/dev/null || true
48
+ }
49
+
42
50
  # 事件块日志变量(各 case 分支按需赋值,脚本末尾统一出块)
43
51
  PREV_STATUS=$(_current_pane_status)
44
52
  TOOL=""
@@ -191,16 +199,32 @@ case "$EVENT" in
191
199
  fi
192
200
  ;;
193
201
  _refresh)
194
- _maybe_repair_hooks
195
- _cleanup_stale_panes
196
- build_all_status
197
- tmux set-option -g @ai_all_status "$ALL" 2>/dev/null || true
202
+ _run_refresh
198
203
  # 诊断日志:记录 pane 状态快照(纯文本,去掉 tmux 格式码)
199
204
  _refresh_snapshot=$(tmux list-panes -a -F "#{session_name}:#{window_index}.#{pane_index}=#{@ai_pane_status}|#{session_attached}" 2>/dev/null \
200
205
  | awk -F'|' '$2+0>0' | cut -d'|' -f1 | tr '\n' ' ')
201
206
  _ai_log "REFRESH: ${_refresh_snapshot:-<empty>}"
202
207
  exit 0
203
208
  ;;
209
+ _session-switched)
210
+ # client-session-changed hook(入口传 #{hook_client_name}):attach 与 switch-client
211
+ # 的共同汇聚点(tmux server_client_set_session),两种「进入」都能捕获。
212
+ # 该 hook 自指 switch 也触发(源码无 old != s 守卫)→ 用 per-client 自维护的
213
+ # 上次 session 对比过滤:cur != prev 才算「真进入」,自指(cur == prev)跳过。
214
+ # 排序语义:刚进入的 session 排最后;无记录的 session 回退 session_created。
215
+ if [ -n "$3" ]; then
216
+ _sw_key=$(printf '%s' "$3" | tr -c 'A-Za-z0-9._-' '_')
217
+ _cur_sess=$(tmux display-message -p -c "$3" '#{session_name}' 2>/dev/null)
218
+ _prev_sess=$(tmux show-option -gv "@ai_prev_sess_${_sw_key}" 2>/dev/null || true)
219
+ if [ -n "$_cur_sess" ] && [ "$_cur_sess" != "$_prev_sess" ]; then
220
+ tmux set-option -g "@ai_prev_sess_${_sw_key}" "$_cur_sess" 2>/dev/null || true
221
+ tmux set-option -t "$_cur_sess" @ai_entered_time "$(date +%s)" 2>/dev/null || true
222
+ _ai_log "ENTERED: client=$3 session=$_cur_sess"
223
+ fi
224
+ fi
225
+ _run_refresh
226
+ exit 0
227
+ ;;
204
228
  *)
205
229
  exit 0
206
230
  ;;
@@ -70,11 +70,14 @@ fi
70
70
  # --- 注册 tmux session/client 变化 hook,刷新聚合状态 ---
71
71
  # session-closed: session 被销毁时清除残留条目
72
72
  # client-detached: client 断开连接时排除已变为 detached 的 session
73
- # client-attached: client 重新连接时恢复该 session 的状态
73
+ # client-session-changed: attach 与 switch-client 的共同汇聚点 = 「进入」→ 记
74
+ # @ai_entered_time(排序用:刚进入的 session 排最后;handler 内以 per-client
75
+ # 上次 session 对比过滤自指 switch)+ 刷新聚合
74
76
  # 注:_refresh 与 TOOL_ID 无关(仅重建聚合 + 自修复 claude hooks),统一传 claude。
75
77
  tmux set-hook -g session-closed "run-shell '${CURRENT_DIR}/scripts/tmux-ai-status claude _refresh'"
76
78
  tmux set-hook -g client-detached "run-shell '${CURRENT_DIR}/scripts/tmux-ai-status claude _refresh'"
77
- tmux set-hook -g client-attached "run-shell '${CURRENT_DIR}/scripts/tmux-ai-status claude _refresh'"
79
+ tmux set-hook -g client-session-changed "run-shell '${CURRENT_DIR}/scripts/tmux-ai-status claude _session-switched #{hook_client_name}'" 2>/dev/null || true
80
+ # (client-attached 不再注册:attach 场景由 client-session-changed 覆盖)
78
81
  # pane-exited: 程序自然退出 → 触发孤儿清理(#{pane_id} 在此 hook 中不可靠)
79
82
  tmux set-hook -g pane-exited "run-shell '${CURRENT_DIR}/scripts/tmux-ai-status claude _refresh'"
80
83
  # after-kill-pane: kill-pane 后触发孤儿清理