@skillstate/codex 2.0.5 → 2.0.6

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/README.md CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  # @skillstate/codex
4
4
 
5
- **OpenAI Codex CLI adapter for the @skillstate/core runtime — AGENTS.md amendments plus lifecycle hook scripts.**
5
+ **OpenAI Codex CLI adapter (codex 0.142) for the @skillstate/core runtime — `hooks.json` lifecycle hooks, hook scripts, MCP registration, `SKILL.md`, and a programmatic O(1) fork-trim session.**
6
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/@skillstate/codex)](https://www.npmjs.com/package/@skillstate/codex)
8
8
  [![node](https://img.shields.io/node/v/@skillstate/codex)](https://www.npmjs.com/package/@skillstate/codex)
9
- [![Tests](https://img.shields.io/badge/tests-873%20passing-brightgreen)](https://github.com/vitalykuzyaev/skillstate)
9
+ [![Tests](https://img.shields.io/badge/tests-924%20passing-brightgreen)](https://github.com/vitalykuzyaev/skillstate)
10
10
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](https://github.com/vitalykuzyaev/skillstate/blob/main/LICENSE)
11
11
 
12
12
  </div>
@@ -14,16 +14,37 @@
14
14
  ---
15
15
 
16
16
  `@skillstate/codex` bridges the paper-exact runtime ([`@skillstate/core`](../core))
17
- into **OpenAI Codex CLI** sessions. It generates an `AGENTS.md` amendment that
18
- puts the agent in state-based execution mode, plus a `hooks.json` document and
19
- per-event hook scripts that inject the state on prompt submit and persist the
20
- `state_patch` after tool use.
17
+ into **OpenAI Codex CLI** (0.142) sessions. It generates:
18
+
19
+ - a **`hooks.json`** document wiring three lifecycle events — inject the state
20
+ on every prompt submit (`UserPromptSubmit`), re-inject it after compaction
21
+ (`SessionStart` matcher `^compact$`), and persist `state_patch` blocks from
22
+ Bash tool outputs (`PostToolUse` matcher `^Bash$`);
23
+ - **self-contained `.cjs` hook scripts** (Node builtins only, no
24
+ `@skillstate/*` import) that resolve the per-project state from the session
25
+ `cwd` at runtime — one global script directory serves every project;
26
+ - a **`[mcp_servers.skillstate]` TOML block** for `~/.codex/config.toml`
27
+ (used by `@skillstate/cli init`; see `installCodexHost`);
28
+ - a **`SKILL.md`** for `~/.codex/skills/<name>/` that makes the hook-injected
29
+ state authoritative (history is not reliable);
30
+ - **`CodexForkSession`** (`fork-trim.ts`) — a `codex app-server` JSON-RPC
31
+ client providing **programmatic O(1) history trimming** via
32
+ `thread/fork` / `thread/rollback` (experimental, non-interactive runs).
21
33
 
22
34
  > **@non-paper** — no adapters exist in arXiv 2608.26263v3. This adapter is an
23
35
  > additive integration, not part of the paper.
24
36
 
25
37
  ## Installation
26
38
 
39
+ The one-command host install (hooks + scripts + MCP + skill + per-project
40
+ state, idempotent, with backups):
41
+
42
+ ```bash
43
+ npm i -g @skillstate/cli && skillstate init --host codex
44
+ ```
45
+
46
+ Or use the adapter as a library:
47
+
27
48
  ```bash
28
49
  npm i @skillstate/core @skillstate/codex
29
50
  ```
@@ -33,63 +54,139 @@ Requires Node.js >= 20. TypeScript types are bundled.
33
54
  ## Quick start
34
55
 
35
56
  ```ts
36
- import { CodexAdapter } from '@skillstate/codex';
57
+ import { CodexAdapter, CodexForkSession, resolveStateForCwd } from '@skillstate/codex';
37
58
  import { INTERCODE_CTF_SPEC } from '@skillstate/core/schemas';
38
59
 
39
60
  const adapter = new CodexAdapter();
40
61
 
41
- // AGENTS.md amendment: read .skillstate.json each step, discard reasoning,
42
- // emit a two-key state_patch/action JSON block:
43
- const agentsMd = adapter.generateCodexAmendments('./.skillstate.json');
44
-
45
- // Standalone "read the state file" instruction block (skill / system prompt):
46
- const stateRead = adapter.generateCodexStateRead('./.skillstate.json');
62
+ // Per-project state file for a cwd — SAME semantics as the OpenCode plugin
63
+ // and the MCP server: <cwd>/.skillstate/skillstate.json (global bucket
64
+ // ~/.skillstate/global/skillstate.json when cwd === home). Pure path
65
+ // arithmetic, no filesystem access:
66
+ const statePath = resolveStateForCwd(process.cwd());
47
67
 
48
68
  // Codex hooks.json: inject state on UserPromptSubmit, re-inject after
49
- // compaction (SessionStart matcher: compact), persist state_patch on PostToolUse:
50
- const hooksJson = adapter.generateCodexHooksConfig('./.skillstate.json');
69
+ // compaction (SessionStart matcher ^compact$), persist state_patch from
70
+ // Bash outputs (PostToolUse matcher ^Bash$):
71
+ const hooksJson = adapter.generateHooksConfig(statePath, {
72
+ scriptDir: '~/.codex/hooks/skillstate',
73
+ });
74
+
75
+ // Merge the skillstate hook groups into an existing hooks.json (idempotent:
76
+ // already-wired documents come back unchanged; foreign hooks are kept):
77
+ const merged = adapter.mergeHooksConfig(existingHooksJson, {
78
+ scriptDir: '/home/me/.codex/hooks/skillstate',
79
+ });
80
+
81
+ // Canonical absolute hook-script path for an event. generateHooksConfig and
82
+ // saveHookScript share this convention so the hooks.json commands and the
83
+ // on-disk scripts ALWAYS agree:
84
+ const script = adapter.codexHookScriptPath(
85
+ '/home/me/.codex/hooks/skillstate',
86
+ 'post-tool-use',
87
+ ); // -> /home/me/.codex/hooks/skillstate/post-tool-use.cjs
88
+
89
+ // Generate one self-contained .cjs hook script and persist it:
90
+ const scriptPath = await adapter.saveHookScript(
91
+ 'post-tool-use',
92
+ '/home/me/.codex/hooks/skillstate/post-tool-use.cjs',
93
+ statePath,
94
+ );
95
+
96
+ // SKILL.md for ~/.codex/skills/skillstate/SKILL.md — the injected state is
97
+ // authoritative; persist via the MCP tools state.patch / state.get, and/or
98
+ // print a fenced ```json state_patch block inside a Bash call:
99
+ const skillMd = adapter.generateSkillMd(INTERCODE_CTF_SPEC, './.skillstate/skillstate.json');
100
+ await adapter.saveSkillMd('~/.codex/skills/skillstate/SKILL.md', INTERCODE_CTF_SPEC);
101
+ ```
51
102
 
52
- // Canonical hook-script path for a given event. Both generateCodexHooksConfig
53
- // and saveCodexHookScript use this single convention so hooks.json commands
54
- // and on-disk scripts ALWAYS agree by filename:
55
- const script = adapter.codexHookScriptPath('./.skillstate.json', 'PostToolUse');
56
- // -> path/to/.codex-.skillstate-post-tool-use.cjs
103
+ ### Programmatic O(1) — `CodexForkSession` (experimental)
57
104
 
58
- // Generate one hook script and persist it to the canonical path:
59
- const scriptPath = await adapter.saveCodexHookScript('PostToolUse', './.skillstate.json');
105
+ Codex hooks cannot trim host history (hook outputs are limited to
106
+ additionalContext / decision / systemMessage), so hooks alone give O(T)
107
+ prompts. For **non-interactive** runs, `CodexForkSession` drives
108
+ `codex app-server` over newline-delimited JSON-RPC and trims history
109
+ programmatically: each `step()` starts a turn (`thread/start` +
110
+ `turn/start`), waits for the `turn/completed` notification, reads the state
111
+ file, and `trim(keepTurns)` forks the thread **before** an old turn
112
+ (`thread/fork { beforeTurnId }`) so the new prompt holds only instructions +
113
+ state file + the newest turns → O(1).
114
+
115
+ ```ts
116
+ import { CodexForkSession } from '@skillstate/codex';
117
+
118
+ const session = new CodexForkSession({ cwd: process.cwd() });
119
+ await session.start(); // thread/start
120
+
121
+ const step = await session.step('ls -la /'); // turn/start → turn/completed
122
+ console.log(step.observation); // final agent message
123
+ console.log(step.state); // state read from the state file
124
+ console.log(step.threadId, step.turnId);
125
+
126
+ await session.trim(1); // thread/fork before an old turn → O(1)
127
+ await session.rollback(1); // or trim the CURRENT thread in place
128
+ await session.close();
60
129
  ```
61
130
 
62
131
  ## API / Exports
63
132
 
64
- Root path `@skillstate/codex` exports `CodexAdapter`, plus the shared
65
- constants/types `CODEX_HOOK_SCRIPT_SUFFIX`, `CodexHookEvent`,
66
- `CodexHookEventSuffix`, `CodexAmendmentsOptions`, `CodexHooksConfigOptions`.
133
+ Root path `@skillstate/codex` exports `CodexAdapter`, the fork-trim session,
134
+ and the shared constants/types `CODEX_HOOK_EVENTS`, `CODEX_SESSION_START_MATCHER`,
135
+ `CODEX_POST_TOOL_USE_MATCHER`, `CODEX_ADDITIONAL_CONTEXT_LIMIT`,
136
+ `CODEX_HOOK_TIMEOUT_SECONDS`, `CodexHookEvent`, `CodexHooksConfigOptions`,
137
+ `resolveStateForCwd`, `CodexForkSession`, `APP_SERVER_JSONRPC_VERSION`.
138
+
139
+ Events (`CodexHookEvent`): `'user-prompt-submit' | 'session-start-compact' | 'post-tool-use'`.
67
140
 
68
141
  - `new CodexAdapter()` — `name = 'codex'`.
69
- - `generateCodexAmendments(statePath, options?): string` — AGENTS.md amendment
70
- (`CodexAmendmentsOptions.spec` and `.includeHooksNote`).
71
- - `generateCodexStateRead(statePath): string` — inline state-read block.
72
- - `generateCodexHookScript(eventType, statePath, schema?): string` —
73
- `CodexHookEvent` is `'UserPromptSubmit' | 'PostToolUse' | 'SessionStart'`.
74
- `PostToolUse` reads `tool_response` from stdin, extracts `state_patch`,
75
- validates it, and merges it. Accepts raw paths or `{ root, name }` refs.
76
- - `generateCodexHooksConfig(statePath, options?): string` —
77
- `CodexHooksConfigOptions.command` and `.sessionStartMatcher`.
78
- - `codexHookScriptPath(statePath, eventType): string` — canonical `.cjs` path.
79
- - `saveCodexAmendments(target, statePath, options?): Promise<string>`,
80
- `saveCodexHooksConfig(target, statePath, options?): Promise<string>`,
81
- `saveCodexHookScript(eventType, statePath, schema?): Promise<string>`
82
- (or the explicit-`target` overload) — atomic writes returning the destination.
142
+ - `generateHooksConfig(statePath, options?): string` — the three-event
143
+ `hooks.json` document (`CodexHooksConfigOptions.scriptDir`, `.command`,
144
+ `.timeoutSeconds`, `.maxHistoryMessages`). Commands are absolute
145
+ `node <script> <event>` lines; every entry sets `additionalContextLimit`
146
+ (2500) and `timeout` (30s).
147
+ - `generateHookScript(event, statePath?): string` — a self-contained CommonJS
148
+ script for the event. It reads ONE hook JSON document from stdin, resolves
149
+ the state from `input.cwd` (per-project resolver, global bucket when
150
+ cwd === home), and:
151
+ - `user-prompt-submit` / `session-start-compact`: emits
152
+ `{ hookSpecificOutput: { hookEventName, additionalContext } }` with the
153
+ current state JSON;
154
+ - `post-tool-use`: extracts `state_patch` from the `tool_response` (fenced
155
+ ```json block or raw JSON, wrapper-tolerant), applies the ⊕
156
+ null-deletion merge and writes the state file; stdout is `{}` or a
157
+ `systemMessage` when the patch is invalid.
158
+ - `generateSkillMd(spec, statePath?): string` — `SKILL.md` frontmatter
159
+ (name/description/version + `execution_context`) and the state-based
160
+ process body.
161
+ - `mergeHooksConfig(existingJson, options?): string` — idempotent merge of the
162
+ skillstate hook groups into an existing `hooks.json` (foreign hooks are
163
+ preserved; missing/malformed files start a fresh document).
164
+ - `codexHookScriptPath(scriptDir, event): string` — canonical absolute `.cjs`
165
+ path (`<scriptDir>/<event>.cjs`).
166
+ - `saveHooksConfig(target, statePath, options?): Promise<string>`,
167
+ `saveHookScript(event, target, statePath?): Promise<string>`,
168
+ `saveSkillMd(target, spec, statePath?): Promise<string>` — atomic writes
169
+ returning the absolute destination.
170
+ - `resolveStateForCwd(cwd, home?): string` — per-project state resolution
171
+ shared by the hooks, the fork-trim session, and the CLI install.
172
+ - `new CodexForkSession({ cwd, codexBin?, home?, requestTimeoutMs?,
173
+ developerInstructions? })` — app-server client (`start()`, `step(action)`,
174
+ `forkBefore(turnId)`, `trim(keepTurns)`, `rollback(numTurns)`, `close()`).
83
175
 
84
176
  ## Notes
85
177
 
86
- - **Honest limitation.** Codex has no `messages.transform` equivalent, so host
87
- history is never trimmed — true O(1) is not possible. The hooks keep state
88
- injected per prompt and persisted per tool call; the `AGENTS.md` amendment
89
- tells the model to trust the state file over the conversation.
90
- - `PostToolUse` accepts both fenced ```json blocks and an unfenced
91
- JSON object, and tolerates wrappers such as `Here is: {...}`. Malformed
92
- outputs are rejected and never persisted.
178
+ - **Honest limitation.** Codex hooks cannot trim host conversation history —
179
+ hooks alone give O(T) prompts with fresh state injection. The programmatic
180
+ O(1) path is `CodexForkSession` (`fork-trim.ts`, `codex app-server`
181
+ `thread/fork` / `thread/rollback`) — **experimental**, for non-interactive
182
+ runs.
183
+ - One global `hooks.json` + one script directory serve **every project**:
184
+ each script resolves the per-project state from the session `cwd`
185
+ (`<cwd>/.skillstate/skillstate.json`; the global bucket
186
+ `~/.skillstate/global/skillstate.json` when cwd === home).
187
+ - The `post-tool-use` script accepts both fenced ```json blocks and an
188
+ unfenced JSON object, and tolerates wrappers such as `Here is: {...}`.
189
+ Malformed outputs are rejected and never persisted.
93
190
  - Depends on [`@skillstate/core`](../core) for `atomicWriteFile`,
94
191
  `resolveStatePath`, and the `ProceduralSpec` type.
95
192
 
@@ -97,6 +194,7 @@ constants/types `CODEX_HOOK_SCRIPT_SUFFIX`, `CodexHookEvent`,
97
194
 
98
195
  - Paper: [arXiv:2608.26263](https://arxiv.org/abs/2608.26263).
99
196
  - Core runtime: [`@skillstate/core`](../core).
197
+ - Host install CLI: [`@skillstate/cli`](../cli) (`skillstate init --host codex`).
100
198
  - [`state.md`](../../state.md) — design notes.
101
199
  - Other adapters: `@skillstate/claude`, `@skillstate/opencode`, `@skillstate/mcp`.
102
200
 
@@ -1,125 +1,121 @@
1
- import type { StatePathRef } from '@skillstate/core';
2
- import type { ProceduralSpec } from '@skillstate/core';
3
- /** Codex lifecycle hook events this adapter can generate scripted hooks for. */
4
- export type CodexHookEvent = 'UserPromptSubmit' | 'PostToolUse' | 'SessionStart';
1
+ import type { ProceduralSpec, StatePathRef } from '@skillstate/core';
2
+ /** Codex hook events this adapter generates scripts for (script/CLI names). */
3
+ export type CodexHookEvent = 'user-prompt-submit' | 'session-start-compact' | 'post-tool-use';
4
+ /** All {@link CodexHookEvent} values in generation order. */
5
+ export declare const CODEX_HOOK_EVENTS: readonly ["user-prompt-submit", "session-start-compact", "post-tool-use"];
6
+ /** SessionStart matcher that fires after Codex compacts the conversation. */
7
+ export declare const CODEX_SESSION_START_MATCHER = "^compact$";
8
+ /** PostToolUse matcher restricted to Bash tool results. */
9
+ export declare const CODEX_POST_TOOL_USE_MATCHER = "^Bash$";
5
10
  /**
6
- * Canonical `.cjs` filename suffix per Codex hook event, used by
7
- * {@link CodexAdapter.codexHookScriptPath} so `hooks.json` commands and the
8
- * on-disk hook scripts always agree.
11
+ * `additionalContextLimit` written into every generated hook entry — the
12
+ * schema default (2500 chars), spelled out so the budget is explicit.
9
13
  */
10
- export declare const CODEX_HOOK_SCRIPT_SUFFIX: {
11
- readonly UserPromptSubmit: 'user-prompt-submit';
12
- readonly PostToolUse: 'post-tool-use';
13
- readonly SessionStart: 'session-start-compact';
14
- };
15
- /** Executable hook-script suffix for a {@link CodexHookEvent}. */
16
- export type CodexHookEventSuffix = (typeof CODEX_HOOK_SCRIPT_SUFFIX)[CodexHookEvent];
17
- /** Options for {@link CodexAdapter.generateCodexAmendments}. */
18
- export interface CodexAmendmentsOptions {
19
- /** Fill a `## State schema` section from the provided spec. */
20
- spec?: ProceduralSpec;
21
- /** Append the hook setup note (default true). */
22
- includeHooksNote?: boolean;
23
- }
24
- /** Options for {@link CodexAdapter.generateCodexHooksConfig}. */
14
+ export declare const CODEX_ADDITIONAL_CONTEXT_LIMIT = 2500;
15
+ /** Default hook `timeout` in seconds (the scripts are tiny readers/writers). */
16
+ export declare const CODEX_HOOK_TIMEOUT_SECONDS = 30;
17
+ /** Options for {@link CodexAdapter.generateHooksConfig}. */
25
18
  export interface CodexHooksConfigOptions {
26
- /** Command that runs the per-event hook scripts. Overrides the default. */
19
+ /**
20
+ * Directory holding the generated `.cjs` hook scripts. Defaults to the
21
+ * state file's directory; the CLI install passes `~/.codex/hooks/skillstate`.
22
+ */
23
+ scriptDir?: string;
24
+ /** Non-system messages the plugin keeps (records intent in the header). */
25
+ maxHistoryMessages?: number;
26
+ /** Full command override for every event (defaults to `node <script> <event>`). */
27
27
  command?: string;
28
- /** `matcher` for the `SessionStart` hook (default `compact`). */
29
- sessionStartMatcher?: string;
28
+ /** Hook `timeout` in seconds (default {@link CODEX_HOOK_TIMEOUT_SECONDS}). */
29
+ timeoutSeconds?: number;
30
30
  }
31
31
  /**
32
- * OpenAI Codex platform adapter (@non-paper; see module doc).
33
- *
34
- * Codegen mirrors the Claude adapter's shape: every generator accepts a
35
- * raw path or a `{ root, name }` ref confined by
36
- * `resolveStatePath` — `..` escapes throw instead of embedding an unsafe
37
- * path into the generated artifact.
32
+ * Resolve the per-project state file for a working directory — the SAME
33
+ * semantics as the OpenCode plugin (`<cwd>/.skillstate/skillstate.json`;
34
+ * the global bucket `<home>/.skillstate/global/skillstate.json` when cwd
35
+ * equals home). Pure path arithmetic, no filesystem access. Keep any copy
36
+ * (generated scripts, fork-trim, MCP server) in sync.
38
37
  */
38
+ export declare function resolveStateForCwd(cwd: string, home?: string): string;
39
39
  export declare class CodexAdapter {
40
40
  readonly name = "codex";
41
41
  /**
42
- * Generate an `AGENTS.md`-compatible amendment that puts the agent in
43
- * state-based execution mode: read `.skillstate.json` each step, treat
44
- * reasoning as discarded, and emit a `state_patch` that the hooks merge
45
- * back into the state file.
42
+ * Canonical absolute path of the hook script for `event` inside
43
+ * `scriptDir` (e.g. `~/.codex/hooks/skillstate/post-tool-use.cjs`).
44
+ * {@link generateHooksConfig} and {@link saveHookScript} share this
45
+ * convention so the hooks.json commands and the on-disk scripts agree.
46
46
  */
47
- generateCodexAmendments(statePath: string | StatePathRef, options?: CodexAmendmentsOptions): string;
47
+ codexHookScriptPath(scriptDir: string, event: CodexHookEvent): string;
48
48
  /**
49
- * Generate a markdown "read the state file" instruction block — the
50
- * inline form of the state-read contract (the core line the model
51
- * must follow), suitable for embedding in an AGENTS.md, a skill body, or
52
- * a system prompt.
53
- */
54
- generateCodexStateRead(statePath: string | StatePathRef): string;
55
- /**
56
- * Generate a self-contained Node CommonJS hook script for a Codex
57
- * lifecycle event. The script is invoked by the hook's `command`; the
58
- * event config (matcher) lives in the hooks.json document.
49
+ * Generate a Codex `hooks.json` document wiring the state lifecycle:
59
50
  *
60
- * - `UserPromptSubmit`: read the state file and inject it as
61
- * `additionalContext` (runs on every prompt submit).
62
- * - `SessionStart`: same injection shape; combined with a `compact`
63
- * matcher it re-injects state after Codex compacts the chat.
64
- * - `PostToolUse`: read `tool_response` from stdin, extract
65
- * `state_patch`, schema-validate (when a schema is provided) and merge
66
- * it into the state file via the paper ⊕ operator. Malformed outputs
67
- * are rejected and never persisted.
68
- */
69
- generateCodexHookScript(eventType: CodexHookEvent, statePath: string, schema?: ProceduralSpec['schema']): string;
70
- generateCodexHookScript(eventType: CodexHookEvent, stateRef: StatePathRef, schema?: ProceduralSpec['schema']): string;
71
- /**
72
- * Generate a Codex `hooks.json` document that wires the state-injection /
73
- * persistence hooks into the agent lifecycle:
51
+ * - `UserPromptSubmit` → inject the current state as additionalContext;
52
+ * - `SessionStart` (matcher `^compact$`) → re-inject after compaction;
53
+ * - `PostToolUse` (matcher `^Bash$`) → persist `state_patch` blocks from
54
+ * Bash tool outputs.
74
55
  *
75
- * - `UserPromptSubmit` → inject current state (every prompt).
76
- * - `SessionStart` (matcher `compact`) → re-inject state after compaction.
77
- * - `PostToolUse` → extract `state_patch` and persist it.
56
+ * Commands are absolute `node <script> <event>` lines pointing at the
57
+ * generated `.cjs` scripts in `options.scriptDir` (default: the state
58
+ * file's directory).
78
59
  */
79
- generateCodexHooksConfig(statePath: string | StatePathRef, options?: CodexHooksConfigOptions): string;
60
+ generateHooksConfig(statePath: string | StatePathRef, options?: CodexHooksConfigOptions): string;
80
61
  /**
81
- * Canonical absolute path of the generated hook script for a Codex event,
82
- * derived from the state file name. Both {@link generateCodexHooksConfig}
83
- * and {@link saveCodexHookScript} use this single convention so the
84
- * `hooks.json` commands and the on-disk scripts always agree.
62
+ * Generate a self-contained CommonJS hook script for a Codex lifecycle
63
+ * event. The script reads ONE hook JSON document from stdin, resolves the
64
+ * state file from `input.cwd` (the session cwd) via the
65
+ * {@link resolveStateForCwd} semantics, and:
85
66
  *
86
- * For `./.skillstate.json`:
87
- * - `UserPromptSubmit` → `.../.codex-.skillstate-user-prompt-submit.cjs`
88
- * - `SessionStart` → `.../.codex-.skillstate-session-start-compact.cjs`
89
- * - `PostToolUse` → `.../.codex-.skillstate-post-tool-use.cjs`
67
+ * - `user-prompt-submit`: emits
68
+ * `{ hookSpecificOutput: { hookEventName: "UserPromptSubmit",
69
+ * additionalContext } }` carrying the current state JSON;
70
+ * - `session-start-compact`: the same injection with
71
+ * `hookEventName: "SessionStart"` (state survives compaction);
72
+ * - `post-tool-use`: extracts a `state_patch` from the tool_response
73
+ * (fenced ```json block or raw JSON), applies the ⊕ null-deletion merge
74
+ * and writes the state file; stdout is `{}` or a `systemMessage` when
75
+ * the patch is invalid.
90
76
  *
91
- * Accepts a raw state path or a `{ root, name }` ref resolved via
92
- * `resolveStatePath`.
77
+ * `statePath` is accepted for `{ root, name }` confinement (traversal
78
+ * refs throw) and documented in the script header; the content itself is
79
+ * cwd-resolving and never bakes an absolute state path in.
80
+ */
81
+ generateHookScript(event: CodexHookEvent, statePath?: string | StatePathRef): string;
82
+ /**
83
+ * Generate a SKILL.md for Codex's skill directory
84
+ * (`~/.codex/skills/<name>/SKILL.md`). The body instructs the agent to
85
+ * treat the hook-injected state as authoritative (history is not
86
+ * reliable), to read state via the skillstate MCP tool `state.get`, and
87
+ * to persist via `state.patch` — the PostToolUse hook also merges any
88
+ * fenced ```json `state_patch` block printed by a Bash tool call.
93
89
  */
94
- codexHookScriptPath(statePath: string | StatePathRef, eventType: CodexHookEvent): string;
90
+ generateSkillMd(spec: ProceduralSpec, statePath?: string): string;
95
91
  /**
96
- * @non-paper additive helper: generate the AGENTS.md amendment and persist
97
- * it via `atomicWriteFile` (tmp + fsync + rename). Both the destination and
98
- * the embedded state path accept raw strings or
92
+ * Generate the hooks.json document and persist it via `atomicWriteFile`.
93
+ * Both the destination and the embedded state path accept raw strings or
99
94
  * `{ root, name }` refs confined by `resolveStatePath`. Returns the
100
95
  * absolute destination path.
101
96
  */
102
- saveCodexAmendments(target: string | StatePathRef, statePath: string | StatePathRef, options?: CodexAmendmentsOptions): Promise<string>;
97
+ saveHooksConfig(target: string | StatePathRef, statePath: string | StatePathRef, options?: CodexHooksConfigOptions): Promise<string>;
103
98
  /**
104
- * @non-paper additive helper: generate the hooks.json document and persist
105
- * it via `atomicWriteFile`. Both the destination and the embedded state
106
- * path accept raw strings or `{ root, name }` refs. Returns the absolute
107
- * destination path.
99
+ * Merge the skillstate hook groups into an existing `hooks.json` text.
100
+ * Idempotent: if any skillstate command is already wired, the document is
101
+ * returned unchanged. Existing (non-skillstate) hooks are preserved.
108
102
  */
109
- saveCodexHooksConfig(target: string | StatePathRef, statePath: string | StatePathRef, options?: CodexHooksConfigOptions): Promise<string>;
103
+ mergeHooksConfig(existingJson: string, options?: CodexHooksConfigOptions): string;
110
104
  /**
111
- * @non-paper additive helper: generate a single hook script and persist it
112
- * via `atomicWriteFile`. Accepts raw strings or `{ root, name }` refs for
113
- * both the destination and the embedded state path. Returns the absolute
114
- * destination path.
105
+ * Generate a hook script and persist it via `atomicWriteFile`. `target`
106
+ * is the script destination (usually
107
+ * {@link CodexAdapter.codexHookScriptPath}); `statePath` is forwarded to
108
+ * {@link generateHookScript}. Returns the absolute destination path.
109
+ */
110
+ saveHookScript(event: CodexHookEvent, target: string | StatePathRef, statePath?: string | StatePathRef): Promise<string>;
111
+ /**
112
+ * Generate a SKILL.md and persist it via `atomicWriteFile`. Returns the
113
+ * absolute destination path.
115
114
  */
116
- saveCodexHookScript(eventType: CodexHookEvent, statePath: string | StatePathRef, schema?: ProceduralSpec['schema']): Promise<string>;
117
- saveCodexHookScript(target: string | StatePathRef, eventType: CodexHookEvent, statePath: string | StatePathRef, schema?: ProceduralSpec['schema']): Promise<string>;
115
+ saveSkillMd(target: string | StatePathRef, spec: ProceduralSpec, statePath?: string): Promise<string>;
118
116
  /** Resolve a `string | StatePathRef` via `resolveStatePath` (throws on `..`). */
119
117
  private resolve;
120
- /** Shared injection body for injection-only hooks (read + emit context). */
121
- private buildInjection;
122
- /** PostToolUse body: extract, validate (if schema given), merge, persist. */
123
- private buildPostToolUse;
118
+ /** PostToolUse script: extract state_patch, ⊕ merge, persist. */
119
+ private buildPostToolUseScript;
124
120
  }
125
121
  //# sourceMappingURL=codex-adapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"codex-adapter.d.ts","sourceRoot":"","sources":["../src/codex-adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"codex-adapter.d.ts","sourceRoot":"","sources":["../src/codex-adapter.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErE,+EAA+E;AAC/E,MAAM,MAAM,cAAc,GACtB,oBAAoB,GACpB,uBAAuB,GACvB,eAAe,CAAC;AAEpB,6DAA6D;AAC7D,eAAO,MAAM,iBAAiB,2EAIgB,CAAC;AAE/C,6EAA6E;AAC7E,eAAO,MAAM,2BAA2B,cAAc,CAAC;AAEvD,2DAA2D;AAC3D,eAAO,MAAM,2BAA2B,WAAW,CAAC;AAEpD;;;GAGG;AACH,eAAO,MAAM,8BAA8B,OAAO,CAAC;AAEnD,gFAAgF;AAChF,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAE7C,4DAA4D;AAC5D,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAOrE;AAgBD,qBAAa,YAAY;IACvB,QAAQ,CAAC,IAAI,WAAW;IAExB;;;;;OAKG;IACH,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,MAAM,CAEpE;IAED;;;;;;;;;;;OAWG;IACH,mBAAmB,CACjB,SAAS,EAAE,MAAM,GAAG,YAAY,EAChC,OAAO,CAAC,EAAE,uBAAuB,GAChC,MAAM,CA6CR;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,kBAAkB,CAChB,KAAK,EAAE,cAAc,EACrB,SAAS,CAAC,EAAE,MAAM,GAAG,YAAY,GAChC,MAAM,CAuER;IAED;;;;;;;OAOG;IACH,eAAe,CAAC,IAAI,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAyDhE;IAED;;;;;OAKG;IACG,eAAe,CACnB,MAAM,EAAE,MAAM,GAAG,YAAY,EAC7B,SAAS,EAAE,MAAM,GAAG,YAAY,EAChC,OAAO,CAAC,EAAE,uBAAuB,GAChC,OAAO,CAAC,MAAM,CAAC,CAIjB;IAED;;;;OAIG;IACH,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,MAAM,CA0ChF;IAED;;;;;OAKG;IACG,cAAc,CAClB,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,MAAM,GAAG,YAAY,EAC7B,SAAS,CAAC,EAAE,MAAM,GAAG,YAAY,GAChC,OAAO,CAAC,MAAM,CAAC,CAIjB;IAED;;;OAGG;IACG,WAAW,CACf,MAAM,EAAE,MAAM,GAAG,YAAY,EAC7B,IAAI,EAAE,cAAc,EACpB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAIjB;IAMD,iFAAiF;IACjF,OAAO,CAAC,OAAO;IAMf,iEAAiE;IACjE,OAAO,CAAC,sBAAsB;CAmK/B"}