fix: pin codex resume sandbox override

This commit is contained in:
Peter Steinberger
2026-04-16 17:30:02 +01:00
parent d842ec4179
commit 1183832d4f
6 changed files with 48 additions and 7 deletions

View File

@@ -43,7 +43,7 @@ Docs: https://docs.openclaw.ai
- Agents/replay: re-run tool/result pairing after strict replay tool-call ID sanitization on outbound requests so Anthropic-compatible providers like MiniMax no longer receive malformed orphan tool-result IDs such as `...toolresult1` during compaction and retry flows. (#67620) Thanks @stainlu.
- Gateway/startup: fix spurious SIGUSR1 restart loop on Linux/systemd when plugin auto-enable is the only startup config write; the config hash guard was not captured for that write path, causing chokidar to treat each boot write as an external change and trigger a reload → restart cycle that corrupts manifest.db after repeated cycles. Fixes #67436. (#67557) thanks @openperf
- Codex/harness: auto-enable the Codex plugin when `codex` is selected as an embedded agent harness runtime, including forced default, per-agent, and `OPENCLAW_AGENT_RUNTIME` paths. (#67474) Thanks @duqaXxX.
- OpenAI Codex/CLI: keep resumed `codex exec resume` runs on the safe non-interactive path without reintroducing the removed dangerous bypass flag by passing the supported `--skip-git-repo-check` resume arg that real Codex CLI requires outside trusted git directories. (#67666) Thanks @plgonzalezrx8.
- OpenAI Codex/CLI: keep resumed `codex exec resume` runs on the safe non-interactive path without reintroducing the removed dangerous bypass flag by passing the supported `--skip-git-repo-check` resume arg plus Codex's native `sandbox_mode="workspace-write"` config override. (#67666) Thanks @plgonzalezrx8.
- Codex/app-server: parse Desktop-originated app-server user agents such as `Codex Desktop/0.118.0`, keeping the version gate working when the Codex CLI inherits a multi-word originator. (#64666) Thanks @cyrusaf.
- Cron/announce delivery: keep isolated announce `NO_REPLY` stripping case-insensitive across direct and text delivery, preserve structured media-only sends when a caption strips silent, and derive main-session awareness from the cleaned payloads so silent captions no longer leak stale `NO_REPLY` text. (#65016) Thanks @BKF-Gitty.
- Sessions/Codex: skip redundant `delivery-mirror` transcript appends only when the latest assistant message has the same visible text, preventing duplicate visible replies on Codex-backed turns without suppressing repeated answers across turns. (#67185) Thanks @andyylin.

View File

@@ -221,7 +221,7 @@ The bundled OpenAI plugin also registers a default for `codex-cli`:
- `command: "codex"`
- `args: ["exec","--json","--color","never","--sandbox","workspace-write","--skip-git-repo-check"]`
- `resumeArgs: ["exec","resume","{sessionId}","--skip-git-repo-check"]`
- `resumeArgs: ["exec","resume","{sessionId}","-c","sandbox_mode=\"workspace-write\"","--skip-git-repo-check"]`
- `output: "jsonl"`
- `resumeOutput: "text"`
- `modelArg: "--model"`

View File

@@ -31,7 +31,14 @@ export function buildOpenAICodexCliBackend(): CliBackendPlugin {
"workspace-write",
"--skip-git-repo-check",
],
resumeArgs: ["exec", "resume", "{sessionId}", "--skip-git-repo-check"],
resumeArgs: [
"exec",
"resume",
"{sessionId}",
"-c",
'sandbox_mode="workspace-write"',
"--skip-git-repo-check",
],
output: "jsonl",
resumeOutput: "text",
input: "arg",

View File

@@ -244,7 +244,14 @@ beforeEach(() => {
"workspace-write",
"--skip-git-repo-check",
],
resumeArgs: ["exec", "resume", "{sessionId}", "--skip-git-repo-check"],
resumeArgs: [
"exec",
"resume",
"{sessionId}",
"-c",
'sandbox_mode="workspace-write"',
"--skip-git-repo-check",
],
systemPromptFileConfigArg: "-c",
systemPromptFileConfigKey: "model_instructions_file",
systemPromptWhen: "first",
@@ -309,7 +316,7 @@ beforeEach(() => {
});
describe("resolveCliBackendConfig reliability merge", () => {
it("defaults codex-cli fresh sandboxing and resume trust bypass for non-git runs", () => {
it("defaults codex-cli fresh sandboxing and config-pinned resume sandboxing", () => {
const resolved = resolveCliBackendConfig("codex-cli");
expect(resolved).not.toBeNull();
@@ -326,6 +333,8 @@ describe("resolveCliBackendConfig reliability merge", () => {
"exec",
"resume",
"{sessionId}",
"-c",
'sandbox_mode="workspace-write"',
"--skip-git-repo-check",
]);
});

View File

@@ -120,7 +120,14 @@ function buildOpenAICodexCliBackendFixture(): CliBackendPlugin {
"workspace-write",
"--skip-git-repo-check",
],
resumeArgs: ["exec", "resume", "{sessionId}", "--skip-git-repo-check"],
resumeArgs: [
"exec",
"resume",
"{sessionId}",
"-c",
'sandbox_mode="workspace-write"',
"--skip-git-repo-check",
],
output: "jsonl",
resumeOutput: "text",
input: "arg",

View File

@@ -33,6 +33,12 @@ type BootstrapContext = {
bootstrapFiles: WorkspaceBootstrapFile[];
contextFiles: EmbeddedContextFile[];
};
function normalizeMockProviderId(providerId?: string): string {
const normalized = normalizeLowercaseStringOrEmpty(providerId);
return normalized === "z.ai" || normalized === "z-ai" ? "zai" : normalized;
}
type SessionManagerMocks = {
getLeafEntry: UnknownMock;
branch: UnknownMock;
@@ -411,7 +417,19 @@ vi.mock("../../../image-generation/runtime.js", () => ({
}));
vi.mock("../../model-selection.js", () => ({
normalizeProviderId: (providerId?: string) => normalizeLowercaseStringOrEmpty(providerId),
findNormalizedProviderValue: <T>(entries: Record<string, T> | undefined, provider: string) => {
if (!entries) {
return undefined;
}
const providerKey = normalizeMockProviderId(provider);
for (const [key, value] of Object.entries(entries)) {
if (normalizeMockProviderId(key) === providerKey) {
return value;
}
}
return undefined;
},
normalizeProviderId: normalizeMockProviderId,
resolveDefaultModelForAgent: () => ({ provider: "openai", model: "gpt-test" }),
}));