fix(gateway): resolve configured thinking default in session rows (#72324)

* fix(gateway): resolve configured thinking default in session rows

* fix(gateway): preserve model thinking precedence
This commit is contained in:
Vincent Koc
2026-04-26 19:10:21 -07:00
committed by GitHub
parent de0ece20d1
commit 0c30d0d0b8
3 changed files with 111 additions and 6 deletions

View File

@@ -51,6 +51,7 @@ Docs: https://docs.openclaw.ai
- WebChat/Control UI: support non-video file attachments in chat uploads while preserving the existing image attachment path and MIME-sniff fallback for generic image uploads. (#70947) Thanks @IAMSamuelRodda.
- Skills/memory: restore Chokidar v5 hot reloads by watching concrete skill and memory roots with filters, including SKILL.md removals and deleted skill folders without broad workspace recursion. Fixes #27404, #33585, and #41606. Thanks @shelvenzhou, @08820048, and @rocke2020.
- Gateway/chat: keep duplicate attachment-backed `chat.send` retries with the same idempotency key on the documented in-flight path so aborts still target the real active run. Fixes #70139. Thanks @Feelw00.
- Gateway/session rows: report the same config-resolved thinking default that runtime sessions use, including global and per-agent defaults, so Control UI and TUI default labels stay aligned. (#71779, #70981, #71033, #70302) Thanks @chen-zhang-cs-code, @SymbolStar, and @cholaolu-boop.
- Plugins: share package entrypoint resolution between install and discovery, reject mismatched `runtimeExtensions`, and cache bundled runtime-dependency manifest reads during scans. Thanks @codex.
- WhatsApp/Web: keep quiet but healthy linked-device sessions connected by basing the watchdog on WhatsApp Web transport activity, while retaining a longer app-silence cap so frame activity cannot mask a stuck session forever. Fixes #70678; carries forward the focused #71466 approach and keeps #63939 as related configurable-timeout follow-up. Thanks @vincentkoc and @oromeis.
- Discord/gateway: count failed health-monitor restart attempts toward cooldown and hourly caps, and evict stale account lifecycle state during channel reloads so repeated Discord gateway recovery cannot loop on old status. Fixes #38596. (#40413) Thanks @jellyAI-dev and @vashquez.

View File

@@ -9,6 +9,7 @@ import { createEmptyPluginRegistry } from "../plugins/registry-empty.js";
import { resetPluginRuntimeStateForTest, setActivePluginRegistry } from "../plugins/runtime.js";
import { withStateDirEnv } from "../test-helpers/state-dir-env.js";
import {
buildGatewaySessionRow,
capArrayByJsonBytes,
classifySessionKey,
deriveSessionTitle,
@@ -139,6 +140,88 @@ describe("gateway session utils", () => {
);
});
test("session defaults use configured thinking default", () => {
const defaults = getSessionDefaults({
agents: {
defaults: {
model: { primary: "openai-codex/gpt-5.5" },
thinkingDefault: "high",
},
},
} as OpenClawConfig);
expect(defaults).toMatchObject({
modelProvider: "openai-codex",
model: "gpt-5.5",
thinkingDefault: "high",
});
});
test("session rows use per-agent thinking default from config", () => {
const cfg = {
agents: {
defaults: {
model: { primary: "openai-codex/gpt-5.5" },
thinkingDefault: "low",
models: {
"openai-codex/gpt-5.5": {
params: { thinking: "max" },
},
},
},
list: [
{
id: "alpha",
default: true,
thinkingDefault: "high",
},
],
},
} as OpenClawConfig;
const row = buildGatewaySessionRow({
cfg,
storePath: "",
store: {},
key: "agent:alpha:main",
});
expect(row).toMatchObject({
modelProvider: "openai-codex",
model: "gpt-5.5",
thinkingDefault: "high",
});
});
test("session rows prefer per-model thinking over global default", () => {
const cfg = {
agents: {
defaults: {
model: { primary: "openai-codex/gpt-5.5" },
thinkingDefault: "low",
models: {
"openai-codex/gpt-5.5": {
params: { thinking: "max" },
},
},
},
},
} as OpenClawConfig;
const row = buildGatewaySessionRow({
cfg,
storePath: "",
store: {},
key: "main",
});
expect(row).toMatchObject({
modelProvider: "openai-codex",
model: "gpt-5.5",
thinkingDefault: "max",
});
});
test("classifySessionKey respects chat type + prefixes", () => {
expect(classifySessionKey("global")).toBe("global");
expect(classifySessionKey("unknown")).toBe("unknown");

View File

@@ -2,6 +2,7 @@ import fs from "node:fs";
import path from "node:path";
import {
listAgentIds,
resolveAgentConfig,
resolveAgentEffectiveModelPrimary,
resolveAgentModelFallbacksOverride,
resolveAgentWorkspaceDir,
@@ -17,6 +18,7 @@ import {
resolveConfiguredModelRef,
resolveDefaultModelForAgent,
resolvePersistedSelectedModelRef,
resolveThinkingDefault,
} from "../agents/model-selection.js";
import {
countActiveDescendantRuns,
@@ -31,10 +33,7 @@ import {
RECENT_ENDED_SUBAGENT_CHILD_SESSION_MS,
shouldKeepSubagentRunChildLink,
} from "../agents/subagent-run-liveness.js";
import {
listThinkingLevelOptions,
resolveThinkingDefaultForModel,
} from "../auto-reply/thinking.js";
import { listThinkingLevelOptions } from "../auto-reply/thinking.js";
import { loadConfig } from "../config/config.js";
import { resolveAgentModelFallbackValues } from "../config/model-input.js";
import { resolveStateDir } from "../config/paths.js";
@@ -1038,6 +1037,25 @@ export function resolveGatewaySessionStoreTarget(params: {
export { loadCombinedSessionStoreForGateway } from "../config/sessions/combined-store-gateway.js";
function resolveGatewaySessionThinkingDefault(params: {
cfg: OpenClawConfig;
provider: string;
model: string;
agentId?: string;
}) {
const agentThinkingDefault = params.agentId
? resolveAgentConfig(params.cfg, params.agentId)?.thinkingDefault
: undefined;
return (
agentThinkingDefault ??
resolveThinkingDefault({
cfg: params.cfg,
provider: params.provider,
model: params.model,
})
);
}
export function getSessionDefaults(cfg: OpenClawConfig): GatewaySessionsDefaults {
const resolved = resolveConfiguredModelRef({
cfg,
@@ -1055,7 +1073,8 @@ export function getSessionDefaults(cfg: OpenClawConfig): GatewaySessionsDefaults
contextTokens: contextTokens ?? null,
thinkingLevels,
thinkingOptions: thinkingLevels.map((level) => level.label),
thinkingDefault: resolveThinkingDefaultForModel({
thinkingDefault: resolveGatewaySessionThinkingDefault({
cfg,
provider: resolved.provider,
model: resolved.model,
}),
@@ -1429,9 +1448,11 @@ export function buildGatewaySessionRow(params: {
thinkingLevel: entry?.thinkingLevel,
thinkingLevels,
thinkingOptions: thinkingLevels.map((level) => level.label),
thinkingDefault: resolveThinkingDefaultForModel({
thinkingDefault: resolveGatewaySessionThinkingDefault({
cfg,
provider: thinkingProvider,
model: thinkingModel,
agentId: sessionAgentId,
}),
fastMode: entry?.fastMode,
verboseLevel: entry?.verboseLevel,