324 lines
9.0 KiB
TypeScript
324 lines
9.0 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
import type { ProviderPlugin } from "../plugins/types.js";
|
|
import type { ProviderAuthMethod } from "../plugins/types.js";
|
|
import type { ApplyAuthChoiceParams } from "./auth-choice.apply.js";
|
|
import {
|
|
applyAuthChoiceLoadedPluginProvider,
|
|
applyAuthChoicePluginProvider,
|
|
runProviderPluginAuthMethod,
|
|
} from "./auth-choice.apply.plugin-provider.js";
|
|
|
|
const resolvePluginProviders = vi.hoisted(() => vi.fn<() => ProviderPlugin[]>(() => []));
|
|
vi.mock("../plugins/providers.js", () => ({
|
|
resolvePluginProviders,
|
|
}));
|
|
|
|
const resolveProviderPluginChoice = vi.hoisted(() =>
|
|
vi.fn<() => { provider: ProviderPlugin; method: ProviderAuthMethod } | null>(),
|
|
);
|
|
const runExtensionHostProviderModelSelectedHook = vi.hoisted(() => vi.fn(async () => {}));
|
|
vi.mock("../plugins/provider-wizard.js", () => ({
|
|
resolveProviderPluginChoice,
|
|
}));
|
|
vi.mock("../extension-host/contributions/provider-model-selection.js", () => ({
|
|
runExtensionHostProviderModelSelectedHook,
|
|
}));
|
|
|
|
const upsertAuthProfile = vi.hoisted(() => vi.fn());
|
|
vi.mock("../agents/auth-profiles.js", () => ({
|
|
upsertAuthProfile,
|
|
}));
|
|
|
|
const resolveDefaultAgentId = vi.hoisted(() => vi.fn(() => "default"));
|
|
const resolveAgentWorkspaceDir = vi.hoisted(() => vi.fn(() => "/tmp/workspace"));
|
|
const resolveAgentDir = vi.hoisted(() => vi.fn(() => "/tmp/agent"));
|
|
vi.mock("../agents/agent-scope.js", () => ({
|
|
resolveDefaultAgentId,
|
|
resolveAgentDir,
|
|
resolveAgentWorkspaceDir,
|
|
}));
|
|
|
|
const resolveDefaultAgentWorkspaceDir = vi.hoisted(() => vi.fn(() => "/tmp/workspace"));
|
|
vi.mock("../agents/workspace.js", () => ({
|
|
resolveDefaultAgentWorkspaceDir,
|
|
}));
|
|
|
|
const resolveOpenClawAgentDir = vi.hoisted(() => vi.fn(() => "/tmp/agent"));
|
|
vi.mock("../agents/agent-paths.js", () => ({
|
|
resolveOpenClawAgentDir,
|
|
}));
|
|
|
|
const applyAuthProfileConfig = vi.hoisted(() => vi.fn((config) => config));
|
|
vi.mock("./onboard-auth.js", () => ({
|
|
applyAuthProfileConfig,
|
|
}));
|
|
|
|
const isRemoteEnvironment = vi.hoisted(() => vi.fn(() => false));
|
|
vi.mock("./oauth-env.js", () => ({
|
|
isRemoteEnvironment,
|
|
}));
|
|
|
|
const createVpsAwareOAuthHandlers = vi.hoisted(() => vi.fn());
|
|
vi.mock("./oauth-flow.js", () => ({
|
|
createVpsAwareOAuthHandlers,
|
|
}));
|
|
|
|
const openUrl = vi.hoisted(() => vi.fn(async () => {}));
|
|
vi.mock("./onboard-helpers.js", () => ({
|
|
openUrl,
|
|
}));
|
|
|
|
function buildProvider(): ProviderPlugin {
|
|
return {
|
|
id: "ollama",
|
|
label: "Ollama",
|
|
auth: [
|
|
{
|
|
id: "local",
|
|
label: "Ollama",
|
|
kind: "custom",
|
|
run: async () => ({
|
|
profiles: [
|
|
{
|
|
profileId: "ollama:default",
|
|
credential: {
|
|
type: "api_key",
|
|
provider: "ollama",
|
|
key: "ollama-local",
|
|
},
|
|
},
|
|
],
|
|
defaultModel: "ollama/qwen3:4b",
|
|
}),
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
function buildParams(overrides: Partial<ApplyAuthChoiceParams> = {}): ApplyAuthChoiceParams {
|
|
return {
|
|
authChoice: "ollama",
|
|
config: {},
|
|
prompter: {
|
|
note: vi.fn(async () => {}),
|
|
} as unknown as ApplyAuthChoiceParams["prompter"],
|
|
runtime: {} as ApplyAuthChoiceParams["runtime"],
|
|
setDefaultModel: true,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe("applyAuthChoiceLoadedPluginProvider", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
applyAuthProfileConfig.mockImplementation((config) => config);
|
|
});
|
|
|
|
it("returns an agent model override when default model application is deferred", async () => {
|
|
const provider = buildProvider();
|
|
resolvePluginProviders.mockReturnValue([provider]);
|
|
resolveProviderPluginChoice.mockReturnValue({
|
|
provider,
|
|
method: provider.auth[0],
|
|
});
|
|
|
|
const result = await applyAuthChoiceLoadedPluginProvider(
|
|
buildParams({
|
|
setDefaultModel: false,
|
|
}),
|
|
);
|
|
|
|
expect(result).toEqual({
|
|
config: {},
|
|
agentModelOverride: "ollama/qwen3:4b",
|
|
});
|
|
expect(runExtensionHostProviderModelSelectedHook).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("applies the default model and runs provider post-setup hooks", async () => {
|
|
const provider = buildProvider();
|
|
resolvePluginProviders.mockReturnValue([provider]);
|
|
resolveProviderPluginChoice.mockReturnValue({
|
|
provider,
|
|
method: provider.auth[0],
|
|
});
|
|
|
|
const result = await applyAuthChoiceLoadedPluginProvider(buildParams());
|
|
|
|
expect(result?.config.agents?.defaults?.model).toEqual({
|
|
primary: "ollama/qwen3:4b",
|
|
});
|
|
expect(upsertAuthProfile).toHaveBeenCalledWith({
|
|
profileId: "ollama:default",
|
|
credential: {
|
|
type: "api_key",
|
|
provider: "ollama",
|
|
key: "ollama-local",
|
|
},
|
|
agentDir: "/tmp/agent",
|
|
});
|
|
expect(runExtensionHostProviderModelSelectedHook).toHaveBeenCalledWith({
|
|
config: result?.config,
|
|
model: "ollama/qwen3:4b",
|
|
prompter: expect.objectContaining({ note: expect.any(Function) }),
|
|
agentDir: undefined,
|
|
workspaceDir: "/tmp/workspace",
|
|
});
|
|
});
|
|
|
|
it("merges provider config patches and emits provider notes", async () => {
|
|
applyAuthProfileConfig.mockImplementation(((
|
|
config: {
|
|
auth?: {
|
|
profiles?: Record<string, { provider: string; mode: string }>;
|
|
};
|
|
},
|
|
profile: { profileId: string; provider: string; mode: string },
|
|
) => ({
|
|
...config,
|
|
auth: {
|
|
profiles: {
|
|
...config.auth?.profiles,
|
|
[profile.profileId]: {
|
|
provider: profile.provider,
|
|
mode: profile.mode,
|
|
},
|
|
},
|
|
},
|
|
})) as never);
|
|
|
|
const note = vi.fn(async () => {});
|
|
const method: ProviderAuthMethod = {
|
|
id: "local",
|
|
label: "Local",
|
|
kind: "custom",
|
|
run: async () => ({
|
|
profiles: [
|
|
{
|
|
profileId: "ollama:default",
|
|
credential: {
|
|
type: "api_key",
|
|
provider: "ollama",
|
|
key: "ollama-local",
|
|
},
|
|
},
|
|
],
|
|
configPatch: {
|
|
models: {
|
|
providers: {
|
|
ollama: {
|
|
api: "ollama",
|
|
baseUrl: "http://127.0.0.1:11434",
|
|
models: [],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
defaultModel: "ollama/qwen3:4b",
|
|
notes: ["Detected local Ollama runtime.", "Pulled model metadata."],
|
|
}),
|
|
};
|
|
|
|
const result = await runProviderPluginAuthMethod({
|
|
config: {
|
|
agents: {
|
|
defaults: {
|
|
model: { primary: "anthropic/claude-sonnet-4-5" },
|
|
},
|
|
},
|
|
},
|
|
runtime: {} as ApplyAuthChoiceParams["runtime"],
|
|
prompter: {
|
|
note,
|
|
} as unknown as ApplyAuthChoiceParams["prompter"],
|
|
method,
|
|
});
|
|
|
|
expect(result.defaultModel).toBe("ollama/qwen3:4b");
|
|
expect(result.config.models?.providers?.ollama).toEqual({
|
|
api: "ollama",
|
|
baseUrl: "http://127.0.0.1:11434",
|
|
models: [],
|
|
});
|
|
expect(result.config.auth?.profiles?.["ollama:default"]).toEqual({
|
|
provider: "ollama",
|
|
mode: "api_key",
|
|
});
|
|
expect(note).toHaveBeenCalledWith(
|
|
"Detected local Ollama runtime.\nPulled model metadata.",
|
|
"Provider notes",
|
|
);
|
|
});
|
|
|
|
it("returns an agent-scoped override for plugin auth choices when default model application is deferred", async () => {
|
|
const provider = buildProvider();
|
|
resolvePluginProviders.mockReturnValue([provider]);
|
|
|
|
const note = vi.fn(async () => {});
|
|
const result = await applyAuthChoicePluginProvider(
|
|
buildParams({
|
|
authChoice: "provider-plugin:ollama:local",
|
|
agentId: "worker",
|
|
setDefaultModel: false,
|
|
prompter: {
|
|
note,
|
|
} as unknown as ApplyAuthChoiceParams["prompter"],
|
|
}),
|
|
{
|
|
authChoice: "provider-plugin:ollama:local",
|
|
pluginId: "ollama",
|
|
providerId: "ollama",
|
|
methodId: "local",
|
|
label: "Ollama",
|
|
},
|
|
);
|
|
|
|
expect(result?.agentModelOverride).toBe("ollama/qwen3:4b");
|
|
expect(result?.config.plugins).toEqual({
|
|
entries: {
|
|
ollama: {
|
|
enabled: true,
|
|
},
|
|
},
|
|
});
|
|
expect(runExtensionHostProviderModelSelectedHook).not.toHaveBeenCalled();
|
|
expect(note).toHaveBeenCalledWith(
|
|
'Default model set to ollama/qwen3:4b for agent "worker".',
|
|
"Model configured",
|
|
);
|
|
});
|
|
|
|
it("stops early when the plugin is disabled in config", async () => {
|
|
const note = vi.fn(async () => {});
|
|
|
|
const result = await applyAuthChoicePluginProvider(
|
|
buildParams({
|
|
config: {
|
|
plugins: {
|
|
enabled: false,
|
|
},
|
|
},
|
|
prompter: {
|
|
note,
|
|
} as unknown as ApplyAuthChoiceParams["prompter"],
|
|
}),
|
|
{
|
|
authChoice: "ollama",
|
|
pluginId: "ollama",
|
|
providerId: "ollama",
|
|
label: "Ollama",
|
|
},
|
|
);
|
|
|
|
expect(result).toEqual({
|
|
config: {
|
|
plugins: {
|
|
enabled: false,
|
|
},
|
|
},
|
|
});
|
|
expect(resolvePluginProviders).not.toHaveBeenCalled();
|
|
expect(note).toHaveBeenCalledWith("Ollama plugin is disabled (plugins disabled).", "Ollama");
|
|
});
|
|
});
|