@pushary/agent-hooks 0.95.8 → 0.98.0
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 +27 -0
- package/dist/bin/pushary-bell-hook.js +19 -21
- package/dist/bin/pushary-bell.js +6 -8
- package/dist/bin/pushary-claude.js +21 -23
- package/dist/bin/pushary-clean.js +19 -22
- package/dist/bin/pushary-codex-bridge.js +13 -14
- package/dist/bin/pushary-codex-hook.js +452 -104
- package/dist/bin/pushary-codex.js +8 -8
- package/dist/bin/pushary-connect.js +6 -6
- package/dist/bin/pushary-cowork.js +3 -3
- package/dist/bin/pushary-daemon.js +25 -27
- package/dist/bin/pushary-disconnect.js +6 -8
- package/dist/bin/pushary-doctor.js +28 -23
- package/dist/bin/pushary-elicitation-hook.js +19 -21
- package/dist/bin/pushary-gemini-bridge.js +11 -12
- package/dist/bin/pushary-gemini-hook.js +22 -24
- package/dist/bin/pushary-hook.js +24 -26
- package/dist/bin/pushary-login.js +7 -8
- package/dist/bin/pushary-logout.js +4 -4
- package/dist/bin/pushary-mode.js +3 -3
- package/dist/bin/pushary-notification-hook.js +21 -23
- package/dist/bin/pushary-opencode-hook.js +22 -24
- package/dist/bin/pushary-permission-denied-hook.js +28 -27
- package/dist/bin/pushary-permission-hook.js +24 -26
- package/dist/bin/pushary-post-hook.js +21 -23
- package/dist/bin/pushary-prompt-hook.js +21 -23
- package/dist/bin/pushary-session-end-hook.js +21 -23
- package/dist/bin/pushary-session-start-hook.js +24 -26
- package/dist/bin/pushary-setup.js +45 -40
- package/dist/bin/pushary-stats.js +2 -2
- package/dist/bin/pushary-status.js +10 -11
- package/dist/bin/pushary-stop-hook.js +21 -23
- package/dist/bin/pushary-stopfailure-hook.js +21 -23
- package/dist/bin/pushary-transcript-register.js +17 -19
- package/dist/bin/pushary-transcripts.js +5 -5
- package/dist/bin/pushary-upgrade.js +17 -20
- package/dist/bin/pushary-wait.js +3 -3
- package/dist/{chunk-GOPIMNVC.js → chunk-2GLOHBYB.js} +1 -1
- package/dist/{chunk-BQL7UDIB.js → chunk-3RVCQDC4.js} +1 -1
- package/dist/chunk-53QCTSWY.js +202 -0
- package/dist/{chunk-3YFJGKJQ.js → chunk-5B5QV3KC.js} +8 -8
- package/dist/{chunk-FRXZMCVA.js → chunk-5KLAETSU.js} +1 -1
- package/dist/{chunk-SDNTRS76.js → chunk-6C6MS57P.js} +1 -1
- package/dist/{chunk-A22VQ5ZL.js → chunk-6CYB77VD.js} +111 -55
- package/dist/{chunk-QD73WATQ.js → chunk-6LRGZJFB.js} +21 -21
- package/dist/{chunk-Z4JVEL7R.js → chunk-A76GNRIK.js} +191 -2
- package/dist/{chunk-RE25RJ5A.js → chunk-B35OCFXH.js} +4 -4
- package/dist/{chunk-UKMLSQXA.js → chunk-CP34FI4B.js} +2 -2
- package/dist/{chunk-I7LKI4WO.js → chunk-DOD3A6EU.js} +6 -8
- package/dist/{chunk-N6FAXQDD.js → chunk-FAJ4R7IB.js} +1 -1
- package/dist/{chunk-U5RIXR7I.js → chunk-HB2KB7QL.js} +1 -1
- package/dist/{chunk-QV266EGS.js → chunk-HFQ7WSHZ.js} +11 -14
- package/dist/{chunk-QJPYJVL3.js → chunk-IRLTW6KF.js} +1 -1
- package/dist/{chunk-Y6SCMXR6.js → chunk-J44RPHUZ.js} +2 -2
- package/dist/{chunk-R6LBGKWQ.js → chunk-JQU6PMH4.js} +17 -15
- package/dist/{chunk-4DUEIUUO.js → chunk-K6CH5NVW.js} +1 -1
- package/dist/{chunk-XZWUOCJZ.js → chunk-LBNAGGLV.js} +1 -1
- package/dist/{chunk-XS33QBJA.js → chunk-LGXUGYUH.js} +50 -1
- package/dist/{chunk-XO3JR3OP.js → chunk-LX4NNYII.js} +2 -2
- package/dist/{chunk-XEVOPOKT.js → chunk-M4TVEMLH.js} +1 -1
- package/dist/{chunk-TY6IJY6I.js → chunk-NIXVMMJM.js} +1 -1
- package/dist/{chunk-VERXHIQF.js → chunk-NQGYPTJQ.js} +1 -1
- package/dist/{chunk-EMGGUO2Q.js → chunk-OBYC6SN4.js} +1 -1
- package/dist/{chunk-XUTSZYYJ.js → chunk-OPR2BPD4.js} +1 -4
- package/dist/{chunk-MC5WUOJJ.js → chunk-OUAE3GKO.js} +75 -1
- package/dist/{chunk-ATKGKAP6.js → chunk-QXIF6R4P.js} +16 -13
- package/dist/chunk-SI7GYBQP.js +15 -0
- package/dist/{chunk-VMQU7YEJ.js → chunk-SJLGOVC6.js} +1 -1
- package/dist/{chunk-54W7ELDQ.js → chunk-TZHDKRMG.js} +2 -2
- package/dist/{chunk-F4TMY6XI.js → chunk-V47GITZV.js} +3 -3
- package/dist/{chunk-L7NOG547.js → chunk-VZD2GEKB.js} +1 -1
- package/dist/{chunk-R3OZ5ISU.js → chunk-W2MG2P46.js} +4 -4
- package/dist/{chunk-E47WV7BJ.js → chunk-WU6LSXJ6.js} +2 -2
- package/dist/{chunk-NOVA7KZ2.js → chunk-XL3RKJYQ.js} +308 -35
- package/dist/{chunk-5GKNAQTG.js → chunk-XOOWC62T.js} +1 -1
- package/dist/{chunk-SKPXQRKN.js → chunk-XPPXOKIG.js} +1 -1
- package/dist/{chunk-HUGIKB5O.js → chunk-YJDRHQLG.js} +6 -6
- package/dist/src/index.js +11 -11
- package/package.json +1 -1
- package/dist/chunk-3AJIK5AO.js +0 -57
- package/dist/chunk-L4ZCFMWW.js +0 -177
- package/dist/chunk-VDI645ZX.js +0 -18
|
@@ -2,15 +2,16 @@ import {
|
|
|
2
2
|
CLAUDE_HOOK_EVENTS,
|
|
3
3
|
GEMINI_HOOK_EVENTS,
|
|
4
4
|
hasGeminiHooks
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-HFQ7WSHZ.js";
|
|
6
6
|
import {
|
|
7
7
|
CODEX_HOOK_EVENTS,
|
|
8
8
|
hasCodexHooks
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-XL3RKJYQ.js";
|
|
10
10
|
import {
|
|
11
11
|
CURSOR_GATE_EVENTS,
|
|
12
|
-
HOOK_LOCATOR_BINARY
|
|
13
|
-
|
|
12
|
+
HOOK_LOCATOR_BINARY,
|
|
13
|
+
hookCommandHoldBudget
|
|
14
|
+
} from "./chunk-OUAE3GKO.js";
|
|
14
15
|
|
|
15
16
|
// src/diagnostics/wiring.ts
|
|
16
17
|
var record = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -72,31 +73,20 @@ var toSeconds = (timeout, unit) => {
|
|
|
72
73
|
};
|
|
73
74
|
var registeredHooks = (entries, shape, unit) => {
|
|
74
75
|
if (!Array.isArray(entries)) return [];
|
|
75
|
-
return entries.flatMap((entry
|
|
76
|
+
return entries.flatMap((entry) => {
|
|
76
77
|
const container = record(entry);
|
|
77
78
|
if (!container) return [];
|
|
78
79
|
const hooks = shape === "nested" ? Array.isArray(container.hooks) ? container.hooks : [] : [container];
|
|
79
|
-
return hooks.flatMap((hook
|
|
80
|
+
return hooks.flatMap((hook) => {
|
|
80
81
|
const command = record(hook)?.command;
|
|
81
82
|
if (typeof command !== "string" || command.trim() === "") return [];
|
|
82
|
-
return [{
|
|
83
|
-
command,
|
|
84
|
-
timeoutSeconds: toSeconds(record(hook)?.timeout, unit),
|
|
85
|
-
order: [entryIndex, hookIndex]
|
|
86
|
-
}];
|
|
83
|
+
return [{ command, timeoutSeconds: toSeconds(record(hook)?.timeout, unit) }];
|
|
87
84
|
});
|
|
88
85
|
});
|
|
89
86
|
};
|
|
90
|
-
var runsBefore = (a, b) => a[0] < b[0] || a[0] === b[0] && a[1] < b[1];
|
|
91
87
|
var holdersOnEvent = (event, hooks) => {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return hooks.filter((hook) => pusharyHookExecutable(hook.command) === null).map((hook) => ({
|
|
95
|
-
event,
|
|
96
|
-
command: hook.command,
|
|
97
|
-
timeoutSeconds: hook.timeoutSeconds,
|
|
98
|
-
position: runsBefore(hook.order, ours.order) ? "before" : "after"
|
|
99
|
-
}));
|
|
88
|
+
if (!hooks.some((hook) => pusharyHookExecutable(hook.command) !== null)) return [];
|
|
89
|
+
return hooks.filter((hook) => pusharyHookExecutable(hook.command) === null).map((hook) => ({ event, command: hook.command, timeoutSeconds: hook.timeoutSeconds }));
|
|
100
90
|
};
|
|
101
91
|
var otherHolders = (hooks, events, shape, unit) => {
|
|
102
92
|
const table = record(hooks);
|
|
@@ -111,6 +101,14 @@ var claudeOtherHolders = (settings) => otherHolders(record(settings)?.hooks, CLA
|
|
|
111
101
|
var codexOtherHolders = (hooks) => otherHolders(record(hooks)?.hooks, CODEX_GATE_EVENTS, "nested", "seconds");
|
|
112
102
|
var geminiOtherHolders = (settings) => otherHolders(record(settings)?.hooks, GEMINI_GATE_EVENTS, "nested", "milliseconds");
|
|
113
103
|
var cursorOtherHolders = (userHooks) => otherHolders(record(userHooks)?.hooks, CURSOR_GATE_EVENTS, "flat", "seconds");
|
|
104
|
+
var holdEvents = (table) => table.filter((hook) => hook.holds).map((hook) => hook.event);
|
|
105
|
+
var unprovenHolds = (hooks, events) => {
|
|
106
|
+
const table = record(hooks);
|
|
107
|
+
if (!table) return [];
|
|
108
|
+
return events.filter((event) => registeredHooks(table[event], "nested", "seconds").some((hook) => pusharyHookExecutable(hook.command) !== null && hookCommandHoldBudget(hook.command) === void 0));
|
|
109
|
+
};
|
|
110
|
+
var claudeUnprovenHolds = (settings) => unprovenHolds(record(settings)?.hooks, holdEvents(CLAUDE_HOOK_EVENTS));
|
|
111
|
+
var codexUnprovenHolds = (hooks) => unprovenHolds(record(hooks)?.hooks, holdEvents(CODEX_HOOK_EVENTS));
|
|
114
112
|
var holdsLong = (holder) => holder.timeoutSeconds !== null && holder.timeoutSeconds > LONG_HOLD_SECONDS;
|
|
115
113
|
var SHELLS = /* @__PURE__ */ new Set(["/bin/sh", "/bin/bash", "/bin/zsh", "/usr/bin/env"]);
|
|
116
114
|
var holderExecutable = (command) => {
|
|
@@ -125,7 +123,7 @@ var describeHoldTimeout = (holder) => {
|
|
|
125
123
|
if (seconds >= 60 && seconds % 60 === 0) return `${seconds / 60}m timeout`;
|
|
126
124
|
return `${seconds}s timeout`;
|
|
127
125
|
};
|
|
128
|
-
var describeOtherHolder = (holder) => `another hook on ${holder.event}: ${holderExecutable(holder.command)} (${describeHoldTimeout(holder)}
|
|
126
|
+
var describeOtherHolder = (holder) => `another hook also registered on ${holder.event}: ${holderExecutable(holder.command)} (${describeHoldTimeout(holder)})`;
|
|
129
127
|
var describeHoldSentence = (agentLabel) => `${agentLabel} waits for every hook on an event, so the terminal cannot move until that one returns, however fast your phone answered.`;
|
|
130
128
|
|
|
131
129
|
export {
|
|
@@ -139,6 +137,8 @@ export {
|
|
|
139
137
|
codexOtherHolders,
|
|
140
138
|
geminiOtherHolders,
|
|
141
139
|
cursorOtherHolders,
|
|
140
|
+
claudeUnprovenHolds,
|
|
141
|
+
codexUnprovenHolds,
|
|
142
142
|
holdsLong,
|
|
143
143
|
describeOtherHolder,
|
|
144
144
|
describeHoldSentence
|
|
@@ -3,9 +3,10 @@ import {
|
|
|
3
3
|
AGENT_LABELS_BY_TYPE,
|
|
4
4
|
DECISION_LINE_MAX,
|
|
5
5
|
FILE_TARGET_TOOLS,
|
|
6
|
+
GATE_MAX_TOOL_INPUTS,
|
|
6
7
|
redactSecrets,
|
|
7
8
|
redactSecretsDeep
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-OUAE3GKO.js";
|
|
9
10
|
|
|
10
11
|
// ../hook-mapping/src/describe.ts
|
|
11
12
|
import { isAbsolute, relative, resolve } from "path";
|
|
@@ -173,6 +174,90 @@ var OPENCODE_TOOL_NAMES = {
|
|
|
173
174
|
websearch: "WebSearch",
|
|
174
175
|
task: "Task"
|
|
175
176
|
};
|
|
177
|
+
var canonicalGateInputs = (source, toolName, toolInputs, cwd) => {
|
|
178
|
+
if (source === "codex" && toolName === "apply_patch" || source === "vscode" && ["apply_patch", "applyPatch", "copilot_applyPatch"].includes(toolName)) {
|
|
179
|
+
const paths = [...new Set(toolInputs.flatMap((input) => parseApplyPatchFiles(input.command ?? input.input ?? input.patch)))];
|
|
180
|
+
if (paths.length > GATE_MAX_TOOL_INPUTS) return null;
|
|
181
|
+
return {
|
|
182
|
+
toolName: "Edit",
|
|
183
|
+
toolInputs: paths.length === 0 ? toolInputs.map((input) => ({ file_path: input.command })) : paths.map((path) => ({ file_path: cwd && !isAbsolute(path) ? resolve(cwd, path) : path }))
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
if (source === "opencode") {
|
|
187
|
+
const canonical2 = OPENCODE_TOOL_NAMES[toolName] ?? toolName;
|
|
188
|
+
return {
|
|
189
|
+
toolName: canonical2,
|
|
190
|
+
toolInputs: toolInputs.map((input) => {
|
|
191
|
+
const path = input.file_path;
|
|
192
|
+
return typeof path === "string" && path.length > 0 && cwd && !isAbsolute(path) ? { ...input, file_path: resolve(cwd, path) } : input;
|
|
193
|
+
})
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
if (source === "vscode" || source === "cursor") {
|
|
197
|
+
if (source === "vscode" && toolName.startsWith("mcp_pushary_")) return { toolName: `mcp__pushary__${toolName.slice("mcp_pushary_".length)}`, toolInputs };
|
|
198
|
+
const alias = toolName.replace(/^copilot_/, "").toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
199
|
+
const shells = [
|
|
200
|
+
"runterminalcommand",
|
|
201
|
+
"runinterminal",
|
|
202
|
+
"runcommand",
|
|
203
|
+
"terminalcommand",
|
|
204
|
+
"executecommand",
|
|
205
|
+
"runinterminalcommand",
|
|
206
|
+
"bash",
|
|
207
|
+
"shell",
|
|
208
|
+
"terminal",
|
|
209
|
+
"sendtoterminal",
|
|
210
|
+
"powershell",
|
|
211
|
+
"localshell"
|
|
212
|
+
];
|
|
213
|
+
const canonical2 = shells.includes(alias) ? "Bash" : ["createfile", "write", "createdirectory", "createnewjupyternotebook"].includes(alias) ? "Write" : ["replacestringinfile", "multireplacestringinfile", "replacestring", "multireplacestring", "inserteditintofile", "insertedit", "edit", "editfile", "editfiles", "editnotebookfile", "editnotebook"].includes(alias) ? "Edit" : [
|
|
214
|
+
"readfile",
|
|
215
|
+
"viewimage",
|
|
216
|
+
"listdir",
|
|
217
|
+
"listdirectory",
|
|
218
|
+
"filesearch",
|
|
219
|
+
"findfiles",
|
|
220
|
+
"grepsearch",
|
|
221
|
+
"findtextinfiles",
|
|
222
|
+
"semanticsearch",
|
|
223
|
+
"searchcodebase",
|
|
224
|
+
"searchworkspacesymbols",
|
|
225
|
+
"geterrors",
|
|
226
|
+
"getchangedfiles",
|
|
227
|
+
"readprojectstructure",
|
|
228
|
+
"getnotebooksummary",
|
|
229
|
+
"readnotebookcelloutput",
|
|
230
|
+
"testsearch",
|
|
231
|
+
"findtestfiles",
|
|
232
|
+
"testfailure",
|
|
233
|
+
"getvscodeapi",
|
|
234
|
+
"getterminaloutput",
|
|
235
|
+
"gettaskoutput",
|
|
236
|
+
"terminalselection",
|
|
237
|
+
"terminallastcommand"
|
|
238
|
+
].includes(alias) ? "Read" : toolName;
|
|
239
|
+
const inputs = toolInputs.flatMap((input) => ["multireplacestringinfile", "multireplacestring"].includes(alias) && Array.isArray(input.replacements) ? input.replacements.filter((item) => !!item && typeof item === "object" && !Array.isArray(item)) : alias === "editfiles" && Array.isArray(input.files) ? input.files.map((file) => typeof file === "string" ? { file_path: file } : file).filter((file) => !!file && typeof file === "object" && !Array.isArray(file)) : [input]);
|
|
240
|
+
if (inputs.length > GATE_MAX_TOOL_INPUTS) return null;
|
|
241
|
+
return { toolName: canonical2, toolInputs: inputs.map((input) => {
|
|
242
|
+
if (canonical2 === "Bash") return { ...input, command: [input.command, input.commandLine, input.command_line, input.cmd, input.script, input.input, input.text].find((value) => typeof value === "string") };
|
|
243
|
+
const path = input.file_path ?? input.filePath ?? input.path;
|
|
244
|
+
return typeof path === "string" ? { ...input, file_path: cwd && !isAbsolute(path) ? resolve(cwd, path) : path } : input;
|
|
245
|
+
}) };
|
|
246
|
+
}
|
|
247
|
+
if (source !== "gemini") return { toolName, toolInputs };
|
|
248
|
+
if (toolName === "run_shell_command") {
|
|
249
|
+
return { toolName: "Bash", toolInputs: toolInputs.map((input) => ({ command: input.command })) };
|
|
250
|
+
}
|
|
251
|
+
const canonical = { write_file: "Write", replace: "Edit", read_file: "Read" }[toolName];
|
|
252
|
+
if (!canonical) return { toolName, toolInputs };
|
|
253
|
+
return {
|
|
254
|
+
toolName: canonical,
|
|
255
|
+
toolInputs: toolInputs.map((input) => {
|
|
256
|
+
const path = [input.file_path, input.absolute_path, input.path].find((value) => typeof value === "string" && value.length > 0);
|
|
257
|
+
return path ? { file_path: cwd && !isAbsolute(path) ? resolve(cwd, path) : path } : {};
|
|
258
|
+
})
|
|
259
|
+
};
|
|
260
|
+
};
|
|
176
261
|
var EXIT_CODE_FAILURE = /^Error: Exit code \d+/;
|
|
177
262
|
var isToolResultError = (toolResult) => {
|
|
178
263
|
try {
|
|
@@ -388,6 +473,105 @@ var sessionIdentityOf = (payload) => {
|
|
|
388
473
|
return { sessionId: agentId, parentSessionId: sessionId };
|
|
389
474
|
};
|
|
390
475
|
|
|
476
|
+
// ../hook-mapping/src/codex-rollout.ts
|
|
477
|
+
var CODEX_TURN_CONTEXT_TYPE = "turn_context";
|
|
478
|
+
var CODEX_AUTO_REVIEWER = "auto_review";
|
|
479
|
+
var CODEX_GUARDIAN_THREAD_SOURCE = "guardian_review";
|
|
480
|
+
var CODEX_PLANNED_ACTION_MARKER = "Planned action JSON:\n";
|
|
481
|
+
var CODEX_APPROVAL_REQUEST_END = ">>> APPROVAL REQUEST END";
|
|
482
|
+
var CODEX_SHELL_TOOL = "exec_command";
|
|
483
|
+
var CODEX_SHELL_COMMAND_FLAGS = ["-lc", "-c"];
|
|
484
|
+
var asRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
485
|
+
var parseRecord = (text) => {
|
|
486
|
+
try {
|
|
487
|
+
return asRecord(JSON.parse(text));
|
|
488
|
+
} catch {
|
|
489
|
+
return null;
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
var nonEmptyString = (value) => typeof value === "string" && value.length > 0 ? value : void 0;
|
|
493
|
+
var isTimestamp = (value) => typeof value === "string" && Number.isFinite(Date.parse(value));
|
|
494
|
+
var readCodexTurnContext = (line) => {
|
|
495
|
+
const entry = parseRecord(line);
|
|
496
|
+
if (entry?.type !== CODEX_TURN_CONTEXT_TYPE) return null;
|
|
497
|
+
const payload = asRecord(entry.payload);
|
|
498
|
+
const turnId = nonEmptyString(payload?.turn_id);
|
|
499
|
+
if (!payload || !turnId) return null;
|
|
500
|
+
return {
|
|
501
|
+
turnId,
|
|
502
|
+
approvalsReviewer: payload.approvals_reviewer === CODEX_AUTO_REVIEWER ? "auto_review" : "user",
|
|
503
|
+
...isTimestamp(entry.timestamp) ? { startedAt: entry.timestamp } : {}
|
|
504
|
+
};
|
|
505
|
+
};
|
|
506
|
+
var isCodexGuardianRolloutHead = (line, sessionId) => {
|
|
507
|
+
if (!sessionId) return false;
|
|
508
|
+
const entry = parseRecord(line);
|
|
509
|
+
const payload = asRecord(entry?.payload);
|
|
510
|
+
return entry?.type === "session_meta" && payload?.parent_thread_id === sessionId && payload.thread_source === CODEX_GUARDIAN_THREAD_SOURCE;
|
|
511
|
+
};
|
|
512
|
+
var readCodexPlannedAction = (message) => {
|
|
513
|
+
const marker = message.lastIndexOf(CODEX_PLANNED_ACTION_MARKER);
|
|
514
|
+
if (marker < 0) return null;
|
|
515
|
+
const body = message.slice(marker + CODEX_PLANNED_ACTION_MARKER.length);
|
|
516
|
+
const end = body.lastIndexOf(CODEX_APPROVAL_REQUEST_END);
|
|
517
|
+
if (end < 0 || body.slice(end + CODEX_APPROVAL_REQUEST_END.length).trim().length > 0) return null;
|
|
518
|
+
return parseRecord(body.slice(0, end).trim());
|
|
519
|
+
};
|
|
520
|
+
var readCodexReviewVerdict = (message) => {
|
|
521
|
+
const verdict = parseRecord(message.trim());
|
|
522
|
+
if (verdict?.outcome !== "allow" && verdict?.outcome !== "deny") return null;
|
|
523
|
+
const rationale = typeof verdict.rationale === "string" ? verdict.rationale.trim() : "";
|
|
524
|
+
return { outcome: verdict.outcome, ...rationale ? { rationale } : {} };
|
|
525
|
+
};
|
|
526
|
+
var scanCodexGuardianReviews = (lines) => {
|
|
527
|
+
const reviews = [];
|
|
528
|
+
let pending = null;
|
|
529
|
+
for (const line of lines) {
|
|
530
|
+
const entry = parseRecord(line.text);
|
|
531
|
+
const payload = asRecord(entry?.payload);
|
|
532
|
+
if (entry?.type !== "event_msg" || typeof payload?.message !== "string") continue;
|
|
533
|
+
if (payload.type === "user_message") {
|
|
534
|
+
const plannedAction = readCodexPlannedAction(payload.message);
|
|
535
|
+
pending = plannedAction ? { offset: line.offset, plannedAction, ...isTimestamp(entry.timestamp) ? { requestedAt: entry.timestamp } : {} } : null;
|
|
536
|
+
continue;
|
|
537
|
+
}
|
|
538
|
+
if (payload.type !== "agent_message" || !pending) continue;
|
|
539
|
+
const verdict = readCodexReviewVerdict(payload.message);
|
|
540
|
+
if (!verdict) continue;
|
|
541
|
+
reviews.push({ ...pending, verdict });
|
|
542
|
+
pending = null;
|
|
543
|
+
}
|
|
544
|
+
return { reviews, ...pending ? { pendingOffset: pending.offset } : {} };
|
|
545
|
+
};
|
|
546
|
+
var codexPlannedShellCommand = (plannedAction) => {
|
|
547
|
+
if (plannedAction?.tool !== CODEX_SHELL_TOOL) return null;
|
|
548
|
+
const argv = plannedAction.command;
|
|
549
|
+
if (!Array.isArray(argv) || argv.length !== 3) return null;
|
|
550
|
+
const [shell, flag, command] = argv;
|
|
551
|
+
if (typeof shell !== "string" || shell.trim().length === 0) return null;
|
|
552
|
+
if (typeof flag !== "string" || !CODEX_SHELL_COMMAND_FLAGS.includes(flag)) return null;
|
|
553
|
+
if (typeof command !== "string" || command.trim().length === 0) return null;
|
|
554
|
+
const cwd = nonEmptyString(plannedAction.cwd);
|
|
555
|
+
return { command, ...cwd ? { cwd } : {} };
|
|
556
|
+
};
|
|
557
|
+
var codexReviewerDenialsSince = (reviews, since) => {
|
|
558
|
+
const sinceMs = Date.parse(since);
|
|
559
|
+
if (!Number.isFinite(sinceMs)) return [];
|
|
560
|
+
return reviews.flatMap((review) => {
|
|
561
|
+
if (review.verdict.outcome !== "deny" || !review.requestedAt) return [];
|
|
562
|
+
if (Date.parse(review.requestedAt) < sinceMs) return [];
|
|
563
|
+
const shell = codexPlannedShellCommand(review.plannedAction);
|
|
564
|
+
if (!shell) return [];
|
|
565
|
+
return [{
|
|
566
|
+
...shell,
|
|
567
|
+
offset: review.offset,
|
|
568
|
+
requestedAt: review.requestedAt,
|
|
569
|
+
plannedAction: review.plannedAction,
|
|
570
|
+
...review.verdict.rationale ? { rationale: review.verdict.rationale } : {}
|
|
571
|
+
}];
|
|
572
|
+
});
|
|
573
|
+
};
|
|
574
|
+
|
|
391
575
|
export {
|
|
392
576
|
HOOK_FALLBACK_MAX,
|
|
393
577
|
UNNAMED_ACTION,
|
|
@@ -396,6 +580,7 @@ export {
|
|
|
396
580
|
parseApplyPatchOps,
|
|
397
581
|
parseApplyPatchFiles,
|
|
398
582
|
OPENCODE_TOOL_NAMES,
|
|
583
|
+
canonicalGateInputs,
|
|
399
584
|
isToolResultError,
|
|
400
585
|
toolResultErrorText,
|
|
401
586
|
deriveReceiptMeta,
|
|
@@ -415,5 +600,9 @@ export {
|
|
|
415
600
|
notificationAction,
|
|
416
601
|
describeStopFailure,
|
|
417
602
|
permissionDeniedAction,
|
|
418
|
-
sessionIdentityOf
|
|
603
|
+
sessionIdentityOf,
|
|
604
|
+
readCodexTurnContext,
|
|
605
|
+
isCodexGuardianRolloutHead,
|
|
606
|
+
scanCodexGuardianReviews,
|
|
607
|
+
codexReviewerDenialsSince
|
|
419
608
|
};
|
|
@@ -2,24 +2,24 @@ import {
|
|
|
2
2
|
detectProviderLiveCapabilities,
|
|
3
3
|
hasSpawnProvider,
|
|
4
4
|
resolveControlPolicy
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-TZHDKRMG.js";
|
|
6
6
|
import {
|
|
7
7
|
daemonHasRemoteProof,
|
|
8
8
|
daemonServiceManagerAvailable,
|
|
9
9
|
hasDaemonServiceDefinition,
|
|
10
10
|
readDaemonNeedsLogin,
|
|
11
11
|
readDaemonStatus
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-DOD3A6EU.js";
|
|
13
13
|
import {
|
|
14
14
|
getMachineId
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-WU6LSXJ6.js";
|
|
16
16
|
import {
|
|
17
17
|
getPackageVersion
|
|
18
18
|
} from "./chunk-DINDL2CF.js";
|
|
19
19
|
import {
|
|
20
20
|
readControlMode,
|
|
21
21
|
readKeySource
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-SJLGOVC6.js";
|
|
23
23
|
import {
|
|
24
24
|
getBaseUrl
|
|
25
25
|
} from "./chunk-2UMNXADU.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SETUP_FLAGS
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LBNAGGLV.js";
|
|
4
4
|
import {
|
|
5
5
|
parseFlags
|
|
6
6
|
} from "./chunk-GMXKITVA.js";
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
CLAUDE_CONNECTOR_URL,
|
|
15
15
|
COWORK_CONNECTOR_LIMIT,
|
|
16
16
|
COWORK_STANDING_INSTRUCTIONS
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-OUAE3GKO.js";
|
|
18
18
|
|
|
19
19
|
// src/cli/cowork.ts
|
|
20
20
|
import { readFileSync } from "fs";
|
|
@@ -2,27 +2,25 @@ import {
|
|
|
2
2
|
needsShell,
|
|
3
3
|
spawnClaude
|
|
4
4
|
} from "./chunk-XHKBHWLX.js";
|
|
5
|
-
import {
|
|
6
|
-
resolveGlobalBinary
|
|
7
|
-
} from "./chunk-L4ZCFMWW.js";
|
|
8
5
|
import {
|
|
9
6
|
getMachineId
|
|
10
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-WU6LSXJ6.js";
|
|
11
8
|
import {
|
|
12
|
-
pusharyDir
|
|
13
|
-
|
|
9
|
+
pusharyDir,
|
|
10
|
+
resolveGlobalBinary
|
|
11
|
+
} from "./chunk-XL3RKJYQ.js";
|
|
14
12
|
import {
|
|
15
13
|
getPackageVersion
|
|
16
14
|
} from "./chunk-DINDL2CF.js";
|
|
17
15
|
import {
|
|
18
16
|
readControlMode
|
|
19
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-SJLGOVC6.js";
|
|
20
18
|
import {
|
|
21
19
|
readJsonSafe,
|
|
22
20
|
writeFileAtomic,
|
|
23
21
|
writeJsonAtomic,
|
|
24
22
|
writeJsonAtomicDurable
|
|
25
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-VZD2GEKB.js";
|
|
26
24
|
import {
|
|
27
25
|
getApiKey
|
|
28
26
|
} from "./chunk-2UMNXADU.js";
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
NOTIFICATION_MATCHED_TYPES,
|
|
3
|
-
POSTTOOLUSE_MIRRORED_TOOLS
|
|
4
|
-
|
|
5
|
-
} from "./chunk-XUTSZYYJ.js";
|
|
3
|
+
POSTTOOLUSE_MIRRORED_TOOLS
|
|
4
|
+
} from "./chunk-OPR2BPD4.js";
|
|
6
5
|
import {
|
|
7
|
-
isProtectedByScope
|
|
8
|
-
|
|
6
|
+
isProtectedByScope,
|
|
7
|
+
registerHookEntry
|
|
8
|
+
} from "./chunk-XL3RKJYQ.js";
|
|
9
9
|
import {
|
|
10
|
+
CLAUDE_PRETOOLUSE_MATCHER,
|
|
10
11
|
HOOK_BUDGETS,
|
|
11
|
-
HOOK_LOCATOR_BINARY
|
|
12
|
-
|
|
13
|
-
} from "./chunk-MC5WUOJJ.js";
|
|
12
|
+
HOOK_LOCATOR_BINARY
|
|
13
|
+
} from "./chunk-OUAE3GKO.js";
|
|
14
14
|
|
|
15
15
|
// src/gemini-config.ts
|
|
16
16
|
var GEMINI_HOOK_BINARY = "pushary-gemini-hook";
|
|
@@ -52,8 +52,7 @@ var addGeminiHooks = (settings, command) => {
|
|
|
52
52
|
const hooks = ensureRecord(settings, "hooks");
|
|
53
53
|
for (const definition of GEMINI_HOOK_EVENTS) {
|
|
54
54
|
const existing = Array.isArray(hooks[definition.event]) ? hooks[definition.event] : [];
|
|
55
|
-
|
|
56
|
-
entries.push({
|
|
55
|
+
hooks[definition.event] = registerHookEntry(existing, isPusharyGeminiHook, {
|
|
57
56
|
...definition.matcher ? { matcher: definition.matcher } : {},
|
|
58
57
|
hooks: [{
|
|
59
58
|
name: "pushary",
|
|
@@ -62,7 +61,6 @@ var addGeminiHooks = (settings, command) => {
|
|
|
62
61
|
timeout: definition.timeoutMs
|
|
63
62
|
}]
|
|
64
63
|
});
|
|
65
|
-
hooks[definition.event] = entries;
|
|
66
64
|
}
|
|
67
65
|
};
|
|
68
66
|
var removeGeminiHooks = (settings, scope) => {
|
|
@@ -128,12 +126,11 @@ var atLeast = (version, floor) => compareVersion(version, floor) >= 0;
|
|
|
128
126
|
var formatVersion = (version) => version.join(".");
|
|
129
127
|
|
|
130
128
|
// src/claude-events.ts
|
|
131
|
-
var GATED_TOOLS = [...PRETOOLUSE_GATED_TOOLS, ...PRETOOLUSE_PHONE_ANSWERED_TOOLS].join("|");
|
|
132
129
|
var MIRRORED_TOOLS = POSTTOOLUSE_MIRRORED_TOOLS.join("|");
|
|
133
130
|
var ESTABLISHED = [1, 0, 0];
|
|
134
131
|
var OBSERVED = [2, 0, 0];
|
|
135
132
|
var CLAUDE_HOOK_EVENTS = [
|
|
136
|
-
{ event: "PreToolUse", binary: "pushary-hook", matcher:
|
|
133
|
+
{ event: "PreToolUse", binary: "pushary-hook", matcher: CLAUDE_PRETOOLUSE_MATCHER, timeout: HOOK_BUDGETS.claude.budgetSeconds, delivery: "approval", since: ESTABLISHED },
|
|
137
134
|
{ event: "PostToolUse", binary: "pushary-post-hook", matcher: MIRRORED_TOOLS, timeout: 10, delivery: "telemetry", since: ESTABLISHED },
|
|
138
135
|
{ event: "Stop", binary: "pushary-stop-hook", timeout: 10, delivery: "telemetry", since: ESTABLISHED },
|
|
139
136
|
{ event: "UserPromptSubmit", binary: "pushary-prompt-hook", timeout: 10, delivery: "telemetry", since: ESTABLISHED },
|
|
@@ -142,7 +139,7 @@ var CLAUDE_HOOK_EVENTS = [
|
|
|
142
139
|
{ event: "SessionEnd", binary: "pushary-session-end-hook", timeout: 10, delivery: "telemetry", since: ESTABLISHED },
|
|
143
140
|
{ event: "StopFailure", binary: "pushary-stopfailure-hook", timeout: 10, delivery: "telemetry", since: ESTABLISHED },
|
|
144
141
|
{ event: "PermissionRequest", binary: "pushary-permission-hook", timeout: HOOK_BUDGETS.claude.budgetSeconds, delivery: "approval", since: ESTABLISHED },
|
|
145
|
-
{ event: "PermissionDenied", binary: "pushary-permission-denied-hook", timeout:
|
|
142
|
+
{ event: "PermissionDenied", binary: "pushary-permission-denied-hook", timeout: HOOK_BUDGETS.claude.budgetSeconds, delivery: "approval", holds: true, since: ESTABLISHED },
|
|
146
143
|
// Observability only. Each carries session shape the island cannot get any other
|
|
147
144
|
// way, and none of them decides anything.
|
|
148
145
|
{ event: "SubagentStart", binary: "pushary-session-start-hook", timeout: 10, delivery: "telemetry", since: OBSERVED },
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
detectClaudeVersion
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-K6CH5NVW.js";
|
|
4
4
|
import {
|
|
5
5
|
addClaudeMcpServer,
|
|
6
6
|
addPusharyHooks,
|
|
7
7
|
addPusharyToolPermissions
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-QXIF6R4P.js";
|
|
9
9
|
import {
|
|
10
10
|
claudeWired,
|
|
11
11
|
codexWired,
|
|
12
12
|
geminiWired
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-6LRGZJFB.js";
|
|
14
14
|
import {
|
|
15
15
|
CLAUDE_HOOK_EVENTS,
|
|
16
16
|
GEMINI_HOOK_BINARY,
|
|
@@ -21,14 +21,7 @@ import {
|
|
|
21
21
|
needsReregistration,
|
|
22
22
|
registrationSignatures,
|
|
23
23
|
supportedClaudeEvents
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import {
|
|
26
|
-
guardBinary
|
|
27
|
-
} from "./chunk-3AJIK5AO.js";
|
|
28
|
-
import {
|
|
29
|
-
resolveGlobalBinDir,
|
|
30
|
-
resolveGlobalBinary
|
|
31
|
-
} from "./chunk-L4ZCFMWW.js";
|
|
24
|
+
} from "./chunk-HFQ7WSHZ.js";
|
|
32
25
|
import {
|
|
33
26
|
CODEX_HOOK_BINARY,
|
|
34
27
|
addCodexHookTrust,
|
|
@@ -38,16 +31,21 @@ import {
|
|
|
38
31
|
codexConfigToml,
|
|
39
32
|
codexHookPositions,
|
|
40
33
|
codexHooksJson,
|
|
34
|
+
codexVacatedIndexes,
|
|
35
|
+
dropVacatedCodexHookTrust,
|
|
36
|
+
guardBinary,
|
|
41
37
|
hasCodexHooks,
|
|
38
|
+
resolveGlobalBinDir,
|
|
39
|
+
resolveGlobalBinary,
|
|
42
40
|
vscodePluginMcp
|
|
43
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-XL3RKJYQ.js";
|
|
44
42
|
import {
|
|
45
43
|
readJsonSafe,
|
|
46
44
|
writeJsonAtomic
|
|
47
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-VZD2GEKB.js";
|
|
48
46
|
import {
|
|
49
47
|
HOOK_LOCATOR_BINARY
|
|
50
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-OUAE3GKO.js";
|
|
51
49
|
|
|
52
50
|
// src/reapply.ts
|
|
53
51
|
import { join } from "path";
|
|
@@ -218,6 +216,7 @@ var reapplyCodexSettings = (apiKey, paths = {}) => {
|
|
|
218
216
|
const command = guardBinary(resolveGlobalBinary(CODEX_HOOK_BINARY) ?? CODEX_HOOK_BINARY);
|
|
219
217
|
let hooks = false;
|
|
220
218
|
let mcp = false;
|
|
219
|
+
const vacated = codexVacatedIndexes(hooksConfig ?? void 0);
|
|
221
220
|
if (hooksConfig != null) {
|
|
222
221
|
try {
|
|
223
222
|
addCodexHooks(hooksConfig, command);
|
|
@@ -228,7 +227,10 @@ var reapplyCodexSettings = (apiKey, paths = {}) => {
|
|
|
228
227
|
}
|
|
229
228
|
if (config != null) {
|
|
230
229
|
try {
|
|
231
|
-
if (hooks)
|
|
230
|
+
if (hooks) {
|
|
231
|
+
dropVacatedCodexHookTrust(config, hooksPath, vacated);
|
|
232
|
+
addCodexHookTrust(config, hooksPath, command, codexHookPositions(hooksConfig ?? void 0));
|
|
233
|
+
}
|
|
232
234
|
if (apiKey) {
|
|
233
235
|
addCodexMcpServer(config, apiKey);
|
|
234
236
|
mcp = true;
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from "./chunk-7QLSKOSU.js";
|
|
7
7
|
import {
|
|
8
8
|
isValidApiKey
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-OUAE3GKO.js";
|
|
10
10
|
|
|
11
11
|
// src/setup/options.ts
|
|
12
12
|
var AGENT_CHOICES = ["claude_code", "codex", "gemini_cli", "hermes", "cursor", "vscode", "opencode", "custom"];
|