Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fair-moonshotai.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"workers-ai-provider": patch
---

Support Moonshot AI unified billing catalog slugs such as `moonshotai/kimi-k3`.
11 changes: 11 additions & 0 deletions packages/gateway-core/src/gateway-providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,17 @@ export const GATEWAY_PROVIDERS: GatewayProviderInfo[] = [
billing: "unified",
authHeaders: ["authorization"],
},
{
// Moonshot AI / Kimi is served by the unified billing run catalog using
// the OpenAI-compatible response format. It has no native gateway path.
resolverKey: "moonshotai",
gatewayProviderId: "moonshotai",
wireFormat: "openai",
runCatalog: true,
gatewayPath: false,
billing: "unified",
authHeaders: ["authorization"],
},
{
resolverKey: "google-vertex",
gatewayProviderId: "google-vertex-ai",
Expand Down
10 changes: 10 additions & 0 deletions packages/gateway-core/test/gateway-providers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ describe("findProviderBySlug", () => {
expect(findProviderBySlug("azure")?.resolverKey).toBe("azure-openai");
});

it("resolves the Moonshot AI unified catalog slug", () => {
expect(findProviderBySlug("moonshotai")).toMatchObject({
gatewayProviderId: "moonshotai",
wireFormat: "openai",
runCatalog: true,
gatewayPath: false,
billing: "unified",
});
});

it("maps google ⇒ google-ai-studio gateway id, anthropic native run wire", () => {
expect(findProviderBySlug("google")?.gatewayProviderId).toBe("google-ai-studio");
const anthropic = findProviderBySlug("anthropic");
Expand Down
8 changes: 6 additions & 2 deletions packages/workers-ai-provider/test/gateway-delegate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ describe("createGatewayDelegate", () => {
);
});

it("builds alibaba + minimax on the run path with the openai plugin", () => {
it("builds unified run-only providers with the openai plugin", () => {
const { binding } = makeBinding();
const wai = createGatewayDelegate({
binding,
Expand All @@ -353,6 +353,7 @@ describe("createGatewayDelegate", () => {
// so a single openai plugin is enough.
expect(wai("alibaba/qwen3-max").modelId).toBe("qwen3-max");
expect(wai("minimax/m3").modelId).toBe("m3");
expect(wai("moonshotai/kimi-k3").modelId).toBe("kimi-k3");
});

it("rejects gateway-path use of a run-only provider with a clear error", () => {
Expand All @@ -362,10 +363,13 @@ describe("createGatewayDelegate", () => {
gateway: "default",
providers: [capturePlugin("openai").plugin],
});
// alibaba/minimax have no gateway path — caching, server fallback, and
// run-only providers have no gateway path — caching, server fallback, and
// transport:"gateway" must fail fast at build time, not upstream.
expect(() => wai("alibaba/qwen3-max", { transport: "gateway" })).toThrow(/no gateway path/);
expect(() => wai("alibaba/qwen3-max", { cacheTtl: 60 })).toThrow(/no gateway path/);
expect(() => wai("moonshotai/kimi-k3", { transport: "gateway" })).toThrow(
/no gateway path/,
);
expect(() =>
wai("minimax/m3", { fallback: { mode: "server", models: ["minimax/m2.7"] } }),
).toThrow(/no gateway path/);
Expand Down
7 changes: 4 additions & 3 deletions packages/workers-ai-provider/test/gateway-providers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ describe("gateway provider registry", () => {
.map((p) => p.resolverKey)
.sort();
// The headline directory set (openai/anthropic/google/xai/groq), the
// run-only unified chat providers alibaba + minimax, and deepseek — the one
// run-only unified chat providers alibaba + minimax + moonshotai, and deepseek — the one
// OpenAI-wire long-tail provider actually on the unified `env.AI.run` catalog
// (#596). The rest of the long tail (mistral/perplexity/cerebras/openrouter/
// fireworks) is BYOK gateway-path only, verified by the e2e run-path probe.
Expand All @@ -216,13 +216,14 @@ describe("gateway provider registry", () => {
"google",
"groq",
"minimax",
"moonshotai",
"openai",
"xai",
]);
});

it("adds alibaba + minimax as run-only openai-wire chat providers", () => {
for (const slug of ["alibaba", "minimax"]) {
it("adds run-only openai-wire chat providers", () => {
for (const slug of ["alibaba", "minimax", "moonshotai"]) {
const info = findProviderBySlug(slug);
expect(info, slug).toMatchObject({
runCatalog: true,
Expand Down