Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

extensions/klaus/src/models.ts

Raw
import type {
	AnthropicMessagesCompat,
	Api,
	Model,
} from "@earendil-works/pi-ai";
import {
	getBuiltinModel,
	getBuiltinModels,
} from "@earendil-works/pi-ai/providers/all";
import type { ProviderModelConfig } from "@earendil-works/pi-coding-agent";
import { dbg } from "./debug.js";

const FABLE_FALLBACK_IDS = ["claude-opus-4-8", "claude-opus-5"] as const;

/** Dated snapshot ids (e.g. `claude-opus-4-5-20251101`) stay hidden; the
 * current id of each family is always projected. */
export function isProjectableClaudeModel(model: Model<Api>): boolean {
	return (
		model.provider === "anthropic" &&
		!/-\d{8}$/.test(model.id) &&
		!model.id.endsWith("-latest")
	);
}

/** Pi catalog entries may be tuned for the direct Anthropic API, where request
 * headers unlock capacity that the Claude Agent SDK path does not provide.
 * Klaus drops those headers, so it must not advertise more than the builtin
 * catalog promises for the same model. */
/** Typed escape hatch: catalog lookups accept only literal ids at the type
 * level, but klaus passes runtime catalog ids from enumerations. */
function builtinAnthropic(modelId: string): Model<Api> | undefined {
	return getBuiltinModel(
		"anthropic",
		modelId as Parameters<typeof getBuiltinModel>[1],
	) as Model<Api> | undefined;
}

function clampToBaseline(
	field: "contextWindow" | "maxTokens",
	value: number,
	baseline: Model<Api> | undefined,
): number {
	const ceiling = baseline?.[field];
	if (ceiling === undefined || value <= ceiling) return value;
	dbg?.("models.clamp");
	return ceiling;
}

function fableCompat(model: Model<Api>): Model<Api>["compat"] {
	return {
		...(structuredClone(model.compat) as AnthropicMessagesCompat),
		allowedFallbackModels: FABLE_FALLBACK_IDS.flatMap((id) => {
			const fallback = getBuiltinModel("anthropic", id);
			return fallback
				? [
						{
							provider: "anthropic",
							model: id,
							cost: structuredClone(fallback.cost),
						},
					]
				: [];
		}),
	} satisfies AnthropicMessagesCompat;
}

/** Project one Pi Anthropic model onto the Klaus provider. Transport-owned
 * fields (`api`, `baseUrl`, `headers`, sampling parameters) are never
 * inherited, because the Claude Agent SDK owns the request. */
export function projectModel(model: Model<Api>): ProviderModelConfig {
	dbg?.("models.projectModel");
	const baseline = builtinAnthropic(model.id);
	return {
		id: model.id,
		name: model.name,
		reasoning: model.reasoning,
		thinkingLevelMap: model.thinkingLevelMap,
		input: [...model.input],
		cost: structuredClone(model.cost),
		compat:
			model.id === "claude-fable-5-1"
				? fableCompat(model)
				: structuredClone(model.compat),
		contextWindow: clampToBaseline(
			"contextWindow",
			model.contextWindow,
			baseline,
		),
		maxTokens: clampToBaseline("maxTokens", model.maxTokens, baseline),
	};
}

/** Project every projectable Claude model from a catalog enumeration. */
export function projectModels(models: Model<Api>[]): ProviderModelConfig[] {
	const projected = models.filter(isProjectableClaudeModel).map(projectModel);
	dbg?.("models.projectModels", { count: projected.length });
	return projected;
}

/** Startup projection from Pi's builtin catalog before any session exists. */
export function projectBuiltinModels(): ProviderModelConfig[] {
	return projectModels(getBuiltinModels("anthropic"));
}

/** Stable identity of a projected catalog, used to skip redundant provider
 * registrations. */
export function modelsSignature(models: ProviderModelConfig[]): string {
	return JSON.stringify(models);
}