mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-11 01:01:13 +00:00
180 lines
5.7 KiB
TypeScript
180 lines
5.7 KiB
TypeScript
import type { StreamFn } from "@mariozechner/pi-agent-core";
|
|
import type { Context, Model } from "@mariozechner/pi-ai";
|
|
import { describe, expect, it, vi } from "vitest";
|
|
import {
|
|
registerProviderPlugin,
|
|
requireRegisteredProvider,
|
|
} from "../../test/helpers/plugins/provider-registration.js";
|
|
import minimaxPlugin from "./index.js";
|
|
|
|
describe("minimax provider hooks", () => {
|
|
it("keeps native reasoning mode for MiniMax transports", async () => {
|
|
const { providers } = await registerProviderPlugin({
|
|
plugin: minimaxPlugin,
|
|
id: "minimax",
|
|
name: "MiniMax Provider",
|
|
});
|
|
const apiProvider = requireRegisteredProvider(providers, "minimax");
|
|
const portalProvider = requireRegisteredProvider(providers, "minimax-portal");
|
|
|
|
expect(apiProvider.hookAliases).toContain("minimax-cn");
|
|
expect(
|
|
apiProvider.resolveReasoningOutputMode?.({
|
|
provider: "minimax",
|
|
modelApi: "anthropic-messages",
|
|
modelId: "MiniMax-M2.7",
|
|
} as never),
|
|
).toBe("native");
|
|
|
|
expect(portalProvider.hookAliases).toContain("minimax-portal-cn");
|
|
expect(
|
|
portalProvider.resolveReasoningOutputMode?.({
|
|
provider: "minimax-portal",
|
|
modelApi: "anthropic-messages",
|
|
modelId: "MiniMax-M2.7",
|
|
} as never),
|
|
).toBe("native");
|
|
});
|
|
|
|
it("owns replay policy for Anthropic and OpenAI-compatible MiniMax transports", async () => {
|
|
const { providers } = await registerProviderPlugin({
|
|
plugin: minimaxPlugin,
|
|
id: "minimax",
|
|
name: "MiniMax Provider",
|
|
});
|
|
const apiProvider = requireRegisteredProvider(providers, "minimax");
|
|
const portalProvider = requireRegisteredProvider(providers, "minimax-portal");
|
|
|
|
expect(
|
|
apiProvider.buildReplayPolicy?.({
|
|
provider: "minimax",
|
|
modelApi: "anthropic-messages",
|
|
modelId: "MiniMax-M2.7",
|
|
} as never),
|
|
).toMatchObject({
|
|
sanitizeMode: "full",
|
|
sanitizeToolCallIds: true,
|
|
preserveSignatures: true,
|
|
validateAnthropicTurns: true,
|
|
});
|
|
|
|
expect(
|
|
portalProvider.buildReplayPolicy?.({
|
|
provider: "minimax-portal",
|
|
modelApi: "openai-completions",
|
|
modelId: "MiniMax-M2.7",
|
|
} as never),
|
|
).toMatchObject({
|
|
sanitizeToolCallIds: true,
|
|
toolCallIdMode: "strict",
|
|
applyAssistantFirstOrderingFix: true,
|
|
validateGeminiTurns: true,
|
|
validateAnthropicTurns: true,
|
|
});
|
|
});
|
|
|
|
it("owns fast-mode stream wrapping for MiniMax transports", async () => {
|
|
const { providers } = await registerProviderPlugin({
|
|
plugin: minimaxPlugin,
|
|
id: "minimax",
|
|
name: "MiniMax Provider",
|
|
});
|
|
const apiProvider = requireRegisteredProvider(providers, "minimax");
|
|
const portalProvider = requireRegisteredProvider(providers, "minimax-portal");
|
|
|
|
let resolvedApiModelId = "";
|
|
const captureApiModel: StreamFn = (model) => {
|
|
resolvedApiModelId = String(model.id ?? "");
|
|
return {} as ReturnType<StreamFn>;
|
|
};
|
|
const wrappedApiStream = apiProvider.wrapStreamFn?.({
|
|
provider: "minimax",
|
|
modelId: "MiniMax-M2.7",
|
|
extraParams: { fastMode: true },
|
|
streamFn: captureApiModel,
|
|
} as never);
|
|
|
|
void wrappedApiStream?.(
|
|
{
|
|
api: "anthropic-messages",
|
|
provider: "minimax",
|
|
id: "MiniMax-M2.7",
|
|
} as Model<"anthropic-messages">,
|
|
{ messages: [] } as Context,
|
|
{},
|
|
);
|
|
|
|
let resolvedPortalModelId = "";
|
|
const capturePortalModel: StreamFn = (model) => {
|
|
resolvedPortalModelId = String(model.id ?? "");
|
|
return {} as ReturnType<StreamFn>;
|
|
};
|
|
const wrappedPortalStream = portalProvider.wrapStreamFn?.({
|
|
provider: "minimax-portal",
|
|
modelId: "MiniMax-M2.7",
|
|
extraParams: { fastMode: true },
|
|
streamFn: capturePortalModel,
|
|
} as never);
|
|
|
|
void wrappedPortalStream?.(
|
|
{
|
|
api: "anthropic-messages",
|
|
provider: "minimax-portal",
|
|
id: "MiniMax-M2.7",
|
|
} as Model<"anthropic-messages">,
|
|
{ messages: [] } as Context,
|
|
{},
|
|
);
|
|
|
|
expect(resolvedApiModelId).toBe("MiniMax-M2.7-highspeed");
|
|
expect(resolvedPortalModelId).toBe("MiniMax-M2.7-highspeed");
|
|
});
|
|
|
|
it("registers the bundled MiniMax web search provider", () => {
|
|
const webSearchProviders: unknown[] = [];
|
|
|
|
minimaxPlugin.register({
|
|
registerProvider() {},
|
|
registerMediaUnderstandingProvider() {},
|
|
registerImageGenerationProvider() {},
|
|
registerSpeechProvider() {},
|
|
registerWebSearchProvider(provider: unknown) {
|
|
webSearchProviders.push(provider);
|
|
},
|
|
} as never);
|
|
|
|
expect(webSearchProviders).toHaveLength(1);
|
|
expect(webSearchProviders[0]).toMatchObject({
|
|
id: "minimax",
|
|
label: "MiniMax Search",
|
|
envVars: ["MINIMAX_CODE_PLAN_KEY", "MINIMAX_CODING_API_KEY"],
|
|
});
|
|
});
|
|
|
|
it("prefers minimax-portal oauth when resolving MiniMax usage auth", async () => {
|
|
const { providers } = await registerProviderPlugin({
|
|
plugin: minimaxPlugin,
|
|
id: "minimax",
|
|
name: "MiniMax Provider",
|
|
});
|
|
const apiProvider = requireRegisteredProvider(providers, "minimax");
|
|
const resolveOAuthToken = vi.fn(async (params?: { provider?: string }) =>
|
|
params?.provider === "minimax-portal" ? { token: "portal-oauth-token" } : null,
|
|
);
|
|
const resolveApiKeyFromConfigAndStore = vi.fn(() => undefined);
|
|
|
|
await expect(
|
|
apiProvider.resolveUsageAuth?.({
|
|
provider: "minimax",
|
|
config: {},
|
|
env: {},
|
|
resolveOAuthToken,
|
|
resolveApiKeyFromConfigAndStore,
|
|
} as never),
|
|
).resolves.toEqual({ token: "portal-oauth-token" });
|
|
|
|
expect(resolveOAuthToken).toHaveBeenCalledWith({ provider: "minimax-portal" });
|
|
expect(resolveApiKeyFromConfigAndStore).not.toHaveBeenCalled();
|
|
});
|
|
});
|