mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-19 00:34:46 +00:00
fix: address Codex guard review findings
This commit is contained in:
@@ -266,6 +266,55 @@ describe("createCodexDynamicToolBridge", () => {
|
||||
expect(text).toContain("rerun with narrower args");
|
||||
});
|
||||
|
||||
it("honors normalized per-agent dynamic tool result caps", async () => {
|
||||
const bridge = createCodexDynamicToolBridge({
|
||||
tools: [
|
||||
createTool({
|
||||
name: "large_lookup",
|
||||
execute: vi.fn(async () => textToolResult("x".repeat(400))),
|
||||
}),
|
||||
],
|
||||
signal: new AbortController().signal,
|
||||
hookContext: {
|
||||
agentId: "research-bot",
|
||||
config: {
|
||||
agents: {
|
||||
defaults: {
|
||||
contextLimits: {
|
||||
toolResultMaxChars: 1_000,
|
||||
},
|
||||
},
|
||||
list: [
|
||||
{
|
||||
id: "Research Bot",
|
||||
contextLimits: {
|
||||
toolResultMaxChars: 180,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
} as never,
|
||||
},
|
||||
});
|
||||
|
||||
const result = await bridge.handleToolCall({
|
||||
threadId: "thread-1",
|
||||
turnId: "turn-1",
|
||||
callId: "call-1",
|
||||
namespace: null,
|
||||
tool: "large_lookup",
|
||||
arguments: {},
|
||||
});
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
const firstItem = result.contentItems[0];
|
||||
if (firstItem?.type !== "inputText" || typeof firstItem.text !== "string") {
|
||||
throw new Error("expected inputText tool result");
|
||||
}
|
||||
expect(firstItem.text.length).toBeLessThanOrEqual(180);
|
||||
expect(firstItem.text).toContain("OpenClaw truncated dynamic tool result");
|
||||
});
|
||||
|
||||
it("keeps truncation notices within tiny configured caps", async () => {
|
||||
const bridge = createCodexDynamicToolBridge({
|
||||
tools: [
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
type MessagingToolSourceReplyPayload,
|
||||
wrapToolWithBeforeToolCallHook,
|
||||
} from "openclaw/plugin-sdk/agent-harness-runtime";
|
||||
import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
|
||||
import type { CodexDynamicToolsLoading } from "./config.js";
|
||||
import { invalidInlineImageText, sanitizeInlineImageDataUrl } from "./image-payload-sanitizer.js";
|
||||
import {
|
||||
@@ -253,7 +254,11 @@ function resolveAgentContextLimitValue(params: {
|
||||
if (!Array.isArray(list)) {
|
||||
return defaultValue;
|
||||
}
|
||||
const agent = list.find((entry) => readRecord(entry)?.id === params.agentId);
|
||||
const normalizedAgentId = normalizeAgentId(params.agentId);
|
||||
const agent = list.find((entry) => {
|
||||
const entryId = readRecord(entry)?.id;
|
||||
return typeof entryId === "string" && normalizeAgentId(entryId) === normalizedAgentId;
|
||||
});
|
||||
const agentValue = readPositiveInteger(
|
||||
readRecord(readRecord(agent)?.contextLimits)?.[params.key],
|
||||
);
|
||||
|
||||
@@ -6452,6 +6452,45 @@ describe("runCodexAppServerAttempt", () => {
|
||||
expect(savedBinding).toBeUndefined();
|
||||
});
|
||||
|
||||
it("clears native rollouts at the configured byte limit", async () => {
|
||||
const sessionFile = path.join(tempDir, "session.jsonl");
|
||||
const workspaceDir = path.join(tempDir, "workspace");
|
||||
const agentDir = path.join(tempDir, "agent");
|
||||
await writeExistingBinding(sessionFile, workspaceDir, { dynamicToolsFingerprint: "[]" });
|
||||
await fs.writeFile(
|
||||
path.join(path.dirname(sessionFile), "sessions.json"),
|
||||
JSON.stringify({
|
||||
"agent:main:session-1": {
|
||||
sessionFile,
|
||||
totalTokens: 12_000,
|
||||
},
|
||||
}),
|
||||
);
|
||||
const rolloutDir = path.join(agentDir, "codex-home", "sessions");
|
||||
await fs.mkdir(rolloutDir, { recursive: true });
|
||||
await fs.writeFile(path.join(rolloutDir, "rollout-thread-existing.jsonl"), "x".repeat(1_000));
|
||||
|
||||
const binding = await __testing.rotateOversizedCodexAppServerStartupBinding({
|
||||
binding: await readCodexAppServerBinding(sessionFile),
|
||||
sessionFile,
|
||||
agentDir,
|
||||
config: {
|
||||
agents: {
|
||||
defaults: {
|
||||
compaction: {
|
||||
truncateAfterCompaction: true,
|
||||
maxActiveTranscriptBytes: 1_000,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
});
|
||||
|
||||
expect(binding).toBeUndefined();
|
||||
const savedBinding = await readCodexAppServerBinding(sessionFile);
|
||||
expect(savedBinding).toBeUndefined();
|
||||
});
|
||||
|
||||
it("resumes a bound Codex thread when only dynamic tool descriptions change", async () => {
|
||||
const sessionFile = path.join(tempDir, "session.jsonl");
|
||||
const workspaceDir = path.join(tempDir, "workspace");
|
||||
|
||||
@@ -679,7 +679,7 @@ async function rotateOversizedCodexAppServerStartupBinding(params: {
|
||||
params.codexHome,
|
||||
);
|
||||
if (maxBytes !== undefined) {
|
||||
const oversizedFiles = rolloutFiles.filter((file) => file.bytes > maxBytes);
|
||||
const oversizedFiles = rolloutFiles.filter((file) => file.bytes >= maxBytes);
|
||||
if (oversizedFiles.length > 0) {
|
||||
embeddedAgentLog.warn(
|
||||
"codex app-server native transcript exceeded active byte limit; starting a fresh thread",
|
||||
|
||||
Reference in New Issue
Block a user