mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-03 13:51:36 +00:00
* fix(ollama): persist local auth only after model selection * fix(ollama): preserve native max thinking effort * fix(lmstudio): preserve model tool capabilities * fix(lmstudio): preserve configured model compatibility * test(ollama): prove isolated onboarding and persisted gateway turns * fix(ollama): fail closed on unresolved secret references * fix(ollama): keep local onboarding model catalogs installed-only * fix(onboard): preflight local models before reset * fix(lmstudio): normalize unsupported tool schema patterns * Revert "test(ollama): prove isolated onboarding and persisted gateway turns" This reverts commit1d333d4c67. * Revert "fix(ollama): preserve native max thinking effort" This reverts commit5d2600b098. * fix(lmstudio): preserve typed model compatibility * test(lmstudio): await provider catalog augmentation * test(ollama): narrow optional discovery auth fixture * test(lmstudio): narrow reset validator registration * fix(onboard): preserve verified local model lean defaults * test(ollama): split non-interactive onboarding auth regressions * fix(onboard): exclude hosted Ollama models from lean defaults * test(onboard): prove local reset preflight order
164 lines
5.3 KiB
TypeScript
164 lines
5.3 KiB
TypeScript
import type { OpenClawConfig } from "openclaw/plugin-sdk/plugin-entry";
|
|
import { capturePluginRegistration } from "openclaw/plugin-sdk/plugin-test-runtime";
|
|
import { describe, expect, it } from "vitest";
|
|
import plugin from "./index.js";
|
|
|
|
function augmentConfiguredLmstudioCompat(compat: Record<string, unknown>) {
|
|
const provider = capturePluginRegistration(plugin).providers[0];
|
|
const config = {
|
|
models: {
|
|
providers: {
|
|
lmstudio: {
|
|
models: [{ id: "qwen3-8b-instruct", compat }],
|
|
},
|
|
},
|
|
},
|
|
} as unknown as OpenClawConfig;
|
|
|
|
expect(provider?.id).toBe("lmstudio");
|
|
return provider?.augmentModelCatalog?.({
|
|
config,
|
|
agentDir: "/tmp/openclaw",
|
|
env: {},
|
|
entries: [],
|
|
});
|
|
}
|
|
|
|
describe("LM Studio configured model tool capabilities", () => {
|
|
it.each([
|
|
{ label: "enabled", supportsTools: true },
|
|
{ label: "disabled", supportsTools: false },
|
|
{ label: "unknown", supportsTools: undefined },
|
|
])("preserves $label tool support during provider catalog augmentation", ({ supportsTools }) => {
|
|
const provider = capturePluginRegistration(plugin).providers[0];
|
|
const config = {
|
|
models: {
|
|
providers: {
|
|
lmstudio: {
|
|
models: [
|
|
{
|
|
id: "qwen3-8b-instruct",
|
|
compat: {
|
|
...(supportsTools === undefined ? {} : { supportsTools }),
|
|
supportsReasoningEffort: true,
|
|
supportedReasoningEfforts: ["off", "on"],
|
|
reasoningEffortMap: { off: "off", high: "on" },
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
} as unknown as OpenClawConfig;
|
|
|
|
expect(provider?.id).toBe("lmstudio");
|
|
expect(
|
|
provider?.augmentModelCatalog?.({
|
|
config,
|
|
agentDir: "/tmp/openclaw",
|
|
env: {},
|
|
entries: [],
|
|
}),
|
|
).toEqual([
|
|
{
|
|
provider: "lmstudio",
|
|
id: "qwen3-8b-instruct",
|
|
name: "qwen3-8b-instruct",
|
|
compat: {
|
|
supportsUsageInStreaming: true,
|
|
...(supportsTools === undefined ? {} : { supportsTools }),
|
|
supportsReasoningEffort: true,
|
|
supportedReasoningEfforts: ["none", "minimal", "low", "medium", "high", "xhigh"],
|
|
reasoningEffortMap: {
|
|
off: "none",
|
|
none: "none",
|
|
adaptive: "xhigh",
|
|
max: "xhigh",
|
|
},
|
|
},
|
|
contextWindow: undefined,
|
|
contextTokens: undefined,
|
|
reasoning: undefined,
|
|
input: undefined,
|
|
},
|
|
]);
|
|
});
|
|
|
|
it.each([
|
|
{
|
|
label: "all schema-approved compatibility fields",
|
|
configuredCompat: {
|
|
supportsStore: false,
|
|
supportsPromptCacheKey: false,
|
|
supportsDeveloperRole: false,
|
|
supportsReasoningEffort: true,
|
|
supportsTemperature: false,
|
|
supportsUsageInStreaming: false,
|
|
supportsTools: false,
|
|
supportsStrictMode: false,
|
|
supportsJsonSchemaResponseFormat: false,
|
|
requiresStringContent: true,
|
|
strictMessageKeys: true,
|
|
visibleReasoningDetailTypes: ["reasoning.summary"],
|
|
supportedReasoningEfforts: ["low", "high"],
|
|
reasoningEffortMap: { off: "none", high: "high" },
|
|
maxTokensField: "max_tokens",
|
|
thinkingFormat: "qwen",
|
|
requiresToolResultName: true,
|
|
requiresAssistantAfterToolResult: true,
|
|
requiresThinkingAsText: true,
|
|
requiresReasoningContentOnAssistantMessages: true,
|
|
toolSchemaProfile: "lmstudio",
|
|
unsupportedToolSchemaKeywords: ["additionalProperties"],
|
|
toolCallArgumentsEncoding: "string",
|
|
requiresOpenAiAnthropicToolPayload: true,
|
|
},
|
|
expectedOverride: { supportsUsageInStreaming: true },
|
|
},
|
|
{
|
|
label: "explicit false flags and empty schema-approved lists",
|
|
configuredCompat: {
|
|
supportsStore: false,
|
|
supportsPromptCacheKey: false,
|
|
supportsDeveloperRole: false,
|
|
supportsReasoningEffort: false,
|
|
supportsTemperature: false,
|
|
supportsUsageInStreaming: false,
|
|
supportsTools: false,
|
|
supportsStrictMode: false,
|
|
supportsJsonSchemaResponseFormat: false,
|
|
requiresStringContent: false,
|
|
strictMessageKeys: false,
|
|
visibleReasoningDetailTypes: [],
|
|
maxTokensField: "max_completion_tokens",
|
|
thinkingFormat: "qwen-chat-template",
|
|
requiresToolResultName: false,
|
|
requiresAssistantAfterToolResult: false,
|
|
requiresThinkingAsText: false,
|
|
requiresReasoningContentOnAssistantMessages: false,
|
|
toolSchemaProfile: "",
|
|
unsupportedToolSchemaKeywords: [],
|
|
toolCallArgumentsEncoding: "",
|
|
requiresOpenAiAnthropicToolPayload: false,
|
|
},
|
|
expectedOverride: { supportsUsageInStreaming: true },
|
|
},
|
|
])(
|
|
"preserves $label through the registered provider catalog",
|
|
async ({ configuredCompat, expectedOverride }) => {
|
|
const entries = await augmentConfiguredLmstudioCompat(configuredCompat);
|
|
|
|
if (!Array.isArray(entries)) {
|
|
throw new Error("Expected LM Studio provider catalog augmentation to return model entries");
|
|
}
|
|
|
|
expect(entries).toHaveLength(1);
|
|
expect(entries[0]).toMatchObject({
|
|
provider: "lmstudio",
|
|
id: "qwen3-8b-instruct",
|
|
});
|
|
expect(entries[0]?.compat).toEqual({ ...configuredCompat, ...expectedOverride });
|
|
},
|
|
);
|
|
});
|