@pushary/agent-hooks 0.89.9 → 0.89.10
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/CHANGELOG.md +23 -0
- package/dist/bin/pushary-bell-hook.js +4 -4
- package/dist/bin/pushary-bell.js +7 -7
- package/dist/bin/pushary-claude.js +64 -33
- package/dist/bin/pushary-clean.js +52 -45
- package/dist/bin/pushary-codex-bridge.js +8 -8
- package/dist/bin/pushary-codex-hook.js +12 -8
- package/dist/bin/pushary-codex.js +7 -7
- package/dist/bin/pushary-connect.js +6 -6
- package/dist/bin/pushary-daemon.js +16 -16
- package/dist/bin/pushary-disconnect.js +34 -9
- package/dist/bin/pushary-doctor.js +19 -19
- package/dist/bin/pushary-elicitation-hook.js +4 -4
- package/dist/bin/pushary-gemini-bridge.js +7 -7
- package/dist/bin/pushary-gemini-hook.js +8 -8
- package/dist/bin/pushary-hook.js +11 -10
- package/dist/bin/pushary-login.js +4 -4
- package/dist/bin/pushary-logout.js +4 -4
- package/dist/bin/pushary-mode.js +3 -3
- package/dist/bin/pushary-notification-hook.js +7 -7
- package/dist/bin/pushary-opencode-hook.js +8 -8
- package/dist/bin/pushary-permission-denied-hook.js +11 -10
- package/dist/bin/pushary-permission-hook.js +11 -10
- package/dist/bin/pushary-post-hook.js +7 -7
- package/dist/bin/pushary-prompt-hook.js +7 -7
- package/dist/bin/pushary-session-end-hook.js +7 -7
- package/dist/bin/pushary-session-start-hook.js +7 -7
- package/dist/bin/pushary-setup.js +52 -54
- package/dist/bin/pushary-stats.js +2 -2
- package/dist/bin/pushary-status.js +8 -8
- package/dist/bin/pushary-stop-hook.js +7 -7
- package/dist/bin/pushary-stopfailure-hook.js +7 -7
- package/dist/bin/pushary-upgrade.js +15 -15
- package/dist/bin/pushary-wait.js +3 -3
- package/dist/{chunk-SS72Z7FV.js → chunk-253WC6O5.js} +1 -1
- package/dist/{chunk-T3LRWZKI.js → chunk-2LPEZYMC.js} +1 -1
- package/dist/{chunk-O5B7EK5U.js → chunk-34GN3IPX.js} +1 -1
- package/dist/{chunk-V6N4Q223.js → chunk-3CUDMTL4.js} +1 -1
- package/dist/{chunk-VZKXBFUA.js → chunk-3HFK3UXM.js} +1 -1
- package/dist/{chunk-543KNJKC.js → chunk-3SQYKLBW.js} +3 -3
- package/dist/{chunk-ATBKJNWS.js → chunk-6EKQZA6R.js} +5 -1
- package/dist/{chunk-NKHEHEUM.js → chunk-6XUABEX2.js} +1 -1
- package/dist/{chunk-I5L6SK5V.js → chunk-BLODMQKJ.js} +1 -1
- package/dist/{chunk-DKDDLF5P.js → chunk-DKWM5T3P.js} +1 -1
- package/dist/{chunk-BAE45YLP.js → chunk-FZ73G2RO.js} +3 -3
- package/dist/{chunk-EJT2ER6G.js → chunk-GSSFSVAQ.js} +15 -21
- package/dist/{chunk-4XZCDSNG.js → chunk-GTZLL7F4.js} +5 -5
- package/dist/{chunk-PMHTCDEO.js → chunk-IUN6VOKV.js} +1 -1
- package/dist/{chunk-OFRNZWC4.js → chunk-IUWRVTQK.js} +1 -1
- package/dist/{chunk-J2JZJZKB.js → chunk-KVE5RCQL.js} +1 -1
- package/dist/{chunk-A4O5ROZK.js → chunk-MZGWKIUZ.js} +2 -2
- package/dist/chunk-NCVIWGVA.js +18 -0
- package/dist/{chunk-C623LWJR.js → chunk-OLAGKKSR.js} +1 -1
- package/dist/{chunk-EA3E74P2.js → chunk-PZRWFWSR.js} +6 -6
- package/dist/{chunk-VA7VUNRD.js → chunk-Q223OM5J.js} +58 -8
- package/dist/{chunk-GMI5QZLG.js → chunk-QA72MKIT.js} +5 -1
- package/dist/{chunk-AIGDBRIJ.js → chunk-SYUIXXQW.js} +1 -1
- package/dist/{chunk-TF247BET.js → chunk-TEZ2FZD6.js} +1 -1
- package/dist/{chunk-KOPUTJQC.js → chunk-TG3T3M4K.js} +1 -1
- package/dist/{chunk-FX5QSMPY.js → chunk-TRVIRETT.js} +1 -1
- package/dist/{chunk-U5TQCQ25.js → chunk-TY5HVMXT.js} +1 -1
- package/dist/chunk-UDBJHQMG.js +240 -0
- package/dist/{chunk-GKAKAOKC.js → chunk-UXHMWF4H.js} +64 -11
- package/dist/{chunk-PZA7G4CN.js → chunk-X4ZUUFKV.js} +1 -0
- package/dist/{chunk-L4C2JXJS.js → chunk-X6RXX2NF.js} +5 -0
- package/dist/src/index.js +11 -10
- package/package.json +1 -1
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolvePathBinary
|
|
3
|
+
} from "./chunk-X4ZUUFKV.js";
|
|
4
|
+
|
|
5
|
+
// src/hermes-config.ts
|
|
6
|
+
import { execFileSync } from "child_process";
|
|
7
|
+
import { existsSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
8
|
+
import { homedir, tmpdir } from "os";
|
|
9
|
+
import { join } from "path";
|
|
10
|
+
var isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
11
|
+
var isSnapshot = (value) => isRecord(value) && typeof value.present === "boolean" && Object.hasOwn(value, "value");
|
|
12
|
+
var isHermesConfigReceipt = (value) => {
|
|
13
|
+
if (!isRecord(value)) return false;
|
|
14
|
+
return ["security", "approval", "transport", "fallback", "plugins", "enabled", "agent", "disabled"].every((key) => isSnapshot(value[key])) && typeof value.pushary_enabled === "boolean" && typeof value.clarify_disabled === "boolean";
|
|
15
|
+
};
|
|
16
|
+
var HERMES_CONFIG_SCRIPT = String.raw`
|
|
17
|
+
import json, os, sys
|
|
18
|
+
from hermes_cli.config import load_config, save_config
|
|
19
|
+
|
|
20
|
+
mode, receipt_path = sys.argv[1], sys.argv[2]
|
|
21
|
+
c = load_config()
|
|
22
|
+
|
|
23
|
+
def snap(obj, key):
|
|
24
|
+
return {"present": key in obj, "value": obj.get(key)}
|
|
25
|
+
|
|
26
|
+
restore_conflicts = []
|
|
27
|
+
|
|
28
|
+
def restore(obj, key, before, ours):
|
|
29
|
+
if before.get("present") and before.get("value") == ours:
|
|
30
|
+
return
|
|
31
|
+
if before.get("present"):
|
|
32
|
+
if key in obj and obj.get(key) == before.get("value"):
|
|
33
|
+
return
|
|
34
|
+
elif key not in obj:
|
|
35
|
+
return
|
|
36
|
+
if obj.get(key) != ours:
|
|
37
|
+
restore_conflicts.append(key)
|
|
38
|
+
return
|
|
39
|
+
if before.get("present"):
|
|
40
|
+
obj[key] = before.get("value")
|
|
41
|
+
else:
|
|
42
|
+
obj.pop(key, None)
|
|
43
|
+
|
|
44
|
+
def restore_container(obj, key, before, current, changed):
|
|
45
|
+
raw = obj.get(key)
|
|
46
|
+
if isinstance(before.get("value"), dict):
|
|
47
|
+
if not isinstance(raw, dict):
|
|
48
|
+
if changed:
|
|
49
|
+
restore_conflicts.append(key)
|
|
50
|
+
return
|
|
51
|
+
if current or before.get("present"):
|
|
52
|
+
obj[key] = current
|
|
53
|
+
else:
|
|
54
|
+
obj.pop(key, None)
|
|
55
|
+
elif isinstance(raw, dict) and current:
|
|
56
|
+
restore_conflicts.append(key)
|
|
57
|
+
else:
|
|
58
|
+
restore(obj, key, before, {})
|
|
59
|
+
|
|
60
|
+
def restore_list_member(obj, key, before, ours, ours_before):
|
|
61
|
+
raw = obj.get(key)
|
|
62
|
+
if isinstance(before.get("value"), list):
|
|
63
|
+
if ours_before:
|
|
64
|
+
return
|
|
65
|
+
if not isinstance(raw, list):
|
|
66
|
+
restore_conflicts.append(key)
|
|
67
|
+
return
|
|
68
|
+
remaining = [item for item in raw if item != ours]
|
|
69
|
+
if remaining or before.get("present"):
|
|
70
|
+
obj[key] = remaining
|
|
71
|
+
else:
|
|
72
|
+
obj.pop(key, None)
|
|
73
|
+
return
|
|
74
|
+
if before.get("present") and raw == before.get("value"):
|
|
75
|
+
return
|
|
76
|
+
if not before.get("present") and key not in obj:
|
|
77
|
+
return
|
|
78
|
+
if not isinstance(raw, list):
|
|
79
|
+
restore_conflicts.append(key)
|
|
80
|
+
return
|
|
81
|
+
remaining = [item for item in raw if item != ours]
|
|
82
|
+
if remaining:
|
|
83
|
+
restore_conflicts.append(key)
|
|
84
|
+
else:
|
|
85
|
+
restore(obj, key, before, raw)
|
|
86
|
+
|
|
87
|
+
def valid_snapshot(value):
|
|
88
|
+
return isinstance(value, dict) and isinstance(value.get("present"), bool) and "value" in value
|
|
89
|
+
|
|
90
|
+
def valid_receipt(value):
|
|
91
|
+
snapshots = ["security", "approval", "transport", "fallback", "plugins", "enabled", "agent", "disabled"]
|
|
92
|
+
return (isinstance(value, dict)
|
|
93
|
+
and all(valid_snapshot(value.get(key)) for key in snapshots)
|
|
94
|
+
and isinstance(value.get("pushary_enabled"), bool)
|
|
95
|
+
and isinstance(value.get("clarify_disabled"), bool))
|
|
96
|
+
|
|
97
|
+
if mode == "setup":
|
|
98
|
+
security_before = snap(c, "security")
|
|
99
|
+
s = c.get("security") if isinstance(c.get("security"), dict) else {}
|
|
100
|
+
approval_before = snap(s, "approval")
|
|
101
|
+
ap = s.get("approval") if isinstance(s.get("approval"), dict) else {}
|
|
102
|
+
plugins_before = snap(c, "plugins")
|
|
103
|
+
p = c.get("plugins") if isinstance(c.get("plugins"), dict) else {}
|
|
104
|
+
agent_before = snap(c, "agent")
|
|
105
|
+
a = c.get("agent") if isinstance(c.get("agent"), dict) else {}
|
|
106
|
+
enabled = p.get("enabled") if isinstance(p.get("enabled"), list) else []
|
|
107
|
+
disabled = a.get("disabled_toolsets") if isinstance(a.get("disabled_toolsets"), list) else []
|
|
108
|
+
receipt = {
|
|
109
|
+
"security": security_before,
|
|
110
|
+
"approval": approval_before,
|
|
111
|
+
"transport": snap(ap, "transport"),
|
|
112
|
+
"fallback": snap(ap, "transport_fallback"),
|
|
113
|
+
"plugins": plugins_before,
|
|
114
|
+
"enabled": snap(p, "enabled"),
|
|
115
|
+
"pushary_enabled": "pushary" in enabled,
|
|
116
|
+
"agent": agent_before,
|
|
117
|
+
"disabled": snap(a, "disabled_toolsets"),
|
|
118
|
+
"clarify_disabled": "clarify" in disabled,
|
|
119
|
+
}
|
|
120
|
+
if os.path.exists(receipt_path):
|
|
121
|
+
with open(receipt_path, encoding="utf-8") as handle:
|
|
122
|
+
existing_receipt = json.load(handle)
|
|
123
|
+
if not valid_receipt(existing_receipt):
|
|
124
|
+
raise ValueError("invalid Pushary Hermes setup receipt")
|
|
125
|
+
else:
|
|
126
|
+
os.makedirs(os.path.dirname(receipt_path), exist_ok=True)
|
|
127
|
+
temp = receipt_path + ".tmp"
|
|
128
|
+
with open(temp, "x", encoding="utf-8") as handle:
|
|
129
|
+
json.dump(receipt, handle)
|
|
130
|
+
os.chmod(temp, 0o600)
|
|
131
|
+
os.replace(temp, receipt_path)
|
|
132
|
+
ap["transport"] = "pushary"
|
|
133
|
+
ap["transport_fallback"] = "builtin"
|
|
134
|
+
s["approval"] = ap
|
|
135
|
+
c["security"] = s
|
|
136
|
+
p["enabled"] = enabled if "pushary" in enabled else enabled + ["pushary"]
|
|
137
|
+
c["plugins"] = p
|
|
138
|
+
a["disabled_toolsets"] = disabled if "clarify" in disabled else disabled + ["clarify"]
|
|
139
|
+
c["agent"] = a
|
|
140
|
+
else:
|
|
141
|
+
receipt_exists = os.path.exists(receipt_path)
|
|
142
|
+
try:
|
|
143
|
+
with open(receipt_path, encoding="utf-8") as handle:
|
|
144
|
+
receipt = json.load(handle)
|
|
145
|
+
except (OSError, ValueError):
|
|
146
|
+
if receipt_exists:
|
|
147
|
+
raise
|
|
148
|
+
receipt = None
|
|
149
|
+
s = c.get("security") if isinstance(c.get("security"), dict) else {}
|
|
150
|
+
ap = s.get("approval") if isinstance(s.get("approval"), dict) else {}
|
|
151
|
+
if receipt:
|
|
152
|
+
if not valid_receipt(receipt):
|
|
153
|
+
raise ValueError("invalid Pushary Hermes setup receipt")
|
|
154
|
+
approval_changed = (not receipt["transport"].get("present")
|
|
155
|
+
or receipt["transport"].get("value") != "pushary"
|
|
156
|
+
or not receipt["fallback"].get("present")
|
|
157
|
+
or receipt["fallback"].get("value") != "builtin")
|
|
158
|
+
plugins_changed = not (isinstance(receipt["enabled"].get("value"), list)
|
|
159
|
+
and receipt["pushary_enabled"])
|
|
160
|
+
agent_changed = not (isinstance(receipt["disabled"].get("value"), list)
|
|
161
|
+
and receipt["clarify_disabled"])
|
|
162
|
+
restore(ap, "transport", receipt["transport"], "pushary")
|
|
163
|
+
restore(ap, "transport_fallback", receipt["fallback"], "builtin")
|
|
164
|
+
else:
|
|
165
|
+
if ap.get("transport") == "pushary": ap.pop("transport", None)
|
|
166
|
+
if ap.get("transport_fallback") == "builtin": ap.pop("transport_fallback", None)
|
|
167
|
+
if receipt:
|
|
168
|
+
restore_container(s, "approval", receipt["approval"], ap, approval_changed)
|
|
169
|
+
restore_container(c, "security", receipt["security"], s, approval_changed)
|
|
170
|
+
else:
|
|
171
|
+
if ap: s["approval"] = ap
|
|
172
|
+
else: s.pop("approval", None)
|
|
173
|
+
if s: c["security"] = s
|
|
174
|
+
else: c.pop("security", None)
|
|
175
|
+
|
|
176
|
+
p = c.get("plugins") if isinstance(c.get("plugins"), dict) else {}
|
|
177
|
+
if receipt:
|
|
178
|
+
restore_list_member(p, "enabled", receipt["enabled"], "pushary", receipt["pushary_enabled"])
|
|
179
|
+
restore_container(c, "plugins", receipt["plugins"], p, plugins_changed)
|
|
180
|
+
else:
|
|
181
|
+
enabled = p.get("enabled") if isinstance(p.get("enabled"), list) else []
|
|
182
|
+
enabled = [item for item in enabled if item != "pushary"]
|
|
183
|
+
if enabled: p["enabled"] = enabled
|
|
184
|
+
else: p.pop("enabled", None)
|
|
185
|
+
if p: c["plugins"] = p
|
|
186
|
+
else: c.pop("plugins", None)
|
|
187
|
+
|
|
188
|
+
a = c.get("agent") if isinstance(c.get("agent"), dict) else {}
|
|
189
|
+
if receipt:
|
|
190
|
+
restore_list_member(a, "disabled_toolsets", receipt["disabled"], "clarify", receipt["clarify_disabled"])
|
|
191
|
+
restore_container(c, "agent", receipt["agent"], a, agent_changed)
|
|
192
|
+
else:
|
|
193
|
+
disabled = a.get("disabled_toolsets") if isinstance(a.get("disabled_toolsets"), list) else []
|
|
194
|
+
disabled = [item for item in disabled if item != "clarify"]
|
|
195
|
+
if disabled: a["disabled_toolsets"] = disabled
|
|
196
|
+
else: a.pop("disabled_toolsets", None)
|
|
197
|
+
if a: c["agent"] = a
|
|
198
|
+
else: c.pop("agent", None)
|
|
199
|
+
|
|
200
|
+
if receipt and restore_conflicts:
|
|
201
|
+
raise ValueError("Hermes config changed after Pushary setup")
|
|
202
|
+
|
|
203
|
+
save_config(c)
|
|
204
|
+
`;
|
|
205
|
+
var resolveHermesPython = () => {
|
|
206
|
+
const launcher = resolvePathBinary("hermes");
|
|
207
|
+
if (launcher && process.platform !== "win32") {
|
|
208
|
+
try {
|
|
209
|
+
const shebang = readFileSync(launcher, "utf-8").split("\n", 1)[0];
|
|
210
|
+
const interpreter = shebang?.startsWith("#!") ? shebang.slice(2).trim().split(/\s+/)[0] : void 0;
|
|
211
|
+
if (interpreter && /python/i.test(interpreter) && existsSync(interpreter)) return interpreter;
|
|
212
|
+
} catch {
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
const root = join(homedir(), ".hermes", "hermes-agent", "venv");
|
|
216
|
+
const candidates = process.platform === "win32" ? [join(root, "Scripts", "python.exe"), join(root, "Scripts", "python3.exe")] : [join(root, "bin", "python3"), join(root, "bin", "python")];
|
|
217
|
+
return candidates.find(existsSync) ?? null;
|
|
218
|
+
};
|
|
219
|
+
var runHermesPythonScript = (python, script, ...args) => {
|
|
220
|
+
const path = join(tmpdir(), `pushary-hermes-${process.pid}-${Date.now()}.py`);
|
|
221
|
+
try {
|
|
222
|
+
writeFileSync(path, script, { encoding: "utf-8", mode: 384 });
|
|
223
|
+
execFileSync(python, [path, ...args], { env: { ...process.env }, stdio: "pipe", timeout: 15e3 });
|
|
224
|
+
return true;
|
|
225
|
+
} catch {
|
|
226
|
+
return false;
|
|
227
|
+
} finally {
|
|
228
|
+
try {
|
|
229
|
+
rmSync(path, { force: true });
|
|
230
|
+
} catch {
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
export {
|
|
236
|
+
isHermesConfigReceipt,
|
|
237
|
+
HERMES_CONFIG_SCRIPT,
|
|
238
|
+
resolveHermesPython,
|
|
239
|
+
runHermesPythonScript
|
|
240
|
+
};
|
|
@@ -82,13 +82,14 @@ var commandDirFor = (sessionId, namespace = "") => join(
|
|
|
82
82
|
createHash("sha256").update(namespace).digest("hex").slice(0, 16),
|
|
83
83
|
sanitize(sessionId)
|
|
84
84
|
);
|
|
85
|
-
var
|
|
86
|
-
var
|
|
85
|
+
var legacyCommandFile = (sessionId, namespace = "") => join(commandDirFor(sessionId, namespace), "command.json");
|
|
86
|
+
var commandFile = (sessionId, id, namespace = "") => join(commandDirFor(sessionId, namespace), `${createHash("sha256").update(id).digest("hex")}.json`);
|
|
87
|
+
var readCommandFile = (file) => {
|
|
87
88
|
try {
|
|
88
|
-
const value = JSON.parse(readFileSync(
|
|
89
|
+
const value = JSON.parse(readFileSync(file, "utf-8"));
|
|
89
90
|
if (typeof value.id !== "string" || typeof value.text !== "string" || typeof value.expiresAtMs !== "number") return null;
|
|
90
91
|
if (value.expiresAtMs <= Date.now()) {
|
|
91
|
-
unlinkSync(
|
|
92
|
+
unlinkSync(file);
|
|
92
93
|
return null;
|
|
93
94
|
}
|
|
94
95
|
return {
|
|
@@ -100,23 +101,68 @@ var readPendingCommand = (sessionId, namespace = "") => {
|
|
|
100
101
|
return null;
|
|
101
102
|
}
|
|
102
103
|
};
|
|
104
|
+
var readPendingCommandById = (sessionId, id, namespace = "") => {
|
|
105
|
+
const current = readCommandFile(commandFile(sessionId, id, namespace));
|
|
106
|
+
if (current?.id === id) return current;
|
|
107
|
+
const legacy = readCommandFile(legacyCommandFile(sessionId, namespace));
|
|
108
|
+
return legacy?.id === id ? legacy : null;
|
|
109
|
+
};
|
|
110
|
+
var pruneExpiredCommands = (dir) => {
|
|
111
|
+
let files;
|
|
112
|
+
try {
|
|
113
|
+
files = readdirSync(dir).filter((file) => file.endsWith(".json"));
|
|
114
|
+
} catch {
|
|
115
|
+
return [];
|
|
116
|
+
}
|
|
117
|
+
return files.flatMap((file) => {
|
|
118
|
+
const command = readCommandFile(join(dir, file));
|
|
119
|
+
return command ? [command] : [];
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
var pruneExpiredCommandStore = () => {
|
|
123
|
+
let namespaces;
|
|
124
|
+
try {
|
|
125
|
+
namespaces = readdirSync(COMMAND_DIR, { withFileTypes: true });
|
|
126
|
+
} catch {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
for (const namespace of namespaces.filter((entry) => entry.isDirectory())) {
|
|
130
|
+
const namespaceDir = join(COMMAND_DIR, namespace.name);
|
|
131
|
+
let sessions;
|
|
132
|
+
try {
|
|
133
|
+
sessions = readdirSync(namespaceDir, { withFileTypes: true });
|
|
134
|
+
} catch {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
for (const session of sessions.filter((entry) => entry.isDirectory())) {
|
|
138
|
+
pruneExpiredCommands(join(namespaceDir, session.name));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
var readPendingCommand = (sessionId, namespace = "") => {
|
|
143
|
+
const commands = pruneExpiredCommands(commandDirFor(sessionId, namespace));
|
|
144
|
+
return commands.find((command) => !command.delivered && !command.failed) ?? commands[0] ?? null;
|
|
145
|
+
};
|
|
103
146
|
var savePendingCommand = (sessionId, command, namespace = "") => {
|
|
104
147
|
const dir = commandDirFor(sessionId, namespace);
|
|
105
148
|
try {
|
|
106
149
|
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
107
|
-
|
|
150
|
+
pruneExpiredCommandStore();
|
|
151
|
+
if (readPendingCommandById(sessionId, command.id, namespace)) return false;
|
|
152
|
+
writeFileSync(commandFile(sessionId, command.id, namespace), JSON.stringify(command), { encoding: "utf-8", mode: 384, flag: "wx" });
|
|
108
153
|
return true;
|
|
109
154
|
} catch {
|
|
110
155
|
return false;
|
|
111
156
|
}
|
|
112
157
|
};
|
|
113
158
|
var updatePendingCommand = (sessionId, id, update, namespace = "") => {
|
|
114
|
-
const command =
|
|
115
|
-
if (!command
|
|
116
|
-
const
|
|
159
|
+
const command = readPendingCommandById(sessionId, id, namespace);
|
|
160
|
+
if (!command) return false;
|
|
161
|
+
const currentFile = commandFile(sessionId, id, namespace);
|
|
162
|
+
const file = existsSync(currentFile) ? currentFile : legacyCommandFile(sessionId, namespace);
|
|
117
163
|
const temporary = `${file}.${process.pid}.tmp`;
|
|
118
164
|
try {
|
|
119
|
-
writeFileSync(temporary, JSON.stringify({ ...command, ...update }), { encoding: "utf-8", mode: 384 });
|
|
165
|
+
writeFileSync(temporary, JSON.stringify({ ...command, ...update, text: "" }), { encoding: "utf-8", mode: 384 });
|
|
120
166
|
renameSync(temporary, file);
|
|
121
167
|
return true;
|
|
122
168
|
} catch {
|
|
@@ -130,9 +176,15 @@ var updatePendingCommand = (sessionId, id, update, namespace = "") => {
|
|
|
130
176
|
var markPendingCommandDelivered = (sessionId, id, namespace = "") => updatePendingCommand(sessionId, id, { delivered: true, failed: void 0 }, namespace);
|
|
131
177
|
var markPendingCommandFailed = (sessionId, id, namespace = "") => updatePendingCommand(sessionId, id, { delivered: false, failed: true }, namespace);
|
|
132
178
|
var removePendingCommand = (sessionId, id, namespace = "") => {
|
|
133
|
-
if (
|
|
179
|
+
if (!readPendingCommandById(sessionId, id, namespace)) return;
|
|
180
|
+
try {
|
|
181
|
+
unlinkSync(commandFile(sessionId, id, namespace));
|
|
182
|
+
} catch {
|
|
183
|
+
}
|
|
134
184
|
try {
|
|
135
|
-
|
|
185
|
+
if (readCommandFile(legacyCommandFile(sessionId, namespace))?.id === id) {
|
|
186
|
+
unlinkSync(legacyCommandFile(sessionId, namespace));
|
|
187
|
+
}
|
|
136
188
|
} catch {
|
|
137
189
|
}
|
|
138
190
|
};
|
|
@@ -181,6 +233,7 @@ export {
|
|
|
181
233
|
cancelQuestion,
|
|
182
234
|
sendNotification,
|
|
183
235
|
DEFAULT_SESSION,
|
|
236
|
+
readPendingCommandById,
|
|
184
237
|
readPendingCommand,
|
|
185
238
|
savePendingCommand,
|
|
186
239
|
markPendingCommandDelivered,
|
|
@@ -1080,6 +1080,9 @@ var shouldDeferToNativeMode = (permissionMode, toolName, options = {}) => {
|
|
|
1080
1080
|
if (permissionMode === "bypassPermissions") return options.deferBypass === true;
|
|
1081
1081
|
return false;
|
|
1082
1082
|
};
|
|
1083
|
+
var ASKED_IN_EVERY_MODE_TOOLS = ["AskUserQuestion", "ExitPlanMode"];
|
|
1084
|
+
var ASKED_IN_EVERY_MODE = new Set(ASKED_IN_EVERY_MODE_TOOLS);
|
|
1085
|
+
var isAskedInEveryMode = (toolName) => ASKED_IN_EVERY_MODE.has(toolName);
|
|
1083
1086
|
var resolveGate = (input) => {
|
|
1084
1087
|
const { modeState, config, toolName, toolInputs, cwd, repoKey, sessionId } = input;
|
|
1085
1088
|
if (modeState.kill) return { kind: "kill", reason: KILL_REASON };
|
|
@@ -1088,6 +1091,7 @@ var resolveGate = (input) => {
|
|
|
1088
1091
|
const autoApproves = verdict === "allow";
|
|
1089
1092
|
const autoDenies = verdict === "deny";
|
|
1090
1093
|
if (autoDenies) return { kind: "deny", policy, reason: `Denied by policy for ${policy.tool}` };
|
|
1094
|
+
if (isAskedInEveryMode(toolName)) return { kind: "gate", policy };
|
|
1091
1095
|
if (isModeStateDegraded(modeState)) {
|
|
1092
1096
|
if (autoApproves) {
|
|
1093
1097
|
return survivesDegraded(config, toolName, toolInputs, cwd, repoKey, sessionId) ? { kind: "allow", policy, source: "allowlist" } : { kind: "defer", policy };
|
|
@@ -1359,6 +1363,7 @@ export {
|
|
|
1359
1363
|
resolvePolicy,
|
|
1360
1364
|
KILL_REASON,
|
|
1361
1365
|
shouldDeferToNativeMode,
|
|
1366
|
+
ASKED_IN_EVERY_MODE_TOOLS,
|
|
1362
1367
|
resolveGate,
|
|
1363
1368
|
modeStateFromResponse,
|
|
1364
1369
|
claudePreToolUseOutput,
|
package/dist/src/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
handlePreToolUse
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-GSSFSVAQ.js";
|
|
4
|
+
import "../chunk-6EKQZA6R.js";
|
|
5
|
+
import "../chunk-NCVIWGVA.js";
|
|
6
|
+
import "../chunk-3HFK3UXM.js";
|
|
6
7
|
import "../chunk-YHG74UFF.js";
|
|
7
8
|
import {
|
|
8
9
|
fetchModeOverride,
|
|
@@ -12,18 +13,18 @@ import {
|
|
|
12
13
|
handlePostToolUse,
|
|
13
14
|
handleStop,
|
|
14
15
|
reportEvent
|
|
15
|
-
} from "../chunk-
|
|
16
|
+
} from "../chunk-GTZLL7F4.js";
|
|
16
17
|
import {
|
|
17
18
|
askUser,
|
|
18
19
|
cancelQuestion,
|
|
19
20
|
waitForAnswer
|
|
20
|
-
} from "../chunk-
|
|
21
|
-
import "../chunk-
|
|
22
|
-
import "../chunk-
|
|
23
|
-
import "../chunk-
|
|
21
|
+
} from "../chunk-UXHMWF4H.js";
|
|
22
|
+
import "../chunk-TG3T3M4K.js";
|
|
23
|
+
import "../chunk-DKWM5T3P.js";
|
|
24
|
+
import "../chunk-QA72MKIT.js";
|
|
24
25
|
import "../chunk-BSZYIAZL.js";
|
|
25
26
|
import "../chunk-SAF6HGAA.js";
|
|
26
|
-
import "../chunk-
|
|
27
|
+
import "../chunk-IUWRVTQK.js";
|
|
27
28
|
import "../chunk-7QLSKOSU.js";
|
|
28
29
|
import "../chunk-KZERVKTD.js";
|
|
29
30
|
import "../chunk-XX2V4QS5.js";
|
|
@@ -33,7 +34,7 @@ import {
|
|
|
33
34
|
} from "../chunk-2UMNXADU.js";
|
|
34
35
|
import {
|
|
35
36
|
resolvePolicy
|
|
36
|
-
} from "../chunk-
|
|
37
|
+
} from "../chunk-X6RXX2NF.js";
|
|
37
38
|
export {
|
|
38
39
|
askUser,
|
|
39
40
|
cancelQuestion,
|