@mnemonik/codex-hooks 0.1.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/dist/hook.d.ts +2 -0
- package/dist/hook.js +306 -0
- package/dist/hook.js.map +1 -0
- package/dist/install.d.ts +3 -0
- package/dist/install.js +109 -0
- package/dist/install.js.map +1 -0
- package/dist/lib/applyPatch.d.ts +6 -0
- package/dist/lib/applyPatch.js +58 -0
- package/dist/lib/applyPatch.js.map +1 -0
- package/dist/lib/codexOutput.d.ts +6 -0
- package/dist/lib/codexOutput.js +46 -0
- package/dist/lib/codexOutput.js.map +1 -0
- package/dist/lib/env.d.ts +4 -0
- package/dist/lib/env.js +78 -0
- package/dist/lib/env.js.map +1 -0
- package/dist/lib/http.d.ts +46 -0
- package/dist/lib/http.js +153 -0
- package/dist/lib/http.js.map +1 -0
- package/dist/lib/shellTokens.d.ts +6 -0
- package/dist/lib/shellTokens.js +173 -0
- package/dist/lib/shellTokens.js.map +1 -0
- package/dist/lib/types.d.ts +78 -0
- package/dist/lib/types.js +9 -0
- package/dist/lib/types.js.map +1 -0
- package/package.json +33 -0
package/dist/hook.d.ts
ADDED
package/dist/hook.js
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { stdout, stderr, stdin, exit } from 'node:process';
|
|
4
|
+
import { relative } from 'node:path';
|
|
5
|
+
import { extractToolFileTargets } from './lib/applyPatch.js';
|
|
6
|
+
import { additionalContext, continueStop, denyPreToolUse, systemMessage, trimContext, } from './lib/codexOutput.js';
|
|
7
|
+
import { isNonInteractive, parseBypass, resolveConfig } from './lib/env.js';
|
|
8
|
+
import { fetchHookContext, fetchSnapshot, reportBypass, reportGateFired, trackIdeEdit, } from './lib/http.js';
|
|
9
|
+
import { BUILT_IN_DESTRUCTIVE, matchCommand, tokenize } from './lib/shellTokens.js';
|
|
10
|
+
const POLICY_DEDUP_WINDOW_MS = 60_000;
|
|
11
|
+
const MUST_CONFIRM_DEDUP_WINDOW_MS = 60_000;
|
|
12
|
+
async function readStdin() {
|
|
13
|
+
return new Promise((res) => {
|
|
14
|
+
let buf = '';
|
|
15
|
+
let settled = false;
|
|
16
|
+
const finish = (value) => {
|
|
17
|
+
if (settled)
|
|
18
|
+
return;
|
|
19
|
+
settled = true;
|
|
20
|
+
res(value);
|
|
21
|
+
};
|
|
22
|
+
stdin.setEncoding('utf8');
|
|
23
|
+
stdin.on('data', (chunk) => {
|
|
24
|
+
buf += chunk;
|
|
25
|
+
if (buf.length > 1_048_576)
|
|
26
|
+
finish(null);
|
|
27
|
+
});
|
|
28
|
+
stdin.on('end', () => {
|
|
29
|
+
try {
|
|
30
|
+
finish(JSON.parse(buf));
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
finish(null);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
stdin.on('error', () => finish(null));
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function writeOutput(output) {
|
|
40
|
+
if (output)
|
|
41
|
+
stdout.write(JSON.stringify(output));
|
|
42
|
+
exit(0);
|
|
43
|
+
}
|
|
44
|
+
function writeAllow() {
|
|
45
|
+
exit(0);
|
|
46
|
+
}
|
|
47
|
+
function warnAndAllow(message) {
|
|
48
|
+
stderr.write(`mnemonik-codex-hook: ${message}\n`);
|
|
49
|
+
exit(0);
|
|
50
|
+
}
|
|
51
|
+
function sessionId(input) {
|
|
52
|
+
return input.session_id ?? input.turn_id ?? 'codex-unknown-session';
|
|
53
|
+
}
|
|
54
|
+
async function emitGateFired(input, config, tool, mode, outcome) {
|
|
55
|
+
await reportGateFired({
|
|
56
|
+
server: config.server,
|
|
57
|
+
apiKey: config.apiKey,
|
|
58
|
+
cwd: input.cwd,
|
|
59
|
+
codexSessionId: sessionId(input),
|
|
60
|
+
tool,
|
|
61
|
+
mode,
|
|
62
|
+
outcome,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function covered(snapshot, cwd, absolutePath) {
|
|
66
|
+
const rel = relative(cwd, absolutePath);
|
|
67
|
+
return snapshot.coveredFiles.includes(absolutePath) || snapshot.coveredFiles.includes(rel);
|
|
68
|
+
}
|
|
69
|
+
async function getSnapshotOrFailOpen(input, config, tool, mode) {
|
|
70
|
+
if (!config.apiKey) {
|
|
71
|
+
warnAndAllow('MNEMONIK_API_KEY missing - fail-open. Run mnemonik-codex-hooks install.');
|
|
72
|
+
}
|
|
73
|
+
const snapshot = await fetchSnapshot({
|
|
74
|
+
server: config.server,
|
|
75
|
+
apiKey: config.apiKey,
|
|
76
|
+
cwd: input.cwd,
|
|
77
|
+
codexSessionId: sessionId(input),
|
|
78
|
+
});
|
|
79
|
+
if (!snapshot) {
|
|
80
|
+
await emitGateFired(input, config, tool, mode, 'unreachable');
|
|
81
|
+
warnAndAllow('mnemonik server unreachable - fail-open.');
|
|
82
|
+
}
|
|
83
|
+
if (!snapshot.ok && snapshot.reason !== 'no_active_session') {
|
|
84
|
+
await emitGateFired(input, config, tool, mode, snapshot.reason ?? 'snapshot_not_ok');
|
|
85
|
+
writeAllow();
|
|
86
|
+
}
|
|
87
|
+
return snapshot;
|
|
88
|
+
}
|
|
89
|
+
async function handleContextEvent(input, config) {
|
|
90
|
+
if (config.contextualHooks.promptContext === 'off')
|
|
91
|
+
writeAllow();
|
|
92
|
+
if (!config.apiKey)
|
|
93
|
+
writeAllow();
|
|
94
|
+
const ctx = await fetchHookContext({
|
|
95
|
+
server: config.server,
|
|
96
|
+
apiKey: config.apiKey,
|
|
97
|
+
cwd: input.cwd,
|
|
98
|
+
codexSessionId: sessionId(input),
|
|
99
|
+
event: input.hook_event_name,
|
|
100
|
+
prompt: input.prompt,
|
|
101
|
+
toolName: input.tool_name,
|
|
102
|
+
});
|
|
103
|
+
if (!ctx?.ok || !ctx.additionalContext)
|
|
104
|
+
writeAllow();
|
|
105
|
+
writeOutput(additionalContext(input.hook_event_name, trimContext(ctx.additionalContext)));
|
|
106
|
+
}
|
|
107
|
+
async function handlePreEdit(input, config) {
|
|
108
|
+
const mode = config.contextualHooks.preEditGate;
|
|
109
|
+
const tool = input.tool_name ?? 'apply_patch';
|
|
110
|
+
if (mode === 'off') {
|
|
111
|
+
await emitGateFired(input, config, tool, 'off', 'off');
|
|
112
|
+
writeAllow();
|
|
113
|
+
}
|
|
114
|
+
const targets = extractToolFileTargets(tool, input.tool_input, input.cwd);
|
|
115
|
+
const existingTargets = targets.filter((t) => t.operation !== 'add' && existsSync(t.path));
|
|
116
|
+
if (existingTargets.length === 0) {
|
|
117
|
+
await emitGateFired(input, config, tool, mode, 'new_or_no_file');
|
|
118
|
+
writeAllow();
|
|
119
|
+
}
|
|
120
|
+
const snapshot = await getSnapshotOrFailOpen(input, config, tool, mode);
|
|
121
|
+
if (!snapshot)
|
|
122
|
+
writeAllow();
|
|
123
|
+
const uncovered = existingTargets.filter((t) => !covered(snapshot, input.cwd, t.path));
|
|
124
|
+
if (uncovered.length === 0) {
|
|
125
|
+
await emitGateFired(input, config, tool, mode, 'covered');
|
|
126
|
+
writeAllow();
|
|
127
|
+
}
|
|
128
|
+
const files = uncovered.map((t) => relative(input.cwd, t.path));
|
|
129
|
+
if (mode === 'advisory') {
|
|
130
|
+
await emitGateFired(input, config, tool, mode, 'nudge');
|
|
131
|
+
writeOutput(systemMessage([
|
|
132
|
+
`Mnemonik: file_context has not been called for ${files.map((f) => `"${f}"`).join(', ')} in this session.`,
|
|
133
|
+
'Codex PreToolUse cannot inject additionalContext reliably, so this is a systemMessage advisory.',
|
|
134
|
+
'Recommended: call mnemonik.file_context({ filePaths: [...] }) before editing existing files.',
|
|
135
|
+
].join(' ')));
|
|
136
|
+
}
|
|
137
|
+
await emitGateFired(input, config, tool, mode, 'deny');
|
|
138
|
+
writeOutput(denyPreToolUse([
|
|
139
|
+
'MNEMONIK_FILE_CONTEXT_REQUIRED',
|
|
140
|
+
`Edit blocked: file_context has not been called for ${files.map((f) => `"${f}"`).join(', ')} in this session.`,
|
|
141
|
+
'Fix: call mnemonik.file_context({ filePaths: [...] }) first.',
|
|
142
|
+
'Bypass: MNEMONIK_BYPASS_HOOKS=1 MNEMONIK_BYPASS_TYPE=<typo|formatting|regenerated|already_grounded|other>.',
|
|
143
|
+
].join('\n')));
|
|
144
|
+
}
|
|
145
|
+
async function handlePreBash(input, config) {
|
|
146
|
+
const mode = config.contextualHooks.preBashGate;
|
|
147
|
+
if (mode === 'off') {
|
|
148
|
+
await emitGateFired(input, config, 'Bash', 'off', 'off');
|
|
149
|
+
writeAllow();
|
|
150
|
+
}
|
|
151
|
+
const command = typeof input.tool_input?.command === 'string' ? input.tool_input.command : '';
|
|
152
|
+
if (!command.trim())
|
|
153
|
+
writeAllow();
|
|
154
|
+
const snapshot = await getSnapshotOrFailOpen(input, config, 'Bash', mode);
|
|
155
|
+
if (!snapshot)
|
|
156
|
+
writeAllow();
|
|
157
|
+
const projectForbidden = snapshot.policies.forbiddenCommand.map((p) => p.pattern);
|
|
158
|
+
const projectMustConfirm = snapshot.policies.mustConfirm.map((p) => p.pattern);
|
|
159
|
+
const forbiddenPatterns = [...BUILT_IN_DESTRUCTIVE, ...projectForbidden];
|
|
160
|
+
const { commands } = tokenize(command);
|
|
161
|
+
let forbiddenHit = null;
|
|
162
|
+
let mustConfirmHit = null;
|
|
163
|
+
for (const tokens of commands) {
|
|
164
|
+
forbiddenHit = forbiddenHit ?? matchCommand(tokens, forbiddenPatterns);
|
|
165
|
+
mustConfirmHit = mustConfirmHit ?? matchCommand(tokens, projectMustConfirm);
|
|
166
|
+
if (forbiddenHit && mustConfirmHit)
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
if (!forbiddenHit && !mustConfirmHit) {
|
|
170
|
+
await emitGateFired(input, config, 'Bash', mode, 'no_match');
|
|
171
|
+
writeAllow();
|
|
172
|
+
}
|
|
173
|
+
const now = snapshot.now;
|
|
174
|
+
const checkedRecently = (pattern) => {
|
|
175
|
+
const ts = snapshot.recentPolicyChecks[pattern];
|
|
176
|
+
return typeof ts === 'number' && now - ts < POLICY_DEDUP_WINDOW_MS;
|
|
177
|
+
};
|
|
178
|
+
const pausedRecently = typeof snapshot.mustConfirmPauseAt === 'number' &&
|
|
179
|
+
now - snapshot.mustConfirmPauseAt < MUST_CONFIRM_DEDUP_WINDOW_MS;
|
|
180
|
+
const hit = forbiddenHit ?? mustConfirmHit;
|
|
181
|
+
if (forbiddenHit && checkedRecently(forbiddenHit)) {
|
|
182
|
+
await emitGateFired(input, config, 'Bash', mode, 'dedup_checked');
|
|
183
|
+
writeAllow();
|
|
184
|
+
}
|
|
185
|
+
if (mustConfirmHit && (checkedRecently(mustConfirmHit) || pausedRecently)) {
|
|
186
|
+
await emitGateFired(input, config, 'Bash', mode, 'dedup_paused');
|
|
187
|
+
writeAllow();
|
|
188
|
+
}
|
|
189
|
+
if (mode === 'advisory') {
|
|
190
|
+
const kind = forbiddenHit ? 'forbiddenCommand' : 'mustConfirm';
|
|
191
|
+
await emitGateFired(input, config, 'Bash', mode, `advisory_${kind}`);
|
|
192
|
+
writeOutput(systemMessage([
|
|
193
|
+
`Mnemonik policy hit (${kind}): pattern "${hit}" matched the command.`,
|
|
194
|
+
'Recommended: call mnemonik.policy({ action: "check", command }) before running, or pause for user confirmation where required.',
|
|
195
|
+
].join(' ')));
|
|
196
|
+
}
|
|
197
|
+
await emitGateFired(input, config, 'Bash', mode, 'deny');
|
|
198
|
+
writeOutput(denyPreToolUse([
|
|
199
|
+
'MNEMONIK_POLICY_GATE',
|
|
200
|
+
`Bash blocked: pattern "${hit}" requires a manual policy check or mustConfirm pause first.`,
|
|
201
|
+
'Fix: call mnemonik.policy({ action: "check", command }) and act on the response.',
|
|
202
|
+
].join('\n')));
|
|
203
|
+
}
|
|
204
|
+
async function handlePostTool(input, config) {
|
|
205
|
+
const tool = input.tool_name ?? '';
|
|
206
|
+
const targets = extractToolFileTargets(tool, input.tool_input, input.cwd);
|
|
207
|
+
for (const target of targets) {
|
|
208
|
+
await trackIdeEdit({
|
|
209
|
+
server: config.server,
|
|
210
|
+
apiKey: config.apiKey,
|
|
211
|
+
sessionId: sessionId(input),
|
|
212
|
+
filePath: target.path,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
if (!config.apiKey)
|
|
216
|
+
writeAllow();
|
|
217
|
+
const ctx = await fetchHookContext({
|
|
218
|
+
server: config.server,
|
|
219
|
+
apiKey: config.apiKey,
|
|
220
|
+
cwd: input.cwd,
|
|
221
|
+
codexSessionId: sessionId(input),
|
|
222
|
+
event: 'PostToolUse',
|
|
223
|
+
toolName: tool,
|
|
224
|
+
filePaths: targets.map((t) => t.path),
|
|
225
|
+
});
|
|
226
|
+
if (!ctx?.ok || !ctx.additionalContext)
|
|
227
|
+
writeAllow();
|
|
228
|
+
writeOutput(additionalContext('PostToolUse', trimContext(ctx.additionalContext, 8_000)));
|
|
229
|
+
}
|
|
230
|
+
async function handleStop(input, config) {
|
|
231
|
+
if (config.contextualHooks.checkpointPressure === 'off' || input.stop_hook_active === true) {
|
|
232
|
+
writeAllow();
|
|
233
|
+
}
|
|
234
|
+
if (!config.apiKey)
|
|
235
|
+
writeAllow();
|
|
236
|
+
const ctx = await fetchHookContext({
|
|
237
|
+
server: config.server,
|
|
238
|
+
apiKey: config.apiKey,
|
|
239
|
+
cwd: input.cwd,
|
|
240
|
+
codexSessionId: sessionId(input),
|
|
241
|
+
event: 'Stop',
|
|
242
|
+
lastAssistantMessage: input.last_assistant_message,
|
|
243
|
+
});
|
|
244
|
+
if (!ctx?.ok || !ctx.continuationReason)
|
|
245
|
+
writeAllow();
|
|
246
|
+
writeOutput(continueStop(trimContext(ctx.continuationReason, 4_000)));
|
|
247
|
+
}
|
|
248
|
+
async function dispatch(input) {
|
|
249
|
+
if (isNonInteractive())
|
|
250
|
+
writeAllow();
|
|
251
|
+
const bypass = parseBypass();
|
|
252
|
+
if (bypass.invalidReason) {
|
|
253
|
+
stderr.write(`mnemonik-codex-hook: invalid bypass envelope - ${bypass.invalidReason}\n`);
|
|
254
|
+
}
|
|
255
|
+
const config = await resolveConfig(input.cwd);
|
|
256
|
+
if (bypass.active) {
|
|
257
|
+
await reportBypass({
|
|
258
|
+
server: config.server,
|
|
259
|
+
apiKey: config.apiKey,
|
|
260
|
+
cwd: input.cwd,
|
|
261
|
+
codexSessionId: sessionId(input),
|
|
262
|
+
tool: input.tool_name ?? input.hook_event_name,
|
|
263
|
+
bypassType: bypass.type ?? 'unknown',
|
|
264
|
+
detail: bypass.detail,
|
|
265
|
+
});
|
|
266
|
+
writeAllow();
|
|
267
|
+
}
|
|
268
|
+
switch (input.hook_event_name) {
|
|
269
|
+
case 'SessionStart':
|
|
270
|
+
case 'UserPromptSubmit':
|
|
271
|
+
await handleContextEvent(input, config);
|
|
272
|
+
break;
|
|
273
|
+
case 'PreToolUse':
|
|
274
|
+
if (input.tool_name === 'apply_patch' ||
|
|
275
|
+
input.tool_name === 'Edit' ||
|
|
276
|
+
input.tool_name === 'Write') {
|
|
277
|
+
await handlePreEdit(input, config);
|
|
278
|
+
}
|
|
279
|
+
if (input.tool_name === 'Bash' || input.tool_name === 'shell') {
|
|
280
|
+
await handlePreBash(input, config);
|
|
281
|
+
}
|
|
282
|
+
writeAllow();
|
|
283
|
+
break;
|
|
284
|
+
case 'PostToolUse':
|
|
285
|
+
await handlePostTool(input, config);
|
|
286
|
+
break;
|
|
287
|
+
case 'Stop':
|
|
288
|
+
await handleStop(input, config);
|
|
289
|
+
break;
|
|
290
|
+
default:
|
|
291
|
+
writeAllow();
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
(async () => {
|
|
295
|
+
try {
|
|
296
|
+
const input = await readStdin();
|
|
297
|
+
if (!input)
|
|
298
|
+
writeAllow();
|
|
299
|
+
await dispatch(input);
|
|
300
|
+
}
|
|
301
|
+
catch (err) {
|
|
302
|
+
stderr.write(`mnemonik-codex-hook: dispatcher error (fail-open) - ${err instanceof Error ? err.message : String(err)}\n`);
|
|
303
|
+
writeAllow();
|
|
304
|
+
}
|
|
305
|
+
})();
|
|
306
|
+
//# sourceMappingURL=hook.js.map
|
package/dist/hook.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook.js","sourceRoot":"","sources":["../src/hook.ts"],"names":[],"mappings":"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"}
|
package/dist/install.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { dirname, join, resolve } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
const HOOK_TAG = 'mnemonik-codex-hooks';
|
|
7
|
+
function resolveDispatcherPath() {
|
|
8
|
+
const here = fileURLToPath(import.meta.url);
|
|
9
|
+
return resolve(dirname(here), 'hook.js');
|
|
10
|
+
}
|
|
11
|
+
function buildHookEntry(dispatcher, statusMessage, timeout = 5) {
|
|
12
|
+
return {
|
|
13
|
+
type: 'command',
|
|
14
|
+
command: `node ${JSON.stringify(dispatcher)}`,
|
|
15
|
+
timeout,
|
|
16
|
+
statusMessage,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function isMnemonikGroup(group) {
|
|
20
|
+
if (group.matcher === HOOK_TAG)
|
|
21
|
+
return true;
|
|
22
|
+
return Boolean(group.hooks?.some((h) => typeof h.command === 'string' && h.command.includes('codex-hooks')));
|
|
23
|
+
}
|
|
24
|
+
function patchHookGroup(groups, matcher, entry) {
|
|
25
|
+
const filtered = (groups ?? []).filter((g) => !isMnemonikGroup(g));
|
|
26
|
+
const group = { hooks: [entry] };
|
|
27
|
+
if (matcher !== undefined)
|
|
28
|
+
group.matcher = matcher;
|
|
29
|
+
filtered.push(group);
|
|
30
|
+
return filtered;
|
|
31
|
+
}
|
|
32
|
+
async function readHooksJson(path) {
|
|
33
|
+
if (!existsSync(path))
|
|
34
|
+
return {};
|
|
35
|
+
try {
|
|
36
|
+
const raw = await readFile(path, 'utf8');
|
|
37
|
+
return JSON.parse(raw);
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
throw new Error(`Could not parse ${path}: ${err instanceof Error ? err.message : String(err)}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function writeJson(path, value) {
|
|
44
|
+
await mkdir(dirname(path), { recursive: true });
|
|
45
|
+
await writeFile(path, JSON.stringify(value, null, 2) + '\n', 'utf8');
|
|
46
|
+
}
|
|
47
|
+
function ensureCodexHooksFeature(configToml) {
|
|
48
|
+
if (/^\s*codex_hooks\s*=\s*true\s*$/m.test(configToml))
|
|
49
|
+
return configToml;
|
|
50
|
+
if (/^\s*codex_hooks\s*=/m.test(configToml)) {
|
|
51
|
+
return configToml.replace(/^\s*codex_hooks\s*=.*$/m, 'codex_hooks = true');
|
|
52
|
+
}
|
|
53
|
+
const featureHeader = configToml.match(/^\[features\]\s*$/m);
|
|
54
|
+
if (!featureHeader?.index && featureHeader?.index !== 0) {
|
|
55
|
+
const prefix = configToml.endsWith('\n') || configToml.length === 0 ? configToml : `${configToml}\n`;
|
|
56
|
+
return `${prefix}\n[features]\ncodex_hooks = true\n`;
|
|
57
|
+
}
|
|
58
|
+
const insertAt = featureHeader.index + featureHeader[0].length;
|
|
59
|
+
return `${configToml.slice(0, insertAt)}\ncodex_hooks = true${configToml.slice(insertAt)}`;
|
|
60
|
+
}
|
|
61
|
+
async function ensureConfigFlag(path) {
|
|
62
|
+
const raw = existsSync(path) ? await readFile(path, 'utf8') : '';
|
|
63
|
+
const next = ensureCodexHooksFeature(raw);
|
|
64
|
+
if (next !== raw) {
|
|
65
|
+
await mkdir(dirname(path), { recursive: true });
|
|
66
|
+
await writeFile(path, next.endsWith('\n') ? next : `${next}\n`, 'utf8');
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function main() {
|
|
70
|
+
const cwd = process.cwd();
|
|
71
|
+
const codexDir = join(cwd, '.codex');
|
|
72
|
+
const hooksPath = join(codexDir, 'hooks.json');
|
|
73
|
+
const configPath = join(codexDir, 'config.toml');
|
|
74
|
+
const dispatcher = resolveDispatcherPath();
|
|
75
|
+
if (!existsSync(dispatcher)) {
|
|
76
|
+
console.error(`mnemonik-codex-hooks: dispatcher not found at ${dispatcher}. Did the package install correctly?`);
|
|
77
|
+
return 1;
|
|
78
|
+
}
|
|
79
|
+
const hooksJson = await readHooksJson(hooksPath);
|
|
80
|
+
const hooks = (hooksJson.hooks ?? {});
|
|
81
|
+
const entry = buildHookEntry(dispatcher, 'Checking Mnemonik context');
|
|
82
|
+
hooks.SessionStart = patchHookGroup(hooks.SessionStart, 'startup|resume|clear', buildHookEntry(dispatcher, 'Loading Mnemonik context'));
|
|
83
|
+
hooks.UserPromptSubmit = patchHookGroup(hooks.UserPromptSubmit, undefined, buildHookEntry(dispatcher, 'Loading Mnemonik prompt context'));
|
|
84
|
+
hooks.PreToolUse = patchHookGroup(hooks.PreToolUse, 'Bash|apply_patch|Edit|Write', entry);
|
|
85
|
+
hooks.PostToolUse = patchHookGroup(hooks.PostToolUse, 'apply_patch|Edit|Write|mcp__mnemonik__.*', buildHookEntry(dispatcher, 'Updating Mnemonik context'));
|
|
86
|
+
hooks.Stop = patchHookGroup(hooks.Stop, undefined, buildHookEntry(dispatcher, 'Checking Mnemonik checkpoint state'));
|
|
87
|
+
hooksJson.hooks = hooks;
|
|
88
|
+
await writeJson(hooksPath, hooksJson);
|
|
89
|
+
await ensureConfigFlag(configPath);
|
|
90
|
+
console.log([
|
|
91
|
+
`mnemonik-codex-hooks: wired into ${hooksPath}`,
|
|
92
|
+
` feature flag -> ${configPath}`,
|
|
93
|
+
` dispatcher -> ${dispatcher}`,
|
|
94
|
+
'',
|
|
95
|
+
'Installed Codex hooks only. This does not install or modify skills, rules, AGENTS.md, .mnemonik.json, or MCP config.',
|
|
96
|
+
'Defaults are advisory. Configure .mnemonik.json contextualHooks to change modes.',
|
|
97
|
+
].join('\n'));
|
|
98
|
+
return 0;
|
|
99
|
+
}
|
|
100
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
101
|
+
main()
|
|
102
|
+
.then((code) => process.exit(code))
|
|
103
|
+
.catch((err) => {
|
|
104
|
+
console.error(`mnemonik-codex-hooks: ${err instanceof Error ? err.message : String(err)}`);
|
|
105
|
+
process.exit(1);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
export { ensureCodexHooksFeature };
|
|
109
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export interface PatchTarget {
|
|
2
|
+
path: string;
|
|
3
|
+
operation: 'add' | 'update' | 'delete';
|
|
4
|
+
}
|
|
5
|
+
export declare function extractPatchTargets(patch: string, cwd: string): PatchTarget[];
|
|
6
|
+
export declare function extractToolFileTargets(toolName: string, toolInput: Record<string, unknown> | undefined, cwd: string): PatchTarget[];
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { isAbsolute, resolve } from 'node:path';
|
|
2
|
+
const ADD = '*** Add File: ';
|
|
3
|
+
const UPDATE = '*** Update File: ';
|
|
4
|
+
const DELETE = '*** Delete File: ';
|
|
5
|
+
export function extractPatchTargets(patch, cwd) {
|
|
6
|
+
const targets = [];
|
|
7
|
+
const seen = new Set();
|
|
8
|
+
for (const rawLine of patch.split(/\r?\n/)) {
|
|
9
|
+
const line = rawLine.trimEnd();
|
|
10
|
+
let operation = null;
|
|
11
|
+
let filePath = '';
|
|
12
|
+
if (line.startsWith(ADD)) {
|
|
13
|
+
operation = 'add';
|
|
14
|
+
filePath = line.slice(ADD.length).trim();
|
|
15
|
+
}
|
|
16
|
+
else if (line.startsWith(UPDATE)) {
|
|
17
|
+
operation = 'update';
|
|
18
|
+
filePath = line.slice(UPDATE.length).trim();
|
|
19
|
+
}
|
|
20
|
+
else if (line.startsWith(DELETE)) {
|
|
21
|
+
operation = 'delete';
|
|
22
|
+
filePath = line.slice(DELETE.length).trim();
|
|
23
|
+
}
|
|
24
|
+
if (!operation || !filePath)
|
|
25
|
+
continue;
|
|
26
|
+
const absolute = isAbsolute(filePath) ? filePath : resolve(cwd, filePath);
|
|
27
|
+
const key = `${operation}:${absolute}`;
|
|
28
|
+
if (seen.has(key))
|
|
29
|
+
continue;
|
|
30
|
+
seen.add(key);
|
|
31
|
+
targets.push({ path: absolute, operation });
|
|
32
|
+
}
|
|
33
|
+
return targets;
|
|
34
|
+
}
|
|
35
|
+
export function extractToolFileTargets(toolName, toolInput, cwd) {
|
|
36
|
+
if (!toolInput)
|
|
37
|
+
return [];
|
|
38
|
+
if (toolName === 'apply_patch') {
|
|
39
|
+
const patch = typeof toolInput.patch === 'string'
|
|
40
|
+
? toolInput.patch
|
|
41
|
+
: typeof toolInput.input === 'string'
|
|
42
|
+
? toolInput.input
|
|
43
|
+
: typeof toolInput.command === 'string'
|
|
44
|
+
? toolInput.command
|
|
45
|
+
: '';
|
|
46
|
+
return extractPatchTargets(patch, cwd);
|
|
47
|
+
}
|
|
48
|
+
const raw = typeof toolInput.file_path === 'string'
|
|
49
|
+
? toolInput.file_path
|
|
50
|
+
: typeof toolInput.path === 'string'
|
|
51
|
+
? toolInput.path
|
|
52
|
+
: null;
|
|
53
|
+
if (!raw)
|
|
54
|
+
return [];
|
|
55
|
+
const path = isAbsolute(raw) ? raw : resolve(cwd, raw);
|
|
56
|
+
return [{ path, operation: toolName === 'Write' ? 'add' : 'update' }];
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=applyPatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyPatch.js","sourceRoot":"","sources":["../../src/lib/applyPatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CodexHookEvent, CodexHookOutput } from './types.js';
|
|
2
|
+
export declare function additionalContext(event: CodexHookEvent, text: string): CodexHookOutput;
|
|
3
|
+
export declare function systemMessage(message: string): CodexHookOutput;
|
|
4
|
+
export declare function denyPreToolUse(reason: string): CodexHookOutput;
|
|
5
|
+
export declare function continueStop(reason: string): CodexHookOutput;
|
|
6
|
+
export declare function trimContext(text: string, maxBytes?: number): string;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export function additionalContext(event, text) {
|
|
2
|
+
return {
|
|
3
|
+
hookSpecificOutput: {
|
|
4
|
+
hookEventName: event,
|
|
5
|
+
additionalContext: text,
|
|
6
|
+
},
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export function systemMessage(message) {
|
|
10
|
+
return { systemMessage: message };
|
|
11
|
+
}
|
|
12
|
+
export function denyPreToolUse(reason) {
|
|
13
|
+
return {
|
|
14
|
+
decision: 'block',
|
|
15
|
+
reason,
|
|
16
|
+
hookSpecificOutput: {
|
|
17
|
+
hookEventName: 'PreToolUse',
|
|
18
|
+
permissionDecision: 'deny',
|
|
19
|
+
permissionDecisionReason: reason,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export function continueStop(reason) {
|
|
24
|
+
return {
|
|
25
|
+
decision: 'block',
|
|
26
|
+
reason,
|
|
27
|
+
hookSpecificOutput: {
|
|
28
|
+
hookEventName: 'Stop',
|
|
29
|
+
additionalContext: reason,
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export function trimContext(text, maxBytes = 12_000) {
|
|
34
|
+
if (Buffer.byteLength(text, 'utf8') <= maxBytes)
|
|
35
|
+
return text;
|
|
36
|
+
const suffix = '\n\n[Mnemonik: context exceeded hook budget. Call memory_get/file_context for full detail if needed.]';
|
|
37
|
+
const budget = Math.max(0, maxBytes - Buffer.byteLength(suffix, 'utf8'));
|
|
38
|
+
let out = '';
|
|
39
|
+
for (const ch of text) {
|
|
40
|
+
if (Buffer.byteLength(out + ch, 'utf8') > budget)
|
|
41
|
+
break;
|
|
42
|
+
out += ch;
|
|
43
|
+
}
|
|
44
|
+
return out + suffix;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=codexOutput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexOutput.js","sourceRoot":"","sources":["../../src/lib/codexOutput.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,iBAAiB,CAAC,KAAqB,EAAE,IAAY;IACnE,OAAO;QACL,kBAAkB,EAAE;YAClB,aAAa,EAAE,KAAK;YACpB,iBAAiB,EAAE,IAAI;SACxB;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,OAAO;QACL,QAAQ,EAAE,OAAO;QACjB,MAAM;QACN,kBAAkB,EAAE;YAClB,aAAa,EAAE,YAAY;YAC3B,kBAAkB,EAAE,MAAM;YAC1B,wBAAwB,EAAE,MAAM;SACjC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,OAAO;QACL,QAAQ,EAAE,OAAO;QACjB,MAAM;QACN,kBAAkB,EAAE;YAClB,aAAa,EAAE,MAAM;YACrB,iBAAiB,EAAE,MAAM;SAC1B;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,QAAQ,GAAG,MAAM;IACzD,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC7D,MAAM,MAAM,GACV,uGAAuG,CAAC;IAC1G,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACzE,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;QACtB,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,GAAG,EAAE,EAAE,MAAM,CAAC,GAAG,MAAM;YAAE,MAAM;QACxD,GAAG,IAAI,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,GAAG,GAAG,MAAM,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type BypassEnvelope, type HookConfig } from './types.js';
|
|
2
|
+
export declare function isNonInteractive(env?: NodeJS.ProcessEnv): boolean;
|
|
3
|
+
export declare function parseBypass(env?: NodeJS.ProcessEnv): BypassEnvelope;
|
|
4
|
+
export declare function resolveConfig(cwd: string, env?: NodeJS.ProcessEnv): Promise<HookConfig>;
|
package/dist/lib/env.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { DEFAULT_CONTEXTUAL_HOOKS, DEFAULT_SERVER, } from './types.js';
|
|
5
|
+
const VALID_BYPASS_TYPES = new Set([
|
|
6
|
+
'typo',
|
|
7
|
+
'formatting',
|
|
8
|
+
'regenerated',
|
|
9
|
+
'already_grounded',
|
|
10
|
+
'other',
|
|
11
|
+
]);
|
|
12
|
+
export function isNonInteractive(env = process.env) {
|
|
13
|
+
if (env.CI === 'true')
|
|
14
|
+
return true;
|
|
15
|
+
if (env.GITHUB_ACTIONS === 'true')
|
|
16
|
+
return true;
|
|
17
|
+
if (env.MNEMONIK_NONINTERACTIVE === '1')
|
|
18
|
+
return true;
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
export function parseBypass(env = process.env) {
|
|
22
|
+
if (env.MNEMONIK_BYPASS_HOOKS !== '1') {
|
|
23
|
+
return { active: false, type: null, detail: null, invalidReason: null };
|
|
24
|
+
}
|
|
25
|
+
const rawType = (env.MNEMONIK_BYPASS_TYPE ?? '').trim().toLowerCase();
|
|
26
|
+
if (!rawType) {
|
|
27
|
+
return {
|
|
28
|
+
active: false,
|
|
29
|
+
type: null,
|
|
30
|
+
detail: null,
|
|
31
|
+
invalidReason: 'MNEMONIK_BYPASS_TYPE is required when MNEMONIK_BYPASS_HOOKS=1',
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
if (!VALID_BYPASS_TYPES.has(rawType)) {
|
|
35
|
+
return {
|
|
36
|
+
active: false,
|
|
37
|
+
type: null,
|
|
38
|
+
detail: null,
|
|
39
|
+
invalidReason: `MNEMONIK_BYPASS_TYPE must be one of ${[...VALID_BYPASS_TYPES].join('|')}`,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const type = rawType;
|
|
43
|
+
if (type === 'other') {
|
|
44
|
+
const detail = (env.MNEMONIK_BYPASS_DETAIL ?? '').trim();
|
|
45
|
+
if (detail.length < 50 || detail.length > 200) {
|
|
46
|
+
return {
|
|
47
|
+
active: false,
|
|
48
|
+
type: null,
|
|
49
|
+
detail: null,
|
|
50
|
+
invalidReason: "MNEMONIK_BYPASS_TYPE='other' requires MNEMONIK_BYPASS_DETAIL of 50-200 chars",
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return { active: true, type, detail, invalidReason: null };
|
|
54
|
+
}
|
|
55
|
+
return { active: true, type, detail: null, invalidReason: null };
|
|
56
|
+
}
|
|
57
|
+
async function readJson(path) {
|
|
58
|
+
try {
|
|
59
|
+
const raw = await readFile(path, 'utf8');
|
|
60
|
+
return JSON.parse(raw);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export async function resolveConfig(cwd, env = process.env) {
|
|
67
|
+
const scanner = await readJson(join(homedir(), '.mnemonik', 'scanner.json'));
|
|
68
|
+
const projectConfig = await readJson(join(cwd, '.mnemonik.json'));
|
|
69
|
+
const apiKey = env.MNEMONIK_API_KEY?.trim() || scanner?.apiKey?.trim() || null;
|
|
70
|
+
const server = (env.MNEMONIK_SERVER?.trim() || scanner?.server?.trim() || DEFAULT_SERVER).replace(/\/$/, '');
|
|
71
|
+
const contextualHooks = {
|
|
72
|
+
...DEFAULT_CONTEXTUAL_HOOKS,
|
|
73
|
+
...(projectConfig?.forcingFunctions ?? {}),
|
|
74
|
+
...(projectConfig?.contextualHooks ?? {}),
|
|
75
|
+
};
|
|
76
|
+
return { apiKey, server, contextualHooks };
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/lib/env.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { HookContextResponse, SnapshotResponse } from './types.js';
|
|
2
|
+
export interface FetchSnapshotInput {
|
|
3
|
+
server: string;
|
|
4
|
+
apiKey: string;
|
|
5
|
+
cwd: string;
|
|
6
|
+
codexSessionId: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function fetchSnapshot(input: FetchSnapshotInput): Promise<SnapshotResponse | null>;
|
|
9
|
+
export interface FetchHookContextInput {
|
|
10
|
+
server: string;
|
|
11
|
+
apiKey: string;
|
|
12
|
+
cwd: string;
|
|
13
|
+
codexSessionId: string;
|
|
14
|
+
event: string;
|
|
15
|
+
prompt?: string;
|
|
16
|
+
toolName?: string;
|
|
17
|
+
filePaths?: string[];
|
|
18
|
+
lastAssistantMessage?: string | null;
|
|
19
|
+
}
|
|
20
|
+
export declare function fetchHookContext(input: FetchHookContextInput): Promise<HookContextResponse | null>;
|
|
21
|
+
export interface ReportGateFiredInput {
|
|
22
|
+
server: string;
|
|
23
|
+
apiKey: string | null;
|
|
24
|
+
cwd: string;
|
|
25
|
+
codexSessionId: string;
|
|
26
|
+
tool: string;
|
|
27
|
+
mode: 'advisory' | 'enforce' | 'off';
|
|
28
|
+
outcome: string;
|
|
29
|
+
}
|
|
30
|
+
export declare function reportGateFired(input: ReportGateFiredInput): Promise<void>;
|
|
31
|
+
export interface ReportBypassInput {
|
|
32
|
+
server: string;
|
|
33
|
+
apiKey: string | null;
|
|
34
|
+
cwd: string;
|
|
35
|
+
codexSessionId: string;
|
|
36
|
+
tool: string;
|
|
37
|
+
bypassType: string;
|
|
38
|
+
detail: string | null;
|
|
39
|
+
}
|
|
40
|
+
export declare function reportBypass(input: ReportBypassInput): Promise<void>;
|
|
41
|
+
export declare function trackIdeEdit(input: {
|
|
42
|
+
server: string;
|
|
43
|
+
apiKey: string | null;
|
|
44
|
+
sessionId: string;
|
|
45
|
+
filePath: string;
|
|
46
|
+
}): Promise<void>;
|
package/dist/lib/http.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
const FETCH_TIMEOUT_MS = 2000;
|
|
2
|
+
const TELEMETRY_TIMEOUT_MS = 500;
|
|
3
|
+
const POST_TOOL_TIMEOUT_MS = 1500;
|
|
4
|
+
function withTimeout(ms) {
|
|
5
|
+
const ac = new AbortController();
|
|
6
|
+
const timer = setTimeout(() => ac.abort(), ms);
|
|
7
|
+
return { signal: ac.signal, cleanup: () => clearTimeout(timer) };
|
|
8
|
+
}
|
|
9
|
+
export async function fetchSnapshot(input) {
|
|
10
|
+
const url = `${input.server.replace(/\/$/, '')}/api/v1/hooks/snapshot`;
|
|
11
|
+
const { signal, cleanup } = withTimeout(FETCH_TIMEOUT_MS);
|
|
12
|
+
try {
|
|
13
|
+
const res = await fetch(url, {
|
|
14
|
+
method: 'POST',
|
|
15
|
+
headers: {
|
|
16
|
+
'content-type': 'application/json',
|
|
17
|
+
authorization: `Bearer ${input.apiKey}`,
|
|
18
|
+
},
|
|
19
|
+
body: JSON.stringify({
|
|
20
|
+
cwd: input.cwd,
|
|
21
|
+
claudeSessionId: input.codexSessionId,
|
|
22
|
+
host: 'codex',
|
|
23
|
+
}),
|
|
24
|
+
signal,
|
|
25
|
+
});
|
|
26
|
+
if (!res.ok)
|
|
27
|
+
return null;
|
|
28
|
+
return (await res.json());
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
cleanup();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export async function fetchHookContext(input) {
|
|
38
|
+
const url = `${input.server.replace(/\/$/, '')}/api/v1/hooks/context`;
|
|
39
|
+
const { signal, cleanup } = withTimeout(FETCH_TIMEOUT_MS);
|
|
40
|
+
try {
|
|
41
|
+
const res = await fetch(url, {
|
|
42
|
+
method: 'POST',
|
|
43
|
+
headers: {
|
|
44
|
+
'content-type': 'application/json',
|
|
45
|
+
authorization: `Bearer ${input.apiKey}`,
|
|
46
|
+
},
|
|
47
|
+
body: JSON.stringify({
|
|
48
|
+
host: 'codex',
|
|
49
|
+
event: input.event,
|
|
50
|
+
cwd: input.cwd,
|
|
51
|
+
sessionId: input.codexSessionId,
|
|
52
|
+
prompt: input.prompt,
|
|
53
|
+
toolName: input.toolName,
|
|
54
|
+
filePaths: input.filePaths,
|
|
55
|
+
lastAssistantMessage: input.lastAssistantMessage,
|
|
56
|
+
}),
|
|
57
|
+
signal,
|
|
58
|
+
});
|
|
59
|
+
if (!res.ok)
|
|
60
|
+
return null;
|
|
61
|
+
return (await res.json());
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
cleanup();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export async function reportGateFired(input) {
|
|
71
|
+
if (!input.apiKey)
|
|
72
|
+
return;
|
|
73
|
+
const url = `${input.server.replace(/\/$/, '')}/api/v1/hooks/gate-fired`;
|
|
74
|
+
const { signal, cleanup } = withTimeout(TELEMETRY_TIMEOUT_MS);
|
|
75
|
+
try {
|
|
76
|
+
await fetch(url, {
|
|
77
|
+
method: 'POST',
|
|
78
|
+
headers: {
|
|
79
|
+
'content-type': 'application/json',
|
|
80
|
+
authorization: `Bearer ${input.apiKey}`,
|
|
81
|
+
},
|
|
82
|
+
body: JSON.stringify({
|
|
83
|
+
cwd: input.cwd,
|
|
84
|
+
host: 'codex',
|
|
85
|
+
codexSessionId: input.codexSessionId,
|
|
86
|
+
tool: input.tool,
|
|
87
|
+
mode: input.mode,
|
|
88
|
+
outcome: input.outcome,
|
|
89
|
+
}),
|
|
90
|
+
signal,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Telemetry must not crash hooks.
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
cleanup();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
export async function reportBypass(input) {
|
|
101
|
+
if (!input.apiKey)
|
|
102
|
+
return;
|
|
103
|
+
const url = `${input.server.replace(/\/$/, '')}/api/v1/hooks/bypass`;
|
|
104
|
+
const { signal, cleanup } = withTimeout(TELEMETRY_TIMEOUT_MS);
|
|
105
|
+
try {
|
|
106
|
+
await fetch(url, {
|
|
107
|
+
method: 'POST',
|
|
108
|
+
headers: {
|
|
109
|
+
'content-type': 'application/json',
|
|
110
|
+
authorization: `Bearer ${input.apiKey}`,
|
|
111
|
+
},
|
|
112
|
+
body: JSON.stringify({
|
|
113
|
+
cwd: input.cwd,
|
|
114
|
+
host: 'codex',
|
|
115
|
+
codexSessionId: input.codexSessionId,
|
|
116
|
+
tool: input.tool,
|
|
117
|
+
bypassType: input.bypassType,
|
|
118
|
+
detail: input.detail,
|
|
119
|
+
}),
|
|
120
|
+
signal,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// Telemetry must not crash hooks.
|
|
125
|
+
}
|
|
126
|
+
finally {
|
|
127
|
+
cleanup();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
export async function trackIdeEdit(input) {
|
|
131
|
+
if (!input.apiKey)
|
|
132
|
+
return;
|
|
133
|
+
const url = `${input.server.replace(/\/$/, '')}/api/v1/session/track-ide-edit`;
|
|
134
|
+
const { signal, cleanup } = withTimeout(POST_TOOL_TIMEOUT_MS);
|
|
135
|
+
try {
|
|
136
|
+
await fetch(url, {
|
|
137
|
+
method: 'POST',
|
|
138
|
+
headers: {
|
|
139
|
+
'content-type': 'application/json',
|
|
140
|
+
authorization: `Bearer ${input.apiKey}`,
|
|
141
|
+
},
|
|
142
|
+
body: JSON.stringify({ sessionId: input.sessionId, filePath: input.filePath, host: 'codex' }),
|
|
143
|
+
signal,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
// Best effort only.
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
cleanup();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/lib/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export interface TokenizeResult {
|
|
2
|
+
commands: string[][];
|
|
3
|
+
}
|
|
4
|
+
export declare const BUILT_IN_DESTRUCTIVE: readonly string[];
|
|
5
|
+
export declare function tokenize(input: string): TokenizeResult;
|
|
6
|
+
export declare function matchCommand(commandTokens: string[], patterns: string[]): string | null;
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
export const BUILT_IN_DESTRUCTIVE = [
|
|
2
|
+
'git push origin main',
|
|
3
|
+
'git push origin master',
|
|
4
|
+
'git push --force',
|
|
5
|
+
'git reset --hard',
|
|
6
|
+
'git merge main',
|
|
7
|
+
'git merge master',
|
|
8
|
+
'git branch -D',
|
|
9
|
+
'npm publish',
|
|
10
|
+
'pnpm publish',
|
|
11
|
+
'yarn publish',
|
|
12
|
+
'docker rm',
|
|
13
|
+
'docker rmi',
|
|
14
|
+
'kubectl delete',
|
|
15
|
+
'rm -rf /',
|
|
16
|
+
'rm -rf ~',
|
|
17
|
+
'rm -rf $HOME',
|
|
18
|
+
];
|
|
19
|
+
export function tokenize(input) {
|
|
20
|
+
const commands = [];
|
|
21
|
+
let current = [];
|
|
22
|
+
let buf = '';
|
|
23
|
+
let mode = 'normal';
|
|
24
|
+
const flushToken = () => {
|
|
25
|
+
if (buf.length > 0) {
|
|
26
|
+
current.push(buf);
|
|
27
|
+
buf = '';
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const flushCommand = () => {
|
|
31
|
+
flushToken();
|
|
32
|
+
if (current.length > 0)
|
|
33
|
+
commands.push(current);
|
|
34
|
+
current = [];
|
|
35
|
+
};
|
|
36
|
+
for (let i = 0; i < input.length; i++) {
|
|
37
|
+
const c = input[i];
|
|
38
|
+
if (mode === 'single') {
|
|
39
|
+
if (c === "'")
|
|
40
|
+
mode = 'normal';
|
|
41
|
+
else
|
|
42
|
+
buf += c;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (mode === 'double') {
|
|
46
|
+
if (c === '"')
|
|
47
|
+
mode = 'normal';
|
|
48
|
+
else if (c === '\\' && i + 1 < input.length)
|
|
49
|
+
buf += input[++i];
|
|
50
|
+
else
|
|
51
|
+
buf += c;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (c === "'") {
|
|
55
|
+
mode = 'single';
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (c === '"') {
|
|
59
|
+
mode = 'double';
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (c === '\\' && i + 1 < input.length) {
|
|
63
|
+
buf += input[++i];
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (c === ' ' || c === '\t' || c === '\n') {
|
|
67
|
+
flushToken();
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if ((c === '|' && input[i + 1] === '|') ||
|
|
71
|
+
(c === '&' && input[i + 1] === '&') ||
|
|
72
|
+
(c === '>' && input[i + 1] === '>') ||
|
|
73
|
+
(c === '<' && input[i + 1] === '<')) {
|
|
74
|
+
flushCommand();
|
|
75
|
+
i++;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (c === '|' || c === ';' || c === '&' || c === '>' || c === '<') {
|
|
79
|
+
flushCommand();
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
buf += c;
|
|
83
|
+
}
|
|
84
|
+
flushCommand();
|
|
85
|
+
return { commands };
|
|
86
|
+
}
|
|
87
|
+
export function matchCommand(commandTokens, patterns) {
|
|
88
|
+
if (commandTokens.length === 0 || patterns.length === 0)
|
|
89
|
+
return null;
|
|
90
|
+
const joined = commandTokens.join(' ').trim();
|
|
91
|
+
for (const raw of patterns) {
|
|
92
|
+
const pattern = raw.trim();
|
|
93
|
+
if (!pattern)
|
|
94
|
+
continue;
|
|
95
|
+
const explicitRegex = parseExplicitRegex(pattern);
|
|
96
|
+
if (explicitRegex !== null) {
|
|
97
|
+
try {
|
|
98
|
+
if (new RegExp(explicitRegex.body, explicitRegex.flags).test(joined))
|
|
99
|
+
return pattern;
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
/* ignore invalid regex */
|
|
103
|
+
}
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
const segments = pattern.includes('|')
|
|
107
|
+
? pattern
|
|
108
|
+
.split('|')
|
|
109
|
+
.map((s) => s.trim())
|
|
110
|
+
.filter(Boolean)
|
|
111
|
+
: [pattern];
|
|
112
|
+
for (const segment of segments) {
|
|
113
|
+
if (matchOneSegment(segment, commandTokens, joined))
|
|
114
|
+
return pattern;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
function matchOneSegment(segment, commandTokens, joined) {
|
|
120
|
+
if (looksLikeRegex(segment)) {
|
|
121
|
+
try {
|
|
122
|
+
return new RegExp(segment).test(joined);
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const tokens = segment.split(/\s+/).filter(Boolean);
|
|
129
|
+
if (tokens.length === 0)
|
|
130
|
+
return false;
|
|
131
|
+
return matchTokenSubsequence(commandTokens, tokens);
|
|
132
|
+
}
|
|
133
|
+
function parseExplicitRegex(pattern) {
|
|
134
|
+
if (!pattern.startsWith('/'))
|
|
135
|
+
return null;
|
|
136
|
+
const tail = pattern.endsWith('/i') ? '/i' : pattern.endsWith('/') ? '/' : null;
|
|
137
|
+
if (!tail)
|
|
138
|
+
return null;
|
|
139
|
+
return { body: pattern.slice(1, pattern.length - tail.length), flags: tail === '/i' ? 'i' : '' };
|
|
140
|
+
}
|
|
141
|
+
function looksLikeRegex(pattern) {
|
|
142
|
+
return /[|\\.^$()+?{}[\]]/.test(pattern);
|
|
143
|
+
}
|
|
144
|
+
function matchTokenSubsequence(commandTokens, patternTokens) {
|
|
145
|
+
for (let start = 0; start <= commandTokens.length - patternTokens.length; start++) {
|
|
146
|
+
let ok = true;
|
|
147
|
+
for (let i = 0; i < patternTokens.length; i++) {
|
|
148
|
+
const cmd = commandTokens[start + i] ?? '';
|
|
149
|
+
const pat = patternTokens[i] ?? '';
|
|
150
|
+
if (pat === '*')
|
|
151
|
+
continue;
|
|
152
|
+
if (pat.includes('*')) {
|
|
153
|
+
const escaped = pat
|
|
154
|
+
.split('*')
|
|
155
|
+
.map((seg) => seg.replace(/[.+?^${}()|[\]\\]/g, '\\$&'))
|
|
156
|
+
.join('.*');
|
|
157
|
+
if (!new RegExp(`^${escaped}$`).test(cmd)) {
|
|
158
|
+
ok = false;
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (cmd !== pat) {
|
|
164
|
+
ok = false;
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (ok)
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=shellTokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shellTokens.js","sourceRoot":"","sources":["../../src/lib/shellTokens.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export type CodexHookEvent = 'SessionStart' | 'UserPromptSubmit' | 'PreToolUse' | 'PermissionRequest' | 'PostToolUse' | 'Stop';
|
|
2
|
+
export interface CodexHookInput {
|
|
3
|
+
session_id?: string;
|
|
4
|
+
cwd: string;
|
|
5
|
+
hook_event_name: CodexHookEvent;
|
|
6
|
+
turn_id?: string;
|
|
7
|
+
source?: 'startup' | 'resume' | string;
|
|
8
|
+
prompt?: string;
|
|
9
|
+
stop_hook_active?: boolean;
|
|
10
|
+
last_assistant_message?: string | null;
|
|
11
|
+
tool_name?: string;
|
|
12
|
+
tool_use_id?: string;
|
|
13
|
+
tool_input?: Record<string, unknown>;
|
|
14
|
+
tool_response?: unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface CodexHookOutput {
|
|
17
|
+
continue?: boolean;
|
|
18
|
+
stopReason?: string;
|
|
19
|
+
systemMessage?: string;
|
|
20
|
+
suppressOutput?: boolean;
|
|
21
|
+
decision?: 'block';
|
|
22
|
+
reason?: string;
|
|
23
|
+
hookSpecificOutput?: {
|
|
24
|
+
hookEventName: CodexHookEvent;
|
|
25
|
+
additionalContext?: string;
|
|
26
|
+
permissionDecision?: 'deny';
|
|
27
|
+
permissionDecisionReason?: string;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export type BypassType = 'typo' | 'formatting' | 'regenerated' | 'already_grounded' | 'other';
|
|
31
|
+
export interface BypassEnvelope {
|
|
32
|
+
active: boolean;
|
|
33
|
+
type: BypassType | null;
|
|
34
|
+
detail: string | null;
|
|
35
|
+
invalidReason: string | null;
|
|
36
|
+
}
|
|
37
|
+
export interface SnapshotResponse {
|
|
38
|
+
ok: boolean;
|
|
39
|
+
reason?: 'unauthorized' | 'no_project' | 'no_active_session';
|
|
40
|
+
coveredFiles: string[];
|
|
41
|
+
editedFiles: string[];
|
|
42
|
+
mustConfirmPauseAt: number | null;
|
|
43
|
+
recentPolicyChecks: Record<string, number>;
|
|
44
|
+
policies: {
|
|
45
|
+
forbiddenCommand: Array<{
|
|
46
|
+
pattern: string;
|
|
47
|
+
description: string;
|
|
48
|
+
}>;
|
|
49
|
+
mustConfirm: Array<{
|
|
50
|
+
pattern: string;
|
|
51
|
+
description: string;
|
|
52
|
+
replacement: string | null;
|
|
53
|
+
}>;
|
|
54
|
+
};
|
|
55
|
+
sessionsMerged: number;
|
|
56
|
+
now: number;
|
|
57
|
+
}
|
|
58
|
+
export interface HookContextResponse {
|
|
59
|
+
ok: boolean;
|
|
60
|
+
reason?: 'unauthorized' | 'no_project' | 'invalid' | 'unavailable';
|
|
61
|
+
additionalContext?: string;
|
|
62
|
+
systemMessage?: string;
|
|
63
|
+
continuationReason?: string;
|
|
64
|
+
contextBytes?: number;
|
|
65
|
+
}
|
|
66
|
+
export interface HookConfig {
|
|
67
|
+
apiKey: string | null;
|
|
68
|
+
server: string;
|
|
69
|
+
contextualHooks: {
|
|
70
|
+
promptContext: 'advisory' | 'off';
|
|
71
|
+
preEditGate: 'advisory' | 'enforce' | 'off';
|
|
72
|
+
preBashGate: 'advisory' | 'enforce' | 'off';
|
|
73
|
+
checkpointPressure: 'advisory' | 'off';
|
|
74
|
+
advisoryAutoFetch: boolean;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export declare const DEFAULT_CONTEXTUAL_HOOKS: HookConfig['contextualHooks'];
|
|
78
|
+
export declare const DEFAULT_SERVER = "https://api.mnemonik.dev";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const DEFAULT_CONTEXTUAL_HOOKS = {
|
|
2
|
+
promptContext: 'advisory',
|
|
3
|
+
preEditGate: 'advisory',
|
|
4
|
+
preBashGate: 'advisory',
|
|
5
|
+
checkpointPressure: 'advisory',
|
|
6
|
+
advisoryAutoFetch: true,
|
|
7
|
+
};
|
|
8
|
+
export const DEFAULT_SERVER = 'https://api.mnemonik.dev';
|
|
9
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAmFA,MAAM,CAAC,MAAM,wBAAwB,GAAkC;IACrE,aAAa,EAAE,UAAU;IACzB,WAAW,EAAE,UAAU;IACvB,WAAW,EAAE,UAAU;IACvB,kBAAkB,EAAE,UAAU;IAC9B,iBAAiB,EAAE,IAAI;CACxB,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,0BAA0B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mnemonik/codex-hooks",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Codex lifecycle hooks for Mnemonik memory awareness and host-side grounding gates. Hooks only: does not install skills, rules, AGENTS.md, .mnemonik.json, or MCP config.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"mnemonik-codex-hooks": "dist/install.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "dist/install.js",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"typecheck": "tsc --noEmit",
|
|
16
|
+
"test": "vitest run",
|
|
17
|
+
"test:watch": "vitest"
|
|
18
|
+
},
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=20"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"mnemonik",
|
|
24
|
+
"codex",
|
|
25
|
+
"hooks"
|
|
26
|
+
],
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/node": "^22.0.0",
|
|
30
|
+
"typescript": "^5.3.3",
|
|
31
|
+
"vitest": "^4.1.5"
|
|
32
|
+
}
|
|
33
|
+
}
|