From e7fe087677a659004d805c8ccd947db4ebfc0fed Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Mon, 6 Apr 2026 17:24:09 +0100 Subject: [PATCH] fix(openai): normalize prompt overlay personality config --- CHANGELOG.md | 2 + docs/providers/openai.md | 4 ++ extensions/openai/index.test.ts | 53 ++++++++++++++++++++++++++ extensions/openai/openclaw.plugin.json | 4 +- extensions/openai/prompt-overlay.ts | 6 ++- 5 files changed, 66 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6725f18833b..8be3e8b457a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ Docs: https://docs.openclaw.ai - Providers/Google: recognize Gemma model ids in native Google forward-compat resolution, keep the requested provider when cloning fallback templates, and force Gemma reasoning off so Gemma 4 routes stop failing through the Google catalog fallback. (#61507) Thanks @eyjohn. - Providers/Anthropic: skip `service_tier` injection for OAuth-authenticated stream wrapper requests so Claude OAuth requests stop failing with HTTP 401. (#60356) thanks @openperf. - Providers/OpenAI: keep WebSocket text buffered until a real assistant phase arrives, even when text deltas land before a phaseless `output_item.added` announcement. (#61954) Thanks @100yenadmin. +- Providers/OpenAI: accept case-insensitive `plugins.entries.openai.config.personality` values, keep unknown overrides on the friendly overlay path, and add `on` as an alias for `friendly`. Thanks @vincentkoc. - Discord/thread titles: stop forcing a hardcoded temperature for generated auto-thread names so Codex-backed thread title generation works on `openai-codex/*` models again. (#59525) - Agents/message tool: add a `read` plus `threadId` discoverability hint when the configured channel actions support threaded message reads. - Agents/context overflow: combine oversized and aggregate tool-result recovery in one repair pass, and restore a total-context overflow backstop during tool loops so recoverable sessions retry instead of failing early. (#61651) Thanks @Takhoffman. @@ -56,6 +57,7 @@ Docs: https://docs.openclaw.ai - Docs/i18n: relocalize final localized-page links after translation so generated locale pages stop keeping stale English-root links when targets appear later in the same run. (#61796) thanks @hxy91819. - Docs/i18n: remove the zh-CN homepage redirect override so Mintlify can resolve the localized Chinese homepage without self-redirecting `/zh-CN/index`. - Tools/web_fetch and web_search: fix `TypeError: fetch failed` caused by undici 8.0 enabling HTTP/2 by default; pinned SSRF-guard dispatchers now explicitly set `allowH2: false` to restore HTTP/1.1 behavior and keep the custom DNS-pinning lookup compatible. (#61738, #61777) Thanks @zozo123. + ## 2026.4.5 ### Breaking diff --git a/docs/providers/openai.md b/docs/providers/openai.md index 0dcd44b5d6a..bb712fe275b 100644 --- a/docs/providers/openai.md +++ b/docs/providers/openai.md @@ -28,6 +28,7 @@ Config key: Allowed values: - `"friendly"`: default; enable the OpenAI-specific overlay. +- `"on"`: alias for `"friendly"`. - `"off"`: disable the overlay and use the base OpenClaw prompt only. Scope: @@ -77,6 +78,9 @@ You can also set it directly with the config CLI: openclaw config set plugins.entries.openai.config.personality off ``` +OpenClaw normalizes this setting case-insensitively at runtime, so values like +`"Off"` still disable the friendly overlay. + ## Option A: OpenAI API key (OpenAI Platform) **Best for:** direct API access and usage-based billing. diff --git a/extensions/openai/index.test.ts b/extensions/openai/index.test.ts index 041e166d41c..5062cd75309 100644 --- a/extensions/openai/index.test.ts +++ b/extensions/openai/index.test.ts @@ -387,6 +387,32 @@ describe("openai plugin", () => { }); }); + it("treats mixed-case off values as disabling the friendly prompt overlay", async () => { + const { providers } = await registerOpenAIPluginWithHook({ + pluginConfig: { personality: "Off" }, + }); + + const openaiProvider = requireRegisteredProvider(providers, "openai"); + expect( + openaiProvider.resolveSystemPromptContribution?.({ + config: undefined, + agentDir: undefined, + workspaceDir: undefined, + provider: "openai", + modelId: "gpt-5.4", + promptMode: "full", + runtimeChannel: undefined, + runtimeCapabilities: undefined, + agentId: undefined, + }), + ).toEqual({ + stablePrefix: OPENAI_GPT5_OUTPUT_CONTRACT, + sectionOverrides: { + execution_bias: OPENAI_GPT5_EXECUTION_BIAS, + }, + }); + }); + it("supports explicitly configuring the friendly prompt overlay", async () => { const { on, providers } = await registerOpenAIPluginWithHook({ pluginConfig: { personality: "friendly" }, @@ -414,4 +440,31 @@ describe("openai plugin", () => { }, }); }); + + it("treats on as an alias for the friendly prompt overlay", async () => { + const { providers } = await registerOpenAIPluginWithHook({ + pluginConfig: { personality: "on" }, + }); + + const openaiProvider = requireRegisteredProvider(providers, "openai"); + expect( + openaiProvider.resolveSystemPromptContribution?.({ + config: undefined, + agentDir: undefined, + workspaceDir: undefined, + provider: "openai", + modelId: "gpt-5.4", + promptMode: "full", + runtimeChannel: undefined, + runtimeCapabilities: undefined, + agentId: undefined, + }), + ).toEqual({ + stablePrefix: OPENAI_GPT5_OUTPUT_CONTRACT, + sectionOverrides: { + interaction_style: OPENAI_FRIENDLY_PROMPT_OVERLAY, + execution_bias: OPENAI_GPT5_EXECUTION_BIAS, + }, + }); + }); }); diff --git a/extensions/openai/openclaw.plugin.json b/extensions/openai/openclaw.plugin.json index c4b49601eaa..df962ac8b47 100644 --- a/extensions/openai/openclaw.plugin.json +++ b/extensions/openai/openclaw.plugin.json @@ -49,9 +49,9 @@ "properties": { "personality": { "type": "string", - "enum": ["friendly", "off"], + "enum": ["friendly", "on", "off"], "default": "friendly", - "description": "Controls the default OpenAI-specific personality used for OpenAI and OpenAI Codex runs." + "description": "Controls the default OpenAI-specific personality used for OpenAI and OpenAI Codex runs. `friendly` and `on` enable the overlay; `off` disables it." } } } diff --git a/extensions/openai/prompt-overlay.ts b/extensions/openai/prompt-overlay.ts index 1b5214c20ee..b1bd1be5cc6 100644 --- a/extensions/openai/prompt-overlay.ts +++ b/extensions/openai/prompt-overlay.ts @@ -54,7 +54,11 @@ export type OpenAIPromptOverlayMode = "friendly" | "off"; export function resolveOpenAIPromptOverlayMode( pluginConfig?: Record, ): OpenAIPromptOverlayMode { - return pluginConfig?.personality === "off" ? "off" : "friendly"; + const normalized = + typeof pluginConfig?.personality === "string" + ? pluginConfig.personality.trim().toLowerCase() + : ""; + return normalized === "off" ? "off" : "friendly"; } export function shouldApplyOpenAIPromptOverlay(params: {