78 lines
2.9 KiB
TypeScript
78 lines
2.9 KiB
TypeScript
import type { Api, Model } from "@mariozechner/pi-ai";
|
|
import { discoverAuthStorage, discoverModels } from "@mariozechner/pi-coding-agent";
|
|
|
|
import type { ClawdbotConfig } from "../../config/config.js";
|
|
import { resolveClawdbotAgentDir } from "../agent-paths.js";
|
|
import { DEFAULT_CONTEXT_TOKENS } from "../defaults.js";
|
|
import { normalizeModelCompat } from "../model-compat.js";
|
|
|
|
export function buildModelAliasLines(cfg?: ClawdbotConfig) {
|
|
const models = cfg?.agents?.defaults?.models ?? {};
|
|
const entries: Array<{ alias: string; model: string }> = [];
|
|
for (const [keyRaw, entryRaw] of Object.entries(models)) {
|
|
const model = String(keyRaw ?? "").trim();
|
|
if (!model) continue;
|
|
const alias = String((entryRaw as { alias?: string } | undefined)?.alias ?? "").trim();
|
|
if (!alias) continue;
|
|
entries.push({ alias, model });
|
|
}
|
|
return entries
|
|
.sort((a, b) => a.alias.localeCompare(b.alias))
|
|
.map((entry) => `- ${entry.alias}: ${entry.model}`);
|
|
}
|
|
|
|
export function resolveModel(
|
|
provider: string,
|
|
modelId: string,
|
|
agentDir?: string,
|
|
cfg?: ClawdbotConfig,
|
|
): {
|
|
model?: Model<Api>;
|
|
error?: string;
|
|
authStorage: ReturnType<typeof discoverAuthStorage>;
|
|
modelRegistry: ReturnType<typeof discoverModels>;
|
|
} {
|
|
const resolvedAgentDir = agentDir ?? resolveClawdbotAgentDir();
|
|
const authStorage = discoverAuthStorage(resolvedAgentDir);
|
|
const modelRegistry = discoverModels(authStorage, resolvedAgentDir);
|
|
const model = modelRegistry.find(provider, modelId) as Model<Api> | null;
|
|
if (!model) {
|
|
const providers = cfg?.models?.providers ?? {};
|
|
const inlineModels =
|
|
providers[provider]?.models ??
|
|
Object.values(providers)
|
|
.flatMap((entry) => entry?.models ?? [])
|
|
.map((entry) => ({ ...entry, provider }));
|
|
const inlineMatch = inlineModels.find((entry) => entry.id === modelId);
|
|
if (inlineMatch) {
|
|
const normalized = normalizeModelCompat(inlineMatch as Model<Api>);
|
|
return {
|
|
model: normalized,
|
|
authStorage,
|
|
modelRegistry,
|
|
};
|
|
}
|
|
const providerCfg = providers[provider];
|
|
if (providerCfg || modelId.startsWith("mock-")) {
|
|
const fallbackModel: Model<Api> = normalizeModelCompat({
|
|
id: modelId,
|
|
name: modelId,
|
|
api: providerCfg?.api ?? "openai-responses",
|
|
provider,
|
|
reasoning: false,
|
|
input: ["text"],
|
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
contextWindow: providerCfg?.models?.[0]?.contextWindow ?? DEFAULT_CONTEXT_TOKENS,
|
|
maxTokens: providerCfg?.models?.[0]?.maxTokens ?? DEFAULT_CONTEXT_TOKENS,
|
|
} as Model<Api>);
|
|
return { model: fallbackModel, authStorage, modelRegistry };
|
|
}
|
|
return {
|
|
error: `Unknown model: ${provider}/${modelId}`,
|
|
authStorage,
|
|
modelRegistry,
|
|
};
|
|
}
|
|
return { model: normalizeModelCompat(model), authStorage, modelRegistry };
|
|
}
|