mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 09:10:45 +00:00
Harden Codex harness control surfaces (#77459)
* fix(scripts): find codex protocol source from worktrees * fix(test): keep codex harness docker caches writable * fix(test): relax live codex cache mount permissions * test(codex): add live docker harness debug output * fix(test): detect numeric ci env in codex docker harness * fix(codex): skip duplicate agent-command telemetry * fix(tooling): skip sparse-missing oxlint tsconfig * fix(tooling): route changed checks through testbox * fix(qa): keep coverage json source-clean * fix(test): preflight codex docker auth * fix(codex): validate bind option values * fix(codex): parse quoted command arguments * fix(codex): reject extra control args * fix(codex): use content for blank bound prompts * fix(codex): decode local image file urls * fix(codex): treat local media urls as images * fix(codex): keep windows media paths local * fix(codex): reject malformed diagnostics confirmations * fix(codex): reject malformed resume commands * fix(codex): reject malformed thread actions * fix(codex): reject malformed turn controls * fix(codex): reject malformed model controls * fix(codex): resolve empty user input prompts * fix(codex): enforce user input options * fix(codex): reject ambiguous computer-use actions * fix(codex): ignore stale bound turn notifications * test(gateway): close task registries in gateway harness * test(gateway): route cleanup through task seams * fix(codex): describe current permission approvals * fix(codex): disclose command approval amendments * fix(codex): preserve approval detail under truncation * fix(codex): propagate dynamic tool failures * test(codex): align dynamic tool block contract * fix(codex): reject extra read-only command operands * fix(codex): escape command readout fields * fix(codex): escape status probe errors * fix(codex): narrow formatted thread details * fix(codex): escape successful status summaries * fix(codex): escape bound control replies * fix(codex): escape user input prompts * fix(codex): escape control failure replies * fix(codex): escape approval prompt text * test(codex): narrow escaped reply assertions * test(codex): complete strict reply fixtures * test(codex): preserve account fixture literals * test(codex): align status probe fixtures * fix(codex): satisfy sanitizer regex lint * fix(codex): harden command readouts * fix(codex): harden bound image inputs * fix(codex): sanitize command failure replies * test(codex): complete rate limit fixture * test(tooling): isolate postinstall compile cache fixture * fix(codex): keep app-server event ownership explicit --------- Co-authored-by: pashpashpash <nik@vault77.ai>
This commit is contained in:
74
scripts/lib/codex-app-server-protocol-source.ts
Normal file
74
scripts/lib/codex-app-server-protocol-source.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
|
||||
const PROTOCOL_SCHEMA_RELATIVE_PATH = "codex-rs/app-server-protocol/schema";
|
||||
|
||||
export async function resolveCodexAppServerProtocolSource(repoRoot: string): Promise<{
|
||||
codexRepo: string;
|
||||
sourceRoot: string;
|
||||
}> {
|
||||
const candidates = await collectCodexRepoCandidates(repoRoot);
|
||||
const checked: string[] = [];
|
||||
|
||||
for (const candidate of candidates) {
|
||||
const codexRepo = path.resolve(candidate);
|
||||
if (checked.includes(codexRepo)) {
|
||||
continue;
|
||||
}
|
||||
checked.push(codexRepo);
|
||||
const sourceRoot = path.join(codexRepo, PROTOCOL_SCHEMA_RELATIVE_PATH);
|
||||
if (await isDirectory(path.join(sourceRoot, "typescript"))) {
|
||||
return { codexRepo, sourceRoot };
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
[
|
||||
"Codex app-server protocol schema not found.",
|
||||
"Set OPENCLAW_CODEX_REPO to a checkout of openai/codex, or keep a sibling `codex` checkout next to the primary OpenClaw checkout.",
|
||||
`Checked: ${checked.join(", ") || "<none>"}`,
|
||||
].join("\n"),
|
||||
);
|
||||
}
|
||||
|
||||
async function collectCodexRepoCandidates(repoRoot: string): Promise<string[]> {
|
||||
const candidates = [
|
||||
process.env.OPENCLAW_CODEX_REPO,
|
||||
path.resolve(repoRoot, "../codex"),
|
||||
await resolvePrimaryWorktreeSiblingCodex(repoRoot),
|
||||
];
|
||||
return candidates.filter((candidate): candidate is string => Boolean(candidate));
|
||||
}
|
||||
|
||||
async function resolvePrimaryWorktreeSiblingCodex(repoRoot: string): Promise<string | undefined> {
|
||||
const gitFilePath = path.join(repoRoot, ".git");
|
||||
let gitFile: string;
|
||||
try {
|
||||
gitFile = await fs.readFile(gitFilePath, "utf8");
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const match = /^gitdir:\s*(.+)$/m.exec(gitFile);
|
||||
if (!match) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const gitDir = path.resolve(repoRoot, match[1].trim());
|
||||
const worktreeMarker = `${path.sep}.git${path.sep}worktrees${path.sep}`;
|
||||
const markerIndex = gitDir.indexOf(worktreeMarker);
|
||||
if (markerIndex < 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const primaryWorktreeRoot = gitDir.slice(0, markerIndex);
|
||||
return path.join(path.dirname(primaryWorktreeRoot), "codex");
|
||||
}
|
||||
|
||||
async function isDirectory(candidate: string): Promise<boolean> {
|
||||
try {
|
||||
return (await fs.stat(candidate)).isDirectory();
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user