mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 10:20:42 +00:00
fix(ui): show configured thinking defaults
This commit is contained in:
@@ -36,6 +36,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Providers/Ollama: route local web search through Ollama's signed `/api/experimental/web_search` daemon proxy, use hosted `/api/web_search` directly for `ollama.com`, and keep `OLLAMA_API_KEY` scoped to cloud fallback auth. Fixes #69132. Thanks @yoon1012 and @hyspacex.
|
||||
- Memory/doctor: treat Ollama memory embeddings as key-optional so `openclaw doctor` no longer warns about a missing API key when the gateway reports embeddings are ready. Fixes #46584. Thanks @fengly78.
|
||||
- Agents/Ollama: apply provider-owned replay turn normalization to native Ollama chat so Cloud models no longer reject non-alternating replay history in agent/Gateway runs. Fixes #71697. Thanks @ismael-81.
|
||||
- Control UI/Ollama: show the resolved configured thinking default in chat and session thinking dropdowns so inherited `adaptive`/per-model thinking config no longer appears as `Default (off)` or a generic inherit value. Fixes #72407. Thanks @NotecAG.
|
||||
- Agents/Ollama: validate explicit `--thinking max` against catalog-discovered Ollama reasoning metadata so local agent runs accept the same native thinking levels shown in the model catalog. Fixes #71584. Thanks @g0st1n.
|
||||
- CLI/models: include explicitly configured provider models in `openclaw models list --provider <id>` without requiring the full catalog path, so configured Ollama models are visible. Fixes #65207. Thanks @drzeast-png.
|
||||
- Docker/QA: add observability coverage to the normal Docker aggregate so QA-lab OTEL and Prometheus diagnostics run inside Docker. Thanks @vincentkoc.
|
||||
|
||||
@@ -63,6 +63,7 @@ export function createSessionsListResult(
|
||||
defaultsThinkingLevels?: SessionsListResult["defaults"]["thinkingLevels"];
|
||||
defaultsThinkingOptions?: string[];
|
||||
defaultsThinkingDefault?: string;
|
||||
thinkingDefault?: string;
|
||||
omitSessionFromList?: boolean;
|
||||
} = {},
|
||||
): SessionsListResult {
|
||||
@@ -74,6 +75,7 @@ export function createSessionsListResult(
|
||||
defaultsThinkingLevels,
|
||||
defaultsThinkingOptions,
|
||||
defaultsThinkingDefault,
|
||||
thinkingDefault,
|
||||
omitSessionFromList = false,
|
||||
} = params;
|
||||
|
||||
@@ -95,6 +97,7 @@ export function createSessionsListResult(
|
||||
createMainSessionRow({
|
||||
...(modelProvider ? { modelProvider } : {}),
|
||||
...(model ? { model } : {}),
|
||||
...(thinkingDefault ? { thinkingDefault } : {}),
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
@@ -180,6 +180,8 @@ function createChatHeaderState(
|
||||
model?: string | null;
|
||||
modelProvider?: string | null;
|
||||
models?: ModelCatalogEntry[];
|
||||
defaultsThinkingDefault?: string;
|
||||
thinkingDefault?: string;
|
||||
omitSessionFromList?: boolean;
|
||||
} = {},
|
||||
): { state: AppViewState; request: ReturnType<typeof vi.fn> } {
|
||||
@@ -218,6 +220,8 @@ function createChatHeaderState(
|
||||
return createSessionsListResult({
|
||||
model: currentModel,
|
||||
modelProvider: currentModelProvider,
|
||||
defaultsThinkingDefault: overrides.defaultsThinkingDefault,
|
||||
thinkingDefault: overrides.thinkingDefault,
|
||||
omitSessionFromList,
|
||||
});
|
||||
}
|
||||
@@ -240,6 +244,8 @@ function createChatHeaderState(
|
||||
sessionsResult: createSessionsListResult({
|
||||
model: currentModel,
|
||||
modelProvider: currentModelProvider,
|
||||
defaultsThinkingDefault: overrides.defaultsThinkingDefault,
|
||||
thinkingDefault: overrides.thinkingDefault,
|
||||
omitSessionFromList,
|
||||
}),
|
||||
chatModelOverrides: {},
|
||||
@@ -704,4 +710,39 @@ describe("chat session controls", () => {
|
||||
?.textContent?.trim(),
|
||||
).toBe("maximum");
|
||||
});
|
||||
|
||||
it("labels chat thinking default from the active session row", () => {
|
||||
const { state } = createChatHeaderState({
|
||||
model: "gemma4:hermes-e4b",
|
||||
modelProvider: "ollama",
|
||||
thinkingDefault: "adaptive",
|
||||
});
|
||||
const container = document.createElement("div");
|
||||
render(renderChatSessionSelect(state), container);
|
||||
|
||||
const thinkingSelect = container.querySelector<HTMLSelectElement>(
|
||||
'select[data-chat-thinking-select="true"]',
|
||||
);
|
||||
|
||||
expect(thinkingSelect?.value).toBe("");
|
||||
expect(thinkingSelect?.options[0]?.textContent?.trim()).toBe("Default (adaptive)");
|
||||
expect(thinkingSelect?.title).toBe("Default (adaptive)");
|
||||
});
|
||||
|
||||
it("labels chat thinking default from session defaults when the row is absent", () => {
|
||||
const { state } = createChatHeaderState({
|
||||
defaultsThinkingDefault: "adaptive",
|
||||
omitSessionFromList: true,
|
||||
});
|
||||
const container = document.createElement("div");
|
||||
render(renderChatSessionSelect(state), container);
|
||||
|
||||
const thinkingSelect = container.querySelector<HTMLSelectElement>(
|
||||
'select[data-chat-thinking-select="true"]',
|
||||
);
|
||||
|
||||
expect(thinkingSelect?.value).toBe("");
|
||||
expect(thinkingSelect?.options[0]?.textContent?.trim()).toBe("Default (adaptive)");
|
||||
expect(thinkingSelect?.title).toBe("Default (adaptive)");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -109,6 +109,32 @@ describe("sessions view", () => {
|
||||
expect(onPatch).toHaveBeenCalledWith("agent:main:main", { thinkingLevel: "max" });
|
||||
});
|
||||
|
||||
it("labels inherited thinking with the resolved session default", async () => {
|
||||
const container = document.createElement("div");
|
||||
render(
|
||||
renderSessions(
|
||||
buildProps(
|
||||
buildResult({
|
||||
key: "agent:main:main",
|
||||
kind: "direct",
|
||||
updatedAt: Date.now(),
|
||||
thinkingDefault: "adaptive",
|
||||
thinkingLevels: [
|
||||
{ id: "off", label: "off" },
|
||||
{ id: "adaptive", label: "adaptive" },
|
||||
],
|
||||
}),
|
||||
),
|
||||
),
|
||||
container,
|
||||
);
|
||||
await Promise.resolve();
|
||||
|
||||
const thinking = container.querySelector("tbody select") as HTMLSelectElement | null;
|
||||
expect(thinking?.value).toBe("");
|
||||
expect(thinking?.options[0]?.textContent?.trim()).toBe("Default (adaptive)");
|
||||
});
|
||||
|
||||
it("keeps legacy binary thinking labels patching canonical ids", async () => {
|
||||
const container = document.createElement("div");
|
||||
const onPatch = vi.fn();
|
||||
|
||||
@@ -87,6 +87,7 @@ function normalizeThinkingOptionValue(raw: string): string {
|
||||
function resolveThinkLevelOptions(
|
||||
row: GatewaySessionRow,
|
||||
): readonly { value: string; label: string }[] {
|
||||
const defaultLabel = row.thinkingDefault ? `Default (${row.thinkingDefault})` : "inherit";
|
||||
const options: readonly GatewayThinkingLevelOption[] = row.thinkingLevels?.length
|
||||
? row.thinkingLevels
|
||||
: (row.thinkingOptions?.length ? row.thinkingOptions : DEFAULT_THINK_LEVELS).map((label) => ({
|
||||
@@ -94,7 +95,7 @@ function resolveThinkLevelOptions(
|
||||
label,
|
||||
}));
|
||||
return [
|
||||
{ value: "", label: "inherit" },
|
||||
{ value: "", label: defaultLabel },
|
||||
...options.map((option) => ({
|
||||
value: normalizeThinkingOptionValue(option.id),
|
||||
label: option.label,
|
||||
|
||||
Reference in New Issue
Block a user