@astrasyncai/verification-gateway 3.10.0 → 3.11.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/adapter-interface/interface.d.mts +1 -1
- package/dist/adapter-interface/interface.d.ts +1 -1
- package/dist/adapters/express.js +1 -1
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +1 -1
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/mcp.js +1 -1
- package/dist/adapters/mcp.js.map +1 -1
- package/dist/adapters/mcp.mjs +1 -1
- package/dist/adapters/mcp.mjs.map +1 -1
- package/dist/adapters/nextjs.js +1 -1
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +1 -1
- package/dist/adapters/nextjs.mjs.map +1 -1
- package/dist/adapters/sdk.js +1 -1
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +1 -1
- package/dist/adapters/sdk.mjs.map +1 -1
- package/dist/bin/astrasync-claude-hook.js +317 -35
- package/dist/bin/astrasync-codex-hook.js +5107 -0
- package/dist/bin/astrasync-guard.js +430 -40
- package/dist/bin/astrasync.js +453 -41
- package/dist/browser/background.js +279 -24
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +279 -24
- package/dist/browser/background.mjs.map +1 -1
- package/dist/browser/browser-adapter.d.mts +1 -1
- package/dist/browser/browser-adapter.d.ts +1 -1
- package/dist/claude-code/claude-code-adapter.d.mts +1 -1
- package/dist/claude-code/claude-code-adapter.d.ts +1 -1
- package/dist/claude-code/claude-code-adapter.js +9 -1
- package/dist/claude-code/claude-code-adapter.js.map +1 -1
- package/dist/claude-code/claude-code-adapter.mjs +9 -1
- package/dist/claude-code/claude-code-adapter.mjs.map +1 -1
- package/dist/cli/index.d.mts +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/codex/index.d.mts +230 -0
- package/dist/codex/index.d.ts +230 -0
- package/dist/codex/index.js +5225 -0
- package/dist/codex/index.js.map +1 -0
- package/dist/codex/index.mjs +5197 -0
- package/dist/codex/index.mjs.map +1 -0
- package/dist/cursor/cursor-adapter.d.mts +1 -1
- package/dist/cursor/cursor-adapter.d.ts +1 -1
- package/dist/cursor/extension.d.mts +1 -1
- package/dist/cursor/extension.d.ts +1 -1
- package/dist/cursor/extension.js +279 -24
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +279 -24
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/gateway/gateway.d.mts +32 -2
- package/dist/gateway/gateway.d.ts +32 -2
- package/dist/gateway/gateway.js +279 -24
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +279 -24
- package/dist/gateway/gateway.mjs.map +1 -1
- package/dist/git-trigger/git-hooks.d.mts +1 -1
- package/dist/git-trigger/git-hooks.d.ts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/local-evaluator/evaluator.d.mts +1 -1
- package/dist/local-evaluator/evaluator.d.ts +1 -1
- package/dist/local-evaluator/evaluator.js +165 -7
- package/dist/local-evaluator/evaluator.js.map +1 -1
- package/dist/local-evaluator/evaluator.mjs +165 -7
- package/dist/local-evaluator/evaluator.mjs.map +1 -1
- package/dist/{types-D0lCtFQ7.d.mts → types-BV6abBnF.d.mts} +6 -0
- package/dist/{types-YbiXYKx1.d.ts → types-C23_uaY8.d.ts} +6 -0
- package/dist/verify.js +1 -1
- package/dist/verify.js.map +1 -1
- package/dist/verify.mjs +1 -1
- package/dist/verify.mjs.map +1 -1
- package/package.json +8 -2
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { PlatformAdapter, AdapterConfig } from '../adapter-interface/interface.js';
|
|
2
|
+
import { A as AgentAction, I as InterceptResult, P as PDLSSContext, V as VerificationDecision } from '../types-C23_uaY8.js';
|
|
3
|
+
import { AstraSyncGateway } from '../gateway/gateway.js';
|
|
4
|
+
import '../types-9tns4wyl.js';
|
|
5
|
+
import '../metadata-capture.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @astrasyncai/adapter-codex
|
|
9
|
+
*
|
|
10
|
+
* Layer 4 adapter for OpenAI Codex CLI. Intercepts tool calls via Codex's
|
|
11
|
+
* native PreToolUse hooks (stable since Codex v0.124.0): the hook binary
|
|
12
|
+
* receives {tool_name, tool_input, permission_mode, ...} on stdin and may
|
|
13
|
+
* answer with a permissionDecision on stdout.
|
|
14
|
+
*
|
|
15
|
+
* Decision mapping is strictly tightening, with two Codex-specific twists
|
|
16
|
+
* versus the Claude Code adapter (§7.7):
|
|
17
|
+
*
|
|
18
|
+
* - Codex has NO "ask" decision. MANUAL_REVIEW therefore emits nothing —
|
|
19
|
+
* "no matching hook decides" makes Codex fall through to its own native
|
|
20
|
+
* approval prompt, which is the HITL. EXCEPT when the session runs in
|
|
21
|
+
* `dontAsk` / `bypassPermissions` permission mode: no native prompt will
|
|
22
|
+
* catch the fall-through there, so MANUAL_REVIEW escalates to deny.
|
|
23
|
+
* - Codex FAILS OPEN on hook errors/timeouts (it "reports the error and
|
|
24
|
+
* continues the tool call"). The hook binary therefore fails closed
|
|
25
|
+
* internally — every internal failure becomes an explicit deny (unless
|
|
26
|
+
* failOpen is configured). A hard kill/timeout still fails open on
|
|
27
|
+
* Codex's side; that residual gap is documented, and the mitigation is
|
|
28
|
+
* the hook's ~200ms cost against a 10s timeout.
|
|
29
|
+
*
|
|
30
|
+
* ALLOW never emits "allow" (and never `updatedInput`) — a hook allow would
|
|
31
|
+
* suppress Codex's own approval prompt rather than defer to it.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/** The PreToolUse payload Codex CLI writes to the hook's stdin. */
|
|
35
|
+
interface CodexPreToolUsePayload {
|
|
36
|
+
hook_event_name?: string;
|
|
37
|
+
tool_name: string;
|
|
38
|
+
tool_input: Record<string, unknown>;
|
|
39
|
+
session_id?: string;
|
|
40
|
+
turn_id?: string;
|
|
41
|
+
tool_use_id?: string;
|
|
42
|
+
cwd?: string;
|
|
43
|
+
model?: string;
|
|
44
|
+
transcript_path?: string | null;
|
|
45
|
+
/** default | acceptEdits | plan | dontAsk | bypassPermissions */
|
|
46
|
+
permission_mode?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The JSON the hook prints to stdout when it wants to tighten a decision.
|
|
50
|
+
* Deny-only by design: Codex has no "ask", and the guard never emits
|
|
51
|
+
* "allow". Any unsupported field would make Codex mark the hook run failed
|
|
52
|
+
* and continue the call — keep this shape strictly to documented fields.
|
|
53
|
+
*/
|
|
54
|
+
interface CodexHookOutput {
|
|
55
|
+
hookSpecificOutput: {
|
|
56
|
+
hookEventName: 'PreToolUse';
|
|
57
|
+
permissionDecision: 'deny';
|
|
58
|
+
permissionDecisionReason: string;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/** Permission modes with no native approval prompt to catch a fall-through. */
|
|
62
|
+
declare const UNPROMPTED_PERMISSION_MODES: Set<string>;
|
|
63
|
+
/** Session bookkeeping tools that are never governed. */
|
|
64
|
+
declare const DEFAULT_SKIP_TOOLS: string[];
|
|
65
|
+
interface CodexAdapterOptions {
|
|
66
|
+
/** Tool names to never intercept (replaces DEFAULT_SKIP_TOOLS if given) */
|
|
67
|
+
skipTools?: string[];
|
|
68
|
+
/**
|
|
69
|
+
* When true, unmapped non-MCP tools are still intercepted (purpose
|
|
70
|
+
* `tool.<name>`, denied by default policy). When false (default),
|
|
71
|
+
* unmapped tools are skipped — Codex's own approval flow remains their
|
|
72
|
+
* only gate.
|
|
73
|
+
*/
|
|
74
|
+
strictUnmapped?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Govern MCP tools (mcp__{server}__{tool} → purpose {server}.{tool}).
|
|
77
|
+
* Defaults to true; installers default it off until the policy lists
|
|
78
|
+
* {server}.{tool} rules (the evaluator denies unknown purposes).
|
|
79
|
+
*/
|
|
80
|
+
governMcp?: boolean;
|
|
81
|
+
}
|
|
82
|
+
declare class CodexAdapter implements PlatformAdapter {
|
|
83
|
+
readonly interfaceVersion = 1;
|
|
84
|
+
private gateway;
|
|
85
|
+
private skipTools;
|
|
86
|
+
private strictUnmapped;
|
|
87
|
+
private governMcp;
|
|
88
|
+
private _isRunning;
|
|
89
|
+
constructor(options?: CodexAdapterOptions);
|
|
90
|
+
get isRunning(): boolean;
|
|
91
|
+
initialize(config: AdapterConfig): Promise<void>;
|
|
92
|
+
shutdown(): Promise<void>;
|
|
93
|
+
interceptAction(action: AgentAction): Promise<InterceptResult>;
|
|
94
|
+
extractContext(action: AgentAction): PDLSSContext;
|
|
95
|
+
private buildContext;
|
|
96
|
+
/**
|
|
97
|
+
* Translate a gateway decision into hook stdout JSON.
|
|
98
|
+
*
|
|
99
|
+
* Returns null on ALLOW (silent — Codex's own approval flow stays in
|
|
100
|
+
* charge) and on MANUAL_REVIEW in prompted permission modes (the
|
|
101
|
+
* fall-through IS Codex's native prompt). MANUAL_REVIEW in dontAsk /
|
|
102
|
+
* bypassPermissions escalates to deny — no prompt exists to catch it.
|
|
103
|
+
*/
|
|
104
|
+
decisionToHookOutput(decision: VerificationDecision, permissionMode?: string): CodexHookOutput | null;
|
|
105
|
+
/**
|
|
106
|
+
* Convenience for the hook entry: full payload → hook output (or null).
|
|
107
|
+
*
|
|
108
|
+
* apply_patch envelopes are evaluated per touched file (one context per
|
|
109
|
+
* `*** Add/Update/Delete File:` header) and tightened to the worst
|
|
110
|
+
* decision, so file.write blockedPatterns (including guard
|
|
111
|
+
* self-protection) apply to every path in the patch.
|
|
112
|
+
*/
|
|
113
|
+
evaluatePayload(payload: CodexPreToolUsePayload): Promise<CodexHookOutput | null>;
|
|
114
|
+
private evaluateInterceptedPayload;
|
|
115
|
+
/**
|
|
116
|
+
* Enforcement happens via the stdout JSON the hook prints; there is no
|
|
117
|
+
* in-process side to enforce on.
|
|
118
|
+
*/
|
|
119
|
+
enforceDecision(_decision: VerificationDecision): Promise<void>;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Parse an MCP tool name (mcp__{server}__{tool}) into an app-connector
|
|
124
|
+
* style purpose `{server}.{tool}`. Returns null for non-MCP tool names.
|
|
125
|
+
*/
|
|
126
|
+
declare function mapMcpTool(toolName: string): string | null;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @astrasyncai/adapter-codex — tool → purpose mapping
|
|
130
|
+
*
|
|
131
|
+
* Maps OpenAI Codex CLI's built-in tool names (as delivered in PreToolUse
|
|
132
|
+
* hook payloads) to PDLSS purpose categories. MCP tool names use the same
|
|
133
|
+
* mcp__{server}__{tool} convention as Claude Code, so the parser is shared.
|
|
134
|
+
*/
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Codex CLI built-in tool name → PDLSS purpose.
|
|
138
|
+
* Documented canonical names: `Bash`, `apply_patch` (aliases `Edit`/`Write`
|
|
139
|
+
* appear in matcher examples), `web_search`. Undocumented tools stay
|
|
140
|
+
* unmapped and are skipped unless strictUnmapped is on.
|
|
141
|
+
*/
|
|
142
|
+
declare const CODEX_TOOL_MAP: Record<string, string>;
|
|
143
|
+
/**
|
|
144
|
+
* Register the Codex mappings into the shared adapter purpose map.
|
|
145
|
+
* Idempotent; safe to call from both the adapter and the hook entry.
|
|
146
|
+
*/
|
|
147
|
+
declare function registerCodexMappings(): void;
|
|
148
|
+
/**
|
|
149
|
+
* Extract the file paths an apply_patch envelope touches. Codex's patch
|
|
150
|
+
* format marks each file with `*** Add File:` / `*** Update File:` /
|
|
151
|
+
* `*** Delete File:` headers. Returns [] when nothing parseable is found —
|
|
152
|
+
* callers should then fall back to a raw-text target.
|
|
153
|
+
*/
|
|
154
|
+
declare function extractApplyPatchPaths(patchText: string): string[];
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* AstraSync Local Guard for OpenAI Codex CLI — PreToolUse hook entry.
|
|
158
|
+
*
|
|
159
|
+
* Codex invokes this binary for each governed tool call, writing the
|
|
160
|
+
* PreToolUse payload to stdin. The hook evaluates the call against the
|
|
161
|
+
* local PDLSS policy (shared with the Claude Code adapter: same
|
|
162
|
+
* ~/.astrasync/policy.yaml + guard.json) and prints a permissionDecision
|
|
163
|
+
* JSON to stdout only when it wants to tighten the outcome (deny). On
|
|
164
|
+
* ALLOW — and on MANUAL_REVIEW in prompted permission modes — it prints
|
|
165
|
+
* nothing, so Codex's own approval flow stays in charge.
|
|
166
|
+
*
|
|
167
|
+
* Fail posture: Codex itself FAILS OPEN on hook errors ("reports the error
|
|
168
|
+
* and continues the tool call"), so unlike the Claude Code hook we cannot
|
|
169
|
+
* lean on exit codes alone — every internal failure is converted into an
|
|
170
|
+
* explicit deny decision (opt-outs: ASTRASYNC_GUARD_FAIL_OPEN=1 or
|
|
171
|
+
* guard.json {"failOpen": true}). A missing policy file everywhere means
|
|
172
|
+
* the guard simply isn't configured — silent no-op, never a block.
|
|
173
|
+
*/
|
|
174
|
+
|
|
175
|
+
interface ProcessCodexHookOptions {
|
|
176
|
+
env?: NodeJS.ProcessEnv;
|
|
177
|
+
home?: string;
|
|
178
|
+
/** Injectable for tests */
|
|
179
|
+
gatewayFactory?: (config: ConstructorParameters<typeof AstraSyncGateway>[0]) => AstraSyncGateway;
|
|
180
|
+
}
|
|
181
|
+
interface ProcessCodexHookResult {
|
|
182
|
+
output: CodexHookOutput | null;
|
|
183
|
+
exitCode: number;
|
|
184
|
+
}
|
|
185
|
+
declare function processCodexHookPayload(payloadJson: string, options?: ProcessCodexHookOptions): Promise<ProcessCodexHookResult>;
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* AstraSync Local Guard for Claude Code — settings.json installer.
|
|
189
|
+
*
|
|
190
|
+
* Merges the guard's PreToolUse hook entry into a Claude Code settings
|
|
191
|
+
* file (~/.claude/settings.json or <project>/.claude/settings.json)
|
|
192
|
+
* without clobbering anything else in it, and builds the default policy
|
|
193
|
+
* for a coding agent.
|
|
194
|
+
*/
|
|
195
|
+
|
|
196
|
+
interface InstallResult {
|
|
197
|
+
installed: boolean;
|
|
198
|
+
alreadyPresent: boolean;
|
|
199
|
+
updated: boolean;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* AstraSync Local Guard for Codex CLI — hooks.json installer.
|
|
204
|
+
*
|
|
205
|
+
* Codex reads hooks from ~/.codex/hooks.json (user scope) or
|
|
206
|
+
* <repo>/.codex/hooks.json (project scope) with the SAME JSON shape as
|
|
207
|
+
* Claude Code's settings.json (`hooks.PreToolUse[].hooks[]`), so the merge
|
|
208
|
+
* and uninstall machinery is shared with the Claude Code installer — only
|
|
209
|
+
* the marker, matcher, and file location differ.
|
|
210
|
+
*
|
|
211
|
+
* The policy itself is shared with every other Local Guard adapter on the
|
|
212
|
+
* machine: ~/.astrasync/policy.yaml + guard.json. One policy per user.
|
|
213
|
+
*/
|
|
214
|
+
|
|
215
|
+
/** Substring that identifies the guard's hook entry inside hooks.json */
|
|
216
|
+
declare const ASTRASYNC_CODEX_HOOK_MARKER = "astrasync-codex-hook";
|
|
217
|
+
/**
|
|
218
|
+
* Tools worth spawning the hook for. Codex matchers are regexes over
|
|
219
|
+
* tool_name; bookkeeping tools (update_plan) never pay node startup cost.
|
|
220
|
+
*/
|
|
221
|
+
declare const CODEX_HOOK_MATCHER = "Bash|apply_patch|Edit|Write|web_search|mcp__.*";
|
|
222
|
+
/**
|
|
223
|
+
* Merge the guard's PreToolUse entry into a Codex hooks.json file.
|
|
224
|
+
* Same never-clobber/idempotent semantics as the Claude Code installer.
|
|
225
|
+
*/
|
|
226
|
+
declare function installCodexHooks(hooksPath: string, hookCommand: string): InstallResult;
|
|
227
|
+
/** Remove the guard's PreToolUse entry from a Codex hooks.json file. */
|
|
228
|
+
declare function uninstallCodexHooks(hooksPath: string): boolean;
|
|
229
|
+
|
|
230
|
+
export { ASTRASYNC_CODEX_HOOK_MARKER, CODEX_HOOK_MATCHER, CODEX_TOOL_MAP, CodexAdapter, type CodexAdapterOptions, type CodexHookOutput, type CodexPreToolUsePayload, DEFAULT_SKIP_TOOLS, type ProcessCodexHookOptions, type ProcessCodexHookResult, UNPROMPTED_PERMISSION_MODES, extractApplyPatchPaths, installCodexHooks, mapMcpTool, processCodexHookPayload, registerCodexMappings, uninstallCodexHooks };
|