oh-my-codex 0.14.0 → 0.14.2
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/Cargo.lock +5 -5
- package/Cargo.toml +1 -1
- package/README.md +14 -8
- package/crates/omx-explore/src/main.rs +94 -1
- package/crates/omx-sparkshell/src/codex_bridge.rs +59 -12
- package/crates/omx-sparkshell/tests/execution.rs +48 -0
- package/dist/cli/__tests__/explore.test.js +33 -1
- package/dist/cli/__tests__/explore.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +11 -2
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/package-bin-contract.test.js +5 -0
- package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
- package/dist/cli/__tests__/question.test.js +139 -25
- package/dist/cli/__tests__/question.test.js.map +1 -1
- package/dist/cli/__tests__/session-scoped-runtime.test.js +30 -0
- package/dist/cli/__tests__/session-scoped-runtime.test.js.map +1 -1
- package/dist/cli/__tests__/setup-agents-overwrite.test.js +32 -7
- package/dist/cli/__tests__/setup-agents-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/setup-refresh.test.js +8 -6
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
- package/dist/cli/__tests__/sparkshell-cli.test.js +23 -0
- package/dist/cli/__tests__/sparkshell-cli.test.js.map +1 -1
- package/dist/cli/__tests__/uninstall.test.js +65 -5
- package/dist/cli/__tests__/uninstall.test.js.map +1 -1
- package/dist/cli/__tests__/update.test.js +360 -26
- package/dist/cli/__tests__/update.test.js.map +1 -1
- package/dist/cli/explore.d.ts.map +1 -1
- package/dist/cli/explore.js +18 -3
- package/dist/cli/explore.js.map +1 -1
- package/dist/cli/index.d.ts +2 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +7 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +25 -3
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/sparkshell.d.ts.map +1 -1
- package/dist/cli/sparkshell.js +11 -1
- package/dist/cli/sparkshell.js.map +1 -1
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +159 -394
- package/dist/cli/team.js.map +1 -1
- package/dist/cli/uninstall.d.ts.map +1 -1
- package/dist/cli/uninstall.js +3 -1
- package/dist/cli/uninstall.js.map +1 -1
- package/dist/cli/update.d.ts +37 -9
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +204 -26
- package/dist/cli/update.js.map +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +51 -14
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +35 -10
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/generator.d.ts +1 -0
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +61 -7
- package/dist/config/generator.js.map +1 -1
- package/dist/hooks/__tests__/code-review-skill-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/code-review-skill-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/code-review-skill-contract.test.js +56 -0
- package/dist/hooks/__tests__/code-review-skill-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/deep-interview-contract.test.js +31 -0
- package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/explicit-terminal-stop-docs-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-docs-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-docs-contract.test.js +43 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-docs-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-model-docs-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-model-docs-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-model-docs-contract.test.js +38 -0
- package/dist/hooks/__tests__/explicit-terminal-stop-model-docs-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/keyword-detector.test.js +108 -0
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.d.ts.map +1 -1
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.js +16 -1
- package/dist/hooks/__tests__/prompt-guidance-test-helpers.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +34 -8
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/mcp/__tests__/bootstrap.test.js +7 -25
- package/dist/mcp/__tests__/bootstrap.test.js.map +1 -1
- package/dist/mcp/__tests__/server-lifecycle.test.js +60 -0
- package/dist/mcp/__tests__/server-lifecycle.test.js.map +1 -1
- package/dist/mcp/__tests__/state-server.test.js +177 -0
- package/dist/mcp/__tests__/state-server.test.js.map +1 -1
- package/dist/mcp/bootstrap.d.ts.map +1 -1
- package/dist/mcp/bootstrap.js +36 -18
- package/dist/mcp/bootstrap.js.map +1 -1
- package/dist/mcp/state-server.d.ts +17 -0
- package/dist/mcp/state-server.d.ts.map +1 -1
- package/dist/mcp/state-server.js +55 -1
- package/dist/mcp/state-server.js.map +1 -1
- package/dist/notifications/__tests__/index.test.js +0 -3
- package/dist/notifications/__tests__/index.test.js.map +1 -1
- package/dist/notifications/__tests__/session-status.test.js +90 -0
- package/dist/notifications/__tests__/session-status.test.js.map +1 -1
- package/dist/notifications/session-status.d.ts +2 -0
- package/dist/notifications/session-status.d.ts.map +1 -1
- package/dist/notifications/session-status.js +19 -4
- package/dist/notifications/session-status.js.map +1 -1
- package/dist/question/__tests__/deep-interview.test.js +44 -0
- package/dist/question/__tests__/deep-interview.test.js.map +1 -1
- package/dist/question/__tests__/renderer.test.js +192 -12
- package/dist/question/__tests__/renderer.test.js.map +1 -1
- package/dist/question/__tests__/state.test.js +21 -1
- package/dist/question/__tests__/state.test.js.map +1 -1
- package/dist/question/deep-interview.d.ts +3 -0
- package/dist/question/deep-interview.d.ts.map +1 -1
- package/dist/question/deep-interview.js +18 -1
- package/dist/question/deep-interview.js.map +1 -1
- package/dist/question/renderer.d.ts +4 -2
- package/dist/question/renderer.d.ts.map +1 -1
- package/dist/question/renderer.js +87 -18
- package/dist/question/renderer.js.map +1 -1
- package/dist/runtime/__tests__/run-outcome.test.js +38 -0
- package/dist/runtime/__tests__/run-outcome.test.js.map +1 -1
- package/dist/runtime/__tests__/run-state.test.d.ts +2 -0
- package/dist/runtime/__tests__/run-state.test.d.ts.map +1 -0
- package/dist/runtime/__tests__/run-state.test.js +37 -0
- package/dist/runtime/__tests__/run-state.test.js.map +1 -0
- package/dist/runtime/run-loop.d.ts +5 -1
- package/dist/runtime/run-loop.d.ts.map +1 -1
- package/dist/runtime/run-loop.js +8 -3
- package/dist/runtime/run-loop.js.map +1 -1
- package/dist/runtime/run-outcome.d.ts +18 -0
- package/dist/runtime/run-outcome.d.ts.map +1 -1
- package/dist/runtime/run-outcome.js +156 -7
- package/dist/runtime/run-outcome.js.map +1 -1
- package/dist/runtime/run-state.d.ts +5 -1
- package/dist/runtime/run-state.d.ts.map +1 -1
- package/dist/runtime/run-state.js +13 -3
- package/dist/runtime/run-state.js.map +1 -1
- package/dist/runtime/terminal-lifecycle.d.ts +11 -0
- package/dist/runtime/terminal-lifecycle.d.ts.map +1 -0
- package/dist/runtime/terminal-lifecycle.js +52 -0
- package/dist/runtime/terminal-lifecycle.js.map +1 -0
- package/dist/scripts/__tests__/codex-native-hook.test.js +370 -56
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/postinstall.test.d.ts +2 -0
- package/dist/scripts/__tests__/postinstall.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/postinstall.test.js +178 -0
- package/dist/scripts/__tests__/postinstall.test.js.map +1 -0
- package/dist/scripts/codex-native-hook.d.ts +1 -0
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +115 -56
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/postinstall.d.ts +22 -0
- package/dist/scripts/postinstall.d.ts.map +1 -0
- package/dist/scripts/postinstall.js +105 -0
- package/dist/scripts/postinstall.js.map +1 -0
- package/dist/state/__tests__/operations.test.js +60 -0
- package/dist/state/__tests__/operations.test.js.map +1 -1
- package/dist/state/operations.d.ts.map +1 -1
- package/dist/state/operations.js +18 -1
- package/dist/state/operations.js.map +1 -1
- package/dist/team/__tests__/role-router.test.js +6 -0
- package/dist/team/__tests__/role-router.test.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +108 -2
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +18 -4
- package/dist/team/runtime.js.map +1 -1
- package/dist/utils/__tests__/dep-versions.test.js +25 -8
- package/dist/utils/__tests__/dep-versions.test.js.map +1 -1
- package/dist/utils/__tests__/paths.test.js +45 -0
- package/dist/utils/__tests__/paths.test.js.map +1 -1
- package/dist/utils/paths.d.ts +2 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +22 -7
- package/dist/utils/paths.js.map +1 -1
- package/dist/verification/__tests__/ci-rust-gates.test.js +1 -1
- package/dist/verification/__tests__/ci-rust-gates.test.js.map +1 -1
- package/package.json +3 -2
- package/prompts/architect.md +4 -0
- package/prompts/code-reviewer.md +3 -0
- package/skills/code-review/SKILL.md +94 -28
- package/skills/deep-interview/SKILL.md +91 -0
- package/src/scripts/__tests__/codex-native-hook.test.ts +468 -64
- package/src/scripts/__tests__/postinstall.test.ts +210 -0
- package/src/scripts/codex-native-hook.ts +136 -53
- package/src/scripts/postinstall-bootstrap.js +23 -0
- package/src/scripts/postinstall.ts +161 -0
- package/templates/AGENTS.md +1 -1
- package/templates/model-instructions/explore-lightweight-AGENTS.md +11 -0
- package/templates/model-instructions/sparkshell-lightweight-AGENTS.md +10 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postinstall.test.d.ts","sourceRoot":"","sources":["../../../src/scripts/__tests__/postinstall.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { mkdtemp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { describe, it } from "node:test";
|
|
6
|
+
import { writeUserInstallStamp } from "../../cli/update.js";
|
|
7
|
+
import { isGlobalInstallLifecycle, runPostinstall, } from "../postinstall.js";
|
|
8
|
+
describe("isGlobalInstallLifecycle", () => {
|
|
9
|
+
it("accepts npm_config_global=true", () => {
|
|
10
|
+
assert.equal(isGlobalInstallLifecycle({ npm_config_global: "true" }), true);
|
|
11
|
+
});
|
|
12
|
+
it("accepts npm_config_location=global", () => {
|
|
13
|
+
assert.equal(isGlobalInstallLifecycle({ npm_config_location: "global" }), true);
|
|
14
|
+
});
|
|
15
|
+
it("rejects local installs", () => {
|
|
16
|
+
assert.equal(isGlobalInstallLifecycle({ npm_config_global: "false" }), false);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
describe("runPostinstall", () => {
|
|
20
|
+
it("runs interactive setup only for bumped global installs", async () => {
|
|
21
|
+
const root = await mkdtemp(join(tmpdir(), "omx-postinstall-"));
|
|
22
|
+
const stampPath = join(root, ".codex", ".omx", "install-state.json");
|
|
23
|
+
const logs = [];
|
|
24
|
+
let setupCalls = 0;
|
|
25
|
+
try {
|
|
26
|
+
const result = await runPostinstall({
|
|
27
|
+
env: { npm_config_global: "true" },
|
|
28
|
+
getCurrentVersion: async () => "0.14.1",
|
|
29
|
+
isInteractive: () => true,
|
|
30
|
+
log: (message) => logs.push(message),
|
|
31
|
+
readStamp: async () => ({
|
|
32
|
+
installed_version: "0.14.0",
|
|
33
|
+
setup_completed_version: "0.14.0",
|
|
34
|
+
updated_at: "2026-04-20T00:00:00.000Z",
|
|
35
|
+
}),
|
|
36
|
+
runSetup: async () => {
|
|
37
|
+
setupCalls += 1;
|
|
38
|
+
},
|
|
39
|
+
writeStamp: async (stamp) => writeUserInstallStamp(stamp, stampPath),
|
|
40
|
+
});
|
|
41
|
+
assert.equal(result.status, "setup-ran");
|
|
42
|
+
assert.equal(setupCalls, 1);
|
|
43
|
+
assert.match(logs.join("\n"), /Launching interactive setup/);
|
|
44
|
+
const stamp = JSON.parse(await readFile(stampPath, "utf-8"));
|
|
45
|
+
assert.equal(stamp.installed_version, "0.14.1");
|
|
46
|
+
assert.equal(stamp.setup_completed_version, "0.14.1");
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
await rm(root, { recursive: true, force: true });
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
it("records the installed version and prints a hint when no TTY is available", async () => {
|
|
53
|
+
const root = await mkdtemp(join(tmpdir(), "omx-postinstall-"));
|
|
54
|
+
const stampPath = join(root, ".codex", ".omx", "install-state.json");
|
|
55
|
+
const logs = [];
|
|
56
|
+
let setupCalls = 0;
|
|
57
|
+
try {
|
|
58
|
+
const result = await runPostinstall({
|
|
59
|
+
env: { npm_config_global: "true" },
|
|
60
|
+
getCurrentVersion: async () => "0.14.1",
|
|
61
|
+
isInteractive: () => false,
|
|
62
|
+
log: (message) => logs.push(message),
|
|
63
|
+
readStamp: async () => ({
|
|
64
|
+
installed_version: "0.14.0",
|
|
65
|
+
setup_completed_version: "0.14.0",
|
|
66
|
+
updated_at: "2026-04-20T00:00:00.000Z",
|
|
67
|
+
}),
|
|
68
|
+
runSetup: async () => {
|
|
69
|
+
setupCalls += 1;
|
|
70
|
+
},
|
|
71
|
+
writeStamp: async (stamp) => writeUserInstallStamp(stamp, stampPath),
|
|
72
|
+
});
|
|
73
|
+
assert.equal(result.status, "hinted");
|
|
74
|
+
assert.equal(setupCalls, 0);
|
|
75
|
+
assert.match(logs.join("\n"), /Run `omx setup` \(interactive\) or `omx update`/);
|
|
76
|
+
const stamp = JSON.parse(await readFile(stampPath, "utf-8"));
|
|
77
|
+
assert.equal(stamp.installed_version, "0.14.1");
|
|
78
|
+
assert.equal(stamp.setup_completed_version, "0.14.0");
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
await rm(root, { recursive: true, force: true });
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
it("skips local installs", async () => {
|
|
85
|
+
let setupCalls = 0;
|
|
86
|
+
const result = await runPostinstall({
|
|
87
|
+
env: { npm_config_global: "false" },
|
|
88
|
+
getCurrentVersion: async () => "0.14.1",
|
|
89
|
+
isInteractive: () => true,
|
|
90
|
+
runSetup: async () => {
|
|
91
|
+
setupCalls += 1;
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
assert.equal(result.status, "noop-local");
|
|
95
|
+
assert.equal(setupCalls, 0);
|
|
96
|
+
});
|
|
97
|
+
it("does not rerun setup when the installed version matches the saved stamp", async () => {
|
|
98
|
+
let setupCalls = 0;
|
|
99
|
+
const result = await runPostinstall({
|
|
100
|
+
env: { npm_config_global: "true" },
|
|
101
|
+
getCurrentVersion: async () => "0.14.1",
|
|
102
|
+
isInteractive: () => true,
|
|
103
|
+
readStamp: async () => ({
|
|
104
|
+
installed_version: "0.14.1",
|
|
105
|
+
setup_completed_version: "0.14.1",
|
|
106
|
+
updated_at: "2026-04-20T00:00:00.000Z",
|
|
107
|
+
}),
|
|
108
|
+
runSetup: async () => {
|
|
109
|
+
setupCalls += 1;
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
assert.equal(result.status, "noop-same-version");
|
|
113
|
+
assert.equal(setupCalls, 0);
|
|
114
|
+
});
|
|
115
|
+
it("warns and exits cleanly when setup fails", async () => {
|
|
116
|
+
const warnings = [];
|
|
117
|
+
const result = await runPostinstall({
|
|
118
|
+
env: { npm_config_global: "true" },
|
|
119
|
+
getCurrentVersion: async () => "0.14.1",
|
|
120
|
+
isInteractive: () => true,
|
|
121
|
+
readStamp: async () => ({
|
|
122
|
+
installed_version: "0.14.0",
|
|
123
|
+
setup_completed_version: "0.14.0",
|
|
124
|
+
updated_at: "2026-04-20T00:00:00.000Z",
|
|
125
|
+
}),
|
|
126
|
+
runSetup: async () => {
|
|
127
|
+
throw new Error("boom");
|
|
128
|
+
},
|
|
129
|
+
warn: (message) => warnings.push(message),
|
|
130
|
+
writeStamp: async () => { },
|
|
131
|
+
});
|
|
132
|
+
assert.equal(result.status, "setup-failed");
|
|
133
|
+
assert.match(warnings.join("\n"), /non-fatal error: boom/);
|
|
134
|
+
});
|
|
135
|
+
it("runs interactive setup from the npm install prefix instead of the package dir or INIT_CWD", async () => {
|
|
136
|
+
const installRoot = await mkdtemp(join(tmpdir(), "omx-postinstall-install-root-"));
|
|
137
|
+
const packageRoot = await mkdtemp(join(tmpdir(), "omx-postinstall-package-root-"));
|
|
138
|
+
const initCwd = await mkdtemp(join(tmpdir(), "omx-postinstall-init-cwd-"));
|
|
139
|
+
const originalCwd = process.cwd();
|
|
140
|
+
const scopeFile = join(installRoot, ".omx", "setup-scope.json");
|
|
141
|
+
const packageScopeFile = join(packageRoot, ".omx", "setup-scope.json");
|
|
142
|
+
const initCwdScopeFile = join(initCwd, ".omx", "setup-scope.json");
|
|
143
|
+
try {
|
|
144
|
+
process.chdir(packageRoot);
|
|
145
|
+
const result = await runPostinstall({
|
|
146
|
+
env: {
|
|
147
|
+
npm_config_global: "true",
|
|
148
|
+
npm_config_prefix: installRoot,
|
|
149
|
+
INIT_CWD: initCwd,
|
|
150
|
+
},
|
|
151
|
+
getCurrentVersion: async () => "0.14.1",
|
|
152
|
+
isInteractive: () => true,
|
|
153
|
+
readStamp: async () => ({
|
|
154
|
+
installed_version: "0.14.0",
|
|
155
|
+
setup_completed_version: "0.14.0",
|
|
156
|
+
updated_at: "2026-04-20T00:00:00.000Z",
|
|
157
|
+
}),
|
|
158
|
+
runSetup: async () => {
|
|
159
|
+
await mkdir(join(process.cwd(), ".omx"), { recursive: true });
|
|
160
|
+
await writeFile(join(process.cwd(), ".omx", "setup-scope.json"), JSON.stringify({ scope: "project" }));
|
|
161
|
+
},
|
|
162
|
+
writeStamp: async () => { },
|
|
163
|
+
});
|
|
164
|
+
assert.equal(result.status, "setup-ran");
|
|
165
|
+
assert.equal(process.cwd(), packageRoot);
|
|
166
|
+
assert.equal(JSON.parse(await readFile(scopeFile, "utf-8")).scope, "project");
|
|
167
|
+
await assert.rejects(() => readFile(packageScopeFile, "utf-8"));
|
|
168
|
+
await assert.rejects(() => readFile(initCwdScopeFile, "utf-8"));
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
process.chdir(originalCwd);
|
|
172
|
+
await rm(installRoot, { recursive: true, force: true });
|
|
173
|
+
await rm(packageRoot, { recursive: true, force: true });
|
|
174
|
+
await rm(initCwd, { recursive: true, force: true });
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
//# sourceMappingURL=postinstall.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postinstall.test.js","sourceRoot":"","sources":["../../../src/scripts/__tests__/postinstall.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,6 +19,7 @@ export declare function resolveSessionOwnerPidFromAncestry(startPid: number, opt
|
|
|
19
19
|
readProcessCommand?: (pid: number) => string;
|
|
20
20
|
}): number | null;
|
|
21
21
|
export declare function dispatchCodexNativeHook(payload: CodexHookPayload, options?: NativeHookDispatchOptions): Promise<NativeHookDispatchResult>;
|
|
22
|
+
export declare function isCodexNativeHookMainModule(moduleUrl: string, argv1: string | undefined): boolean;
|
|
22
23
|
export declare function runCodexNativeHookCli(): Promise<void>;
|
|
23
24
|
export {};
|
|
24
25
|
//# sourceMappingURL=codex-native-hook.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-native-hook.d.ts","sourceRoot":"","sources":["../../src/scripts/codex-native-hook.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"codex-native-hook.d.ts","sourceRoot":"","sources":["../../src/scripts/codex-native-hook.ts"],"names":[],"mappings":"AA4BA,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,8BAA8B,CAAC;AAiBtC,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAiBlE,KAAK,kBAAkB,GACnB,cAAc,GACd,YAAY,GACZ,aAAa,GACb,kBAAkB,GAClB,MAAM,CAAC;AAEX,KAAK,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEhD,UAAU,yBAAyB;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6BAA6B,CAAC,EAAE,OAAO,2BAA2B,CAAC;CACpE;AAED,MAAM,WAAW,wBAAwB;IACvC,aAAa,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACzC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC5C;AA2FD,wBAAgB,2BAA2B,CACzC,aAAa,EAAE,kBAAkB,GAAG,IAAI,GACvC,MAAM,GAAG,IAAI,CAef;AAiLD,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE;IACP,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC/C,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;CACzC,GACL,MAAM,GAAG,IAAI,CAuBf;AA8sCD,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,gBAAgB,EACzB,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,wBAAwB,CAAC,CAkLnC;AAOD,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,OAAO,CAGT;AAyBD,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAmB3D"}
|
|
@@ -2,11 +2,12 @@ import { execFileSync } from "child_process";
|
|
|
2
2
|
import { existsSync, readFileSync } from "fs";
|
|
3
3
|
import { mkdir, readFile, readdir, writeFile } from "fs/promises";
|
|
4
4
|
import { join, resolve } from "path";
|
|
5
|
+
import { pathToFileURL } from "url";
|
|
5
6
|
import { readModeState, readModeStateForSession, updateModeState } from "../modes/base.js";
|
|
6
7
|
import { listActiveSkills, readVisibleSkillActiveState, } from "../state/skill-active.js";
|
|
7
8
|
import { readSubagentSessionSummary } from "../subagents/tracker.js";
|
|
8
9
|
import { resolveCanonicalTeamStateRoot } from "../team/state-root.js";
|
|
9
|
-
import { readUsableSessionState, reconcileNativeSessionStart } from "../hooks/session.js";
|
|
10
|
+
import { isSessionStateUsable, readSessionState, readUsableSessionState, reconcileNativeSessionStart, } from "../hooks/session.js";
|
|
10
11
|
import { appendTeamEvent, readTeamLeaderAttention, readTeamManifestV2, readTeamPhase, writeTeamLeaderAttention, writeTeamPhase, } from "../team/state.js";
|
|
11
12
|
import { omxNotepadPath, omxProjectMemoryPath } from "../utils/paths.js";
|
|
12
13
|
import { getStateFilePath, getStatePath } from "../mcp/state-paths.js";
|
|
@@ -16,6 +17,7 @@ import { buildNativePostToolUseOutput, buildNativePreToolUseOutput, detectMcpTra
|
|
|
16
17
|
import { buildNativeHookEvent, } from "../hooks/extensibility/events.js";
|
|
17
18
|
import { dispatchHookEvent } from "../hooks/extensibility/dispatcher.js";
|
|
18
19
|
import { reconcileHudForPromptSubmit } from "../hud/reconcile.js";
|
|
20
|
+
import { shellEscapeSingle } from "../hud/tmux.js";
|
|
19
21
|
import { onSessionStart as buildWikiSessionStartContext } from "../wiki/lifecycle.js";
|
|
20
22
|
import { readAutoresearchCompletionStatus, readAutoresearchModeState } from "../autoresearch/skill-validation.js";
|
|
21
23
|
import { shouldContinueRun } from "../runtime/run-loop.js";
|
|
@@ -23,6 +25,7 @@ import { triagePrompt } from "../hooks/triage-heuristic.js";
|
|
|
23
25
|
import { readTriageConfig } from "../hooks/triage-config.js";
|
|
24
26
|
import { readTriageState, writeTriageState, shouldSuppressFollowup, promptSignature, } from "../hooks/triage-state.js";
|
|
25
27
|
import { isPendingDeepInterviewQuestionEnforcement } from "../question/deep-interview.js";
|
|
28
|
+
import { resolveOmxCliEntryPath } from "../utils/paths.js";
|
|
26
29
|
const TERMINAL_MODE_PHASES = new Set(["complete", "failed", "cancelled"]);
|
|
27
30
|
const SKILL_STOP_BLOCKERS = new Set(["ralplan"]);
|
|
28
31
|
const TEAM_TERMINAL_TASK_STATUSES = new Set(["completed", "failed"]);
|
|
@@ -133,24 +136,31 @@ function readPromptText(payload) {
|
|
|
133
136
|
}
|
|
134
137
|
return "";
|
|
135
138
|
}
|
|
136
|
-
function sanitizePayloadForHookContext(payload, hookEventName) {
|
|
137
|
-
if (hookEventName !== "UserPromptSubmit")
|
|
138
|
-
return payload;
|
|
139
|
+
function sanitizePayloadForHookContext(payload, hookEventName, canonicalSessionId = "") {
|
|
139
140
|
const sanitized = { ...payload };
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
141
|
+
if (hookEventName === "UserPromptSubmit") {
|
|
142
|
+
delete sanitized.prompt;
|
|
143
|
+
delete sanitized.input;
|
|
144
|
+
delete sanitized.user_prompt;
|
|
145
|
+
delete sanitized.userPrompt;
|
|
146
|
+
delete sanitized.text;
|
|
147
|
+
return sanitized;
|
|
148
|
+
}
|
|
149
|
+
if (hookEventName === "Stop") {
|
|
150
|
+
delete sanitized.stop_hook_active;
|
|
151
|
+
delete sanitized.stopHookActive;
|
|
152
|
+
delete sanitized.sessionId;
|
|
153
|
+
sanitized.session_id = canonicalSessionId.trim() || safeString(payload.session_id ?? payload.sessionId).trim();
|
|
154
|
+
}
|
|
145
155
|
return sanitized;
|
|
146
156
|
}
|
|
147
|
-
function buildBaseContext(cwd, payload, hookEventName) {
|
|
157
|
+
function buildBaseContext(cwd, payload, hookEventName, canonicalSessionId = "") {
|
|
148
158
|
return {
|
|
149
159
|
cwd,
|
|
150
160
|
project_path: cwd,
|
|
151
161
|
transcript_path: safeString(payload.transcript_path ?? payload.transcriptPath) || null,
|
|
152
162
|
source: safeString(payload.source),
|
|
153
|
-
payload: sanitizePayloadForHookContext(payload, hookEventName),
|
|
163
|
+
payload: sanitizePayloadForHookContext(payload, hookEventName, canonicalSessionId),
|
|
154
164
|
};
|
|
155
165
|
}
|
|
156
166
|
async function readJsonIfExists(path) {
|
|
@@ -183,14 +193,27 @@ async function readActiveAutoresearchState(cwd, sessionId) {
|
|
|
183
193
|
return state;
|
|
184
194
|
}
|
|
185
195
|
async function readActiveRalphState(stateDir, preferredSessionId) {
|
|
186
|
-
const
|
|
187
|
-
const
|
|
196
|
+
const cwd = resolve(stateDir, "..", "..");
|
|
197
|
+
const [rawSessionInfo, usableSessionInfo] = await Promise.all([
|
|
198
|
+
readSessionState(cwd),
|
|
199
|
+
readUsableSessionState(cwd),
|
|
200
|
+
]);
|
|
201
|
+
const currentOmxSessionId = safeString(usableSessionInfo?.session_id).trim();
|
|
202
|
+
const staleCurrentSessionId = rawSessionInfo && !isSessionStateUsable(rawSessionInfo, cwd)
|
|
203
|
+
? safeString(rawSessionInfo.session_id).trim()
|
|
204
|
+
: "";
|
|
188
205
|
const sessionCandidates = [...new Set([
|
|
189
206
|
safeString(preferredSessionId).trim(),
|
|
190
207
|
currentOmxSessionId,
|
|
191
208
|
].filter(Boolean))];
|
|
209
|
+
// Ralph Stop stays authoritative-scope-only once the Stop payload is session-bound.
|
|
210
|
+
// That is intentionally stricter than generic state MCP reads: do not scan sibling
|
|
211
|
+
// session scopes or fall back to root when a current/explicit session is in play.
|
|
192
212
|
for (const sessionId of sessionCandidates) {
|
|
193
|
-
|
|
213
|
+
if (staleCurrentSessionId && sessionId === staleCurrentSessionId) {
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
const sessionScoped = await readStopSessionPinnedState("ralph-state.json", cwd, sessionId);
|
|
194
217
|
if (sessionScoped?.active === true && shouldContinueRun(sessionScoped)) {
|
|
195
218
|
return sessionScoped;
|
|
196
219
|
}
|
|
@@ -201,18 +224,6 @@ async function readActiveRalphState(stateDir, preferredSessionId) {
|
|
|
201
224
|
if (direct?.active === true && shouldContinueRun(direct)) {
|
|
202
225
|
return direct;
|
|
203
226
|
}
|
|
204
|
-
const sessionsRoot = join(stateDir, "sessions");
|
|
205
|
-
if (!existsSync(sessionsRoot))
|
|
206
|
-
return null;
|
|
207
|
-
const entries = await readdir(sessionsRoot, { withFileTypes: true }).catch(() => []);
|
|
208
|
-
for (const entry of entries) {
|
|
209
|
-
if (!entry.isDirectory())
|
|
210
|
-
continue;
|
|
211
|
-
const candidate = await readJsonIfExists(join(sessionsRoot, entry.name, "ralph-state.json"));
|
|
212
|
-
if (candidate?.active === true && shouldContinueRun(candidate)) {
|
|
213
|
-
return candidate;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
227
|
return null;
|
|
217
228
|
}
|
|
218
229
|
function readParentPid(pid) {
|
|
@@ -303,38 +314,60 @@ function resolveSessionOwnerPid(payload) {
|
|
|
303
314
|
return resolved;
|
|
304
315
|
return process.pid;
|
|
305
316
|
}
|
|
306
|
-
|
|
307
|
-
let repoRoot = "";
|
|
317
|
+
function tryReadGitValue(cwd, args) {
|
|
308
318
|
try {
|
|
309
|
-
|
|
319
|
+
const value = execFileSync("git", args, {
|
|
310
320
|
cwd,
|
|
311
321
|
encoding: "utf-8",
|
|
312
322
|
stdio: ["ignore", "pipe", "ignore"],
|
|
313
323
|
windowsHide: true,
|
|
314
324
|
}).trim();
|
|
325
|
+
return value || null;
|
|
315
326
|
}
|
|
316
327
|
catch {
|
|
317
|
-
return
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
function isPathIgnoredByGit(cwd, path) {
|
|
332
|
+
try {
|
|
333
|
+
execFileSync("git", ["check-ignore", "-q", path], {
|
|
334
|
+
cwd,
|
|
335
|
+
stdio: ["ignore", "ignore", "ignore"],
|
|
336
|
+
windowsHide: true,
|
|
337
|
+
});
|
|
338
|
+
return true;
|
|
318
339
|
}
|
|
340
|
+
catch {
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
async function ensureOmxLocalIgnoreEntry(cwd) {
|
|
345
|
+
const repoRoot = tryReadGitValue(cwd, ["rev-parse", "--show-toplevel"]);
|
|
319
346
|
if (!repoRoot)
|
|
320
347
|
return { changed: false };
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
348
|
+
if (isPathIgnoredByGit(repoRoot, ".omx/")) {
|
|
349
|
+
return { changed: false };
|
|
350
|
+
}
|
|
351
|
+
const excludePathValue = tryReadGitValue(repoRoot, ["rev-parse", "--git-path", "info/exclude"]);
|
|
352
|
+
if (!excludePathValue)
|
|
353
|
+
return { changed: false };
|
|
354
|
+
const excludePath = resolve(repoRoot, excludePathValue);
|
|
355
|
+
const existing = existsSync(excludePath)
|
|
356
|
+
? await readFile(excludePath, "utf-8")
|
|
324
357
|
: "";
|
|
325
358
|
const lines = existing.split(/\r?\n/).map((line) => line.trim());
|
|
326
359
|
if (lines.includes(".omx/")) {
|
|
327
|
-
return { changed: false,
|
|
360
|
+
return { changed: false, excludePath };
|
|
328
361
|
}
|
|
329
362
|
const next = `${existing}${existing.endsWith("\n") || existing.length === 0 ? "" : "\n"}.omx/\n`;
|
|
330
|
-
await writeFile(
|
|
331
|
-
return { changed: true,
|
|
363
|
+
await writeFile(excludePath, next);
|
|
364
|
+
return { changed: true, excludePath };
|
|
332
365
|
}
|
|
333
366
|
async function buildSessionStartContext(cwd, sessionId) {
|
|
334
367
|
const sections = [];
|
|
335
|
-
const
|
|
336
|
-
if (
|
|
337
|
-
sections.push(`Added .omx/ to ${
|
|
368
|
+
const localIgnoreResult = await ensureOmxLocalIgnoreEntry(cwd);
|
|
369
|
+
if (localIgnoreResult.changed) {
|
|
370
|
+
sections.push(`Added .omx/ to ${localIgnoreResult.excludePath} to keep local OMX state out of source control without mutating tracked repo ignores.`);
|
|
338
371
|
}
|
|
339
372
|
const modeSummaries = [];
|
|
340
373
|
for (const mode of ["ralph", "autopilot", "ultrawork", "ultraqa", "ralplan", "deep-interview", "team"]) {
|
|
@@ -420,7 +453,12 @@ async function buildSessionStartContext(cwd, sessionId) {
|
|
|
420
453
|
}
|
|
421
454
|
return sections.length > 0 ? sections.join("\n\n") : null;
|
|
422
455
|
}
|
|
423
|
-
function
|
|
456
|
+
function buildDeepInterviewQuestionBridgeInstruction(cwd) {
|
|
457
|
+
const omxBin = resolveOmxCliEntryPath({ cwd }) || process.argv[1] || "omx";
|
|
458
|
+
const bridgeCommand = `${shellEscapeSingle(process.execPath)} ${shellEscapeSingle(omxBin)} question`;
|
|
459
|
+
return `Deep-interview must ask each interview round via \`omx question\`; do not fall back to \`request_user_input\` or plain-text questioning. After starting \`omx question\` in a background terminal, wait for that terminal to finish and read the JSON answer before continuing the interview. If bare \`omx question\` is unavailable in this reused session, use the current-session CLI bridge command: \`${bridgeCommand}\`. Stop remains blocked while a deep-interview question obligation is pending.`;
|
|
460
|
+
}
|
|
461
|
+
function buildAdditionalContextMessage(prompt, skillState, cwd = process.cwd()) {
|
|
424
462
|
if (!prompt)
|
|
425
463
|
return null;
|
|
426
464
|
const promptPriorityMessage = buildPromptPriorityMessage(prompt);
|
|
@@ -442,7 +480,7 @@ function buildAdditionalContextMessage(prompt, skillState) {
|
|
|
442
480
|
? "Prompt-side `$ralph` activation seeds Ralph workflow state only; it does not invoke `omx ralph`. Use `omx ralph --prd ...` only when you explicitly want the PRD-gated CLI startup path."
|
|
443
481
|
: null;
|
|
444
482
|
const deepInterviewPromptActivationNote = skillState?.initialized_mode === "deep-interview"
|
|
445
|
-
?
|
|
483
|
+
? buildDeepInterviewQuestionBridgeInstruction(cwd)
|
|
446
484
|
: null;
|
|
447
485
|
const combinedTransitionMessage = (() => {
|
|
448
486
|
if (!skillState?.transition_message)
|
|
@@ -803,7 +841,11 @@ async function readStopAutoNudgePhase(cwd, sessionId, threadId) {
|
|
|
803
841
|
}
|
|
804
842
|
async function buildDeepInterviewQuestionStopOutput(cwd, sessionId, threadId) {
|
|
805
843
|
const modeState = await readStopSessionPinnedState("deep-interview-state.json", cwd, sessionId);
|
|
806
|
-
if (!modeState
|
|
844
|
+
if (!modeState)
|
|
845
|
+
return null;
|
|
846
|
+
const questionEnforcement = safeObject(modeState.question_enforcement);
|
|
847
|
+
const hasPendingQuestionObligation = isPendingDeepInterviewQuestionEnforcement(questionEnforcement);
|
|
848
|
+
if (modeState.active !== true && !hasPendingQuestionObligation)
|
|
807
849
|
return null;
|
|
808
850
|
const phase = formatPhase(modeState.current_phase, "planning");
|
|
809
851
|
if (TERMINAL_MODE_PHASES.has(phase.toLowerCase()) || phase === "completing") {
|
|
@@ -816,8 +858,7 @@ async function buildDeepInterviewQuestionStopOutput(cwd, sessionId, threadId) {
|
|
|
816
858
|
if (!blocker)
|
|
817
859
|
return null;
|
|
818
860
|
}
|
|
819
|
-
|
|
820
|
-
if (!isPendingDeepInterviewQuestionEnforcement(questionEnforcement)) {
|
|
861
|
+
if (!hasPendingQuestionObligation) {
|
|
821
862
|
return null;
|
|
822
863
|
}
|
|
823
864
|
const obligationId = safeString(questionEnforcement.obligation_id).trim();
|
|
@@ -904,8 +945,8 @@ async function maybeReturnRepeatableStopOutput(payload, stateDir, signature, out
|
|
|
904
945
|
await persistNativeStopSignature(stateDir, payload, signature, canonicalSessionId);
|
|
905
946
|
return output;
|
|
906
947
|
}
|
|
907
|
-
async function returnPersistentStopBlock(payload, stateDir, signatureKind, signatureValue, output, canonicalSessionId) {
|
|
908
|
-
return await maybeReturnRepeatableStopOutput(payload, stateDir, buildRepeatableStopSignature(payload, signatureKind, signatureValue, canonicalSessionId), output, canonicalSessionId,
|
|
948
|
+
async function returnPersistentStopBlock(payload, stateDir, signatureKind, signatureValue, output, canonicalSessionId, options = { allowRepeatDuringStopHook: true }) {
|
|
949
|
+
return await maybeReturnRepeatableStopOutput(payload, stateDir, buildRepeatableStopSignature(payload, signatureKind, signatureValue, canonicalSessionId), output, canonicalSessionId, options);
|
|
909
950
|
}
|
|
910
951
|
async function findCanonicalActiveTeamForSession(cwd, sessionId) {
|
|
911
952
|
if (!sessionId.trim())
|
|
@@ -1099,7 +1140,7 @@ async function buildStopHookOutput(payload, cwd, stateDir) {
|
|
|
1099
1140
|
}
|
|
1100
1141
|
const ultraworkOutput = await buildModeBasedStopOutput("ultrawork", cwd, canonicalSessionId);
|
|
1101
1142
|
if (ultraworkOutput) {
|
|
1102
|
-
return await returnPersistentStopBlock(payload, stateDir, "ultrawork-stop", safeString(ultraworkOutput.stopReason), ultraworkOutput, canonicalSessionId);
|
|
1143
|
+
return await returnPersistentStopBlock(payload, stateDir, "ultrawork-stop", safeString(ultraworkOutput.stopReason), ultraworkOutput, canonicalSessionId, { allowRepeatDuringStopHook: false });
|
|
1103
1144
|
}
|
|
1104
1145
|
const ultraqaOutput = await buildModeBasedStopOutput("ultraqa", cwd, canonicalSessionId);
|
|
1105
1146
|
if (ultraqaOutput) {
|
|
@@ -1165,18 +1206,32 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
1165
1206
|
const nativeSessionId = safeString(payload.session_id ?? payload.sessionId).trim();
|
|
1166
1207
|
const threadId = safeString(payload.thread_id ?? payload.threadId).trim();
|
|
1167
1208
|
const turnId = safeString(payload.turn_id ?? payload.turnId).trim();
|
|
1168
|
-
|
|
1209
|
+
const currentSessionState = await readUsableSessionState(cwd);
|
|
1210
|
+
let canonicalSessionId = safeString(currentSessionState?.session_id).trim();
|
|
1211
|
+
let resolvedNativeSessionId = nativeSessionId;
|
|
1169
1212
|
if (hookEventName === "SessionStart" && nativeSessionId) {
|
|
1170
1213
|
const sessionState = await reconcileNativeSessionStart(cwd, nativeSessionId, {
|
|
1171
1214
|
pid: options.sessionOwnerPid ?? resolveSessionOwnerPid(payload),
|
|
1172
1215
|
});
|
|
1173
1216
|
canonicalSessionId = safeString(sessionState.session_id).trim();
|
|
1217
|
+
resolvedNativeSessionId = safeString(sessionState.native_session_id).trim() || nativeSessionId;
|
|
1174
1218
|
}
|
|
1175
1219
|
else if (!canonicalSessionId) {
|
|
1176
|
-
canonicalSessionId = safeString(
|
|
1220
|
+
canonicalSessionId = safeString(currentSessionState?.session_id).trim();
|
|
1221
|
+
}
|
|
1222
|
+
if (hookEventName === "Stop") {
|
|
1223
|
+
const stopCanonicalSessionId = await resolveInternalSessionIdForPayload(cwd, readPayloadSessionId(payload));
|
|
1224
|
+
if (stopCanonicalSessionId) {
|
|
1225
|
+
canonicalSessionId = stopCanonicalSessionId;
|
|
1226
|
+
}
|
|
1227
|
+
if (canonicalSessionId && safeString(currentSessionState?.session_id).trim() === canonicalSessionId) {
|
|
1228
|
+
resolvedNativeSessionId =
|
|
1229
|
+
safeString(currentSessionState?.native_session_id).trim() || resolvedNativeSessionId;
|
|
1230
|
+
}
|
|
1177
1231
|
}
|
|
1178
1232
|
const eventSessionId = canonicalSessionId || nativeSessionId || undefined;
|
|
1179
1233
|
const sessionIdForState = canonicalSessionId || nativeSessionId;
|
|
1234
|
+
let outputJson = null;
|
|
1180
1235
|
if (hookEventName === "UserPromptSubmit") {
|
|
1181
1236
|
const prompt = readPromptText(payload);
|
|
1182
1237
|
if (prompt) {
|
|
@@ -1263,10 +1318,10 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
1263
1318
|
await reconcileHudForPromptSubmitFn(cwd, { sessionId: canonicalSessionId || sessionIdForState || undefined }).catch(() => { });
|
|
1264
1319
|
}
|
|
1265
1320
|
if (omxEventName) {
|
|
1266
|
-
const baseContext = buildBaseContext(cwd, payload, hookEventName);
|
|
1267
|
-
if (
|
|
1268
|
-
baseContext.native_session_id =
|
|
1269
|
-
baseContext.codex_session_id =
|
|
1321
|
+
const baseContext = buildBaseContext(cwd, payload, hookEventName, canonicalSessionId);
|
|
1322
|
+
if (resolvedNativeSessionId) {
|
|
1323
|
+
baseContext.native_session_id = resolvedNativeSessionId;
|
|
1324
|
+
baseContext.codex_session_id = resolvedNativeSessionId;
|
|
1270
1325
|
}
|
|
1271
1326
|
if (canonicalSessionId) {
|
|
1272
1327
|
baseContext.omx_session_id = canonicalSessionId;
|
|
@@ -1279,11 +1334,10 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
1279
1334
|
});
|
|
1280
1335
|
await dispatchHookEvent(event, { cwd });
|
|
1281
1336
|
}
|
|
1282
|
-
let outputJson = null;
|
|
1283
1337
|
if (hookEventName === "SessionStart" || hookEventName === "UserPromptSubmit") {
|
|
1284
1338
|
const additionalContext = hookEventName === "SessionStart"
|
|
1285
1339
|
? await buildSessionStartContext(cwd, canonicalSessionId || nativeSessionId)
|
|
1286
|
-
: (buildAdditionalContextMessage(readPromptText(payload), skillState) ?? triageAdditionalContext);
|
|
1340
|
+
: (buildAdditionalContextMessage(readPromptText(payload), skillState, cwd) ?? triageAdditionalContext);
|
|
1287
1341
|
if (additionalContext) {
|
|
1288
1342
|
outputJson = {
|
|
1289
1343
|
hookSpecificOutput: {
|
|
@@ -1312,6 +1366,11 @@ export async function dispatchCodexNativeHook(payload, options = {}) {
|
|
|
1312
1366
|
outputJson,
|
|
1313
1367
|
};
|
|
1314
1368
|
}
|
|
1369
|
+
export function isCodexNativeHookMainModule(moduleUrl, argv1) {
|
|
1370
|
+
if (!argv1)
|
|
1371
|
+
return false;
|
|
1372
|
+
return moduleUrl === pathToFileURL(argv1).href;
|
|
1373
|
+
}
|
|
1315
1374
|
async function readStdinJson() {
|
|
1316
1375
|
const chunks = [];
|
|
1317
1376
|
for await (const chunk of process.stdin) {
|
|
@@ -1352,7 +1411,7 @@ export async function runCodexNativeHookCli() {
|
|
|
1352
1411
|
process.stdout.write(`${JSON.stringify(result.outputJson)}\n`);
|
|
1353
1412
|
}
|
|
1354
1413
|
}
|
|
1355
|
-
if (import.meta.url
|
|
1414
|
+
if (isCodexNativeHookMainModule(import.meta.url, process.argv[1])) {
|
|
1356
1415
|
runCodexNativeHookCli().catch((error) => {
|
|
1357
1416
|
process.stderr.write(`[omx] codex-native-hook failed: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
1358
1417
|
process.exitCode = 1;
|