feat(catalog): integrated baseten provider and updated model definitions

- Implement Baseten provider support with authentication and dynamic model discovery.
- Register Baseten in the model catalog and provider priority order.
- Expand model definitions with new DeepSeek, Kimi, NVIDIA, and Claude variants.
- Update model configurations, cost data, and provider-specific metadata.
This commit is contained in:
can1357
2026-07-03 05:52:04 +02:00
parent fbc6ecc44d
commit 4c18cc1a1a
11 changed files with 959 additions and 103 deletions
+4
View File
@@ -2,6 +2,10 @@
## [Unreleased]
### Added
- Added support for Baseten as an AI provider
## [16.3.3] - 2026-07-02
### Added
+22
View File
@@ -0,0 +1,22 @@
import { createApiKeyLogin } from "./api-key-login";
import type { OAuthLoginCallbacks } from "./oauth/types";
import type { ProviderDefinition } from "./types";
export const loginBaseten = createApiKeyLogin({
providerLabel: "Baseten",
authUrl: "https://app.baseten.co/settings/api_keys",
instructions: "Copy your API key from the Baseten dashboard",
promptMessage: "Paste your Baseten API key",
placeholder: "bt_...",
validation: {
kind: "models-endpoint",
provider: "Baseten",
modelsUrl: "https://inference.baseten.co/v1/models",
},
});
export const basetenProvider = {
id: "baseten",
name: "Baseten",
login: (cb: OAuthLoginCallbacks) => loginBaseten(cb),
} as const satisfies ProviderDefinition;
+2
View File
@@ -4,6 +4,7 @@ import { alibabaCodingPlanProvider } from "./alibaba-coding-plan";
import { amazonBedrockProvider } from "./amazon-bedrock";
import { anthropicProvider } from "./anthropic";
import { azureProvider } from "./azure";
import { basetenProvider } from "./baseten";
import { cerebrasProvider } from "./cerebras";
import { cloudflareAiGatewayProvider } from "./cloudflare-ai-gateway";
import { coreWeaveProvider } from "./coreweave";
@@ -105,6 +106,7 @@ const ALL = [
deepseekProvider,
moonshotProvider,
cerebrasProvider,
basetenProvider,
fireworksProvider,
togetherProvider,
nvidiaProvider,
+14
View File
@@ -2,6 +2,20 @@
## [Unreleased]
### Added
- Added Baseten as a supported model provider
- Added support for new models from Baseten, including DeepSeek V4 Pro and Kimi series
- Added new Devin agent models: Claude 5 Fable variants
- Added new Github Copilot models: Kimi K2.7 Code and MAI-Code-1-Flash
- Added Poolside Laguna XS 2.1 models via Kilo and OpenRouter providers
- Added support for Claude Fable 5 (Free) via Zenmux provider
### Changed
- Updated priority ordering to include Baseten
- Updated pricing and limits for various existing models in the catalog
## [16.3.3] - 2026-07-02
### Fixed
+5 -1
View File
@@ -187,7 +187,11 @@ function applyGlobalModelsDevFallback(
const providerScopedKeys = new Set(modelsDevModels.map(model => `${model.provider}/${model.id}`));
const globalReferences = createGlobalModelsDevReferenceMap(modelsDevModels);
return models.map(model => {
if (providerScopedKeys.has(`${model.provider}/${model.id}`) || model.provider === "devin") {
if (
providerScopedKeys.has(`${model.provider}/${model.id}`) ||
model.provider === "devin" ||
model.provider === "baseten"
) {
return model;
}
const reference = globalReferences.get(model.id);
+1
View File
@@ -47,6 +47,7 @@ export const KNOWN_HOSTS = {
xai: { providers: ["xai"], urlMarkers: ["api.x.ai"] },
mistral: { providers: ["mistral"], urlMarkers: ["mistral.ai"] },
together: { providers: ["together"], urlMarkers: ["api.together.xyz"] },
baseten: { providers: ["baseten"], urlMarkers: ["baseten.co"] },
/** URL-only on purpose: the `fireworks`/`firepass` providers route per-model and not every model is Fireworks-shaped. */
fireworks: { urlMarkers: ["fireworks.ai"] },
groq: { providers: ["groq"], urlMarkers: ["api.groq.com"] },
@@ -20,6 +20,7 @@ const DEFAULT_MODEL_PROVIDER_ORDER = [
// High-quality aggregators / hosted inference providers.
"fireworks",
"cerebras",
"baseten",
"openrouter",
"aimlapi",
"together",
File diff suppressed because it is too large Load Diff
@@ -12,6 +12,7 @@ import {
aimlApiModelManagerOptions,
alibabaCodingPlanModelManagerOptions,
anthropicModelManagerOptions,
basetenModelManagerOptions,
cerebrasModelManagerOptions,
cloudflareAiGatewayModelManagerOptions,
coreWeaveModelManagerOptions,
@@ -73,6 +74,14 @@ export const CATALOG_PROVIDERS = [
createModelManagerOptions: (config: ModelManagerConfig) => alibabaCodingPlanModelManagerOptions(config),
catalogDiscovery: { label: "Alibaba Coding Plan" },
},
{
id: "baseten",
defaultModel: "moonshotai/Kimi-K2.7-Code",
envVars: ["BASETEN_API_KEY"],
createModelManagerOptions: (config: ModelManagerConfig) => basetenModelManagerOptions(config),
dynamicModelsAuthoritative: true,
catalogDiscovery: { label: "Baseten" },
},
{
id: "amazon-bedrock",
defaultModel: "us.anthropic.claude-opus-4-8",
@@ -2551,6 +2551,103 @@ export function veniceModelManagerOptions(
};
}
// ---------------------------------------------------------------------------
// 14.5 Baseten
// ---------------------------------------------------------------------------
export interface BasetenModelManagerConfig {
apiKey?: string;
baseUrl?: string;
fetch?: FetchImpl;
}
export function basetenModelManagerOptions(
config?: BasetenModelManagerConfig,
): ModelManagerOptions<"openai-completions"> {
const apiKey = config?.apiKey;
const baseUrl = config?.baseUrl ?? "https://inference.baseten.co/v1";
const references = createBundledReferenceMap<"openai-completions">("baseten");
return {
providerId: "baseten",
dynamicModelsAuthoritative: true,
...(apiKey && {
fetchDynamicModels: () =>
fetchOpenAICompatibleModels({
api: "openai-completions",
provider: "baseten",
baseUrl,
apiKey,
mapModel: (entry, defaults) => {
const reference = references.get(defaults.id);
const raw = entry as Record<string, unknown> & {
supported_features?: unknown;
input_modalities?: unknown;
pricing?: Record<string, unknown>;
};
const features = Array.isArray(raw.supported_features) ? raw.supported_features : [];
const modalities = Array.isArray(raw.input_modalities) ? raw.input_modalities : [];
const isBasetenNativeReasoning =
defaults.id === "openai/gpt-oss-120b" ||
defaults.id === "deepseek-ai/DeepSeek-V4-Pro" ||
defaults.id === "zai-org/GLM-5.2";
const reasoning =
isBasetenNativeReasoning &&
(features.includes("reasoning") || features.includes("reasoning_effort"));
const supportsTools = features.includes("tools") ? undefined : false;
const vision = modalities.includes("image") || (reference?.input.includes("image") ?? false);
const pricing = raw.pricing ?? {};
const cost = {
input: toPositiveNumber(pricing.prompt, 0) * 1_000_000,
output: toPositiveNumber(pricing.completion, 0) * 1_000_000,
cacheRead: toPositiveNumber(pricing.input_cache_read, 0) * 1_000_000,
cacheWrite: 0,
};
const contextWindow = toPositiveNumber(
raw.context_length,
reference?.contextWindow ?? defaults.contextWindow,
);
const maxTokens = toPositiveNumber(
raw.max_completion_tokens,
reference?.maxTokens ?? defaults.maxTokens,
);
const baseModel = mapWithBundledReference(entry, defaults, reference);
const isEffortReasoning = defaults.id === "openai/gpt-oss-120b" || defaults.id === "zai-org/GLM-5.2";
const thinking = isEffortReasoning
? {
mode: "effort" as const,
efforts: [Effort.Minimal, Effort.Low, Effort.Medium, Effort.High, Effort.XHigh],
effortMap: {
minimal: "high",
low: "high",
medium: "high",
high: "high",
xhigh: "max",
},
}
: undefined;
return {
...baseModel,
reasoning,
input: vision ? ["text", "image"] : ["text"],
cost,
contextWindow,
maxTokens,
...(thinking ? { thinking } : {}),
...(supportsTools === false ? { supportsTools } : {}),
};
},
fetch: config?.fetch,
}),
}),
};
}
// ---------------------------------------------------------------------------
// 15. Together
// ---------------------------------------------------------------------------
@@ -0,0 +1,97 @@
import { describe, expect, test } from "bun:test";
import { basetenModelManagerOptions } from "@oh-my-pi/pi-catalog/provider-models/openai-compat";
import type { FetchImpl } from "@oh-my-pi/pi-catalog/types";
describe("Baseten provider discovery", () => {
test("discovers Baseten models with custom metadata", async () => {
const calls: Array<{ url: string; authorization: string | null }> = [];
const fetchMock: FetchImpl = async (input: string | URL | Request, init?: RequestInit) => {
const headers = new Headers(init?.headers);
calls.push({
url: String(input),
authorization: headers.get("authorization"),
});
return new Response(
JSON.stringify({
data: [
{
id: "moonshotai/Kimi-K2.7-Code",
object: "model",
name: "Kimi K2.7 Code",
context_length: 262000,
max_completion_tokens: 262000,
supported_features: ["tools", "json_mode", "structured_outputs", "reasoning"],
input_modalities: ["text", "image"],
pricing: {
prompt: "0.00000095",
completion: "0.000004",
input_cache_read: "0.00000016",
},
},
{
id: "deepseek-ai/DeepSeek-V4-Pro",
object: "model",
name: "DeepSeek V4 Pro",
context_length: 262144,
max_completion_tokens: 262144,
supported_features: ["tools", "json_mode", "structured_outputs", "reasoning"],
input_modalities: ["text"],
pricing: {
prompt: "0.00000174",
completion: "0.00000348",
input_cache_read: "0.000000145",
},
},
],
}),
{ status: 200, headers: { "content-type": "application/json" } },
);
};
const options = basetenModelManagerOptions({ apiKey: "baseten-test-key", fetch: fetchMock });
const models = await options.fetchDynamicModels?.();
expect(calls).toEqual([
{
url: "https://inference.baseten.co/v1/models",
authorization: "Bearer baseten-test-key",
},
]);
const kimi = models?.find(model => model.id === "moonshotai/Kimi-K2.7-Code");
expect(kimi).toBeDefined();
expect(kimi).toMatchObject({
provider: "baseten",
api: "openai-completions",
name: "Kimi K2.7 Code",
reasoning: false,
input: ["text", "image"],
contextWindow: 262000,
maxTokens: 262000,
cost: {
input: 0.95,
output: 4,
cacheRead: 0.16,
cacheWrite: 0,
},
});
const deepseek = models?.find(model => model.id === "deepseek-ai/DeepSeek-V4-Pro");
expect(deepseek).toBeDefined();
expect(deepseek).toMatchObject({
provider: "baseten",
api: "openai-completions",
name: "DeepSeek V4 Pro",
reasoning: true,
input: ["text"],
contextWindow: 262144,
maxTokens: 262144,
cost: {
input: 1.74,
output: 3.48,
cacheRead: 0.145,
cacheWrite: 0,
},
});
});
});