metheus-governance-mcp-cli 0.2.269 → 0.2.270
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.
|
@@ -212,6 +212,67 @@ function readOutputFile(filePath) {
|
|
|
212
212
|
return fs.readFileSync(filePath, "utf8");
|
|
213
213
|
}
|
|
214
214
|
|
|
215
|
+
export function looksLikeCodexCliSessionTranscript(rawText = "") {
|
|
216
|
+
const text = String(rawText || "").trim();
|
|
217
|
+
if (!text) {
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
return /OpenAI Codex v|session id:|^workdir:|^model:|^provider:|^approval:|^sandbox:|^reasoning effort:|^--------|^user$|^codex$|mcp:.*\b(starting|ready)\b/i.test(text);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function summarizeCodexCliFailure({
|
|
224
|
+
status = 0,
|
|
225
|
+
stdoutText = "",
|
|
226
|
+
stderrText = "",
|
|
227
|
+
spawnError = null,
|
|
228
|
+
}) {
|
|
229
|
+
const genericMessage = status
|
|
230
|
+
? `Codex CLI exited before returning a final reply (status ${status})`
|
|
231
|
+
: "Codex CLI exited before returning a final reply";
|
|
232
|
+
if (spawnError) {
|
|
233
|
+
const spawnMessage = String(spawnError?.message || spawnError || "").trim();
|
|
234
|
+
return spawnMessage
|
|
235
|
+
? `${genericMessage}: ${spawnMessage}`
|
|
236
|
+
: genericMessage;
|
|
237
|
+
}
|
|
238
|
+
const candidateLines = `${String(stderrText || "")}\n${String(stdoutText || "")}`
|
|
239
|
+
.split(/\r?\n/)
|
|
240
|
+
.map((line) => String(line || "").trim())
|
|
241
|
+
.filter(Boolean)
|
|
242
|
+
.filter((line) => !looksLikeCodexCliSessionTranscript(line))
|
|
243
|
+
.filter((line) => /(error|failed|timeout|timed out|denied|missing|unavailable|not found|capacity)/i.test(line))
|
|
244
|
+
.slice(0, 2);
|
|
245
|
+
return candidateLines.length
|
|
246
|
+
? `${genericMessage}: ${candidateLines.join(" | ")}`
|
|
247
|
+
: genericMessage;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export function resolveCodexRawTextProcessResult({
|
|
251
|
+
outputText = "",
|
|
252
|
+
stdoutText = "",
|
|
253
|
+
stderrText = "",
|
|
254
|
+
status = 0,
|
|
255
|
+
spawnError = null,
|
|
256
|
+
}) {
|
|
257
|
+
const normalizedOutputText = String(outputText || "").trim();
|
|
258
|
+
if (normalizedOutputText && !looksLikeCodexCliSessionTranscript(normalizedOutputText)) {
|
|
259
|
+
return normalizedOutputText;
|
|
260
|
+
}
|
|
261
|
+
const normalizedStdoutText = String(stdoutText || "").trim();
|
|
262
|
+
if (normalizedStdoutText && !looksLikeCodexCliSessionTranscript(normalizedStdoutText)) {
|
|
263
|
+
return normalizedStdoutText;
|
|
264
|
+
}
|
|
265
|
+
if (spawnError || status !== 0) {
|
|
266
|
+
throw new Error(summarizeCodexCliFailure({
|
|
267
|
+
status,
|
|
268
|
+
stdoutText: normalizedStdoutText,
|
|
269
|
+
stderrText,
|
|
270
|
+
spawnError,
|
|
271
|
+
}));
|
|
272
|
+
}
|
|
273
|
+
throw new Error("Codex CLI did not return a usable final reply");
|
|
274
|
+
}
|
|
275
|
+
|
|
215
276
|
function tryParseEmbeddedJsonObject(text) {
|
|
216
277
|
const raw = String(text || "").trim();
|
|
217
278
|
if (!raw) return null;
|
|
@@ -686,13 +747,13 @@ function runCodexRawText({ promptText, workspaceDir, model, permissionMode, reas
|
|
|
686
747
|
maxBuffer: 8 * 1024 * 1024,
|
|
687
748
|
},
|
|
688
749
|
);
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
750
|
+
return resolveCodexRawTextProcessResult({
|
|
751
|
+
outputText: readOutputFile(outputPath),
|
|
752
|
+
stdoutText: String(result.stdout || ""),
|
|
753
|
+
stderrText: String(result.stderr || ""),
|
|
754
|
+
status: Number.isInteger(result.status) ? result.status : 0,
|
|
755
|
+
spawnError: result.error || null,
|
|
756
|
+
});
|
|
696
757
|
} finally {
|
|
697
758
|
if (fs.existsSync(outputPath)) {
|
|
698
759
|
fs.rmSync(outputPath, { force: true });
|
|
@@ -85,6 +85,9 @@ import {
|
|
|
85
85
|
import {
|
|
86
86
|
finalizeRunnerRequestRootReferenceRecorderState,
|
|
87
87
|
} from "./runner-recorder-request-root-reference-finalization-handoff.mjs";
|
|
88
|
+
import {
|
|
89
|
+
resolveCodexRawTextProcessResult,
|
|
90
|
+
} from "./local-ai-adapters.mjs";
|
|
88
91
|
import {
|
|
89
92
|
buildRunnerInheritedRootReferenceRecorderResult,
|
|
90
93
|
buildRunnerRootThreadRecorderFailure,
|
|
@@ -18701,6 +18704,48 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
18701
18704
|
push("runner_selected_record_terminal_outcome_stays_within_module_4_boundary", false, String(err?.message || err));
|
|
18702
18705
|
}
|
|
18703
18706
|
|
|
18707
|
+
try {
|
|
18708
|
+
const replyText = resolveCodexRawTextProcessResult({
|
|
18709
|
+
outputText: "{\"reply\":\"하이\"}",
|
|
18710
|
+
stdoutText: "",
|
|
18711
|
+
stderrText: "OpenAI Codex v0.114.0\nsession id: test-session\nmcp: metheus ready",
|
|
18712
|
+
status: 1,
|
|
18713
|
+
spawnError: null,
|
|
18714
|
+
});
|
|
18715
|
+
push(
|
|
18716
|
+
"codex_nonzero_exit_uses_final_output_file_when_available",
|
|
18717
|
+
String(replyText || "").trim() === "{\"reply\":\"하이\"}",
|
|
18718
|
+
`reply=${String(replyText || "(none)")}`,
|
|
18719
|
+
);
|
|
18720
|
+
} catch (err) {
|
|
18721
|
+
push("codex_nonzero_exit_uses_final_output_file_when_available", false, String(err?.message || err));
|
|
18722
|
+
}
|
|
18723
|
+
|
|
18724
|
+
try {
|
|
18725
|
+
let errorMessage = "";
|
|
18726
|
+
try {
|
|
18727
|
+
resolveCodexRawTextProcessResult({
|
|
18728
|
+
outputText: "",
|
|
18729
|
+
stdoutText: "",
|
|
18730
|
+
stderrText: "OpenAI Codex v0.114.0\nworkdir: C:\\LUSH KOREA CLI\nsession id: test-session\nmcp: metheus starting\nmcp: metheus ready",
|
|
18731
|
+
status: 1,
|
|
18732
|
+
spawnError: null,
|
|
18733
|
+
});
|
|
18734
|
+
} catch (err) {
|
|
18735
|
+
errorMessage = String(err?.message || err);
|
|
18736
|
+
}
|
|
18737
|
+
push(
|
|
18738
|
+
"codex_failure_summary_does_not_leak_session_transcript",
|
|
18739
|
+
/Codex CLI exited before returning a final reply/i.test(errorMessage)
|
|
18740
|
+
&& !/OpenAI Codex v/i.test(errorMessage)
|
|
18741
|
+
&& !/session id:/i.test(errorMessage)
|
|
18742
|
+
&& !/mcp:/i.test(errorMessage),
|
|
18743
|
+
errorMessage || "(no error message)",
|
|
18744
|
+
);
|
|
18745
|
+
} catch (err) {
|
|
18746
|
+
push("codex_failure_summary_does_not_leak_session_transcript", false, String(err?.message || err));
|
|
18747
|
+
}
|
|
18748
|
+
|
|
18704
18749
|
try {
|
|
18705
18750
|
const prepared = await prepareRunnerSelectedRecordContractContext({
|
|
18706
18751
|
selectedRecord: {
|