tmuxclihook 0.3.3 → 0.3.4
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 +1 -1
- package/scripts/adapters/claude.sh +35 -15
- package/scripts/adapters/codex.sh +36 -6
- package/scripts/adapters/opencode.sh +13 -2
- package/scripts/install-claude-hooks.sh +28 -13
- package/scripts/install-codex-hooks.sh +22 -7
- package/scripts/install-opencode-hooks.sh +22 -7
- package/scripts/lib-install-hooks.sh +13 -0
- package/scripts/lib-tmux-ai-status.sh +6 -0
- package/scripts/tmux-ai-status +6 -2
- package/src/adapters-meta.js +6 -0
- package/src/detect.js +4 -3
- package/tmux-ai-hooks-status.tmux +3 -1
package/package.json
CHANGED
|
@@ -72,10 +72,7 @@ _CLAUDE_JQ_MERGE='
|
|
|
72
72
|
.hooks[]
|
|
73
73
|
| select(.command | contains("tmux-powerline-claude-status") | not)
|
|
74
74
|
| select(.command | contains("tmux-claude-status") | not)
|
|
75
|
-
| select(
|
|
76
|
-
(.command | contains("tmux-ai-status") | not)
|
|
77
|
-
or (.command | startswith($dev_script))
|
|
78
|
-
)
|
|
75
|
+
| select(.command | contains("tmux-ai-status") | not)
|
|
79
76
|
]
|
|
80
77
|
| select(.hooks | length > 0)
|
|
81
78
|
)
|
|
@@ -98,7 +95,7 @@ _CLAUDE_JQ_STRIP='
|
|
|
98
95
|
.hooks |= if . then
|
|
99
96
|
[. | to_entries[] |
|
|
100
97
|
.value |= [
|
|
101
|
-
.[] | .hooks = [.hooks[] | select(.command |
|
|
98
|
+
.[] | .hooks = [.hooks[] | select(.command | contains("tmux-ai-status") | not)]
|
|
102
99
|
| select(.hooks | length > 0)
|
|
103
100
|
]
|
|
104
101
|
| select(.value | length > 0)
|
|
@@ -107,13 +104,12 @@ _CLAUDE_JQ_STRIP='
|
|
|
107
104
|
'
|
|
108
105
|
|
|
109
106
|
_claude_apply_merge() { # $1=输入 JSON 文件 → stdout 变换后全文档
|
|
110
|
-
jq --arg
|
|
111
|
-
--arg tool_cmd "${_LIB_DIR}/tmux-ai-status claude" \
|
|
107
|
+
jq --arg tool_cmd "${_LIB_DIR}/tmux-ai-status claude" \
|
|
112
108
|
"$_CLAUDE_JQ_MERGE" "$1"
|
|
113
109
|
}
|
|
114
110
|
|
|
115
111
|
_claude_apply_strip() { # $1=输入 JSON 文件 → stdout 变换后全文档
|
|
116
|
-
jq
|
|
112
|
+
jq "$_CLAUDE_JQ_STRIP" "$1"
|
|
117
113
|
}
|
|
118
114
|
|
|
119
115
|
_claude_count_registered() { # $1=输入 JSON 文件 → stdout 事件数(jq 失败时为空)
|
|
@@ -187,18 +183,41 @@ ON CONFLICT(key) DO UPDATE SET value = json_patch(settings.value, json($(_sqlquo
|
|
|
187
183
|
}
|
|
188
184
|
|
|
189
185
|
# 完整性检查:cc-switch 模式查通用配置;否则查 hooks 配置文件。
|
|
190
|
-
# 10
|
|
186
|
+
# 三要素:10 事件计数 + 每个事件至少一条条目的脚本文件存活(test -x)。
|
|
187
|
+
# 计数齐但脚本死(npm 包卸载/volta 升级换路径,含部分事件死)→ missing → 自修复重装收敛。
|
|
188
|
+
# 存活提取内联在本函数(jq + test),不依赖 lib-install-hooks.sh——本函数同时被
|
|
189
|
+
# 事件路径(lib-tmux-ai-status.sh)与 install wrapper(lib-install-hooks.sh)两个上下文调用。
|
|
191
190
|
adapter_check_integrity() {
|
|
192
|
-
local registered
|
|
191
|
+
local src registered ev p ok_events=""
|
|
193
192
|
if _ccswitch_active; then
|
|
194
|
-
_ccswitch_dump_common
|
|
195
|
-
registered=$(_claude_count_registered "$tmp")
|
|
196
|
-
rm -f "$tmp"
|
|
193
|
+
_ccswitch_dump_common src || return 1
|
|
197
194
|
else
|
|
198
195
|
[ -f "$ADAPTER_HOOKS_FILE" ] || return 1
|
|
199
|
-
|
|
196
|
+
src="$ADAPTER_HOOKS_FILE"
|
|
197
|
+
fi
|
|
198
|
+
registered=$(_claude_count_registered "$src")
|
|
199
|
+
if [ "${registered:-0}" -ge 10 ]; then
|
|
200
|
+
while IFS=$'\t' read -r ev p; do
|
|
201
|
+
if [ -n "$ev" ] && [ -x "$p" ]; then
|
|
202
|
+
case ",$ok_events," in *",$ev,"*) ;; *) ok_events="$ok_events,$ev" ;; esac
|
|
203
|
+
fi
|
|
204
|
+
done < <(jq -r '.hooks as $h |
|
|
205
|
+
["SessionStart","SessionEnd","UserPromptSubmit","PreToolUse","PostToolUse",
|
|
206
|
+
"PostToolUseFailure","PermissionRequest","Notification","Stop","StopFailure"] as $events |
|
|
207
|
+
$events[] as $e |
|
|
208
|
+
[$h[$e][]?.hooks[]?.command // empty
|
|
209
|
+
| select(contains("tmux-ai-status")) | split(" ")[0]] as $scripts |
|
|
210
|
+
select(($scripts | length) > 0) |
|
|
211
|
+
$scripts[] | "\($e)\t\(.)"' "$src" 2>/dev/null)
|
|
200
212
|
fi
|
|
201
|
-
[ "$
|
|
213
|
+
if [ "$src" != "$ADAPTER_HOOKS_FILE" ]; then
|
|
214
|
+
rm -f "$src"
|
|
215
|
+
fi
|
|
216
|
+
[ "${registered:-0}" -ge 10 ] || return 1
|
|
217
|
+
for ev in SessionStart SessionEnd UserPromptSubmit PreToolUse PostToolUse PostToolUseFailure PermissionRequest Notification Stop StopFailure; do
|
|
218
|
+
case ",$ok_events," in *",$ev,"*) ;; *) return 1 ;; esac
|
|
219
|
+
done
|
|
220
|
+
return 0
|
|
202
221
|
}
|
|
203
222
|
|
|
204
223
|
# 安装:合并式更新,保留他人(masko 等)注册的 hook。cc-switch 模式只写库
|
|
@@ -233,6 +252,7 @@ adapter_uninstall_hooks() {
|
|
|
233
252
|
_install_require_jq
|
|
234
253
|
if _ccswitch_active; then
|
|
235
254
|
local tmp stripped cur_hooks final_hooks patch managed top_patch
|
|
255
|
+
_ccswitch_warn_gui
|
|
236
256
|
_ccswitch_dump_common tmp || return 1
|
|
237
257
|
cur_hooks=$(jq -c '.hooks // {}' "$tmp")
|
|
238
258
|
# 已无本插件条目 → no-op(否则会把保留的他人 hook 重写一遍)
|
|
@@ -36,14 +36,38 @@ ADAPTER_PERMISSION_PRE_TOOL_NAMES="request_permissions"
|
|
|
36
36
|
# 自修复/TUI 调用的安装脚本
|
|
37
37
|
ADAPTER_INSTALLER="${_LIB_DIR}/install-codex-hooks.sh"
|
|
38
38
|
|
|
39
|
-
#
|
|
39
|
+
# 完整性计数:6 个事件中注册了含 tmux-ai-status codex 的 command 的事件数(按事件,
|
|
40
|
+
# 非扁平总数——重复+缺失的组合在扁平计数下会假阳性)。
|
|
41
|
+
_CODEX_JQ_COUNT='
|
|
42
|
+
.hooks as $h |
|
|
43
|
+
["SessionStart","UserPromptSubmit","PreToolUse","PermissionRequest","PostToolUse","Stop"]
|
|
44
|
+
| map(select([$h[.][]?.hooks[]?.command // empty] | any(contains("tmux-ai-status codex"))))
|
|
45
|
+
| length
|
|
46
|
+
'
|
|
47
|
+
|
|
48
|
+
# 完整性检查:6 事件计数 + 每个事件至少一条条目的脚本文件存活(test -x)。
|
|
49
|
+
# 跨安装源路径无关(contains);脚本死路径(npm 包卸载/volta 换路径,含部分事件死)
|
|
50
|
+
# → missing → install 收敛(no-op 门禁随之放行,接受一次 re-trust 代价换功能恢复)。
|
|
40
51
|
adapter_check_integrity() {
|
|
41
52
|
[ -f "$ADAPTER_HOOKS_FILE" ] || return 1
|
|
42
|
-
local n
|
|
43
|
-
n=$(jq
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
53
|
+
local n ev p ok_events=""
|
|
54
|
+
n=$(jq "$_CODEX_JQ_COUNT" "$ADAPTER_HOOKS_FILE" 2>/dev/null)
|
|
55
|
+
[ "${n:-0}" -ge 6 ] || return 1
|
|
56
|
+
while IFS=$'\t' read -r ev p; do
|
|
57
|
+
if [ -n "$ev" ] && [ -x "$p" ]; then
|
|
58
|
+
case ",$ok_events," in *",$ev,"*) ;; *) ok_events="$ok_events,$ev" ;; esac
|
|
59
|
+
fi
|
|
60
|
+
done < <(jq -r '.hooks as $h |
|
|
61
|
+
["SessionStart","UserPromptSubmit","PreToolUse","PermissionRequest","PostToolUse","Stop"] as $events |
|
|
62
|
+
$events[] as $e |
|
|
63
|
+
[$h[$e][]?.hooks[]?.command // empty
|
|
64
|
+
| select(contains("tmux-ai-status codex")) | split(" ")[0]] as $scripts |
|
|
65
|
+
select(($scripts | length) > 0) |
|
|
66
|
+
$scripts[] | "\($e)\t\(.)"' "$ADAPTER_HOOKS_FILE" 2>/dev/null)
|
|
67
|
+
for ev in SessionStart UserPromptSubmit PreToolUse PermissionRequest PostToolUse Stop; do
|
|
68
|
+
case ",$ok_events," in *",$ev,"*) ;; *) return 1 ;; esac
|
|
69
|
+
done
|
|
70
|
+
return 0
|
|
47
71
|
}
|
|
48
72
|
|
|
49
73
|
# Codex 6 事件(全部同步——0.144 静默跳过 async=true 的 hook)
|
|
@@ -73,11 +97,17 @@ _codex_read_existing() {
|
|
|
73
97
|
}
|
|
74
98
|
|
|
75
99
|
# 安装:改写 hooks.json(剥离旧 managed group 后为每事件追加本插件 group),保留他人 hook。
|
|
100
|
+
# no-op if valid:事件齐全且脚本存活时不改写——重写即 trusted_hash 失效(command 路径
|
|
101
|
+
# 变化 → codex 启动要重新 Trust all),跨安装源重复安装因此保持既有授信。
|
|
76
102
|
# 清理旧 hooks.toml(0.144 不再读取)。trust 无法在 bash 复现,靠用户首启 codex TUI 授信。
|
|
77
103
|
adapter_install_hooks() {
|
|
78
104
|
_install_require_jq
|
|
79
105
|
mkdir -p "$(dirname "$ADAPTER_HOOKS_FILE")" 2>/dev/null || true
|
|
80
106
|
[ -f "$_CODEX_LEGACY_TOML" ] && rm -f "$_CODEX_LEGACY_TOML" && echo "移除旧 hooks.toml(0.144 不再读取)"
|
|
107
|
+
if adapter_check_integrity; then
|
|
108
|
+
echo "Codex hooks already installed and valid at $ADAPTER_HOOKS_FILE (no-op, trust preserved)"
|
|
109
|
+
return 0
|
|
110
|
+
fi
|
|
81
111
|
local hook_script="${_LIB_DIR}/tmux-ai-status"
|
|
82
112
|
local new_json
|
|
83
113
|
new_json=$(_codex_read_existing | _codex_strip_managed | jq \
|
|
@@ -39,11 +39,17 @@ ADAPTER_INSTALLER="${_LIB_DIR}/install-opencode-hooks.sh"
|
|
|
39
39
|
|
|
40
40
|
_OPENCODE_MARKER="tmux-ai-status (managed by tmux-ai-hooks-status)"
|
|
41
41
|
|
|
42
|
-
# 完整性检查:plugin
|
|
42
|
+
# 完整性检查:plugin 文件存在 + 本插件标记 + 结构指纹 + HOOK_SCRIPT 指向的脚本存活。
|
|
43
|
+
# 路径无关(不比对当前 _LIB_DIR——跨安装源的合法 plugin 同样有效);
|
|
44
|
+
# 脚本死路径(npm 包卸载/换路径)→ missing → 重装收敛。
|
|
43
45
|
adapter_check_integrity() {
|
|
44
46
|
[ -f "$ADAPTER_HOOKS_FILE" ] || return 1
|
|
45
47
|
grep -q "$_OPENCODE_MARKER" "$ADAPTER_HOOKS_FILE" 2>/dev/null || return 1
|
|
46
|
-
|
|
48
|
+
local script_path
|
|
49
|
+
script_path=$(sed -n 's/^const HOOK_SCRIPT = "\(.*\)"$/\1/p' "$ADAPTER_HOOKS_FILE" 2>/dev/null | head -n 1)
|
|
50
|
+
if [ -z "$script_path" ] || [ ! -x "$script_path" ]; then
|
|
51
|
+
return 1
|
|
52
|
+
fi
|
|
47
53
|
grep -q 'case "permission.asked"' "$ADAPTER_HOOKS_FILE" 2>/dev/null || return 1
|
|
48
54
|
grep -q 'case "question.asked"' "$ADAPTER_HOOKS_FILE" 2>/dev/null || return 1
|
|
49
55
|
grep -q 'case "permission.replied"' "$ADAPTER_HOOKS_FILE" 2>/dev/null || return 1
|
|
@@ -142,7 +148,12 @@ EOF
|
|
|
142
148
|
}
|
|
143
149
|
|
|
144
150
|
# 安装:写出/覆盖 plugin 文件。整文件替换(非合并)——同目录下他人 plugin 文件不受影响。
|
|
151
|
+
# no-op if valid:文件完整且 HOOK_SCRIPT 存活时不重写(避免跨安装源无谓覆盖)。
|
|
145
152
|
adapter_install_hooks() {
|
|
153
|
+
if adapter_check_integrity; then
|
|
154
|
+
echo "opencode plugin already installed and valid at $ADAPTER_HOOKS_FILE (no-op)"
|
|
155
|
+
return 0
|
|
156
|
+
fi
|
|
146
157
|
mkdir -p "$(dirname "$ADAPTER_HOOKS_FILE")" 2>/dev/null || true
|
|
147
158
|
local hook_script="${_LIB_DIR}/tmux-ai-status"
|
|
148
159
|
local content
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# install-claude-hooks.sh — Claude Code hooks 安装/卸载/检查 wrapper
|
|
3
|
-
# 用法: install-claude-hooks.sh [uninstall|check]
|
|
3
|
+
# 用法: install-claude-hooks.sh [install|uninstall|check|auto]
|
|
4
4
|
#
|
|
5
5
|
# 薄 wrapper:source 公共骨架 + claude adapter,dispatch 到 adapter_install_hooks /
|
|
6
6
|
# adapter_uninstall_hooks。实际逻辑在 scripts/adapters/claude.sh。
|
|
7
7
|
# check:输出 ok/missing(exit 0/1),供 TUI 侦测在 cc-switch 模式下走 bash 侧
|
|
8
8
|
# 完整性判定(sqlite 真源),与非 cc-switch 的文件判定共用同一真相。
|
|
9
|
+
# auto:tmux 入口加载时的自动安装——存在卸载意图标记(suppressed-claude)时不装。
|
|
10
|
+
# 显式 uninstall 成功写标记、显式 install 成功清标记(见 lib-install-hooks.sh)。
|
|
9
11
|
|
|
10
12
|
set -o errexit
|
|
11
13
|
set -o pipefail
|
|
@@ -14,15 +16,28 @@ _LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
|
|
14
16
|
source "${_LIB_DIR}/lib-install-hooks.sh"
|
|
15
17
|
source "${_LIB_DIR}/adapters/claude.sh"
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
fi
|
|
19
|
+
case "${1:-install}" in
|
|
20
|
+
uninstall)
|
|
21
|
+
adapter_uninstall_hooks
|
|
22
|
+
_hooks_suppress_write claude
|
|
23
|
+
;;
|
|
24
|
+
check)
|
|
25
|
+
if adapter_check_integrity; then
|
|
26
|
+
echo ok
|
|
27
|
+
else
|
|
28
|
+
echo missing
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
;;
|
|
32
|
+
auto)
|
|
33
|
+
if [ -f "$(_hooks_suppress_file claude)" ]; then
|
|
34
|
+
exit 0
|
|
35
|
+
fi
|
|
36
|
+
adapter_install_hooks
|
|
37
|
+
_hooks_suppress_clear claude
|
|
38
|
+
;;
|
|
39
|
+
*)
|
|
40
|
+
adapter_install_hooks
|
|
41
|
+
_hooks_suppress_clear claude
|
|
42
|
+
;;
|
|
43
|
+
esac
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# install-codex-hooks.sh — Codex CLI hooks
|
|
3
|
-
# 用法: install-codex-hooks.sh [uninstall]
|
|
2
|
+
# install-codex-hooks.sh — Codex CLI hooks 安装/卸载/检查 wrapper(需 codex ≥ 0.144)
|
|
3
|
+
# 用法: install-codex-hooks.sh [install|uninstall|check]
|
|
4
4
|
#
|
|
5
5
|
# 薄 wrapper:source 公共骨架 + codex adapter,dispatch 到 adapter_install_hooks /
|
|
6
6
|
# adapter_uninstall_hooks。实际逻辑在 scripts/adapters/codex.sh。
|
|
7
|
+
# check:输出 ok/missing(exit 0/1),供 TUI 侦测走 bash 侧完整性判定。
|
|
8
|
+
# 显式 uninstall 成功写标记、显式 install 成功清标记(见 lib-install-hooks.sh)。
|
|
7
9
|
|
|
8
10
|
set -o errexit
|
|
9
11
|
set -o pipefail
|
|
@@ -12,8 +14,21 @@ _LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
|
|
12
14
|
source "${_LIB_DIR}/lib-install-hooks.sh"
|
|
13
15
|
source "${_LIB_DIR}/adapters/codex.sh"
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
case "${1:-install}" in
|
|
18
|
+
uninstall)
|
|
19
|
+
adapter_uninstall_hooks
|
|
20
|
+
_hooks_suppress_write codex
|
|
21
|
+
;;
|
|
22
|
+
check)
|
|
23
|
+
if adapter_check_integrity; then
|
|
24
|
+
echo ok
|
|
25
|
+
else
|
|
26
|
+
echo missing
|
|
27
|
+
exit 1
|
|
28
|
+
fi
|
|
29
|
+
;;
|
|
30
|
+
*)
|
|
31
|
+
adapter_install_hooks
|
|
32
|
+
_hooks_suppress_clear codex
|
|
33
|
+
;;
|
|
34
|
+
esac
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# install-opencode-hooks.sh — opencode plugin
|
|
3
|
-
# 用法: install-opencode-hooks.sh [uninstall]
|
|
2
|
+
# install-opencode-hooks.sh — opencode plugin 安装/卸载/检查 wrapper
|
|
3
|
+
# 用法: install-opencode-hooks.sh [install|uninstall|check]
|
|
4
4
|
#
|
|
5
5
|
# 薄 wrapper:source 公共骨架 + opencode adapter,dispatch 到 adapter_install_hooks /
|
|
6
6
|
# adapter_uninstall_hooks。实际逻辑在 scripts/adapters/opencode.sh。
|
|
7
|
+
# check:输出 ok/missing(exit 0/1),供 TUI 侦测走 bash 侧完整性判定。
|
|
8
|
+
# 显式 uninstall 成功写标记、显式 install 成功清标记(见 lib-install-hooks.sh)。
|
|
7
9
|
|
|
8
10
|
set -o errexit
|
|
9
11
|
set -o pipefail
|
|
@@ -12,8 +14,21 @@ _LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
|
|
12
14
|
source "${_LIB_DIR}/lib-install-hooks.sh"
|
|
13
15
|
source "${_LIB_DIR}/adapters/opencode.sh"
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
case "${1:-install}" in
|
|
18
|
+
uninstall)
|
|
19
|
+
adapter_uninstall_hooks
|
|
20
|
+
_hooks_suppress_write opencode
|
|
21
|
+
;;
|
|
22
|
+
check)
|
|
23
|
+
if adapter_check_integrity; then
|
|
24
|
+
echo ok
|
|
25
|
+
else
|
|
26
|
+
echo missing
|
|
27
|
+
exit 1
|
|
28
|
+
fi
|
|
29
|
+
;;
|
|
30
|
+
*)
|
|
31
|
+
adapter_install_hooks
|
|
32
|
+
_hooks_suppress_clear opencode
|
|
33
|
+
;;
|
|
34
|
+
esac
|
|
@@ -24,3 +24,16 @@ _install_atomic_write() {
|
|
|
24
24
|
printf '%s\n' "$content" > "$tmp"
|
|
25
25
|
mv -f "$tmp" "$target"
|
|
26
26
|
}
|
|
27
|
+
|
|
28
|
+
# --- 卸载意图标记(suppression marker)---
|
|
29
|
+
# 显式 uninstall 成功 → 写 suppressed-<tool>;显式 install 成功 → 清。
|
|
30
|
+
# 自动修复路径(_maybe_repair_hooks / 入口 auto / SessionStart 重装)见标记一律不装。
|
|
31
|
+
# ⚠️ _SUPPRESS_DIR 与 lib-tmux-ai-status.sh 中的定义保持一致(两处同步改)。
|
|
32
|
+
_SUPPRESS_DIR="${TMUX_AI_SUPPRESS_DIR:-${XDG_CONFIG_HOME:-${HOME}/.config}/tmuxclihook}"
|
|
33
|
+
|
|
34
|
+
_hooks_suppress_file() { printf '%s/suppressed-%s' "$_SUPPRESS_DIR" "$1"; }
|
|
35
|
+
_hooks_suppress_write() {
|
|
36
|
+
mkdir -p "$_SUPPRESS_DIR" 2>/dev/null || true
|
|
37
|
+
date +%s > "$(_hooks_suppress_file "$1")" 2>/dev/null || true
|
|
38
|
+
}
|
|
39
|
+
_hooks_suppress_clear() { rm -f "$(_hooks_suppress_file "$1")" 2>/dev/null || true; }
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
7
|
|
|
8
8
|
_STATUS_DIR="${TMUX_AI_STATUS_DIR:-/tmp/ai-status}"
|
|
9
|
+
# 卸载意图标记目录(suppressed-<tool>)。⚠️ 与 lib-install-hooks.sh 中的定义保持一致(两处同步改)。
|
|
10
|
+
_SUPPRESS_DIR="${TMUX_AI_SUPPRESS_DIR:-${XDG_CONFIG_HOME:-${HOME}/.config}/tmuxclihook}"
|
|
9
11
|
STATUS_COLOR="#F1FA8C"
|
|
10
12
|
|
|
11
13
|
# --- 日志模块 ---
|
|
@@ -533,6 +535,10 @@ _check_hooks_integrity() {
|
|
|
533
535
|
# 不依赖 SESSION_ID/EVENT,可被 _refresh 触发。60s 节流。
|
|
534
536
|
# 安装器由 adapter 声明(ADAPTER_INSTALLER)。
|
|
535
537
|
_maybe_repair_hooks() {
|
|
538
|
+
# 用户显式卸载意图(suppressed-<tool>)→ 不自动修复,尊重到显式安装为止。
|
|
539
|
+
if [ -f "${_SUPPRESS_DIR}/suppressed-${TOOL_ID:-claude}" ]; then
|
|
540
|
+
return 0
|
|
541
|
+
fi
|
|
536
542
|
local marker="${_STATUS_DIR}/.hooks-repair-${TOOL_ID:-claude}-ts"
|
|
537
543
|
local now
|
|
538
544
|
now=$(date +%s)
|
package/scripts/tmux-ai-status
CHANGED
|
@@ -178,8 +178,12 @@ case "$EVENT" in
|
|
|
178
178
|
STATUS="-"
|
|
179
179
|
_clear_pending
|
|
180
180
|
if ! _check_hooks_integrity; then
|
|
181
|
-
"${
|
|
182
|
-
|
|
181
|
+
if [ -f "${_SUPPRESS_DIR}/suppressed-${TOOL_ID}" ]; then
|
|
182
|
+
_ai_log "REPAIR: suppressed by uninstall marker, skip (${TOOL_ID})"
|
|
183
|
+
else
|
|
184
|
+
"${ADAPTER_INSTALLER}" >/dev/null 2>&1
|
|
185
|
+
tmux display-message "⚠ ${TOOL_ID} hooks 已自动修复(检测到缺失)" 2>/dev/null || true
|
|
186
|
+
fi
|
|
183
187
|
fi
|
|
184
188
|
;;
|
|
185
189
|
SessionEnd)
|
package/src/adapters-meta.js
CHANGED
|
@@ -45,6 +45,9 @@ function buildTools(scriptsDir) {
|
|
|
45
45
|
installer: join(scriptsDir, 'install-codex-hooks.sh'),
|
|
46
46
|
hookMarker: 'tmux-ai-status codex',
|
|
47
47
|
minHookCount: 6,
|
|
48
|
+
// 无 cc-switch 真源(hooks.json 即文件真源),但统一走 wrapper check 以获得
|
|
49
|
+
// 脚本存活校验(死路径 → missing → repair 收敛),与 bash 侧同一份真相。
|
|
50
|
+
checkViaWrapper: true,
|
|
48
51
|
},
|
|
49
52
|
{
|
|
50
53
|
id: 'opencode',
|
|
@@ -62,6 +65,9 @@ function buildTools(scriptsDir) {
|
|
|
62
65
|
installer: join(scriptsDir, 'install-opencode-hooks.sh'),
|
|
63
66
|
hookMarker: 'tmux-ai-status (managed by tmux-ai-hooks-status)',
|
|
64
67
|
minHookCount: 1,
|
|
68
|
+
// 统一走 wrapper check:bash 侧含 HOOK_SCRIPT 存活校验(死路径 → missing →
|
|
69
|
+
// repair 收敛),JS 文件计数判不出死路径。
|
|
70
|
+
checkViaWrapper: true,
|
|
65
71
|
},
|
|
66
72
|
];
|
|
67
73
|
}
|
package/src/detect.js
CHANGED
|
@@ -121,10 +121,11 @@ function hooksInstalled(tool) {
|
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
// 异步判定:声明 checkViaWrapper
|
|
125
|
-
//
|
|
124
|
+
// 异步判定:声明 checkViaWrapper 时走 bash wrapper check(cc-switch 模式在 bash 侧
|
|
125
|
+
// 按 sqlite 通用配置判定真源;所有 adapter check 均含脚本存活校验);未声明的工具
|
|
126
|
+
// 回落本地文件计数。
|
|
126
127
|
async function hooksInstalledAsync(tool) {
|
|
127
|
-
if (tool.checkViaWrapper && tool.ccSwitchDb
|
|
128
|
+
if (tool.checkViaWrapper && (!tool.ccSwitchDb || existsSync(tool.ccSwitchDb))) {
|
|
128
129
|
try {
|
|
129
130
|
const { stdout, exitCode } = await execa('bash', [tool.installer, 'check'], {
|
|
130
131
|
reject: false,
|
|
@@ -58,8 +58,10 @@ if [ -z "$(tmux show-option -gv @claude_hooks_reload_registered 2>/dev/null)" ];
|
|
|
58
58
|
fi
|
|
59
59
|
|
|
60
60
|
# --- 自动注册 Claude hooks(幂等,每次插件加载时确保 hooks 存在)---
|
|
61
|
+
# auto 模式:用户显式卸载过(suppressed-claude 标记在)时静默跳过,尊重卸载意图;
|
|
62
|
+
# 显式安装(prefix+C-h / TUI)才会清除标记恢复自动守护。
|
|
61
63
|
# 注:codex/opencode hooks 不自动安装(非人人安装),用 prefix+M-h / prefix+C-p 手动装。
|
|
62
|
-
"${CURRENT_DIR}/scripts/install-claude-hooks.sh" >/dev/null 2>&1 || true
|
|
64
|
+
"${CURRENT_DIR}/scripts/install-claude-hooks.sh" auto >/dev/null 2>&1 || true
|
|
63
65
|
|
|
64
66
|
# --- 启动 tmux server 级状态监控器 ---
|
|
65
67
|
# Codex/opencode 均无 SessionEnd(codex 的 SessionStart 还延迟到首个 turn);
|