refactor(config): retire redundant settings (#113174)

* refactor(config): retire redundant settings

* style: apply current formatter

* chore: update plugin sdk baseline

* fix: keep Codex tool caps context-aware

* chore: remove stale imports

* test: align WhatsApp QA debounce config

* fix(config): clean up retired config checks

* fix(ci): align config cleanup checks
This commit is contained in:
Peter Steinberger
2026-07-23 17:45:02 -07:00
committed by GitHub
parent 1603781bb0
commit bb657eec93
99 changed files with 796 additions and 1445 deletions
@@ -1,37 +0,0 @@
import type { EmbeddedRunAttemptParams } from "openclaw/plugin-sdk/agent-harness-runtime";
import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
import { asOptionalRecord as readRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
/** Resolves an agent override before falling back to the configured default. */
export function resolveAgentContextLimitValue(params: {
config: EmbeddedRunAttemptParams["config"] | undefined;
agentId?: string;
key: string;
}): number | undefined {
const agents = readRecord(params.config?.agents);
const defaults = readRecord(readRecord(agents?.defaults)?.contextLimits);
const defaultValue = readPositiveInteger(defaults?.[params.key]);
if (!params.agentId) {
return defaultValue;
}
const list = agents?.list;
if (!Array.isArray(list)) {
return defaultValue;
}
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],
);
return agentValue ?? defaultValue;
}
function readPositiveInteger(value: unknown): number | undefined {
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
return undefined;
}
return Math.floor(value);
}
@@ -802,8 +802,8 @@ describe("createCodexDynamicToolBridge", () => {
expectNoNamespace(bridge.specs[1]);
});
it("truncates configured text tool results before returning them to Codex", async () => {
const longText = "x".repeat(400);
it("scales oversized text tool results to the effective context window", async () => {
const longText = "x".repeat(40_000);
const bridge = createCodexDynamicToolBridge({
tools: [
createTool({
@@ -812,18 +812,7 @@ describe("createCodexDynamicToolBridge", () => {
}),
],
signal: new AbortController().signal,
hookContext: {
agentId: "main",
config: {
agents: {
defaults: {
contextLimits: {
toolResultMaxChars: 180,
},
},
},
} as never,
},
hookContext: { contextWindowTokens: 128_000 },
});
const result = await bridge.handleToolCall({
@@ -841,15 +830,43 @@ describe("createCodexDynamicToolBridge", () => {
throw new Error("expected inputText tool result");
}
const text = firstItem.text;
expect(text.length).toBeLessThanOrEqual(180);
expect(text.length).toBeLessThanOrEqual(32_000);
expect(text).toContain("OpenClaw truncated dynamic tool result");
expect(text).toContain("original 400 chars");
expect(text).toContain("original 40000 chars");
expect(text).toContain("rerun with narrower args");
});
it("keeps a whole code point when dynamic tool text crosses the configured boundary", async () => {
const maxChars = 180;
const totalChars = 400;
it("applies the context-share ceiling for small effective windows", async () => {
const bridge = createCodexDynamicToolBridge({
tools: [
createTool({
name: "small_context_lookup",
execute: vi.fn(async () => textToolResult("x".repeat(20_000))),
}),
],
signal: new AbortController().signal,
hookContext: { contextWindowTokens: 8_000 },
});
const result = await bridge.handleToolCall({
threadId: "thread-1",
turnId: "turn-1",
callId: "call-small-context",
namespace: null,
tool: "small_context_lookup",
arguments: {},
});
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(9_600);
expect(firstItem.text).toContain("OpenClaw truncated dynamic tool result");
});
it("keeps a whole code point when dynamic tool text crosses the automatic boundary", async () => {
const maxChars = 16_000;
const totalChars = 20_000;
const noticeText = `...(OpenClaw truncated dynamic tool result: original ${totalChars} chars, showing ${maxChars}; rerun with narrower args.)`;
const textBudget = maxChars - noticeText.length - 1;
const prefix = "a".repeat(textBudget - 1);
@@ -862,12 +879,6 @@ describe("createCodexDynamicToolBridge", () => {
}),
],
signal: new AbortController().signal,
hookContext: {
agentId: "main",
config: {
agents: { defaults: { contextLimits: { toolResultMaxChars: maxChars } } },
} as never,
},
});
const result = await bridge.handleToolCall({
@@ -882,123 +893,21 @@ describe("createCodexDynamicToolBridge", () => {
expect(result.contentItems).toEqual([{ type: "inputText", text: `${prefix}\n${noticeText}` }]);
});
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: [
createTool({
name: "large_lookup",
execute: vi.fn(async () => textToolResult("x".repeat(400))),
}),
],
signal: new AbortController().signal,
hookContext: {
agentId: "main",
config: {
agents: {
defaults: {
contextLimits: {
toolResultMaxChars: 32,
},
},
},
} 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(32);
expect(firstItem.text).toBe("...(OpenClaw truncated dynamic tool".slice(0, 32));
});
it("budgets configured truncation across all text result blocks", async () => {
it("budgets automatic truncation across all text result blocks", async () => {
const bridge = createCodexDynamicToolBridge({
tools: [
createTool({
name: "large_lookup",
execute: vi.fn(async () => ({
content: [
{ type: "text" as const, text: "a".repeat(200) },
{ type: "text" as const, text: "b".repeat(200) },
{ type: "text" as const, text: "a".repeat(10_000) },
{ type: "text" as const, text: "b".repeat(10_000) },
],
details: {},
})),
}),
],
signal: new AbortController().signal,
hookContext: {
agentId: "main",
config: {
agents: {
defaults: {
contextLimits: {
toolResultMaxChars: 180,
},
},
},
} as never,
},
});
const result = await bridge.handleToolCall({
@@ -1014,10 +923,10 @@ describe("createCodexDynamicToolBridge", () => {
const text = result.contentItems
.map((item) => (item.type === "inputText" && typeof item.text === "string" ? item.text : ""))
.join("");
expect(text.length).toBeLessThanOrEqual(180);
expect(text.length).toBeLessThanOrEqual(16_000);
expect(text).toContain("OpenClaw truncated dynamic tool result");
expect(text).toContain("original 400 chars");
expect(text).not.toContain("b".repeat(100));
expect(text).toContain("original 20000 chars");
expect(text).not.toContain("b".repeat(10_000));
});
it.each([
@@ -47,7 +47,6 @@ import type { ImageContent, TextContent } from "openclaw/plugin-sdk/llm";
import { normalizeOpenAIToolSchemas } from "openclaw/plugin-sdk/provider-tools";
import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
import { resolveAgentContextLimitValue } from "./agent-context-limits.js";
import type { CodexDynamicToolsLoading } from "./config.js";
import {
createFailedDynamicToolResponse,
@@ -78,6 +77,7 @@ type CodexDynamicToolHookContext = {
runId?: string;
channelId?: string;
currentChannelProvider?: string;
contextWindowTokens?: number;
currentChannelId?: string;
currentMessagingTarget?: string;
currentMessageId?: string | number;
@@ -386,6 +386,28 @@ const EXPLICIT_MESSAGE_TARGET_KEYS = ["target", "to", "channelId"];
const EXPLICIT_MESSAGE_THREAD_KEYS = ["threadId", "thread_id", "messageThreadId", "topicId"];
const EXPLICIT_MESSAGE_REPLY_KEYS = ["replyTo", "replyToId", "replyToIdFull"];
const DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS = 16_000;
const LARGE_CONTEXT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS = 32_000;
const XL_CONTEXT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS = 64_000;
function resolveCodexDynamicToolResultMaxChars(contextWindowTokens?: number): number {
if (
typeof contextWindowTokens !== "number" ||
!Number.isFinite(contextWindowTokens) ||
contextWindowTokens <= 0
) {
return DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS;
}
const tokens = Math.floor(contextWindowTokens);
const autoCap =
tokens >= 200_000
? XL_CONTEXT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS
: tokens >= 100_000
? LARGE_CONTEXT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS
: DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS;
// Match the core live-result context-share ceiling without importing core
// internals across the bundled-plugin boundary.
return Math.min(autoCap, Math.max(1, Math.floor(tokens * 0.3) * 4));
}
function computerFrameImageIdentity(
content: AgentToolResult<unknown>["content"] | undefined,
@@ -431,7 +453,9 @@ export function createCodexDynamicToolBridge(params: {
directToolNames?: Iterable<string>;
}): CodexDynamicToolBridge {
const toolResultHookContext = toToolResultHookContext(params.hookContext);
const toolResultMaxChars = resolveCodexDynamicToolResultMaxChars(params.hookContext);
const toolResultMaxChars = resolveCodexDynamicToolResultMaxChars(
params.hookContext?.contextWindowTokens,
);
const availableProjection = projectCodexDynamicTools(params.tools);
const registeredProjection = params.registeredTools
? projectCodexDynamicTools(params.registeredTools)
@@ -1165,16 +1189,6 @@ function toToolResultHookContext(
};
}
function resolveCodexDynamicToolResultMaxChars(
ctx: CodexDynamicToolHookContext | undefined,
): number {
const configured = resolveAgentContextLimitValue({
config: ctx?.config,
agentId: ctx?.agentId,
key: "toolResultMaxChars",
});
return configured ?? DEFAULT_CODEX_DYNAMIC_TOOL_RESULT_MAX_CHARS;
}
function composeAbortSignals(...signals: Array<AbortSignal | undefined>): AbortSignal {
const activeSignals = signals.filter((signal): signal is AbortSignal => Boolean(signal));
if (activeSignals.length === 0) {
@@ -229,6 +229,7 @@ export async function prepareCodexAttemptTools(runtime: CodexAttemptRuntime) {
hookContext: {
agentId: sessionAgentId,
config: params.config,
contextWindowTokens: params.contextTokenBudget ?? params.model.contextWindow,
workspaceDir: effectiveWorkspace,
sessionId: params.sessionId,
sessionKey: sandboxSessionKey,
@@ -1042,6 +1042,7 @@ async function createCodexSideToolBridge(input: {
hookContext: {
agentId: input.sessionAgentId,
config: input.params.cfg,
contextWindowTokens: runtimeModel.contextWindow,
sessionId: input.params.sessionId,
sessionKey: input.params.sessionKey,
runId: input.runId,