tmuxclihook 0.5.15 → 0.5.16
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/codex.sh +56 -4
- package/src/check-detail.js +31 -0
package/package.json
CHANGED
|
@@ -74,13 +74,65 @@ adapter_check_integrity() {
|
|
|
74
74
|
_CODEX_EVENTS="SessionStart UserPromptSubmit PreToolUse PermissionRequest PostToolUse Stop"
|
|
75
75
|
_CODEX_LEGACY_TOML="${CODEX_HOME:-$HOME/.codex}/hooks.toml"
|
|
76
76
|
|
|
77
|
+
# Hook 授信记录(trust 维度,check --json 用):codex 把 user 来源 hook 的授信写在
|
|
78
|
+
# 每个实例 config.toml 的 [hooks.state."<hooks.json 路径>:<下划线事件>:<组>:<hook>"]。
|
|
79
|
+
# 只判键是否存在——bash 无法复现 trusted_hash;因此:
|
|
80
|
+
# - 键缺失 = 该 hook 一定不会执行(强信号)
|
|
81
|
+
# - 键存在 ≠ 一定执行(hooks 被改写后旧键仍在、hash 失效,codex 会重新弹 Trust)
|
|
82
|
+
# config.toml 不存在 → trusted:null(无法判定)。
|
|
83
|
+
_CODEX_TRUST_EVENTS="session_start user_prompt_submit pre_tool_use permission_request post_tool_use stop"
|
|
84
|
+
|
|
85
|
+
_codex_trust_scan() { # $1=config.toml $2=hooks.json → 每行 "event<TAB>0|1"
|
|
86
|
+
local cfg="$1" hooks="$2" keys e
|
|
87
|
+
[ -f "$cfg" ] || return 1
|
|
88
|
+
# 只提取键名,绝不读取 trusted_hash 值
|
|
89
|
+
keys=$(sed -n 's/^\[hooks\.state\."\([^"]*\)"\].*/\1/p' "$cfg" 2>/dev/null)
|
|
90
|
+
for e in $_CODEX_TRUST_EVENTS; do
|
|
91
|
+
case "$keys" in
|
|
92
|
+
*"$hooks:$e:"*) printf '%s\t1\n' "$e" ;;
|
|
93
|
+
*) printf '%s\t0\n' "$e" ;;
|
|
94
|
+
esac
|
|
95
|
+
done
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
# 汇总 $HOME/.codex 与所有 cc-switch 实例的授信状态(去重;config.toml 不存在则不收录,
|
|
99
|
+
# 当前实例不存在时 trusted:null)。只读。
|
|
100
|
+
_codex_trust_json() {
|
|
101
|
+
local cfg hooks rows e mark missing trusted seen=""
|
|
102
|
+
for cfg in "${HOME}/.codex/config.toml" "${HOME}"/.cc-switch/instances/codex/*/config.toml; do
|
|
103
|
+
[ -f "$cfg" ] || continue
|
|
104
|
+
[ "$cfg" = "$seen" ] && continue
|
|
105
|
+
seen="$cfg"
|
|
106
|
+
hooks="$(dirname "$cfg")/hooks.json"
|
|
107
|
+
rows=$(_codex_trust_scan "$cfg" "$hooks" 2>/dev/null) || continue
|
|
108
|
+
missing=""
|
|
109
|
+
while IFS=$'\t' read -r e mark; do
|
|
110
|
+
[ "$mark" = "0" ] && missing="${missing}${missing:+,}$e"
|
|
111
|
+
done <<EOF
|
|
112
|
+
$rows
|
|
113
|
+
EOF
|
|
114
|
+
if [ -n "$missing" ]; then trusted=0; else trusted=1; fi
|
|
115
|
+
printf '%s\t%s\t%s\t%s\n' "$cfg" "$hooks" "$trusted" "$missing"
|
|
116
|
+
done | jq -R -s --arg cur "${CODEX_HOME:-$HOME/.codex}/config.toml" '
|
|
117
|
+
split("\n") | map(select(length > 0) | split("\t")) as $rows
|
|
118
|
+
| [$rows[] | {configFile: .[0], hooksFile: .[1],
|
|
119
|
+
trusted: (.[2] == "1"),
|
|
120
|
+
missingEvents: (if .[3] == "" then [] else (.[3] | split(",")) end)}] as $inst
|
|
121
|
+
| ($inst | map(select(.configFile == $cur)) | first) as $cur_obj
|
|
122
|
+
| {configFile: $cur,
|
|
123
|
+
trusted: (if $cur_obj then $cur_obj.trusted else null end),
|
|
124
|
+
missingEvents: (if $cur_obj then $cur_obj.missingEvents else [] end),
|
|
125
|
+
instances: $inst}'
|
|
126
|
+
}
|
|
127
|
+
|
|
77
128
|
# 明细检查(仅 install wrapper 的 check --json 调用;与 claude adapter 同构)。
|
|
78
129
|
# 差异:无 cc-switch 分支(hooks.json 即文件真源,mode 恒 file)、6 事件、
|
|
79
130
|
# 匹配串为 "tmux-ai-status codex"。失败输出空 events 降级片段,不 exit 非 0。
|
|
80
131
|
adapter_check_detail() {
|
|
81
|
-
local src="$ADAPTER_HOOKS_FILE" pairs rows line ev p a
|
|
132
|
+
local src="$ADAPTER_HOOKS_FILE" pairs rows line ev p a trust_json
|
|
133
|
+
trust_json=$(_codex_trust_json)
|
|
82
134
|
if [ ! -f "$src" ]; then
|
|
83
|
-
printf '{"mode":"file","events":{},"plugin":null,"registeredPaths":[]}\n'
|
|
135
|
+
printf '{"mode":"file","events":{},"plugin":null,"registeredPaths":[],"trust":%s}\n' "$trust_json"
|
|
84
136
|
return 0
|
|
85
137
|
fi
|
|
86
138
|
pairs=$(jq -r '.hooks as $h |
|
|
@@ -98,7 +150,7 @@ adapter_check_detail() {
|
|
|
98
150
|
done <<EOF
|
|
99
151
|
$pairs
|
|
100
152
|
EOF
|
|
101
|
-
jq -R -s --arg mode "file" --arg events "$_CODEX_EVENTS" '
|
|
153
|
+
jq -R -s --arg mode "file" --arg events "$_CODEX_EVENTS" --argjson trust "$trust_json" '
|
|
102
154
|
(reduce ($events | split(" ")[]) as $e
|
|
103
155
|
({}; .[$e] = {registered: 0, alive: 0, scriptPaths: []})) as $base
|
|
104
156
|
| reduce (split("\n") | .[] | select(length > 0) | split("\t")) as $r (
|
|
@@ -109,7 +161,7 @@ EOF
|
|
|
109
161
|
scriptPaths: ((.[$r[0]].scriptPaths + [$r[1]]) | unique)
|
|
110
162
|
})
|
|
111
163
|
| {mode: $mode, events: ., plugin: null,
|
|
112
|
-
registeredPaths: ([.[] | .scriptPaths[]] | unique)}
|
|
164
|
+
registeredPaths: ([.[] | .scriptPaths[]] | unique), trust: $trust}
|
|
113
165
|
' <<<"$rows"
|
|
114
166
|
}
|
|
115
167
|
|
package/src/check-detail.js
CHANGED
|
@@ -32,6 +32,9 @@ function baseDetail(tool) {
|
|
|
32
32
|
events: {},
|
|
33
33
|
plugin: null,
|
|
34
34
|
registeredPaths: [],
|
|
35
|
+
// codex 授信维度:{configFile, trusted: true|false|null, missingEvents, instances}
|
|
36
|
+
// 仅 codex adapter 提供;null = 该工具无此概念/旧版 adapter。
|
|
37
|
+
trust: null,
|
|
35
38
|
drift: null,
|
|
36
39
|
error: null,
|
|
37
40
|
raw: null,
|
|
@@ -70,6 +73,7 @@ export async function checkToolDetail(tool, { run } = {}) {
|
|
|
70
73
|
events: parsed.events || {},
|
|
71
74
|
plugin: parsed.plugin ?? null,
|
|
72
75
|
registeredPaths: parsed.registeredPaths || [],
|
|
76
|
+
trust: parsed.trust ?? null,
|
|
73
77
|
drift: parsed.drift || null,
|
|
74
78
|
error: parsed.error,
|
|
75
79
|
raw: stdout,
|
|
@@ -85,6 +89,7 @@ export async function checkToolDetail(tool, { run } = {}) {
|
|
|
85
89
|
events: parsed.events || {},
|
|
86
90
|
plugin: parsed.plugin ?? null,
|
|
87
91
|
registeredPaths: parsed.registeredPaths || [],
|
|
92
|
+
trust: parsed.trust ?? null,
|
|
88
93
|
drift: parsed.drift || null,
|
|
89
94
|
raw: stdout,
|
|
90
95
|
};
|
|
@@ -107,6 +112,32 @@ export function renderToolDetail(detail) {
|
|
|
107
112
|
lines.push(` ${WARN} 存在卸载意图标记(suppressed-${detail.tool}):自动修复已被抑制`);
|
|
108
113
|
}
|
|
109
114
|
|
|
115
|
+
// codex 授信维度:hooks 注册完整 ≠ 会执行。键缺失 = 一定不执行;键存在只说明
|
|
116
|
+
// 有授信记录(bash 无法复现 trusted_hash,改写后仍可能需重新 Trust)。
|
|
117
|
+
const trust = detail.trust;
|
|
118
|
+
if (trust) {
|
|
119
|
+
if (trust.trusted === false) {
|
|
120
|
+
const miss = (trust.missingEvents || []).join(', ') || '全部事件';
|
|
121
|
+
lines.push(
|
|
122
|
+
` ${WARN} hooks 未授信:当前实例缺少 [hooks.state] 记录(${miss})——codex 会跳过这些 hook,请在 codex TUI 选择 "Trust all and continue"`
|
|
123
|
+
);
|
|
124
|
+
} else if (trust.trusted === true) {
|
|
125
|
+
lines.push(` ${OK} 授信记录存在(键存在不等于 hash 匹配:hooks 改写后仍可能需重新 Trust)`);
|
|
126
|
+
} else if (detail.status === 'ok') {
|
|
127
|
+
lines.push(` ${WARN} 无法判定授信状态:${trust.configFile} 不存在`);
|
|
128
|
+
}
|
|
129
|
+
const otherUntrusted = (trust.instances || []).filter(
|
|
130
|
+
(i) => i.configFile !== trust.configFile && i.trusted === false
|
|
131
|
+
);
|
|
132
|
+
if (otherUntrusted.length > 0) {
|
|
133
|
+
lines.push(` ${WARN} 其他实例未授信(首次启动会弹 Hooks need review):`);
|
|
134
|
+
for (const i of otherUntrusted) {
|
|
135
|
+
const miss = (i.missingEvents || []).join(', ') || '全部事件';
|
|
136
|
+
lines.push(` ${i.configFile}(缺 ${miss})`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
110
141
|
// 逐事件缺失明细(cc-switch/文件模式的 tools)
|
|
111
142
|
if (detail.status === 'missing') {
|
|
112
143
|
const broken = [];
|