mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-22 10:25:20 -06:00
fix(codex): keep large AGENTS.md instructions visible (#125966)
* fix(codex): raise native project doc budget Default OpenClaw Codex threads to a bounded 128 KiB aggregate project-document budget so large AGENTS.md chains remain visible. Preserve explicit ordinary-thread overrides and keep restricted or lightweight turns at zero. * test(codex): refresh project doc config expectations
This commit is contained in:
committed by
GitHub
parent
d1f58c4be4
commit
d5aff660a2
@@ -254,6 +254,18 @@ Changing auth order does not make a custom, Completions, HTTP, or
|
||||
request-overridden route Codex-compatible. Valid model-scoped Fast-mode and
|
||||
cutoff controls are runtime controls, not request overrides.
|
||||
|
||||
### Project instructions
|
||||
|
||||
Codex loads `AGENTS.md` files through native project-document discovery. For
|
||||
normal app-server threads, OpenClaw raises Codex's aggregate root-to-working-
|
||||
directory budget from the upstream 32 KiB default to a bounded 128 KiB so later
|
||||
scoped instructions are not silently clipped. Lightweight and restricted turns
|
||||
set the native project-document budget to zero instead.
|
||||
|
||||
This byte budget is separate from the character-based workspace bootstrap
|
||||
limits configured through `agents.defaults.bootstrapMaxChars` and
|
||||
`agents.defaults.bootstrapTotalMaxChars`.
|
||||
|
||||
### Compaction
|
||||
|
||||
Do not set `compaction.model` or `compaction.provider` on Codex-backed
|
||||
|
||||
@@ -330,6 +330,7 @@ describe("codex media understanding provider", () => {
|
||||
"features.multi_agent_v2": false,
|
||||
"features.plugins": false,
|
||||
"features.standalone_web_search": false,
|
||||
project_doc_max_bytes: 131_072,
|
||||
"tools.update_plan.enabled": false,
|
||||
web_search: "disabled",
|
||||
},
|
||||
@@ -676,6 +677,7 @@ describe("codex media understanding provider", () => {
|
||||
"features.multi_agent_v2": false,
|
||||
"features.plugins": false,
|
||||
"features.standalone_web_search": false,
|
||||
project_doc_max_bytes: 131_072,
|
||||
"tools.update_plan.enabled": false,
|
||||
web_search: "disabled",
|
||||
},
|
||||
|
||||
@@ -367,6 +367,9 @@ describe("runBoundedCodexAppServerTurn settled finalization isolation", () => {
|
||||
isolation: "private-stdio",
|
||||
}),
|
||||
).rejects.toThrow("hosted search turn returned no text");
|
||||
|
||||
const startParams = fake.request.mock.calls.find(([method]) => method === "thread/start")?.[1];
|
||||
expect(startParams).toMatchObject({ config: { project_doc_max_bytes: 131_072 } });
|
||||
});
|
||||
|
||||
it("still fails on a terminal error notification", async () => {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { mergeCodexThreadConfigs } from "./plugin-thread-config.js";
|
||||
import type { JsonObject } from "./protocol.js";
|
||||
|
||||
const CODEX_NATIVE_PROJECT_DOC_MAX_BYTES = 128 * 1024;
|
||||
|
||||
export function buildCodexProjectDocThreadConfig(config?: JsonObject): JsonObject {
|
||||
const defaults: JsonObject = { project_doc_max_bytes: CODEX_NATIVE_PROJECT_DOC_MAX_BYTES };
|
||||
return mergeCodexThreadConfigs(defaults, config) ?? defaults;
|
||||
}
|
||||
@@ -663,6 +663,7 @@ describe("runCodexAppServerSideQuestion", () => {
|
||||
expect(forkParams?.approvalsReviewer).toBe("user");
|
||||
expect(forkParams?.cwd).toBe("/tmp/workspace");
|
||||
expect(forkParams?.config).toEqual({
|
||||
project_doc_max_bytes: 131_072,
|
||||
"features.goals": false,
|
||||
"tools.update_plan.enabled": false,
|
||||
"features.code_mode": true,
|
||||
|
||||
@@ -114,6 +114,7 @@ function createParams(sessionFile: string, workspaceDir: string) {
|
||||
}
|
||||
|
||||
const DEFAULT_CODEX_RUNTIME_THREAD_CONFIG = {
|
||||
project_doc_max_bytes: 131_072,
|
||||
"features.goals": false,
|
||||
"tools.update_plan.enabled": false,
|
||||
"features.code_mode": true,
|
||||
|
||||
@@ -360,6 +360,7 @@ describe("Codex ring-zero thread config", () => {
|
||||
dynamicTools: [],
|
||||
hostSystemAgentActive: true,
|
||||
nativeCodeModeEnabled: false,
|
||||
config: { project_doc_max_bytes: 64_000 },
|
||||
});
|
||||
const resume = buildThreadResumeParams(params, {
|
||||
appServer,
|
||||
@@ -367,6 +368,7 @@ describe("Codex ring-zero thread config", () => {
|
||||
hostSystemAgentActive: true,
|
||||
nativeCodeModeEnabled: false,
|
||||
threadId: "thread-1",
|
||||
config: { project_doc_max_bytes: 64_000 },
|
||||
});
|
||||
|
||||
expect(start.environments).toEqual([]);
|
||||
@@ -1434,6 +1436,7 @@ describe("Codex app-server native code mode config", () => {
|
||||
});
|
||||
|
||||
expect(request.config).toEqual({
|
||||
project_doc_max_bytes: 131_072,
|
||||
"features.hooks": true,
|
||||
apps: { _default: { enabled: false } },
|
||||
mcp_servers: {
|
||||
@@ -1588,6 +1591,7 @@ describe("Codex app-server native code mode config", () => {
|
||||
);
|
||||
|
||||
expect(request.config).toEqual({
|
||||
project_doc_max_bytes: 131_072,
|
||||
"features.code_mode": true,
|
||||
"features.code_mode_only": false,
|
||||
"features.goals": false,
|
||||
@@ -1717,6 +1721,7 @@ describe("Codex app-server native code mode config", () => {
|
||||
});
|
||||
|
||||
expect(request.config).toEqual({
|
||||
project_doc_max_bytes: 131_072,
|
||||
"features.code_mode": true,
|
||||
"features.code_mode_only": true,
|
||||
"features.goals": false,
|
||||
@@ -1740,6 +1745,7 @@ describe("Codex app-server native code mode config", () => {
|
||||
});
|
||||
|
||||
expect(request.config).toEqual({
|
||||
project_doc_max_bytes: 131_072,
|
||||
"features.code_mode": true,
|
||||
"features.code_mode_only": true,
|
||||
"features.goals": false,
|
||||
@@ -1799,6 +1805,7 @@ describe("Codex app-server native code mode config", () => {
|
||||
});
|
||||
|
||||
expect(request.config).toEqual({
|
||||
project_doc_max_bytes: 131_072,
|
||||
"features.code_mode": true,
|
||||
"features.code_mode_only": false,
|
||||
"features.goals": false,
|
||||
@@ -1825,6 +1832,7 @@ describe("Codex app-server native code mode config", () => {
|
||||
});
|
||||
|
||||
expect(request.config).toEqual({
|
||||
project_doc_max_bytes: 131_072,
|
||||
"features.code_mode": false,
|
||||
"features.code_mode_only": false,
|
||||
"features.goals": false,
|
||||
@@ -1846,6 +1854,7 @@ describe("Codex app-server native code mode config", () => {
|
||||
});
|
||||
|
||||
expect(request.config).toEqual({
|
||||
project_doc_max_bytes: 131_072,
|
||||
"features.code_mode": false,
|
||||
"features.code_mode_only": false,
|
||||
"features.goals": false,
|
||||
@@ -1887,8 +1896,17 @@ describe("Codex app-server native code mode config", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps native Codex project docs enabled when context is not lightweight", () => {
|
||||
const request = buildThreadResumeParams(
|
||||
it("defaults native Codex project docs to 128 KiB while honoring explicit overrides", () => {
|
||||
const defaultRequest = buildThreadStartParams(
|
||||
createAttemptParams({ provider: "openai", bootstrapContextRunKind: "cron" }),
|
||||
{
|
||||
cwd: "/repo",
|
||||
dynamicTools: [],
|
||||
appServer: createAppServerOptions() as never,
|
||||
developerInstructions: "test instructions",
|
||||
},
|
||||
);
|
||||
const overrideRequest = buildThreadResumeParams(
|
||||
createAttemptParams({ provider: "openai", bootstrapContextRunKind: "cron" }),
|
||||
{
|
||||
threadId: "thread-1",
|
||||
@@ -1900,7 +1918,8 @@ describe("Codex app-server native code mode config", () => {
|
||||
},
|
||||
);
|
||||
|
||||
expect(request.config).toEqual({
|
||||
expect(defaultRequest.config?.project_doc_max_bytes).toBe(131_072);
|
||||
expect(overrideRequest.config).toEqual({
|
||||
project_doc_max_bytes: 64_000,
|
||||
"features.code_mode": true,
|
||||
"features.code_mode_only": false,
|
||||
@@ -2105,6 +2124,7 @@ describe("Codex app-server turn params", () => {
|
||||
approvalPolicy: "on-request",
|
||||
approvalsReviewer: "guardian_subagent",
|
||||
config: {
|
||||
project_doc_max_bytes: 131_072,
|
||||
"features.code_mode": true,
|
||||
"features.code_mode_only": false,
|
||||
"features.goals": false,
|
||||
@@ -3293,6 +3313,7 @@ describe("Codex app-server supervised branch lifecycle", () => {
|
||||
excludeTurns: true,
|
||||
developerInstructions: agentWorkspaceDeveloperInstructions,
|
||||
config: {
|
||||
project_doc_max_bytes: 131_072,
|
||||
allow_login_shell: false,
|
||||
shell_environment_policy: {
|
||||
experimental_use_profile: false,
|
||||
@@ -3312,6 +3333,7 @@ describe("Codex app-server supervised branch lifecycle", () => {
|
||||
dynamicTools,
|
||||
environments: [{ environmentId: "local", cwd: workspaceDir }],
|
||||
config: {
|
||||
project_doc_max_bytes: 131_072,
|
||||
allow_login_shell: false,
|
||||
shell_environment_policy: {
|
||||
experimental_use_profile: false,
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
shouldDisableCodexToolSearchForModel,
|
||||
} from "./dynamic-tool-profile.js";
|
||||
import { mergeCodexThreadConfigs } from "./plugin-thread-config.js";
|
||||
import { buildCodexProjectDocThreadConfig } from "./project-doc-thread-config.js";
|
||||
import {
|
||||
CODEX_OPENCLAW_DIRECT_DYNAMIC_TOOL_NAMESPACE,
|
||||
isJsonObject,
|
||||
@@ -325,6 +326,7 @@ export function buildCodexRuntimeThreadConfig(
|
||||
directOnlyToolNamespaces?: readonly string[];
|
||||
} = {},
|
||||
): JsonObject {
|
||||
const configured = buildCodexProjectDocThreadConfig(config);
|
||||
// Native goal RPCs remain available through app-server, but the Codex goals
|
||||
// feature also starts autonomous turns. Keep it disabled until a run owner exists.
|
||||
const codeModeConfig: JsonObject = {
|
||||
@@ -333,7 +335,7 @@ export function buildCodexRuntimeThreadConfig(
|
||||
};
|
||||
if (options.nativeCodeModeEnabled === false) {
|
||||
const disabledConfig = mergeCodexThreadConfigs(
|
||||
config,
|
||||
configured,
|
||||
CODEX_CODE_MODE_DISABLED_THREAD_CONFIG,
|
||||
CODEX_GOAL_CONTINUATION_DISABLED_THREAD_CONFIG,
|
||||
CODEX_NATIVE_UPDATE_PLAN_DISABLED_THREAD_CONFIG,
|
||||
@@ -350,7 +352,7 @@ export function buildCodexRuntimeThreadConfig(
|
||||
if (options.nativeCodeModeOnlyEnabled === true) {
|
||||
const merged = mergeCodexThreadConfigs(
|
||||
codeModeConfig,
|
||||
config,
|
||||
configured,
|
||||
CODEX_GOAL_CONTINUATION_DISABLED_THREAD_CONFIG,
|
||||
CODEX_NATIVE_UPDATE_PLAN_DISABLED_THREAD_CONFIG,
|
||||
{
|
||||
@@ -366,7 +368,7 @@ export function buildCodexRuntimeThreadConfig(
|
||||
}
|
||||
const merged = mergeCodexThreadConfigs(
|
||||
codeModeConfig,
|
||||
config,
|
||||
configured,
|
||||
CODEX_GOAL_CONTINUATION_DISABLED_THREAD_CONFIG,
|
||||
CODEX_NATIVE_UPDATE_PLAN_DISABLED_THREAD_CONFIG,
|
||||
) ?? {
|
||||
|
||||
@@ -741,6 +741,7 @@ describe("codex conversation binding", () => {
|
||||
expect(requests[0]?.params.model).toBe("gpt-5.4-mini");
|
||||
expect(requests[0]?.params.personality).toBe("none");
|
||||
expect(requests[0]?.params.ephemeral).toBe(true);
|
||||
expect(requests[0]?.params.config).toMatchObject({ project_doc_max_bytes: 131_072 });
|
||||
expect(requests[0]?.params).not.toHaveProperty("modelProvider");
|
||||
await expect(readCodexAppServerBinding(sessionFile)).resolves.toMatchObject({
|
||||
authProfileId: "openai:default",
|
||||
@@ -1020,7 +1021,11 @@ describe("codex conversation binding", () => {
|
||||
expect(requests[1]?.params).toMatchObject({
|
||||
threadId: "thread-native-child",
|
||||
sandbox: "read-only",
|
||||
config: { apps: { _default: { enabled: false } }, "features.apps": false },
|
||||
config: {
|
||||
project_doc_max_bytes: 131_072,
|
||||
apps: { _default: { enabled: false } },
|
||||
"features.apps": false,
|
||||
},
|
||||
});
|
||||
await expect(consumeCodexAppServerLiveThread(client, "thread-native-child")).resolves.toEqual(
|
||||
expect.objectContaining({ release: expect.any(Function) }),
|
||||
|
||||
@@ -59,6 +59,7 @@ import {
|
||||
buildDisabledAppsConfigPatch,
|
||||
mergeCodexThreadConfigs,
|
||||
} from "./app-server/plugin-thread-config.js";
|
||||
import { buildCodexProjectDocThreadConfig } from "./app-server/project-doc-thread-config.js";
|
||||
import { assertCodexThreadStartResponse } from "./app-server/protocol-validators.js";
|
||||
import type {
|
||||
CodexServiceTier,
|
||||
@@ -591,12 +592,10 @@ function codexConversationSandboxOrPermissions(
|
||||
const disabledApps = mergeCodexThreadConfigs(buildDisabledAppsConfigPatch(), {
|
||||
"features.apps": false,
|
||||
})!;
|
||||
if (networkProxy) {
|
||||
return {
|
||||
config: mergeCodexThreadConfigs(networkProxy.configPatch, disabledApps),
|
||||
};
|
||||
}
|
||||
return { sandbox, config: disabledApps };
|
||||
const config = buildCodexProjectDocThreadConfig(
|
||||
mergeCodexThreadConfigs(networkProxy?.configPatch, disabledApps),
|
||||
);
|
||||
return networkProxy ? { config } : { sandbox, config };
|
||||
}
|
||||
|
||||
async function requestNewConversationBindingThread(
|
||||
|
||||
Vendored
+2
@@ -70,6 +70,7 @@
|
||||
"features.code_mode_only": false,
|
||||
"features.goals": false,
|
||||
"features.standalone_web_search": false,
|
||||
"project_doc_max_bytes": 131072,
|
||||
"tools.update_plan.enabled": false,
|
||||
"web_search": "cached"
|
||||
},
|
||||
@@ -113,6 +114,7 @@
|
||||
"features.code_mode_only": false,
|
||||
"features.goals": false,
|
||||
"features.standalone_web_search": false,
|
||||
"project_doc_max_bytes": 131072,
|
||||
"tools.update_plan.enabled": false,
|
||||
"web_search": "cached"
|
||||
},
|
||||
|
||||
test/fixtures/agents/prompt-snapshots/codex-runtime-happy-path/telegram-direct-codex-message-tool.md
Vendored
+2
@@ -70,6 +70,7 @@
|
||||
"features.code_mode_only": false,
|
||||
"features.goals": false,
|
||||
"features.standalone_web_search": false,
|
||||
"project_doc_max_bytes": 131072,
|
||||
"tools.update_plan.enabled": false,
|
||||
"web_search": "cached"
|
||||
},
|
||||
@@ -113,6 +114,7 @@
|
||||
"features.code_mode_only": false,
|
||||
"features.goals": false,
|
||||
"features.standalone_web_search": false,
|
||||
"project_doc_max_bytes": 131072,
|
||||
"tools.update_plan.enabled": false,
|
||||
"web_search": "cached"
|
||||
},
|
||||
|
||||
Vendored
+2
@@ -70,6 +70,7 @@
|
||||
"features.code_mode_only": false,
|
||||
"features.goals": false,
|
||||
"features.standalone_web_search": false,
|
||||
"project_doc_max_bytes": 131072,
|
||||
"tools.update_plan.enabled": false,
|
||||
"web_search": "cached"
|
||||
},
|
||||
@@ -114,6 +115,7 @@
|
||||
"features.code_mode_only": false,
|
||||
"features.goals": false,
|
||||
"features.standalone_web_search": false,
|
||||
"project_doc_max_bytes": 131072,
|
||||
"tools.update_plan.enabled": false,
|
||||
"web_search": "cached"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user