@thomas-powers-jr/cadence-host-codex 1.54.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Thomas Powers
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # @thomas-powers-jr/cadence-host-codex
2
+
3
+ CADENCE host adapter for the OpenAI Codex CLI — the `cadence-host-codex` command
4
+ (hook install + slash-command prompts + event mapping).
5
+
6
+ Part of the [CADENCE](https://github.com/thomas-powers-jr/cadence) monorepo. MIT licensed.
7
+
8
+ ```bash
9
+ # First-run bootstrap from an uninitialized repo
10
+ cadence init --host codex
11
+
12
+ # Install hooks into a project + the cadence slash commands (global prompts)
13
+ npx -y @thomas-powers-jr/cadence-host-codex install
14
+ ```
15
+
16
+ `install` writes project-level hook config to `.codex/hooks.json` and the cadence
17
+ slash commands to the **global** Codex prompts dir (`$CODEX_HOME/prompts/`,
18
+ default `~/.codex/prompts/`) — Codex has no project-level prompt directory yet, so
19
+ the prompts apply to every project on the machine; the CLI warns accordingly. Use
20
+ `--no-commands` to skip them, or `--no-hooks` to skip the hook config.
21
+
22
+ For a new repo, run `cadence init --host codex` before opening Codex. That
23
+ scaffolds `.cadence/`, writes the managed `AGENTS.md` Cadence instructions, and
24
+ runs this adapter installer. After install, approve the hooks in Codex and start
25
+ a new Codex session so prompt commands are loaded. If prompts are not loaded yet,
26
+ ask Codex to run the `cadence` CLI directly, for example `cadence progress`.
27
+
28
+ Use `npx -y @thomas-powers-jr/cadence-host-codex install` by itself only when the
29
+ repo is already initialized. It is adapter-only: it does not create `.cadence/`
30
+ state and it does not write `AGENTS.md`.
31
+
32
+ The second conformance consumer of the CADENCE
33
+ [host-adapter contract](https://github.com/thomas-powers-jr/cadence/blob/main/docs/host-adapters.md);
34
+ see that guide for how the Codex adapter maps Codex's lifecycle onto the shared
35
+ engine.
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ require('node:child_process')
3
+ .spawn(process.execPath, [require('node:path').join(__dirname, '..', 'dist', 'cli.js'), ...process.argv.slice(2)], { stdio: 'inherit' })
4
+ .on('exit', (code) => process.exit(code ?? 0));
@@ -0,0 +1,11 @@
1
+ import type { HostCapabilities } from '@thomas-powers-jr/cadence-types';
2
+ /**
3
+ * What the OpenAI Codex CLI environment can do, per the phase-65 spike
4
+ * (FINDINGS §4). Codex's hook lifecycle is a near-clone of Claude Code's, so the
5
+ * mapped event set matches; the meaningful divergence is the command surface —
6
+ * Codex custom prompts are a real slash-command surface (`slashCommands: true`)
7
+ * but are install-global and deprecated in favor of "skills", so `skillSystem`
8
+ * is `'prompted'` (we ship prompts today; skills are the forward migration).
9
+ */
10
+ export declare const codexCapabilities: HostCapabilities;
11
+ //# sourceMappingURL=capabilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAExE;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,EAAE,gBAyB/B,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * What the OpenAI Codex CLI environment can do, per the phase-65 spike
3
+ * (FINDINGS §4). Codex's hook lifecycle is a near-clone of Claude Code's, so the
4
+ * mapped event set matches; the meaningful divergence is the command surface —
5
+ * Codex custom prompts are a real slash-command surface (`slashCommands: true`)
6
+ * but are install-global and deprecated in favor of "skills", so `skillSystem`
7
+ * is `'prompted'` (we ship prompts today; skills are the forward migration).
8
+ */
9
+ export const codexCapabilities = {
10
+ hooks: [
11
+ 'session-start',
12
+ 'user-prompt',
13
+ 'pre-tool-edit',
14
+ 'post-tool-edit',
15
+ 'session-stop',
16
+ 'subagent-result',
17
+ ],
18
+ slashCommands: true,
19
+ skillSystem: 'prompted',
20
+ // Codex denies a tool via exit-2 / permissionDecision:"deny" (PreToolUse) and
21
+ // can continue/block a turn end (Stop) — both are blocking points.
22
+ blockingHooks: ['pre-tool-edit', 'session-stop'],
23
+ subagentSpawn: 'native',
24
+ streamingOutput: true,
25
+ // Phase 222 AC-3: unlike host-claude-code's event-map.ts (which reads
26
+ // `agent_id`/`agent_type` off the raw hook envelope), host-codex's
27
+ // extractPayload never extracts an agent identifier — the phase-65 spike's
28
+ // documented Codex hook stdin fields (session_id, cwd, hook_event_name,
29
+ // tool_name, tool_input, permission_mode) don't include one, and it's
30
+ // undocumented whether SubagentStop even carries one. Declared `false`
31
+ // rather than left unset so core can notice loudly instead of silently
32
+ // treating "no agentId" as "no active subagent" for this host.
33
+ agentIdentification: false,
34
+ };
35
+ //# sourceMappingURL=capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAqB;IACjD,KAAK,EAAE;QACL,eAAe;QACf,aAAa;QACb,eAAe;QACf,gBAAgB;QAChB,cAAc;QACd,iBAAiB;KAClB;IACD,aAAa,EAAE,IAAI;IACnB,WAAW,EAAE,UAAU;IACvB,8EAA8E;IAC9E,mEAAmE;IACnE,aAAa,EAAE,CAAC,eAAe,EAAE,cAAc,CAAC;IAChD,aAAa,EAAE,QAAQ;IACvB,eAAe,EAAE,IAAI;IACrB,sEAAsE;IACtE,mEAAmE;IACnE,2EAA2E;IAC3E,wEAAwE;IACxE,sEAAsE;IACtE,uEAAuE;IACvE,uEAAuE;IACvE,+DAA+D;IAC/D,mBAAmB,EAAE,KAAK;CAC3B,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,137 @@
1
+ import { Command } from 'commander';
2
+ import { spawn } from 'node:child_process';
3
+ import { readFileSync } from 'node:fs';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { dirname, join } from 'node:path';
6
+ import { installHooks } from './install.js';
7
+ import { installCommands, resolveCodexHome } from './install-commands.js';
8
+ import { routeHookEvent } from './shim.js';
9
+ import { codexCapabilities } from './capabilities.js';
10
+ // Read the real version from package.json so `--version` never drifts.
11
+ const pkg = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), '../package.json'), 'utf8'));
12
+ const program = new Command();
13
+ program.name('cadence-host-codex').description('OpenAI Codex CLI host adapter for CADENCE').version(pkg.version);
14
+ program
15
+ .command('install')
16
+ .description('Write Codex hook config (.codex/hooks.json) and global slash-command prompts')
17
+ .option('--cwd <dir>', 'project root', process.cwd())
18
+ .option('--command <cmd>', 'base command for the shim (default: "npx @thomas-powers-jr/cadence-host-codex hook")')
19
+ .option('--cadence <cmd>', 'base command the shim uses to invoke core (default: "npx @thomas-powers-jr/cadence-core")')
20
+ .option('--codex-home <dir>', 'Codex home dir for prompts (default: $CODEX_HOME or ~/.codex)')
21
+ .option('--no-hooks', 'skip writing .codex/hooks.json')
22
+ .option('--no-commands', 'skip writing slash-command prompts')
23
+ .option('--local', 'use absolute paths to the local workspace builds (monorepo dogfood)')
24
+ .action(async (opts) => {
25
+ try {
26
+ if (opts.hooks) {
27
+ const installOpts = {};
28
+ if (opts.command !== undefined)
29
+ installOpts.command = opts.command;
30
+ if (opts.cadence !== undefined)
31
+ installOpts.cadenceCommand = opts.cadence;
32
+ if (opts.local)
33
+ installOpts.local = true;
34
+ await installHooks(opts.cwd, installOpts);
35
+ process.stdout.write(`Installed CADENCE Codex hooks → ${opts.cwd}/.codex/hooks.json\n`);
36
+ }
37
+ if (opts.commands) {
38
+ const cmdOpts = {};
39
+ if (opts.cadence !== undefined)
40
+ cmdOpts.cadenceCommand = opts.cadence;
41
+ if (opts.codexHome !== undefined)
42
+ cmdOpts.codexHome = opts.codexHome;
43
+ if (opts.local)
44
+ cmdOpts.local = true;
45
+ const promptsDir = join(resolveCodexHome(opts.codexHome), 'prompts');
46
+ await installCommands(opts.cwd, cmdOpts);
47
+ process.stdout.write(`Installed CADENCE slash-command prompts → ${promptsDir}/\n`);
48
+ // Codex prompts are GLOBAL (no project-level dir yet — openai/codex#4734),
49
+ // so they affect every project on this machine. Always say so.
50
+ process.stderr.write(`warning: Codex slash-command prompts install GLOBALLY to ${promptsDir} and ` +
51
+ 'apply to EVERY project on this machine (Codex has no project-level prompt ' +
52
+ 'dir yet). Run `install --no-commands` to skip them.\n');
53
+ }
54
+ process.stdout.write('Approve the new hooks in Codex, then start a new session to activate.\n');
55
+ if (opts.local) {
56
+ const surfaces = [];
57
+ if (opts.hooks)
58
+ surfaces.push('.codex/hooks.json');
59
+ if (opts.commands)
60
+ surfaces.push(`${join(resolveCodexHome(opts.codexHome), 'prompts')}/cadence-*.md`);
61
+ if (surfaces.length > 0) {
62
+ process.stderr.write(`warning: --local wrote machine-absolute paths into ${surfaces.join(' and ')}. ` +
63
+ 'Do NOT commit them — they cannot be resolved on other clones or machines. ' +
64
+ 'Run plain `install` (no --local) for the portable `cadence` form.\n');
65
+ }
66
+ }
67
+ }
68
+ catch (err) {
69
+ process.stderr.write(`install failed: ${err instanceof Error ? err.message : String(err)}\n`);
70
+ process.exitCode = 1;
71
+ }
72
+ });
73
+ program
74
+ .command('hook')
75
+ .description('Shim invoked by Codex hooks: translates stdin and calls cadence hook <event>')
76
+ .option('--cadence <cmd>', 'base command to invoke core (default: "npx @thomas-powers-jr/cadence-core")', 'npx @thomas-powers-jr/cadence-core')
77
+ .action(async (opts) => {
78
+ try {
79
+ let raw = '';
80
+ if (!process.stdin.isTTY) {
81
+ for await (const chunk of process.stdin)
82
+ raw += chunk.toString();
83
+ }
84
+ const { abstractEvent, translatedStdin } = routeHookEvent(raw);
85
+ if (abstractEvent === null)
86
+ return; // exit 0 silently for unmapped events
87
+ const [exe, ...baseArgs] = opts.cadence.split(/\s+/).filter(Boolean);
88
+ if (!exe) {
89
+ process.stderr.write('--cadence command is empty\n');
90
+ process.exitCode = 1;
91
+ return;
92
+ }
93
+ // Phase 222 AC-3: embed this host's declared capabilities so core can
94
+ // check `agentIdentification` before relying on ctx.agentId/agentType
95
+ // (see packages/core/src/hooks/handlers.ts). Best-effort — if
96
+ // translatedStdin isn't a JSON object for some reason, send it through
97
+ // unmodified rather than throwing.
98
+ let stdinToSend = translatedStdin;
99
+ try {
100
+ const parsed = JSON.parse(translatedStdin);
101
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
102
+ stdinToSend = JSON.stringify({ ...parsed, hostCapabilities: codexCapabilities });
103
+ }
104
+ }
105
+ catch {
106
+ // translatedStdin wasn't valid JSON (routeHookEvent only guarantees
107
+ // this when abstractEvent !== null, which is already checked above,
108
+ // but degrade rather than assume) — send the original through.
109
+ }
110
+ const child = spawn(exe, [...baseArgs, 'hook', abstractEvent], {
111
+ stdio: ['pipe', 'inherit', 'inherit'],
112
+ shell: process.platform === 'win32',
113
+ });
114
+ child.stdin.write(stdinToSend);
115
+ child.stdin.end();
116
+ await new Promise((resolve) => {
117
+ child.on('exit', (code) => {
118
+ process.exitCode = code ?? 0;
119
+ resolve();
120
+ });
121
+ child.on('error', (err) => {
122
+ process.stderr.write(`shim spawn failed: ${err.message}\n`);
123
+ process.exitCode = 1;
124
+ resolve();
125
+ });
126
+ });
127
+ }
128
+ catch (err) {
129
+ process.stderr.write(`hook shim failed: ${err instanceof Error ? err.message : String(err)}\n`);
130
+ process.exitCode = 1;
131
+ }
132
+ });
133
+ program.parseAsync(process.argv).catch((err) => {
134
+ process.stderr.write(`${err instanceof Error ? err.message : String(err)}\n`);
135
+ process.exit(1);
136
+ });
137
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { AbstractEvent, ExtractedPayload } from '@thomas-powers-jr/cadence-types';
2
+ export type { ExtractedPayload };
3
+ /** Codex's edit tool. Unlike Claude (Edit/Write/…), all edits flow through one tool. */
4
+ export declare const EDIT_TOOL_MATCHER = "apply_patch";
5
+ /**
6
+ * Map a Codex CLI hook event name to its cadence abstract event, or null when
7
+ * unmapped (e.g. PreCompact/PostCompact/PermissionRequest/SubagentStart — the
8
+ * contract permits null for events cadence does not act on).
9
+ */
10
+ export declare function mapEvent(codexEvent: string, _toolName?: string): AbstractEvent | null;
11
+ /**
12
+ * Extract the normalized payload from a Codex raw hook event. For `apply_patch`
13
+ * (Codex's sole edit tool) the patch envelope lives in `tool_input`, but the
14
+ * Codex docs are ambiguous about the exact field (`input` vs `command`), so we
15
+ * scan every string-valued field for the patch markers. Non-edit tools (Bash,
16
+ * MCP) and non-tool events yield undefined — matching the Claude adapter's shape.
17
+ */
18
+ export declare function extractPayload(raw: unknown): ExtractedPayload | undefined;
19
+ //# sourceMappingURL=event-map.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-map.d.ts","sourceRoot":"","sources":["../src/event-map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAIvF,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAiBjC,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAW/C;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAErF;AAkBD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,GAAG,SAAS,CAkBzE"}
@@ -0,0 +1,74 @@
1
+ // NOTE (phase 222): the shared toolkit package, `@thomas-powers-jr/cadence-host-toolkit`,
2
+ // exports a same-named `mapEvent`/`extractPayload`/`EDIT_TOOL_MATCHER` trio, but
3
+ // those are built for Claude Code's hook shape — the edit tool is
4
+ // `Edit|Write|MultiEdit|NotebookEdit`, payloads carry `tool_input.file_path`,
5
+ // and there's a `Skill`-tool disambiguation branch. Codex's hook shape differs
6
+ // for real: its sole edit tool is `apply_patch`, the touched paths live inside
7
+ // a patch envelope string (scanned via `PATCH_MARKER` below) rather than a
8
+ // `file_path` field, and Codex has no Skill-tool or SubagentStart mapping.
9
+ // Re-exporting the toolkit's versions here would silently change routing
10
+ // behavior (e.g. drop apply_patch boundary-check extraction entirely), so
11
+ // this module keeps its own implementation — only the algorithm's *shape*
12
+ // (8-step parse/validate/map/filter/extract) is shared conceptually, not the
13
+ // code. See `packages/host-toolkit/src/routing.ts` for the Claude-Code-shaped
14
+ // implementation host-claude-code migrated onto.
15
+ /** Codex's edit tool. Unlike Claude (Edit/Write/…), all edits flow through one tool. */
16
+ export const EDIT_TOOL_MATCHER = 'apply_patch';
17
+ const EVENT_TABLE = {
18
+ SessionStart: 'session-start',
19
+ UserPromptSubmit: 'user-prompt',
20
+ PreToolUse: 'pre-tool-edit',
21
+ PostToolUse: 'post-tool-edit',
22
+ Stop: 'session-stop',
23
+ SubagentStop: 'subagent-result',
24
+ };
25
+ /**
26
+ * Map a Codex CLI hook event name to its cadence abstract event, or null when
27
+ * unmapped (e.g. PreCompact/PostCompact/PermissionRequest/SubagentStart — the
28
+ * contract permits null for events cadence does not act on).
29
+ */
30
+ export function mapEvent(codexEvent, _toolName) {
31
+ return EVENT_TABLE[codexEvent] ?? null;
32
+ }
33
+ // `*** Add File: <p>` / `*** Update File: <p>` / `*** Delete File: <p>` /
34
+ // `*** Move to: <p>` — the markers in OpenAI's apply_patch envelope. Each names
35
+ // a path the patch touches; for boundary checking we collect them all (a Move
36
+ // touches both its Update source and its destination).
37
+ const PATCH_MARKER = /^\*\*\* (?:Add File|Update File|Delete File|Move to):\s*(.+?)\s*$/;
38
+ /** Pull every touched path out of an apply_patch envelope string, in order. */
39
+ function pathsFromPatch(patch) {
40
+ const files = [];
41
+ for (const line of patch.split(/\r?\n/)) {
42
+ const m = PATCH_MARKER.exec(line);
43
+ if (m && m[1])
44
+ files.push(m[1]);
45
+ }
46
+ return files;
47
+ }
48
+ /**
49
+ * Extract the normalized payload from a Codex raw hook event. For `apply_patch`
50
+ * (Codex's sole edit tool) the patch envelope lives in `tool_input`, but the
51
+ * Codex docs are ambiguous about the exact field (`input` vs `command`), so we
52
+ * scan every string-valued field for the patch markers. Non-edit tools (Bash,
53
+ * MCP) and non-tool events yield undefined — matching the Claude adapter's shape.
54
+ */
55
+ export function extractPayload(raw) {
56
+ if (!raw || typeof raw !== 'object')
57
+ return undefined;
58
+ const r = raw;
59
+ if (r.hook_event_name !== 'PreToolUse' && r.hook_event_name !== 'PostToolUse')
60
+ return undefined;
61
+ if (r.tool_name !== 'apply_patch')
62
+ return undefined;
63
+ if (!r.tool_input || typeof r.tool_input !== 'object')
64
+ return undefined;
65
+ for (const value of Object.values(r.tool_input)) {
66
+ if (typeof value === 'string' && value.includes('*** ')) {
67
+ const files = pathsFromPatch(value);
68
+ if (files.length > 0)
69
+ return { files };
70
+ }
71
+ }
72
+ return undefined;
73
+ }
74
+ //# sourceMappingURL=event-map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-map.js","sourceRoot":"","sources":["../src/event-map.ts"],"names":[],"mappings":"AAMA,0FAA0F;AAC1F,iFAAiF;AACjF,kEAAkE;AAClE,8EAA8E;AAC9E,+EAA+E;AAC/E,+EAA+E;AAC/E,2EAA2E;AAC3E,2EAA2E;AAC3E,yEAAyE;AACzE,0EAA0E;AAC1E,0EAA0E;AAC1E,6EAA6E;AAC7E,8EAA8E;AAC9E,iDAAiD;AAEjD,wFAAwF;AACxF,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAC;AAE/C,MAAM,WAAW,GAAkC;IACjD,YAAY,EAAE,eAAe;IAC7B,gBAAgB,EAAE,aAAa;IAC/B,UAAU,EAAE,eAAe;IAC3B,WAAW,EAAE,gBAAgB;IAC7B,IAAI,EAAE,cAAc;IACpB,YAAY,EAAE,iBAAiB;CAChC,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,UAAkB,EAAE,SAAkB;IAC7D,OAAO,WAAW,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC;AACzC,CAAC;AAED,0EAA0E;AAC1E,gFAAgF;AAChF,8EAA8E;AAC9E,uDAAuD;AACvD,MAAM,YAAY,GAAG,mEAAmE,CAAC;AAEzF,+EAA+E;AAC/E,SAAS,cAAc,CAAC,KAAa;IACnC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACxC,MAAM,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IACtD,MAAM,CAAC,GAAG,GAIT,CAAC;IACF,IAAI,CAAC,CAAC,eAAe,KAAK,YAAY,IAAI,CAAC,CAAC,eAAe,KAAK,aAAa;QAAE,OAAO,SAAS,CAAC;IAChG,IAAI,CAAC,CAAC,SAAS,KAAK,aAAa;QAAE,OAAO,SAAS,CAAC;IACpD,IAAI,CAAC,CAAC,CAAC,UAAU,IAAI,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAExE,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC;QAChD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACxD,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;YACpC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACzC,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { mapEvent, extractPayload } from './event-map.js';
2
+ import { installHooks } from './install.js';
3
+ import { installCommands } from './install-commands.js';
4
+ export { mapEvent, extractPayload, EDIT_TOOL_MATCHER } from './event-map.js';
5
+ export type { ExtractedPayload } from './event-map.js';
6
+ export { routeHookEvent } from './shim.js';
7
+ export type { RouteResult } from './shim.js';
8
+ export { codexCapabilities } from './capabilities.js';
9
+ export type { HostCapabilities } from '@thomas-powers-jr/cadence-types';
10
+ export { ADAPTER_CONTRACT_VERSION } from '@thomas-powers-jr/cadence-types';
11
+ export type { HostAdapter } from '@thomas-powers-jr/cadence-types';
12
+ export { installHooks } from './install.js';
13
+ export type { InstallOptions } from './install.js';
14
+ export { installCommands } from './install-commands.js';
15
+ export type { InstallCommandsOptions } from './install-commands.js';
16
+ /**
17
+ * The OpenAI Codex CLI host adapter — the second consumer of the
18
+ * {@link HostAdapter} contract (phase 60), proving it is not Claude-Code-shaped.
19
+ * Capabilities + event translation + apply_patch payload extraction (phase 66),
20
+ * the install surface — project `.codex/hooks.json` + global `~/.codex/prompts/`
21
+ * (phase 67) — and the runtime `hook` shim (phase 68) are all wired here. Only
22
+ * the publish/docs remain (phase 69). The `satisfies` check is the compile-time
23
+ * conformance proof.
24
+ */
25
+ export declare const codexAdapter: {
26
+ contractVersion: number;
27
+ capabilities: {
28
+ hooks: ("session-start" | "user-prompt" | "pre-tool-edit" | "post-tool-edit" | "session-stop" | "subagent-result" | "subagent-start" | "skill-invoke")[];
29
+ slashCommands: boolean;
30
+ skillSystem: "none" | "native" | "prompted";
31
+ blockingHooks: ("session-start" | "user-prompt" | "pre-tool-edit" | "post-tool-edit" | "session-stop" | "subagent-result" | "subagent-start" | "skill-invoke")[];
32
+ subagentSpawn: "none" | "native" | "shell-out";
33
+ streamingOutput: boolean;
34
+ agentIdentification?: boolean | undefined;
35
+ };
36
+ mapEvent: typeof mapEvent;
37
+ extractPayload: typeof extractPayload;
38
+ installHooks: typeof installHooks;
39
+ installCommands: typeof installCommands;
40
+ };
41
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE1D,OAAO,EAAE,YAAY,EAAuB,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,eAAe,EAA+B,MAAM,uBAAuB,CAAC;AAErF,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC7E,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,YAAY,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,YAAY,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAEpE;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;CAOsC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,29 @@
1
+ import { ADAPTER_CONTRACT_VERSION } from '@thomas-powers-jr/cadence-types';
2
+ import { mapEvent, extractPayload } from './event-map.js';
3
+ import { codexCapabilities } from './capabilities.js';
4
+ import { installHooks } from './install.js';
5
+ import { installCommands } from './install-commands.js';
6
+ export { mapEvent, extractPayload, EDIT_TOOL_MATCHER } from './event-map.js';
7
+ export { routeHookEvent } from './shim.js';
8
+ export { codexCapabilities } from './capabilities.js';
9
+ export { ADAPTER_CONTRACT_VERSION } from '@thomas-powers-jr/cadence-types';
10
+ export { installHooks } from './install.js';
11
+ export { installCommands } from './install-commands.js';
12
+ /**
13
+ * The OpenAI Codex CLI host adapter — the second consumer of the
14
+ * {@link HostAdapter} contract (phase 60), proving it is not Claude-Code-shaped.
15
+ * Capabilities + event translation + apply_patch payload extraction (phase 66),
16
+ * the install surface — project `.codex/hooks.json` + global `~/.codex/prompts/`
17
+ * (phase 67) — and the runtime `hook` shim (phase 68) are all wired here. Only
18
+ * the publish/docs remain (phase 69). The `satisfies` check is the compile-time
19
+ * conformance proof.
20
+ */
21
+ export const codexAdapter = {
22
+ contractVersion: ADAPTER_CONTRACT_VERSION,
23
+ capabilities: codexCapabilities,
24
+ mapEvent,
25
+ extractPayload,
26
+ installHooks,
27
+ installCommands,
28
+ };
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAoB,MAAM,iCAAiC,CAAC;AAC7F,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAuB,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,eAAe,EAA+B,MAAM,uBAAuB,CAAC;AAErF,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAE7E,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAE3E,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,eAAe,EAAE,wBAAwB;IACzC,YAAY,EAAE,iBAAiB;IAC/B,QAAQ;IACR,cAAc;IACd,YAAY;IACZ,eAAe;CAC8C,CAAC"}
@@ -0,0 +1,27 @@
1
+ export interface InstallCommandsOptions {
2
+ /** Base CLI invocation written into prompts. Default `cadence`. */
3
+ cadenceCommand?: string;
4
+ /**
5
+ * Codex home dir whose `prompts/` receives the files. Default
6
+ * `$CODEX_HOME` ?? `~/.codex`. Tests MUST pass a temp dir here — Codex
7
+ * prompts are GLOBAL, so a real install touches every project.
8
+ */
9
+ codexHome?: string;
10
+ /**
11
+ * Use the absolute workspace core CLI path instead of the `cadence`
12
+ * shorthand. Monorepo dogfood only — writes a machine-absolute path that must
13
+ * not be committed.
14
+ */
15
+ local?: boolean;
16
+ }
17
+ /** Resolve the Codex home dir: explicit override → $CODEX_HOME → ~/.codex. */
18
+ export declare function resolveCodexHome(override?: string): string;
19
+ /**
20
+ * Write the cadence slash commands as Codex custom prompts into
21
+ * `<codexHome>/prompts/cadence-*.md` (FINDINGS §1). Unlike the Claude adapter's
22
+ * project-scoped `.claude/commands/`, Codex has no project-level prompt dir yet
23
+ * (openai/codex#4734), so this is a GLOBAL install — the CLI warns accordingly.
24
+ * User-customized files (missing the managed marker) are left untouched.
25
+ */
26
+ export declare function installCommands(_root: string, opts?: InstallCommandsOptions): Promise<void>;
27
+ //# sourceMappingURL=install-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-commands.d.ts","sourceRoot":"","sources":["../src/install-commands.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,sBAAsB;IACrC,mEAAmE;IACnE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAgCD,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,sBAA2B,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBrG"}
@@ -0,0 +1,66 @@
1
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { COMMANDS } from '@thomas-powers-jr/cadence-host-toolkit';
5
+ import { resolveLocalPaths } from './locate-self.js';
6
+ const MANAGED_MARKER = '<!-- managed-by: cadence -->';
7
+ // The command catalog (which commands exist, their description/cli/
8
+ // argumentHint/trailing/body) now lives in the shared toolkit package,
9
+ // `@thomas-powers-jr/cadence-host-toolkit` (phase 222), so both host adapters
10
+ // render from the identical, undrifted catalog — including cadence-dispatch's
11
+ // DISPATCH_DIALOGUE body, which this adapter's own copy had silently dropped.
12
+ // The host-specific CLI/prompt rendering shape stays here.
13
+ function renderFile(spec, cadenceCommand) {
14
+ const fm = ['---', `description: ${spec.description}`];
15
+ if (spec.argumentHint)
16
+ fm.push(`argument-hint: ${spec.argumentHint}`);
17
+ fm.push('---');
18
+ const lines = [
19
+ fm.join('\n'),
20
+ '',
21
+ MANAGED_MARKER,
22
+ '',
23
+ 'Run the following command in the terminal and act on its output:',
24
+ '',
25
+ '```',
26
+ `${cadenceCommand} ${spec.cli}`.trimEnd(),
27
+ '```',
28
+ '',
29
+ ];
30
+ if (spec.body)
31
+ lines.push(spec.body, '');
32
+ if (spec.trailing)
33
+ lines.push(spec.trailing, '');
34
+ return lines.join('\n');
35
+ }
36
+ /** Resolve the Codex home dir: explicit override → $CODEX_HOME → ~/.codex. */
37
+ export function resolveCodexHome(override) {
38
+ return override ?? process.env.CODEX_HOME ?? join(homedir(), '.codex');
39
+ }
40
+ /**
41
+ * Write the cadence slash commands as Codex custom prompts into
42
+ * `<codexHome>/prompts/cadence-*.md` (FINDINGS §1). Unlike the Claude adapter's
43
+ * project-scoped `.claude/commands/`, Codex has no project-level prompt dir yet
44
+ * (openai/codex#4734), so this is a GLOBAL install — the CLI warns accordingly.
45
+ * User-customized files (missing the managed marker) are left untouched.
46
+ */
47
+ export async function installCommands(_root, opts = {}) {
48
+ const local = opts.local ? resolveLocalPaths() : null;
49
+ const cadenceCommand = opts.cadenceCommand ?? (local ? `node ${local.coreCli}` : 'cadence');
50
+ const dir = join(resolveCodexHome(opts.codexHome), 'prompts');
51
+ await mkdir(dir, { recursive: true });
52
+ for (const spec of COMMANDS) {
53
+ const path = join(dir, `${spec.name}.md`);
54
+ let existing = null;
55
+ try {
56
+ existing = await readFile(path, 'utf8');
57
+ }
58
+ catch {
59
+ // missing — create fresh
60
+ }
61
+ if (existing !== null && !existing.includes(MANAGED_MARKER))
62
+ continue; // user-customized
63
+ await writeFile(path, renderFile(spec, cadenceCommand), 'utf8');
64
+ }
65
+ }
66
+ //# sourceMappingURL=install-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-commands.js","sourceRoot":"","sources":["../src/install-commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ export interface InstallOptions {
2
+ /**
3
+ * Shim command Codex invokes for every hook event. The shim reads stdin,
4
+ * translates the payload, and spawns the core CLI.
5
+ * Default: `npx @thomas-powers-jr/cadence-host-codex hook`.
6
+ */
7
+ command?: string;
8
+ /**
9
+ * Base command the shim itself uses to invoke `@thomas-powers-jr/cadence-core`.
10
+ * If set, appended as `--cadence "<cmd>"`. Default: the shim's own default.
11
+ */
12
+ cadenceCommand?: string;
13
+ /** Hook config path relative to root. Default `.codex/hooks.json`. */
14
+ hooksPath?: string;
15
+ /**
16
+ * Use absolute paths to the local workspace builds instead of the `npx`
17
+ * defaults. Monorepo dogfood only — writes machine-absolute paths.
18
+ */
19
+ local?: boolean;
20
+ }
21
+ /**
22
+ * Write cadence-managed Codex hook entries into project-level
23
+ * `{root}/.codex/hooks.json` (FINDINGS §3). Idempotent: cadence-managed entries
24
+ * are replaced on re-install; user-authored entries on the same event are
25
+ * preserved. Hooks are project-scoped — unlike the global slash-command prompts.
26
+ */
27
+ export declare function installHooks(root: string, opts?: InstallOptions): Promise<void>;
28
+ //# sourceMappingURL=install.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAaD;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAmCzF"}
@@ -0,0 +1,48 @@
1
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
2
+ import { dirname, join } from 'node:path';
3
+ import { mergeManagedHookEntries } from '@thomas-powers-jr/cadence-host-toolkit/install-merge';
4
+ import { EDIT_TOOL_MATCHER } from './event-map.js';
5
+ import { resolveLocalPaths } from './locate-self.js';
6
+ // Codex's apply_patch is the sole edit tool; the matcher is applied to
7
+ // `tool_name` for Pre/PostToolUse, anchored so it matches only apply_patch.
8
+ const PATCH_MATCHER = `^${EDIT_TOOL_MATCHER}$`;
9
+ /**
10
+ * Write cadence-managed Codex hook entries into project-level
11
+ * `{root}/.codex/hooks.json` (FINDINGS §3). Idempotent: cadence-managed entries
12
+ * are replaced on re-install; user-authored entries on the same event are
13
+ * preserved. Hooks are project-scoped — unlike the global slash-command prompts.
14
+ */
15
+ export async function installHooks(root, opts = {}) {
16
+ const local = opts.local ? resolveLocalPaths() : null;
17
+ const base = opts.command ?? (local ? `node ${local.shimCli} hook` : 'npx @thomas-powers-jr/cadence-host-codex hook');
18
+ const cadenceCommand = opts.cadenceCommand ?? (local ? `node ${local.coreCli}` : undefined);
19
+ const command = cadenceCommand ? `${base} --cadence "${cadenceCommand}"` : base;
20
+ const hooksPath = join(root, opts.hooksPath ?? '.codex/hooks.json');
21
+ let current = {};
22
+ try {
23
+ current = JSON.parse(await readFile(hooksPath, 'utf8'));
24
+ }
25
+ catch {
26
+ // absent or malformed → start fresh
27
+ }
28
+ if (typeof current !== 'object' || current === null || Array.isArray(current))
29
+ current = {};
30
+ const plain = () => ({ hooks: [{ type: 'command', command }], _managedBy: 'cadence' });
31
+ const matched = (matcher) => ({
32
+ matcher,
33
+ hooks: [{ type: 'command', command }],
34
+ _managedBy: 'cadence',
35
+ });
36
+ const desired = {
37
+ SessionStart: [plain()],
38
+ UserPromptSubmit: [plain()],
39
+ PreToolUse: [matched(PATCH_MATCHER)],
40
+ PostToolUse: [matched(PATCH_MATCHER)],
41
+ Stop: [plain()],
42
+ SubagentStop: [plain()],
43
+ };
44
+ current.hooks = mergeManagedHookEntries(current.hooks ?? {}, desired);
45
+ await mkdir(dirname(hooksPath), { recursive: true });
46
+ await writeFile(hooksPath, JSON.stringify(current, null, 2) + '\n', 'utf8');
47
+ }
48
+ //# 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,14 @@
1
+ import type { LocalPaths } from '@thomas-powers-jr/cadence-host-toolkit/locate-self';
2
+ export type { LocalPaths };
3
+ /**
4
+ * Resolve absolute paths to the local (workspace) builds of this adapter and
5
+ * `@thomas-powers-jr/cadence-core`. Works both at runtime (running from
6
+ * `packages/host-codex/dist/locate-self.js`) and under vitest (running from
7
+ * `packages/host-codex/src/locate-self.ts`). Mirrors the Claude adapter.
8
+ *
9
+ * Thin wrapper (phase 222) around the shared toolkit implementation — the
10
+ * only adapter-specific bit is passing *this* module's own `import.meta.url`
11
+ * so the shared function anchors to host-codex's own package root.
12
+ */
13
+ export declare function resolveLocalPaths(): LocalPaths;
14
+ //# sourceMappingURL=locate-self.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locate-self.d.ts","sourceRoot":"","sources":["../src/locate-self.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oDAAoD,CAAC;AAErF,YAAY,EAAE,UAAU,EAAE,CAAC;AAE3B;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,IAAI,UAAU,CAE9C"}
@@ -0,0 +1,15 @@
1
+ import { resolveAdapterLocalPaths } from '@thomas-powers-jr/cadence-host-toolkit/locate-self';
2
+ /**
3
+ * Resolve absolute paths to the local (workspace) builds of this adapter and
4
+ * `@thomas-powers-jr/cadence-core`. Works both at runtime (running from
5
+ * `packages/host-codex/dist/locate-self.js`) and under vitest (running from
6
+ * `packages/host-codex/src/locate-self.ts`). Mirrors the Claude adapter.
7
+ *
8
+ * Thin wrapper (phase 222) around the shared toolkit implementation — the
9
+ * only adapter-specific bit is passing *this* module's own `import.meta.url`
10
+ * so the shared function anchors to host-codex's own package root.
11
+ */
12
+ export function resolveLocalPaths() {
13
+ return resolveAdapterLocalPaths(import.meta.url);
14
+ }
15
+ //# sourceMappingURL=locate-self.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locate-self.js","sourceRoot":"","sources":["../src/locate-self.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,oDAAoD,CAAC;AAK9F;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB;IAC/B,OAAO,wBAAwB,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACnD,CAAC"}
package/dist/shim.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import type { RouteResult } from '@thomas-powers-jr/cadence-host-toolkit';
2
+ export type { RouteResult };
3
+ /**
4
+ * Translate one Codex stdin-JSON hook event into a cadence abstract event plus
5
+ * the stdin the core dispatcher should receive. Mirrors the Claude adapter's
6
+ * shim; the difference is Codex's sole edit tool (`apply_patch`) and the
7
+ * multi-file payload extraction. Unmapped events, malformed JSON, and
8
+ * Pre/PostToolUse for non-edit tools return `{ abstractEvent: null }` with the
9
+ * raw stdin passed through (the core never sees them).
10
+ */
11
+ export declare function routeHookEvent(raw: string): RouteResult;
12
+ //# sourceMappingURL=shim.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shim.d.ts","sourceRoot":"","sources":["../src/shim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAC;AAU1E,YAAY,EAAE,WAAW,EAAE,CAAC;AAE5B;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CA8BvD"}
package/dist/shim.js ADDED
@@ -0,0 +1,43 @@
1
+ import { extractPayload, mapEvent, EDIT_TOOL_MATCHER } from './event-map.js';
2
+ /**
3
+ * Translate one Codex stdin-JSON hook event into a cadence abstract event plus
4
+ * the stdin the core dispatcher should receive. Mirrors the Claude adapter's
5
+ * shim; the difference is Codex's sole edit tool (`apply_patch`) and the
6
+ * multi-file payload extraction. Unmapped events, malformed JSON, and
7
+ * Pre/PostToolUse for non-edit tools return `{ abstractEvent: null }` with the
8
+ * raw stdin passed through (the core never sees them).
9
+ */
10
+ export function routeHookEvent(raw) {
11
+ let parsed;
12
+ try {
13
+ parsed = JSON.parse(raw);
14
+ }
15
+ catch {
16
+ return { abstractEvent: null, translatedStdin: raw };
17
+ }
18
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
19
+ return { abstractEvent: null, translatedStdin: raw };
20
+ }
21
+ const obj = parsed;
22
+ if (typeof obj.hook_event_name !== 'string') {
23
+ return { abstractEvent: null, translatedStdin: raw };
24
+ }
25
+ const toolName = typeof obj.tool_name === 'string' ? obj.tool_name : undefined;
26
+ const abstractEvent = mapEvent(obj.hook_event_name, toolName);
27
+ if (abstractEvent === null) {
28
+ return { abstractEvent: null, translatedStdin: raw };
29
+ }
30
+ // Defensive filter: the hooks.json matcher already restricts Pre/PostToolUse to
31
+ // apply_patch, but drop any non-apply_patch edit event that slips through.
32
+ if (abstractEvent === 'pre-tool-edit' || abstractEvent === 'post-tool-edit') {
33
+ if (toolName !== EDIT_TOOL_MATCHER) {
34
+ return { abstractEvent: null, translatedStdin: raw };
35
+ }
36
+ }
37
+ const extracted = extractPayload(parsed);
38
+ const translated = { ...parsed };
39
+ if (extracted?.files)
40
+ translated.files = extracted.files;
41
+ return { abstractEvent, translatedStdin: JSON.stringify(translated) };
42
+ }
43
+ //# sourceMappingURL=shim.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shim.js","sourceRoot":"","sources":["../src/shim.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAW7E;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC;IACvD,CAAC;IACD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnE,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC;IACvD,CAAC;IACD,MAAM,GAAG,GAAG,MAA4D,CAAC;IACzE,IAAI,OAAO,GAAG,CAAC,eAAe,KAAK,QAAQ,EAAE,CAAC;QAC5C,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC;IACvD,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,GAAG,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/E,MAAM,aAAa,GAAG,QAAQ,CAAC,GAAG,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;IAC9D,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC;IACvD,CAAC;IACD,gFAAgF;IAChF,2EAA2E;IAC3E,IAAI,aAAa,KAAK,eAAe,IAAI,aAAa,KAAK,gBAAgB,EAAE,CAAC;QAC5E,IAAI,QAAQ,KAAK,iBAAiB,EAAE,CAAC;YACnC,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC;QACvD,CAAC;IACH,CAAC;IACD,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,UAAU,GAA4B,EAAE,GAAI,MAAkC,EAAE,CAAC;IACvF,IAAI,SAAS,EAAE,KAAK;QAAE,UAAU,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC;IACzD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;AACxE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@thomas-powers-jr/cadence-host-codex",
3
+ "version": "1.54.0",
4
+ "engines": {
5
+ "node": ">=22"
6
+ },
7
+ "description": "OpenAI Codex CLI adapter for CADENCE — installs lifecycle hooks and slash commands that drive the CADENCE engine from inside Codex.",
8
+ "license": "MIT",
9
+ "author": "Thomas Powers",
10
+ "homepage": "https://github.com/thomas-powers-jr/cadence#readme",
11
+ "bugs": "https://github.com/thomas-powers-jr/cadence/issues",
12
+ "keywords": [
13
+ "cadence",
14
+ "codex",
15
+ "openai-codex",
16
+ "ai",
17
+ "agents",
18
+ "hooks",
19
+ "slash-commands"
20
+ ],
21
+ "type": "module",
22
+ "main": "./dist/index.js",
23
+ "types": "./dist/index.d.ts",
24
+ "exports": {
25
+ ".": {
26
+ "import": "./dist/index.js",
27
+ "types": "./dist/index.d.ts"
28
+ }
29
+ },
30
+ "bin": {
31
+ "cadence-host-codex": "./bin/cadence-host-codex.cjs"
32
+ },
33
+ "files": [
34
+ "dist",
35
+ "bin",
36
+ "!dist/tsconfig.tsbuildinfo"
37
+ ],
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "git+https://github.com/thomas-powers-jr/cadence.git",
44
+ "directory": "packages/host-codex"
45
+ },
46
+ "dependencies": {
47
+ "commander": "^14.0.0",
48
+ "@thomas-powers-jr/cadence-host-toolkit": "1.54.0",
49
+ "@thomas-powers-jr/cadence-core": "1.54.0",
50
+ "@thomas-powers-jr/cadence-types": "1.54.0"
51
+ },
52
+ "devDependencies": {
53
+ "vitest": "^2.1.0",
54
+ "@thomas-powers-jr/cadence-testkit": "1.4.0"
55
+ },
56
+ "scripts": {
57
+ "build": "tsc -p tsconfig.json",
58
+ "typecheck": "tsc -p tsconfig.json --noEmit",
59
+ "test": "vitest run",
60
+ "lint": "eslint src",
61
+ "clean": "rm -rf dist .turbo"
62
+ }
63
+ }