@axtary/cli 0.0.1 → 0.2.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/LICENSE +202 -0
- package/README.md +140 -6
- package/dist/bin.js +10 -0
- package/dist/bin.js.map +1 -1
- package/dist/claude-code-hook.d.ts +65 -0
- package/dist/claude-code-hook.d.ts.map +1 -0
- package/dist/claude-code-hook.js +326 -0
- package/dist/claude-code-hook.js.map +1 -0
- package/dist/codex-hook.d.ts +48 -0
- package/dist/codex-hook.d.ts.map +1 -0
- package/dist/codex-hook.js +259 -0
- package/dist/codex-hook.js.map +1 -0
- package/dist/credentials.d.ts +101 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +277 -0
- package/dist/credentials.js.map +1 -0
- package/dist/cursor-hook.d.ts +51 -0
- package/dist/cursor-hook.d.ts.map +1 -0
- package/dist/cursor-hook.js +214 -0
- package/dist/cursor-hook.js.map +1 -0
- package/dist/hook-install.d.ts +21 -0
- package/dist/hook-install.d.ts.map +1 -0
- package/dist/hook-install.js +179 -0
- package/dist/hook-install.js.map +1 -0
- package/dist/index.d.ts +897 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6750 -513
- package/dist/index.js.map +1 -1
- package/dist/mcp-fs-normalize.d.ts +18 -0
- package/dist/mcp-fs-normalize.d.ts.map +1 -0
- package/dist/mcp-fs-normalize.js +39 -0
- package/dist/mcp-fs-normalize.js.map +1 -0
- package/dist/mcp-oauth.d.ts +67 -0
- package/dist/mcp-oauth.d.ts.map +1 -0
- package/dist/mcp-oauth.js +242 -0
- package/dist/mcp-oauth.js.map +1 -0
- package/dist/oauth.d.ts +90 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +339 -0
- package/dist/oauth.js.map +1 -0
- package/dist/render.d.ts +103 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +172 -0
- package/dist/render.js.map +1 -0
- package/dist/shell-file-normalize.d.ts +21 -0
- package/dist/shell-file-normalize.d.ts.map +1 -0
- package/dist/shell-file-normalize.js +269 -0
- package/dist/shell-file-normalize.js.map +1 -0
- package/package.json +17 -13
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import { realpathSync } from "node:fs";
|
|
2
|
+
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
3
|
+
import { parseNormalizedAction, } from "@axtary/actionpass";
|
|
4
|
+
import { classifyShellFileOps, } from "./shell-file-normalize.js";
|
|
5
|
+
export const CLAUDE_CODE_HOOK_SCHEMA_VERSION = "axtary.claude_code_hook.v0";
|
|
6
|
+
export const DEFAULT_PROXY_URL = "http://127.0.0.1:7331";
|
|
7
|
+
export const DEFAULT_HOOK_TIMEOUT_MS = 5_000;
|
|
8
|
+
export function parseClaudeCodeHookPayload(payloadText) {
|
|
9
|
+
let raw;
|
|
10
|
+
try {
|
|
11
|
+
raw = JSON.parse(payloadText);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
throw new Error("claude_code_hook_payload_invalid_json");
|
|
15
|
+
}
|
|
16
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
17
|
+
throw new Error("claude_code_hook_payload_not_object");
|
|
18
|
+
}
|
|
19
|
+
const record = raw;
|
|
20
|
+
const toolName = record.tool_name;
|
|
21
|
+
if (typeof toolName !== "string" || toolName.length === 0) {
|
|
22
|
+
throw new Error("claude_code_hook_tool_name_required");
|
|
23
|
+
}
|
|
24
|
+
const toolInput = record.tool_input && typeof record.tool_input === "object" && !Array.isArray(record.tool_input)
|
|
25
|
+
? record.tool_input
|
|
26
|
+
: {};
|
|
27
|
+
return {
|
|
28
|
+
sessionId: typeof record.session_id === "string" ? record.session_id : null,
|
|
29
|
+
cwd: typeof record.cwd === "string" ? record.cwd : null,
|
|
30
|
+
toolName,
|
|
31
|
+
toolInput,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const READ_TOOLS = {
|
|
35
|
+
Read: "file_path",
|
|
36
|
+
Glob: "path",
|
|
37
|
+
Grep: "path",
|
|
38
|
+
};
|
|
39
|
+
const WRITE_TOOLS = {
|
|
40
|
+
Write: "file_path",
|
|
41
|
+
Edit: "file_path",
|
|
42
|
+
NotebookEdit: "notebook_path",
|
|
43
|
+
};
|
|
44
|
+
const SHELL_TOOLS = new Set(["Bash"]);
|
|
45
|
+
export function normalizeClaudeCodeToolCall(payload, options = {}) {
|
|
46
|
+
if (SHELL_TOOLS.has(payload.toolName)) {
|
|
47
|
+
const command = typeof payload.toolInput.command === "string"
|
|
48
|
+
? payload.toolInput.command
|
|
49
|
+
: "";
|
|
50
|
+
const ops = command ? classifyShellFileOps(command) : [];
|
|
51
|
+
if (ops.length === 0) {
|
|
52
|
+
return { mapped: false, reason: `claude_code_shell_no_file_op:${payload.toolName}` };
|
|
53
|
+
}
|
|
54
|
+
// Every file op a command performs is governed (e.g. `cp secret dest`
|
|
55
|
+
// governs the source read AND the destination write); the run loop denies
|
|
56
|
+
// if any op is denied. Fail-closed across the whole command.
|
|
57
|
+
const actions = ops.map((op) => buildShellContentAction(op, payload, options));
|
|
58
|
+
return { mapped: true, action: actions[0], actions };
|
|
59
|
+
}
|
|
60
|
+
const readPathField = READ_TOOLS[payload.toolName];
|
|
61
|
+
const writePathField = WRITE_TOOLS[payload.toolName];
|
|
62
|
+
if (!readPathField && !writePathField) {
|
|
63
|
+
return {
|
|
64
|
+
mapped: false,
|
|
65
|
+
reason: `claude_code_tool_unmapped:${payload.toolName}`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const pathField = readPathField ?? writePathField;
|
|
69
|
+
const rawPath = payload.toolInput[pathField];
|
|
70
|
+
const path = workspaceRelativePath(typeof rawPath === "string" && rawPath.length > 0 ? rawPath : ".", payload.cwd);
|
|
71
|
+
const repoResource = options.repoResource ?? "repo:local/workspace";
|
|
72
|
+
const taskId = payload.sessionId
|
|
73
|
+
? `claude-code:${payload.sessionId.slice(0, 12)}`
|
|
74
|
+
: "claude-code:session";
|
|
75
|
+
const base = {
|
|
76
|
+
actor: {
|
|
77
|
+
agentId: "agent:claude-code",
|
|
78
|
+
humanOwner: options.humanOwner ?? "user:local-developer",
|
|
79
|
+
runtime: "claude-code",
|
|
80
|
+
},
|
|
81
|
+
intent: {
|
|
82
|
+
taskId,
|
|
83
|
+
declaredGoal: `Claude Code ${payload.toolName} tool call`,
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
if (readPathField) {
|
|
87
|
+
const action = parseNormalizedAction({
|
|
88
|
+
...base,
|
|
89
|
+
capability: {
|
|
90
|
+
tool: "github.contents.read",
|
|
91
|
+
resource: repoResource,
|
|
92
|
+
payload: {
|
|
93
|
+
path,
|
|
94
|
+
source: "claude-code-hook",
|
|
95
|
+
claudeCodeTool: payload.toolName,
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
return { mapped: true, action, actions: [action] };
|
|
100
|
+
}
|
|
101
|
+
const action = parseNormalizedAction({
|
|
102
|
+
...base,
|
|
103
|
+
capability: {
|
|
104
|
+
tool: "github.contents.write",
|
|
105
|
+
resource: repoResource,
|
|
106
|
+
payload: {
|
|
107
|
+
path,
|
|
108
|
+
branch: options.branch ?? "workspace",
|
|
109
|
+
source: "claude-code-hook",
|
|
110
|
+
claudeCodeTool: payload.toolName,
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
return { mapped: true, action, actions: [action] };
|
|
115
|
+
}
|
|
116
|
+
function buildShellContentAction(op, payload, options) {
|
|
117
|
+
const path = workspaceRelativePath(op.path, payload.cwd);
|
|
118
|
+
const repoResource = options.repoResource ?? "repo:local/workspace";
|
|
119
|
+
const taskId = payload.sessionId
|
|
120
|
+
? `claude-code:${payload.sessionId.slice(0, 12)}`
|
|
121
|
+
: "claude-code:session";
|
|
122
|
+
const base = {
|
|
123
|
+
actor: {
|
|
124
|
+
agentId: "agent:claude-code",
|
|
125
|
+
humanOwner: options.humanOwner ?? "user:local-developer",
|
|
126
|
+
runtime: "claude-code",
|
|
127
|
+
},
|
|
128
|
+
intent: {
|
|
129
|
+
taskId,
|
|
130
|
+
declaredGoal: `Claude Code ${payload.toolName} tool call`,
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
if (op.kind === "read") {
|
|
134
|
+
return parseNormalizedAction({
|
|
135
|
+
...base,
|
|
136
|
+
capability: {
|
|
137
|
+
tool: "github.contents.read",
|
|
138
|
+
resource: repoResource,
|
|
139
|
+
payload: {
|
|
140
|
+
path,
|
|
141
|
+
source: "claude-code-hook",
|
|
142
|
+
claudeCodeTool: payload.toolName,
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
return parseNormalizedAction({
|
|
148
|
+
...base,
|
|
149
|
+
capability: {
|
|
150
|
+
tool: "github.contents.write",
|
|
151
|
+
resource: repoResource,
|
|
152
|
+
payload: {
|
|
153
|
+
path,
|
|
154
|
+
branch: options.branch ?? "workspace",
|
|
155
|
+
source: "claude-code-hook",
|
|
156
|
+
claudeCodeTool: payload.toolName,
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
export async function runClaudeCodeHook(input) {
|
|
162
|
+
let payload;
|
|
163
|
+
try {
|
|
164
|
+
payload = parseClaudeCodeHookPayload(input.payloadText);
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
return decisionResult(null, null, "deny", [
|
|
168
|
+
`Axtary blocked this tool call: hook payload could not be parsed (${errorReason(error)}). Protected actions fail closed.`,
|
|
169
|
+
]);
|
|
170
|
+
}
|
|
171
|
+
const normalization = normalizeClaudeCodeToolCall(payload, {
|
|
172
|
+
repoResource: input.repoResource,
|
|
173
|
+
humanOwner: input.humanOwner,
|
|
174
|
+
branch: input.branch,
|
|
175
|
+
});
|
|
176
|
+
if (!normalization.mapped) {
|
|
177
|
+
return {
|
|
178
|
+
schemaVersion: CLAUDE_CODE_HOOK_SCHEMA_VERSION,
|
|
179
|
+
status: "no_opinion",
|
|
180
|
+
tool: payload.toolName,
|
|
181
|
+
normalizedTool: null,
|
|
182
|
+
reason: normalization.reason,
|
|
183
|
+
output: null,
|
|
184
|
+
exitCode: 0,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
const proxyUrl = (input.proxyUrl ?? DEFAULT_PROXY_URL).replace(/\/$/, "");
|
|
188
|
+
const fetchImpl = input.fetch ?? globalThis.fetch;
|
|
189
|
+
const timeoutMs = input.timeoutMs ?? DEFAULT_HOOK_TIMEOUT_MS;
|
|
190
|
+
// Authorize every governed op (e.g. both the source read and destination write
|
|
191
|
+
// of `cp secret dest`); the most restrictive decision wins — deny > step_up >
|
|
192
|
+
// allow — and a hard deny short-circuits the rest. Fail-closed.
|
|
193
|
+
let best = null;
|
|
194
|
+
for (const action of normalization.actions) {
|
|
195
|
+
let response;
|
|
196
|
+
try {
|
|
197
|
+
response = await postAuthorize(fetchImpl, `${proxyUrl}/authorize`, action, timeoutMs);
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
return decisionResult(payload.toolName, action.capability.tool, "deny", [
|
|
201
|
+
`Axtary blocked this tool call: local proxy unreachable at ${proxyUrl} (${errorReason(error)}).`,
|
|
202
|
+
"Start it with: axtary proxy --config axtary.yml",
|
|
203
|
+
]);
|
|
204
|
+
}
|
|
205
|
+
const rank = authorizeRank(response.status);
|
|
206
|
+
if (!best || rank > best.rank) {
|
|
207
|
+
best = { action, response, rank };
|
|
208
|
+
}
|
|
209
|
+
if (rank === DENY_RANK)
|
|
210
|
+
break; // hard deny is maximal
|
|
211
|
+
}
|
|
212
|
+
const response = best.response;
|
|
213
|
+
const normalizedTool = best.action.capability.tool;
|
|
214
|
+
const reasons = response.decision?.reasons ?? [];
|
|
215
|
+
const hints = response.hints ?? [];
|
|
216
|
+
const summary = response.explanation?.summary ?? reasons.join(", ");
|
|
217
|
+
const ledgerLine = typeof response.ledger?.lineNumber === "number"
|
|
218
|
+
? ` Ledger line ${response.ledger.lineNumber}.`
|
|
219
|
+
: "";
|
|
220
|
+
if (response.status === "authorized") {
|
|
221
|
+
return decisionResult(payload.toolName, normalizedTool, "allow", [
|
|
222
|
+
`Axtary authorized ${normalizedTool}: ${summary}${ledgerLine}`,
|
|
223
|
+
]);
|
|
224
|
+
}
|
|
225
|
+
if (response.status === "step_up") {
|
|
226
|
+
return decisionResult(payload.toolName, normalizedTool, "ask", [
|
|
227
|
+
`Axtary requires step-up review for ${normalizedTool}: ${summary}`,
|
|
228
|
+
...hints,
|
|
229
|
+
ledgerLine.trim(),
|
|
230
|
+
]);
|
|
231
|
+
}
|
|
232
|
+
return decisionResult(payload.toolName, normalizedTool, "deny", [
|
|
233
|
+
`Axtary blocked ${normalizedTool}: ${summary}`,
|
|
234
|
+
...hints,
|
|
235
|
+
ledgerLine.trim(),
|
|
236
|
+
]);
|
|
237
|
+
}
|
|
238
|
+
export const DENY_RANK = 3;
|
|
239
|
+
/** Severity rank for picking the most restrictive decision across ops. */
|
|
240
|
+
export function authorizeRank(status) {
|
|
241
|
+
if (status === "blocked" || status === "malformed")
|
|
242
|
+
return DENY_RANK;
|
|
243
|
+
if (status === "step_up")
|
|
244
|
+
return 2;
|
|
245
|
+
return 1; // authorized
|
|
246
|
+
}
|
|
247
|
+
export async function postAuthorize(fetchImpl, url, action, timeoutMs) {
|
|
248
|
+
if (!fetchImpl) {
|
|
249
|
+
throw new Error("fetch_unavailable");
|
|
250
|
+
}
|
|
251
|
+
const response = await fetchImpl(url, {
|
|
252
|
+
method: "POST",
|
|
253
|
+
headers: { "content-type": "application/json" },
|
|
254
|
+
body: JSON.stringify(action),
|
|
255
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
256
|
+
});
|
|
257
|
+
const body = (await response.json());
|
|
258
|
+
if (!response.ok && response.status !== 400) {
|
|
259
|
+
throw new Error(`proxy_authorize_http_${response.status}`);
|
|
260
|
+
}
|
|
261
|
+
if (body.status !== "authorized" &&
|
|
262
|
+
body.status !== "step_up" &&
|
|
263
|
+
body.status !== "blocked" &&
|
|
264
|
+
body.status !== "malformed") {
|
|
265
|
+
throw new Error("proxy_authorize_response_invalid");
|
|
266
|
+
}
|
|
267
|
+
return body;
|
|
268
|
+
}
|
|
269
|
+
function decisionResult(tool, normalizedTool, decision, reasonParts) {
|
|
270
|
+
const reason = reasonParts.filter((part) => part.length > 0).join(" ");
|
|
271
|
+
return {
|
|
272
|
+
schemaVersion: CLAUDE_CODE_HOOK_SCHEMA_VERSION,
|
|
273
|
+
status: decision,
|
|
274
|
+
tool,
|
|
275
|
+
normalizedTool,
|
|
276
|
+
reason,
|
|
277
|
+
output: JSON.stringify({
|
|
278
|
+
hookSpecificOutput: {
|
|
279
|
+
hookEventName: "PreToolUse",
|
|
280
|
+
permissionDecision: decision,
|
|
281
|
+
permissionDecisionReason: reason,
|
|
282
|
+
},
|
|
283
|
+
}),
|
|
284
|
+
exitCode: 0,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
export function workspaceRelativePath(path, cwd) {
|
|
288
|
+
if (!isAbsolute(path)) {
|
|
289
|
+
return path;
|
|
290
|
+
}
|
|
291
|
+
const base = resolve(cwd ?? process.cwd());
|
|
292
|
+
const bases = unique([base, resolveSymlinks(base)]);
|
|
293
|
+
const candidates = unique([path, resolveSymlinks(path)]);
|
|
294
|
+
for (const candidatePath of candidates) {
|
|
295
|
+
for (const candidateBase of bases) {
|
|
296
|
+
const relativePath = relative(candidateBase, candidatePath);
|
|
297
|
+
if (relativePath.length === 0) {
|
|
298
|
+
return ".";
|
|
299
|
+
}
|
|
300
|
+
if (!relativePath.startsWith("..")) {
|
|
301
|
+
return relativePath;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return path;
|
|
306
|
+
}
|
|
307
|
+
function resolveSymlinks(path) {
|
|
308
|
+
try {
|
|
309
|
+
return realpathSync(path);
|
|
310
|
+
}
|
|
311
|
+
catch {
|
|
312
|
+
try {
|
|
313
|
+
return join(realpathSync(dirname(path)), basename(path));
|
|
314
|
+
}
|
|
315
|
+
catch {
|
|
316
|
+
return path;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
function unique(values) {
|
|
321
|
+
return [...new Set(values)];
|
|
322
|
+
}
|
|
323
|
+
export function errorReason(error) {
|
|
324
|
+
return error instanceof Error ? error.message : "unknown_error";
|
|
325
|
+
}
|
|
326
|
+
//# sourceMappingURL=claude-code-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code-hook.js","sourceRoot":"","sources":["../src/claude-code-hook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type JsonValue, type NormalizedAction } from "@axtary/actionpass";
|
|
2
|
+
export { classifyShellCommand, classifyShellFileOps } from "./shell-file-normalize.js";
|
|
3
|
+
export declare const CODEX_HOOK_SCHEMA_VERSION = "axtary.codex_hook.v0";
|
|
4
|
+
export type CodexHookPayload = {
|
|
5
|
+
hookEventName: string | null;
|
|
6
|
+
sessionId: string | null;
|
|
7
|
+
cwd: string | null;
|
|
8
|
+
toolName: string;
|
|
9
|
+
toolInput: Record<string, JsonValue>;
|
|
10
|
+
};
|
|
11
|
+
export type CodexNormalization = {
|
|
12
|
+
mapped: true;
|
|
13
|
+
action: NormalizedAction;
|
|
14
|
+
actions: NormalizedAction[];
|
|
15
|
+
} | {
|
|
16
|
+
mapped: false;
|
|
17
|
+
reason: string;
|
|
18
|
+
};
|
|
19
|
+
export type CodexNormalizeOptions = {
|
|
20
|
+
repoResource?: string;
|
|
21
|
+
humanOwner?: string;
|
|
22
|
+
branch?: string;
|
|
23
|
+
};
|
|
24
|
+
export type CodexHookRunInput = {
|
|
25
|
+
payloadText: string;
|
|
26
|
+
proxyUrl?: string;
|
|
27
|
+
repoResource?: string;
|
|
28
|
+
humanOwner?: string;
|
|
29
|
+
branch?: string;
|
|
30
|
+
timeoutMs?: number;
|
|
31
|
+
fetch?: typeof fetch;
|
|
32
|
+
};
|
|
33
|
+
export type CodexHookRunResult = {
|
|
34
|
+
schemaVersion: typeof CODEX_HOOK_SCHEMA_VERSION;
|
|
35
|
+
/** Proxy decision semantics; `no_opinion` emits no decision. */
|
|
36
|
+
status: "allow" | "step_up" | "deny" | "no_opinion";
|
|
37
|
+
tool: string | null;
|
|
38
|
+
normalizedTool: string | null;
|
|
39
|
+
reason: string | null;
|
|
40
|
+
/** JSON for stdout (Codex `hookSpecificOutput`), or null for no opinion. */
|
|
41
|
+
output: string | null;
|
|
42
|
+
/** Always 0: decisions (incl. fail-closed denials) live in the JSON. */
|
|
43
|
+
exitCode: number;
|
|
44
|
+
};
|
|
45
|
+
export declare function parseCodexHookPayload(payloadText: string): CodexHookPayload;
|
|
46
|
+
export declare function normalizeCodexToolCall(payload: CodexHookPayload, options?: CodexNormalizeOptions): CodexNormalization;
|
|
47
|
+
export declare function runCodexHook(input: CodexHookRunInput): Promise<CodexHookRunResult>;
|
|
48
|
+
//# sourceMappingURL=codex-hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-hook.d.ts","sourceRoot":"","sources":["../src/codex-hook.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAC;AAkB5B,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAoBvF,eAAO,MAAM,yBAAyB,yBAAyB,CAAC;AAEhE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAC1B;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAC;IAAC,OAAO,EAAE,gBAAgB,EAAE,CAAA;CAAE,GACvE;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC,MAAM,MAAM,qBAAqB,GAAG;IAClC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,aAAa,EAAE,OAAO,yBAAyB,CAAC;IAChD,gEAAgE;IAChE,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,YAAY,CAAC;IACpD,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,4EAA4E;IAC5E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,gBAAgB,CAmC3E;AAkED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,gBAAgB,EACzB,OAAO,GAAE,qBAA0B,GAClC,kBAAkB,CAoDpB;AAMD,wBAAsB,YAAY,CAChC,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,kBAAkB,CAAC,CAwG7B"}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { parseNormalizedAction, } from "@axtary/actionpass";
|
|
2
|
+
import { authorizeRank, DENY_RANK, DEFAULT_HOOK_TIMEOUT_MS, DEFAULT_PROXY_URL, errorReason, postAuthorize, workspaceRelativePath, } from "./claude-code-hook.js";
|
|
3
|
+
import { classifyMcpFilesystemTool } from "./mcp-fs-normalize.js";
|
|
4
|
+
import { classifyShellFileOps, } from "./shell-file-normalize.js";
|
|
5
|
+
export { classifyShellCommand, classifyShellFileOps } from "./shell-file-normalize.js";
|
|
6
|
+
// Codex CLI runtime-hook adapter (mega-plan M8.4). Codex calls a configured
|
|
7
|
+
// `PreToolUse` hook before it runs a tool; the hook reads a JSON payload on
|
|
8
|
+
// stdin and returns a decision. Codex's hook contract is Claude-Code-shaped —
|
|
9
|
+
// it emits the same `hookSpecificOutput.permissionDecision` object — so the
|
|
10
|
+
// output side mirrors the Claude hook exactly. Verified against the official
|
|
11
|
+
// Codex hooks docs (2026-06-26).
|
|
12
|
+
//
|
|
13
|
+
// What differs from Claude/Cursor: Codex's reliable hook surface is the SHELL
|
|
14
|
+
// (`Bash`) tool, whose `tool_input.command` is a shell command string — not a
|
|
15
|
+
// file path. So the core work here is mapping a file-touching shell command
|
|
16
|
+
// (and, best-effort, `apply_patch` edits and MCP filesystem tools) onto the
|
|
17
|
+
// same `github.contents.read/write` actions, so the existing secret/path policy
|
|
18
|
+
// applies. Codex docs note hooks fire reliably for shell, less so for
|
|
19
|
+
// apply_patch / most MCP tools — hence those are best-effort.
|
|
20
|
+
//
|
|
21
|
+
// Fail-closed: a step-up renders as a BLOCK on Codex (its PreToolUse contract
|
|
22
|
+
// documents only allow/deny; we do not rely on an unverified "ask"), and any
|
|
23
|
+
// error (bad payload / unreachable proxy) is an explicit deny.
|
|
24
|
+
export const CODEX_HOOK_SCHEMA_VERSION = "axtary.codex_hook.v0";
|
|
25
|
+
export function parseCodexHookPayload(payloadText) {
|
|
26
|
+
let raw;
|
|
27
|
+
try {
|
|
28
|
+
raw = JSON.parse(payloadText);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
throw new Error("codex_hook_payload_invalid_json");
|
|
32
|
+
}
|
|
33
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
34
|
+
throw new Error("codex_hook_payload_not_object");
|
|
35
|
+
}
|
|
36
|
+
const record = raw;
|
|
37
|
+
const toolName = record.tool_name;
|
|
38
|
+
if (typeof toolName !== "string" || toolName.length === 0) {
|
|
39
|
+
throw new Error("codex_hook_tool_name_required");
|
|
40
|
+
}
|
|
41
|
+
const toolInput = record.tool_input &&
|
|
42
|
+
typeof record.tool_input === "object" &&
|
|
43
|
+
!Array.isArray(record.tool_input)
|
|
44
|
+
? record.tool_input
|
|
45
|
+
: {};
|
|
46
|
+
return {
|
|
47
|
+
hookEventName: typeof record.hook_event_name === "string" ? record.hook_event_name : null,
|
|
48
|
+
sessionId: typeof record.session_id === "string" ? record.session_id : null,
|
|
49
|
+
cwd: typeof record.cwd === "string" ? record.cwd : null,
|
|
50
|
+
toolName,
|
|
51
|
+
toolInput,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const SHELL_TOOLS = new Set(["Bash", "shell", "local_shell"]);
|
|
55
|
+
// Codex apply_patch envelope headers name the files touched.
|
|
56
|
+
const APPLY_PATCH_FILE_RE = /^\*\*\*\s+(?:Add|Update|Delete)\s+File:\s+(.+?)\s*$/gm;
|
|
57
|
+
function applyPatchPaths(command) {
|
|
58
|
+
const paths = [];
|
|
59
|
+
let match;
|
|
60
|
+
APPLY_PATCH_FILE_RE.lastIndex = 0;
|
|
61
|
+
while ((match = APPLY_PATCH_FILE_RE.exec(command))) {
|
|
62
|
+
paths.push(match[1]);
|
|
63
|
+
}
|
|
64
|
+
return paths;
|
|
65
|
+
}
|
|
66
|
+
function buildContentAction(op, payload, options, sourceTool) {
|
|
67
|
+
const path = workspaceRelativePath(op.path, payload.cwd);
|
|
68
|
+
const repoResource = options.repoResource ?? "repo:local/workspace";
|
|
69
|
+
const taskId = payload.sessionId
|
|
70
|
+
? `codex:${payload.sessionId.slice(0, 12)}`
|
|
71
|
+
: "codex:session";
|
|
72
|
+
const base = {
|
|
73
|
+
actor: {
|
|
74
|
+
agentId: "agent:codex",
|
|
75
|
+
humanOwner: options.humanOwner ?? "user:local-developer",
|
|
76
|
+
runtime: "codex",
|
|
77
|
+
},
|
|
78
|
+
intent: {
|
|
79
|
+
taskId,
|
|
80
|
+
declaredGoal: `Codex ${payload.toolName} tool call`,
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
if (op.kind === "read") {
|
|
84
|
+
return parseNormalizedAction({
|
|
85
|
+
...base,
|
|
86
|
+
capability: {
|
|
87
|
+
tool: "github.contents.read",
|
|
88
|
+
resource: repoResource,
|
|
89
|
+
payload: { path, source: "codex-hook", codexTool: sourceTool },
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return parseNormalizedAction({
|
|
94
|
+
...base,
|
|
95
|
+
capability: {
|
|
96
|
+
tool: "github.contents.write",
|
|
97
|
+
resource: repoResource,
|
|
98
|
+
payload: {
|
|
99
|
+
path,
|
|
100
|
+
branch: options.branch ?? "workspace",
|
|
101
|
+
source: "codex-hook",
|
|
102
|
+
codexTool: sourceTool,
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
export function normalizeCodexToolCall(payload, options = {}) {
|
|
108
|
+
// Shell (the reliable Codex surface): map every file op a command performs,
|
|
109
|
+
// so `cp secret dest` governs the source read AND the destination write.
|
|
110
|
+
if (SHELL_TOOLS.has(payload.toolName)) {
|
|
111
|
+
const command = typeof payload.toolInput.command === "string"
|
|
112
|
+
? payload.toolInput.command
|
|
113
|
+
: "";
|
|
114
|
+
const ops = command ? classifyShellFileOps(command) : [];
|
|
115
|
+
if (ops.length === 0) {
|
|
116
|
+
return { mapped: false, reason: `codex_shell_no_file_op:${payload.toolName}` };
|
|
117
|
+
}
|
|
118
|
+
return mappedActions(ops.map((op) => buildContentAction(op, payload, options, payload.toolName)));
|
|
119
|
+
}
|
|
120
|
+
// apply_patch (best-effort): the envelope names every file it edits; govern
|
|
121
|
+
// all of them (the run loop denies if any is denied).
|
|
122
|
+
if (payload.toolName === "apply_patch") {
|
|
123
|
+
const command = typeof payload.toolInput.command === "string"
|
|
124
|
+
? payload.toolInput.command
|
|
125
|
+
: "";
|
|
126
|
+
const paths = command ? applyPatchPaths(command) : [];
|
|
127
|
+
if (paths.length === 0) {
|
|
128
|
+
return { mapped: false, reason: "codex_apply_patch_no_files" };
|
|
129
|
+
}
|
|
130
|
+
return mappedActions(paths.map((path) => buildContentAction({ kind: "write", path }, payload, options, payload.toolName)));
|
|
131
|
+
}
|
|
132
|
+
// MCP filesystem tools (best-effort; Codex MCP hooks fire less reliably).
|
|
133
|
+
const classified = classifyMcpFilesystemTool(payload.toolName);
|
|
134
|
+
if (classified) {
|
|
135
|
+
const rawPath = payload.toolInput[classified.pathField];
|
|
136
|
+
if (typeof rawPath === "string" && rawPath.length > 0) {
|
|
137
|
+
return mappedActions([
|
|
138
|
+
buildContentAction({ kind: classified.kind, path: rawPath }, payload, options, payload.toolName),
|
|
139
|
+
]);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return { mapped: false, reason: `codex_tool_unmapped:${payload.toolName}` };
|
|
143
|
+
}
|
|
144
|
+
function mappedActions(actions) {
|
|
145
|
+
return { mapped: true, action: actions[0], actions };
|
|
146
|
+
}
|
|
147
|
+
export async function runCodexHook(input) {
|
|
148
|
+
let payload;
|
|
149
|
+
try {
|
|
150
|
+
payload = parseCodexHookPayload(input.payloadText);
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
return decisionResult(null, null, "deny", [
|
|
154
|
+
`Axtary blocked this tool call: hook payload could not be parsed (${errorReason(error)}). Protected actions fail closed.`,
|
|
155
|
+
]);
|
|
156
|
+
}
|
|
157
|
+
const normalization = normalizeCodexToolCall(payload, {
|
|
158
|
+
repoResource: input.repoResource,
|
|
159
|
+
humanOwner: input.humanOwner,
|
|
160
|
+
branch: input.branch,
|
|
161
|
+
});
|
|
162
|
+
if (!normalization.mapped) {
|
|
163
|
+
return {
|
|
164
|
+
schemaVersion: CODEX_HOOK_SCHEMA_VERSION,
|
|
165
|
+
status: "no_opinion",
|
|
166
|
+
tool: payload.toolName,
|
|
167
|
+
normalizedTool: null,
|
|
168
|
+
reason: normalization.reason,
|
|
169
|
+
output: null,
|
|
170
|
+
exitCode: 0,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
const proxyUrl = (input.proxyUrl ?? DEFAULT_PROXY_URL).replace(/\/$/, "");
|
|
174
|
+
const fetchImpl = input.fetch ?? globalThis.fetch;
|
|
175
|
+
const timeoutMs = input.timeoutMs ?? DEFAULT_HOOK_TIMEOUT_MS;
|
|
176
|
+
// Authorize every governed op; the most restrictive decision wins
|
|
177
|
+
// (deny > step_up > allow) and a hard deny short-circuits. Fail-closed.
|
|
178
|
+
let best = null;
|
|
179
|
+
for (const action of normalization.actions) {
|
|
180
|
+
let response;
|
|
181
|
+
try {
|
|
182
|
+
response = await postAuthorize(fetchImpl, `${proxyUrl}/authorize`, action, timeoutMs);
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
return decisionResult(payload.toolName, action.capability.tool, "deny", [
|
|
186
|
+
`Axtary blocked ${action.capability.tool}: local proxy unreachable at ${proxyUrl} (${errorReason(error)}).`,
|
|
187
|
+
"Start it with: axtary proxy --config axtary.yml",
|
|
188
|
+
]);
|
|
189
|
+
}
|
|
190
|
+
const rank = authorizeRank(response.status);
|
|
191
|
+
if (!best || rank > best.rank) {
|
|
192
|
+
best = { action, response, rank };
|
|
193
|
+
}
|
|
194
|
+
if (rank === DENY_RANK)
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
const response = best.response;
|
|
198
|
+
const normalizedTool = best.action.capability.tool;
|
|
199
|
+
const reasons = response.decision?.reasons ?? [];
|
|
200
|
+
const hints = response.hints ?? [];
|
|
201
|
+
const summary = response.explanation?.summary ?? reasons.join(", ");
|
|
202
|
+
const ledgerLine = typeof response.ledger?.lineNumber === "number"
|
|
203
|
+
? ` Ledger line ${response.ledger.lineNumber}.`
|
|
204
|
+
: "";
|
|
205
|
+
if (response.status === "authorized") {
|
|
206
|
+
// Live-verified against Codex CLI v0.142.3: emitting
|
|
207
|
+
// `permissionDecision:"allow"` errors the hook ("unsupported
|
|
208
|
+
// permissionDecision:allow") and Codex then fails open. For an allow we emit
|
|
209
|
+
// NO decision so Codex proceeds normally; the decision is already recorded by
|
|
210
|
+
// the /authorize call above (only `deny` is honored on PreToolUse).
|
|
211
|
+
return {
|
|
212
|
+
schemaVersion: CODEX_HOOK_SCHEMA_VERSION,
|
|
213
|
+
status: "allow",
|
|
214
|
+
tool: payload.toolName,
|
|
215
|
+
normalizedTool,
|
|
216
|
+
reason: `Axtary authorized ${normalizedTool}: ${summary}${ledgerLine}`,
|
|
217
|
+
output: null,
|
|
218
|
+
exitCode: 0,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
if (response.status === "step_up") {
|
|
222
|
+
// Codex PreToolUse honors only `deny`; we block step-up (fail closed) rather
|
|
223
|
+
// than rely on an unverified interactive "ask", and point to the
|
|
224
|
+
// payload-bound approval path.
|
|
225
|
+
return decisionResult(payload.toolName, normalizedTool, "step_up", [
|
|
226
|
+
`Axtary blocked ${normalizedTool} pending human step-up approval: ${summary}`,
|
|
227
|
+
...hints,
|
|
228
|
+
"Approve the exact payload via the Axtary dashboard / proxy approval path before re-running.",
|
|
229
|
+
ledgerLine.trim(),
|
|
230
|
+
]);
|
|
231
|
+
}
|
|
232
|
+
return decisionResult(payload.toolName, normalizedTool, "deny", [
|
|
233
|
+
`Axtary blocked ${normalizedTool}: ${summary}`,
|
|
234
|
+
...hints,
|
|
235
|
+
ledgerLine.trim(),
|
|
236
|
+
]);
|
|
237
|
+
}
|
|
238
|
+
// Codex PreToolUse honors only `permissionDecision:"deny"` (allow/ask are
|
|
239
|
+
// rejected as unsupported, v0.142.3), so every blocking decision — an explicit
|
|
240
|
+
// deny, a fail-closed step-up, or an error — renders as a deny.
|
|
241
|
+
function decisionResult(tool, normalizedTool, status, reasonParts) {
|
|
242
|
+
const reason = reasonParts.filter((part) => part.length > 0).join(" ");
|
|
243
|
+
return {
|
|
244
|
+
schemaVersion: CODEX_HOOK_SCHEMA_VERSION,
|
|
245
|
+
status,
|
|
246
|
+
tool,
|
|
247
|
+
normalizedTool,
|
|
248
|
+
reason,
|
|
249
|
+
output: JSON.stringify({
|
|
250
|
+
hookSpecificOutput: {
|
|
251
|
+
hookEventName: "PreToolUse",
|
|
252
|
+
permissionDecision: "deny",
|
|
253
|
+
permissionDecisionReason: reason,
|
|
254
|
+
},
|
|
255
|
+
}),
|
|
256
|
+
exitCode: 0,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
//# sourceMappingURL=codex-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-hook.js","sourceRoot":"","sources":["../src/codex-hook.ts"],"names":[],"mappings":"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"}
|