tmuxclihook 0.3.0 → 0.3.2
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/README.md +4 -0
- package/bin/cli.js +15 -2
- package/package.json +1 -1
- package/scripts/lib-tmux-ai-status.sh +7 -2
- package/scripts/tmux-ai-status +28 -4
- package/tmux-ai-hooks-status.tmux +5 -2
package/README.md
CHANGED
package/bin/cli.js
CHANGED
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
} from '../src/adapters-meta.js';
|
|
28
28
|
import { setSource, clearSource, getPersistedSource, originLabel } from '../src/source.js';
|
|
29
29
|
import { note, padDisplay } from '../src/tui.js';
|
|
30
|
-
import { updatePackage } from '../src/update.js';
|
|
30
|
+
import { updatePackage, CURRENT_VERSION } from '../src/update.js';
|
|
31
31
|
|
|
32
32
|
const OK = '✓';
|
|
33
33
|
const NO = '✗';
|
|
@@ -365,13 +365,26 @@ async function main() {
|
|
|
365
365
|
p.outro('完成');
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
-
|
|
368
|
+
const arg = process.argv[2];
|
|
369
|
+
if (arg === 'update') {
|
|
369
370
|
updatePackage().then((ok) => {
|
|
370
371
|
if (!ok) process.exitCode = 1;
|
|
371
372
|
}).catch((err) => {
|
|
372
373
|
console.error(err);
|
|
373
374
|
process.exitCode = 1;
|
|
374
375
|
});
|
|
376
|
+
} else if (arg === '--version' || arg === '-v' || arg === 'version') {
|
|
377
|
+
console.log(`tmuxclihook v${CURRENT_VERSION}`);
|
|
378
|
+
} else if (arg === '--help' || arg === '-h' || arg === 'help') {
|
|
379
|
+
console.log(
|
|
380
|
+
'tmuxclihook — tmux-ai-status 交互式安装器\n' +
|
|
381
|
+
'\n' +
|
|
382
|
+
'用法:\n' +
|
|
383
|
+
' tmuxclihook 打开交互式 TUI 安装器\n' +
|
|
384
|
+
' tmuxclihook update 检查并更新到 npm 最新版本\n' +
|
|
385
|
+
' tmuxclihook version 显示版本(--version / -v 等价)\n' +
|
|
386
|
+
' tmuxclihook help 显示本帮助(--help / -h 等价)',
|
|
387
|
+
);
|
|
375
388
|
} else {
|
|
376
389
|
main().catch((err) => {
|
|
377
390
|
console.error(err);
|
package/package.json
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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 配对)---
|
package/scripts/tmux-ai-status
CHANGED
|
@@ -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
|
-
|
|
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-
|
|
73
|
+
# client-session-changed: attach 与 switch-client 的共同汇聚点 = 「进入」→ 记
|
|
74
|
+
# @ai_entered_time(排序用:刚进入的 session 排最后;handler 内以 per-client
|
|
75
|
+
# 上次 session 对比过滤自指 switch)+ 刷新聚合
|
|
76
|
+
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
|
|
74
77
|
# 注:_refresh 与 TOOL_ID 无关(仅重建聚合 + 自修复 claude hooks),统一传 claude。
|
|
75
78
|
tmux set-hook -g session-closed "run-shell '${CURRENT_DIR}/scripts/tmux-ai-status claude _refresh'"
|
|
76
79
|
tmux set-hook -g client-detached "run-shell '${CURRENT_DIR}/scripts/tmux-ai-status claude _refresh'"
|
|
77
|
-
|
|
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 后触发孤儿清理
|