oh-my-codex 0.18.8 → 0.18.9
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 +12 -12
- package/Cargo.toml +1 -1
- package/dist/autopilot/__tests__/fsm.test.js +3 -0
- package/dist/autopilot/__tests__/fsm.test.js.map +1 -1
- package/dist/autopilot/fsm.js +2 -2
- package/dist/autopilot/fsm.js.map +1 -1
- package/dist/cli/__tests__/auth.test.js +4 -2
- package/dist/cli/__tests__/auth.test.js.map +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +38 -2
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/package-bin-contract.test.js +20 -4
- package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
- package/dist/cli/__tests__/question.test.js +26 -9
- package/dist/cli/__tests__/question.test.js.map +1 -1
- package/dist/cli/__tests__/resume.test.js +50 -1
- package/dist/cli/__tests__/resume.test.js.map +1 -1
- package/dist/cli/__tests__/update.test.js +214 -17
- package/dist/cli/__tests__/update.test.js.map +1 -1
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js +1 -1
- package/dist/cli/index.d.ts +11 -3
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +35 -13
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/update.d.ts +20 -3
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +265 -23
- package/dist/cli/update.js.map +1 -1
- package/dist/cli/version.d.ts.map +1 -1
- package/dist/cli/version.js +5 -9
- package/dist/cli/version.js.map +1 -1
- package/dist/compat/__tests__/doctor-contract.test.js +12 -1
- package/dist/compat/__tests__/doctor-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/code-review-skill-contract.test.js +7 -3
- package/dist/hooks/__tests__/code-review-skill-contract.test.js.map +1 -1
- package/dist/hooks/__tests__/deep-interview-contract.test.js +30 -1
- package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -1
- package/dist/hud/__tests__/reconcile.test.js +121 -0
- package/dist/hud/__tests__/reconcile.test.js.map +1 -1
- package/dist/hud/__tests__/state.test.js +28 -0
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +4 -18
- package/dist/hud/state.js.map +1 -1
- package/dist/question/__tests__/renderer.test.js +566 -1
- package/dist/question/__tests__/renderer.test.js.map +1 -1
- package/dist/question/renderer.d.ts +9 -1
- package/dist/question/renderer.d.ts.map +1 -1
- package/dist/question/renderer.js +246 -70
- package/dist/question/renderer.js.map +1 -1
- package/dist/scripts/__tests__/codex-native-hook.test.js +154 -0
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +20 -9
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/utils/__tests__/platform-command.test.js +16 -1
- package/dist/utils/__tests__/platform-command.test.js.map +1 -1
- package/dist/utils/__tests__/version.test.d.ts +2 -0
- package/dist/utils/__tests__/version.test.d.ts.map +1 -0
- package/dist/utils/__tests__/version.test.js +51 -0
- package/dist/utils/__tests__/version.test.js.map +1 -0
- package/dist/utils/paths.d.ts +8 -1
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +16 -4
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/platform-command.d.ts +9 -0
- package/dist/utils/platform-command.d.ts.map +1 -1
- package/dist/utils/platform-command.js +15 -0
- package/dist/utils/platform-command.js.map +1 -1
- package/dist/utils/version.d.ts +7 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +67 -0
- package/dist/utils/version.js.map +1 -0
- package/dist/verification/__tests__/ci-rust-gates.test.js +8 -0
- package/dist/verification/__tests__/ci-rust-gates.test.js.map +1 -1
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js +16 -2
- package/dist/verification/__tests__/dev-merge-issue-close-workflow.test.js.map +1 -1
- package/package.json +4 -3
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/oh-my-codex/skills/code-review/SKILL.md +2 -2
- package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +51 -11
- package/skills/code-review/SKILL.md +2 -2
- package/skills/deep-interview/SKILL.md +51 -11
- package/src/scripts/__tests__/codex-native-hook.test.ts +175 -0
- package/src/scripts/codex-native-hook.ts +19 -7
- package/src/scripts/prepare-build.js +83 -0
- package/src/scripts/postinstall-bootstrap.js +0 -23
|
@@ -1867,6 +1867,51 @@ describe("codex native hook dispatch", () => {
|
|
|
1867
1867
|
}
|
|
1868
1868
|
});
|
|
1869
1869
|
|
|
1870
|
+
it("includes repo-local .omx project-memory during SessionStart when OMX_ROOT is boxed", async () => {
|
|
1871
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-session-boxed-memory-"));
|
|
1872
|
+
const boxedRoot = await mkdtemp(join(tmpdir(), "omx-native-hook-boxed-root-"));
|
|
1873
|
+
const previousOmxRoot = process.env.OMX_ROOT;
|
|
1874
|
+
try {
|
|
1875
|
+
process.env.OMX_ROOT = boxedRoot;
|
|
1876
|
+
await writeJson(join(cwd, ".omx", "project-memory.json"), {
|
|
1877
|
+
techStack: "Repo-local CLI memory",
|
|
1878
|
+
conventions: "SessionStart should load CLI-written project memory",
|
|
1879
|
+
directives: [
|
|
1880
|
+
{ directive: "Prefer repo-local .omx project memory over boxed runtime fallback.", priority: "high" },
|
|
1881
|
+
],
|
|
1882
|
+
});
|
|
1883
|
+
await writeJson(join(boxedRoot, ".omx", "project-memory.json"), {
|
|
1884
|
+
techStack: "Boxed runtime memory should not win",
|
|
1885
|
+
notes: [{ category: "runtime", content: "stale boxed runtime note", timestamp: new Date().toISOString() }],
|
|
1886
|
+
});
|
|
1887
|
+
|
|
1888
|
+
const result = await dispatchCodexNativeHook(
|
|
1889
|
+
{
|
|
1890
|
+
hook_event_name: "SessionStart",
|
|
1891
|
+
cwd,
|
|
1892
|
+
session_id: "sess-boxed-memory-1",
|
|
1893
|
+
},
|
|
1894
|
+
{ cwd, sessionOwnerPid: 43210 },
|
|
1895
|
+
);
|
|
1896
|
+
|
|
1897
|
+
const additionalContext = String(
|
|
1898
|
+
(result.outputJson as { hookSpecificOutput?: { additionalContext?: string } })?.hookSpecificOutput?.additionalContext ?? "",
|
|
1899
|
+
);
|
|
1900
|
+
assert.match(additionalContext, /\[Project memory\]/);
|
|
1901
|
+
assert.match(additionalContext, /source: \.omx\/project-memory\.json/);
|
|
1902
|
+
assert.match(additionalContext, /Repo-local CLI memory/);
|
|
1903
|
+
assert.match(additionalContext, /SessionStart should load CLI-written project memory/);
|
|
1904
|
+
assert.match(additionalContext, /Prefer repo-local \.omx project memory over boxed runtime fallback\./);
|
|
1905
|
+
assert.doesNotMatch(additionalContext, /Boxed runtime memory should not win/);
|
|
1906
|
+
assert.doesNotMatch(additionalContext, /stale boxed runtime note/);
|
|
1907
|
+
} finally {
|
|
1908
|
+
if (previousOmxRoot === undefined) delete process.env.OMX_ROOT;
|
|
1909
|
+
else process.env.OMX_ROOT = previousOmxRoot;
|
|
1910
|
+
await rm(cwd, { recursive: true, force: true });
|
|
1911
|
+
await rm(boxedRoot, { recursive: true, force: true });
|
|
1912
|
+
}
|
|
1913
|
+
});
|
|
1914
|
+
|
|
1870
1915
|
it("prefers repository project-memory.json during SessionStart while preserving legacy wiki guidance", async () => {
|
|
1871
1916
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-session-root-memory-legacy-wiki-"));
|
|
1872
1917
|
try {
|
|
@@ -13932,6 +13977,136 @@ exit 0
|
|
|
13932
13977
|
}
|
|
13933
13978
|
});
|
|
13934
13979
|
|
|
13980
|
+
it("blocks implementation writes when Autopilot ralplan is visible only in skill-active phase", async () => {
|
|
13981
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-autopilot-skill-ralplan-pretool-block-"));
|
|
13982
|
+
try {
|
|
13983
|
+
const stateDir = join(cwd, ".omx", "state");
|
|
13984
|
+
const sessionId = "sess-autopilot-skill-ralplan-pretool-block";
|
|
13985
|
+
await mkdir(join(stateDir, "sessions", sessionId), { recursive: true });
|
|
13986
|
+
await writeJson(join(stateDir, "session.json"), { session_id: sessionId });
|
|
13987
|
+
await writeJson(join(stateDir, "sessions", sessionId, "skill-active-state.json"), {
|
|
13988
|
+
active: true,
|
|
13989
|
+
skill: "autopilot",
|
|
13990
|
+
phase: "autopilot:ralplan",
|
|
13991
|
+
session_id: sessionId,
|
|
13992
|
+
active_skills: [{ skill: "autopilot", phase: "autopilot:ralplan", active: true, session_id: sessionId }],
|
|
13993
|
+
});
|
|
13994
|
+
await writeJson(join(stateDir, "sessions", sessionId, "autopilot-state.json"), {
|
|
13995
|
+
active: true,
|
|
13996
|
+
mode: "autopilot",
|
|
13997
|
+
current_phase: "planning",
|
|
13998
|
+
session_id: sessionId,
|
|
13999
|
+
state: {
|
|
14000
|
+
handoff_artifacts: {
|
|
14001
|
+
ralplan_consensus_gate: { required: true, complete: false },
|
|
14002
|
+
},
|
|
14003
|
+
},
|
|
14004
|
+
});
|
|
14005
|
+
|
|
14006
|
+
const result = await dispatchCodexNativeHook(
|
|
14007
|
+
{
|
|
14008
|
+
hook_event_name: "PreToolUse",
|
|
14009
|
+
cwd,
|
|
14010
|
+
session_id: sessionId,
|
|
14011
|
+
thread_id: "thread-autopilot-skill-ralplan-pretool-block",
|
|
14012
|
+
tool_name: "Edit",
|
|
14013
|
+
tool_input: { file_path: "src/runtime.ts" },
|
|
14014
|
+
},
|
|
14015
|
+
{ cwd },
|
|
14016
|
+
);
|
|
14017
|
+
|
|
14018
|
+
assert.equal(result.omxEventName, "pre-tool-use");
|
|
14019
|
+
assert.equal(result.outputJson?.decision, "block");
|
|
14020
|
+
assert.match(String(result.outputJson?.reason ?? ""), /Autopilot planning is active .*implementation\/write tools are blocked/i);
|
|
14021
|
+
} finally {
|
|
14022
|
+
await rm(cwd, { recursive: true, force: true });
|
|
14023
|
+
}
|
|
14024
|
+
});
|
|
14025
|
+
|
|
14026
|
+
it("ignores stale Autopilot ralplan skill mirrors after detail state leaves planning", async () => {
|
|
14027
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-autopilot-stale-ralplan-mirror-"));
|
|
14028
|
+
try {
|
|
14029
|
+
const stateDir = join(cwd, ".omx", "state");
|
|
14030
|
+
const sessionId = "sess-autopilot-stale-ralplan-mirror";
|
|
14031
|
+
await mkdir(join(stateDir, "sessions", sessionId), { recursive: true });
|
|
14032
|
+
await writeJson(join(stateDir, "session.json"), { session_id: sessionId });
|
|
14033
|
+
await writeJson(join(stateDir, "sessions", sessionId, "skill-active-state.json"), {
|
|
14034
|
+
active: true,
|
|
14035
|
+
skill: "autopilot",
|
|
14036
|
+
phase: "autopilot:ralplan",
|
|
14037
|
+
session_id: sessionId,
|
|
14038
|
+
active_skills: [{ skill: "autopilot", phase: "autopilot:ralplan", active: true, session_id: sessionId }],
|
|
14039
|
+
});
|
|
14040
|
+
|
|
14041
|
+
for (const phase of ["ultragoal", "code-review", "completing", "complete"]) {
|
|
14042
|
+
await writeJson(join(stateDir, "sessions", sessionId, "autopilot-state.json"), {
|
|
14043
|
+
active: true,
|
|
14044
|
+
mode: "autopilot",
|
|
14045
|
+
current_phase: phase,
|
|
14046
|
+
session_id: sessionId,
|
|
14047
|
+
});
|
|
14048
|
+
|
|
14049
|
+
const result = await dispatchCodexNativeHook(
|
|
14050
|
+
{
|
|
14051
|
+
hook_event_name: "PreToolUse",
|
|
14052
|
+
cwd,
|
|
14053
|
+
session_id: sessionId,
|
|
14054
|
+
thread_id: "thread-autopilot-stale-ralplan-mirror",
|
|
14055
|
+
tool_name: "Edit",
|
|
14056
|
+
tool_input: { file_path: "src/runtime.ts" },
|
|
14057
|
+
},
|
|
14058
|
+
{ cwd },
|
|
14059
|
+
);
|
|
14060
|
+
|
|
14061
|
+
assert.equal(result.omxEventName, "pre-tool-use");
|
|
14062
|
+
assert.equal(result.outputJson, null, `stale skill-active ralplan mirror must not block when Autopilot detail phase is ${phase}`);
|
|
14063
|
+
}
|
|
14064
|
+
} finally {
|
|
14065
|
+
await rm(cwd, { recursive: true, force: true });
|
|
14066
|
+
}
|
|
14067
|
+
});
|
|
14068
|
+
|
|
14069
|
+
it("allows explicit blank Autopilot detail phase to use a ralplan skill mirror", async () => {
|
|
14070
|
+
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-autopilot-blank-phase-mirror-"));
|
|
14071
|
+
try {
|
|
14072
|
+
const stateDir = join(cwd, ".omx", "state");
|
|
14073
|
+
const sessionId = "sess-autopilot-blank-phase-mirror";
|
|
14074
|
+
await mkdir(join(stateDir, "sessions", sessionId), { recursive: true });
|
|
14075
|
+
await writeJson(join(stateDir, "session.json"), { session_id: sessionId });
|
|
14076
|
+
await writeJson(join(stateDir, "sessions", sessionId, "skill-active-state.json"), {
|
|
14077
|
+
active: true,
|
|
14078
|
+
skill: "autopilot",
|
|
14079
|
+
phase: "autopilot:ralplan",
|
|
14080
|
+
session_id: sessionId,
|
|
14081
|
+
active_skills: [{ skill: "autopilot", phase: "autopilot:ralplan", active: true, session_id: sessionId }],
|
|
14082
|
+
});
|
|
14083
|
+
await writeJson(join(stateDir, "sessions", sessionId, "autopilot-state.json"), {
|
|
14084
|
+
active: true,
|
|
14085
|
+
mode: "autopilot",
|
|
14086
|
+
current_phase: "",
|
|
14087
|
+
session_id: sessionId,
|
|
14088
|
+
});
|
|
14089
|
+
|
|
14090
|
+
const result = await dispatchCodexNativeHook(
|
|
14091
|
+
{
|
|
14092
|
+
hook_event_name: "PreToolUse",
|
|
14093
|
+
cwd,
|
|
14094
|
+
session_id: sessionId,
|
|
14095
|
+
thread_id: "thread-autopilot-blank-phase-mirror",
|
|
14096
|
+
tool_name: "Edit",
|
|
14097
|
+
tool_input: { file_path: "src/runtime.ts" },
|
|
14098
|
+
},
|
|
14099
|
+
{ cwd },
|
|
14100
|
+
);
|
|
14101
|
+
|
|
14102
|
+
assert.equal(result.omxEventName, "pre-tool-use");
|
|
14103
|
+
assert.equal(result.outputJson?.decision, "block");
|
|
14104
|
+
assert.match(String(result.outputJson?.reason ?? ""), /Autopilot planning is active .*implementation\/write tools are blocked/i);
|
|
14105
|
+
} finally {
|
|
14106
|
+
await rm(cwd, { recursive: true, force: true });
|
|
14107
|
+
}
|
|
14108
|
+
});
|
|
14109
|
+
|
|
13935
14110
|
it("does not block implementation writes from Autopilot ralplan detail state without canonical skill state", async () => {
|
|
13936
14111
|
const cwd = await mkdtemp(join(tmpdir(), "omx-native-hook-autopilot-ralplan-no-canonical-"));
|
|
13937
14112
|
try {
|
|
@@ -83,6 +83,7 @@ import {
|
|
|
83
83
|
onSessionStart as buildWikiSessionStartContext,
|
|
84
84
|
} from "../wiki/lifecycle.js";
|
|
85
85
|
import { readAutoresearchCompletionStatus, readAutoresearchModeStateForActiveDecision } from "../autoresearch/skill-validation.js";
|
|
86
|
+
import { normalizeAutopilotPhase } from "../autopilot/fsm.js";
|
|
86
87
|
import { readRunState } from "../runtime/run-state.js";
|
|
87
88
|
import { evaluateRalphCompletionAuditEvidence, isRalphCompletePhase } from "../ralph/completion-audit.js";
|
|
88
89
|
import { getRunContinuationSnapshot, shouldContinueRun } from "../runtime/run-loop.js";
|
|
@@ -2592,12 +2593,12 @@ function isActiveRalplanPhase(state: Record<string, unknown> | null): boolean {
|
|
|
2592
2593
|
return true;
|
|
2593
2594
|
}
|
|
2594
2595
|
|
|
2595
|
-
function
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
return phase === "
|
|
2596
|
+
function isAutopilotRalplanLikePhase(phase: string): boolean {
|
|
2597
|
+
return normalizeAutopilotPhase(phase) === "ralplan";
|
|
2598
|
+
}
|
|
2599
|
+
|
|
2600
|
+
function canAutopilotSkillMirrorSupplyRalplanPhase(phase: string): boolean {
|
|
2601
|
+
return phase === "" || normalizeAutopilotPhase(phase) === "ralplan";
|
|
2601
2602
|
}
|
|
2602
2603
|
|
|
2603
2604
|
function hasExplicitExecutionHandoffSkill(
|
|
@@ -2733,7 +2734,9 @@ async function readActiveRalplanStateForPreToolUse(
|
|
|
2733
2734
|
const autopilotState = sessionId
|
|
2734
2735
|
? await readStopSessionPinnedState("autopilot-state.json", cwd, sessionId, stateDir)
|
|
2735
2736
|
: await readJsonIfExists(join(stateDir, "autopilot-state.json"));
|
|
2736
|
-
if (!
|
|
2737
|
+
if (!autopilotState || autopilotState.active !== true) return null;
|
|
2738
|
+
const autopilotMode = safeString(autopilotState.mode).trim();
|
|
2739
|
+
if (autopilotMode && autopilotMode !== "autopilot") return null;
|
|
2737
2740
|
if (!modeStateMatchesSkillStopContext(autopilotState, cwd, sessionId)) return null;
|
|
2738
2741
|
const terminalAutopilotRunState = await readCanonicalTerminalRunStateForStop(cwd, sessionId, "autopilot");
|
|
2739
2742
|
if (terminalAutopilotRunState) return null;
|
|
@@ -2742,6 +2745,15 @@ async function readActiveRalplanStateForPreToolUse(
|
|
|
2742
2745
|
entry.skill === "autopilot"
|
|
2743
2746
|
&& matchesSkillStopContext(entry, canonicalState, sessionId, threadId)
|
|
2744
2747
|
));
|
|
2748
|
+
if (!hasActiveAutopilotSkill) return null;
|
|
2749
|
+
const autopilotStatePhase = safeString(autopilotState.current_phase ?? autopilotState.currentPhase).trim().toLowerCase();
|
|
2750
|
+
if (!canAutopilotSkillMirrorSupplyRalplanPhase(autopilotStatePhase)) return null;
|
|
2751
|
+
const hasRalplanScopedAutopilotSkill = listActiveSkills(canonicalState).some((entry) => (
|
|
2752
|
+
entry.skill === "autopilot"
|
|
2753
|
+
&& isAutopilotRalplanLikePhase(safeString(entry.phase).trim().toLowerCase())
|
|
2754
|
+
&& matchesSkillStopContext(entry, canonicalState, sessionId, threadId)
|
|
2755
|
+
));
|
|
2756
|
+
if (!isAutopilotRalplanLikePhase(autopilotStatePhase) && !hasRalplanScopedAutopilotSkill) return null;
|
|
2745
2757
|
return hasActiveAutopilotSkill ? autopilotState : null;
|
|
2746
2758
|
}
|
|
2747
2759
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, rmSync } from 'node:fs';
|
|
3
|
+
import { delimiter, join } from 'node:path';
|
|
4
|
+
import { spawnSync } from 'node:child_process';
|
|
5
|
+
|
|
6
|
+
const requiredDistFiles = [
|
|
7
|
+
join(process.cwd(), 'dist', 'cli', 'omx.js'),
|
|
8
|
+
join(process.cwd(), 'dist', 'scripts', 'postinstall.js'),
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
if (requiredDistFiles.every((file) => existsSync(file))) {
|
|
12
|
+
process.exit(0);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const npmBin = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
16
|
+
const tscBin = process.platform === 'win32'
|
|
17
|
+
? join(process.cwd(), 'node_modules', '.bin', 'tsc.cmd')
|
|
18
|
+
: join(process.cwd(), 'node_modules', '.bin', 'tsc');
|
|
19
|
+
const nodeModulesDir = join(process.cwd(), 'node_modules');
|
|
20
|
+
|
|
21
|
+
function runNpm(args, env = process.env) {
|
|
22
|
+
return spawnSync(npmBin, args, {
|
|
23
|
+
cwd: process.cwd(),
|
|
24
|
+
stdio: process.env.npm_config_json === 'true' ? ['inherit', 'ignore', 'inherit'] : 'inherit',
|
|
25
|
+
env,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function exitOnFailure(result, label) {
|
|
30
|
+
if (result.error) {
|
|
31
|
+
console.error(`omx prepare: failed to launch ${label}: ${result.error.message}`);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (result.status !== 0) {
|
|
36
|
+
process.exit(typeof result.status === 'number' ? result.status : 1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let shouldCleanupBootstrappedDependencies = false;
|
|
41
|
+
|
|
42
|
+
if (!existsSync(tscBin)) {
|
|
43
|
+
const hadNodeModules = existsSync(nodeModulesDir);
|
|
44
|
+
const installResult = runNpm(
|
|
45
|
+
[
|
|
46
|
+
'install',
|
|
47
|
+
'--global=false',
|
|
48
|
+
'--location=project',
|
|
49
|
+
'--include=dev',
|
|
50
|
+
'--ignore-scripts',
|
|
51
|
+
'--no-audit',
|
|
52
|
+
'--no-progress',
|
|
53
|
+
],
|
|
54
|
+
{
|
|
55
|
+
...process.env,
|
|
56
|
+
npm_config_global: 'false',
|
|
57
|
+
npm_config_location: 'project',
|
|
58
|
+
},
|
|
59
|
+
);
|
|
60
|
+
exitOnFailure(installResult, 'npm dependency bootstrap');
|
|
61
|
+
shouldCleanupBootstrappedDependencies = !hadNodeModules;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const pathWithLocalBins = [
|
|
65
|
+
join(process.cwd(), 'node_modules', '.bin'),
|
|
66
|
+
process.env.PATH ?? '',
|
|
67
|
+
].filter(Boolean).join(delimiter);
|
|
68
|
+
|
|
69
|
+
const buildResult = spawnSync(npmBin, ['run', 'build'], {
|
|
70
|
+
cwd: process.cwd(),
|
|
71
|
+
stdio: process.env.npm_config_json === 'true' ? ['inherit', 'ignore', 'inherit'] : 'inherit',
|
|
72
|
+
env: { ...process.env, PATH: pathWithLocalBins },
|
|
73
|
+
});
|
|
74
|
+
exitOnFailure(buildResult, 'npm build');
|
|
75
|
+
|
|
76
|
+
if (shouldCleanupBootstrappedDependencies) {
|
|
77
|
+
try {
|
|
78
|
+
rmSync(nodeModulesDir, { recursive: true, force: true });
|
|
79
|
+
} catch (error) {
|
|
80
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
81
|
+
console.warn(`[omx:prepare] Warning: could not remove bootstrapped node_modules: ${message}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
|
-
import { dirname, join } from "node:path";
|
|
3
|
-
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
|
-
|
|
5
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
-
const __dirname = dirname(__filename);
|
|
7
|
-
const distScriptPath = join(__dirname, "..", "..", "dist", "scripts", "postinstall.js");
|
|
8
|
-
|
|
9
|
-
if (!existsSync(distScriptPath)) {
|
|
10
|
-
process.exit(0);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const moduleUrl = pathToFileURL(distScriptPath).href;
|
|
14
|
-
try {
|
|
15
|
-
const postinstallModule = await import(moduleUrl);
|
|
16
|
-
if (typeof postinstallModule.main === "function") {
|
|
17
|
-
await postinstallModule.main();
|
|
18
|
-
}
|
|
19
|
-
} catch (error) {
|
|
20
|
-
console.warn(
|
|
21
|
-
`[omx] Postinstall bootstrap skipped after a non-fatal error: ${error instanceof Error ? error.message : String(error)}`,
|
|
22
|
-
);
|
|
23
|
-
}
|