106 lines
3.9 KiB
TypeScript
106 lines
3.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 type { ModelDefinitionConfig } from "../../config/types.js";
|
|
import { resolveClawdbotAgentDir } from "../agent-paths.js";
|
|
import { DEFAULT_CONTEXT_TOKENS } from "../defaults.js";
|
|
import { normalizeModelCompat } from "../model-compat.js";
|
|
import { normalizeProviderId } from "../model-selection.js";
|
|
import { resolveGithubCopilotUserAgent } from "../../providers/github-copilot-utils.js";
|
|
|
|
type InlineModelEntry = ModelDefinitionConfig & { provider: string };
|
|
|
|
function applyProviderModelOverrides(model: Model<Api>): Model<Api> {
|
|
if (model.provider === "github-copilot") {
|
|
const headers = model.headers
|
|
? { ...model.headers, "User-Agent": resolveGithubCopilotUserAgent() }
|
|
: { "User-Agent": resolveGithubCopilotUserAgent() };
|
|
return { ...model, headers };
|
|
}
|
|
return model;
|
|
}
|
|
|
|
export function buildInlineProviderModels(
|
|
providers: Record<string, { models?: ModelDefinitionConfig[] }>,
|
|
): InlineModelEntry[] {
|
|
return Object.entries(providers).flatMap(([providerId, entry]) => {
|
|
const trimmed = providerId.trim();
|
|
if (!trimmed) return [];
|
|
return (entry?.models ?? []).map((model) => ({ ...model, provider: trimmed }));
|
|
});
|
|
}
|
|
|
|
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 = buildInlineProviderModels(providers);
|
|
const normalizedProvider = normalizeProviderId(provider);
|
|
const inlineMatch = inlineModels.find(
|
|
(entry) => normalizeProviderId(entry.provider) === normalizedProvider && entry.id === modelId,
|
|
);
|
|
if (inlineMatch) {
|
|
const normalized = normalizeModelCompat(inlineMatch as Model<Api>);
|
|
return {
|
|
model: applyProviderModelOverrides(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: applyProviderModelOverrides(fallbackModel), authStorage, modelRegistry };
|
|
}
|
|
return {
|
|
error: `Unknown model: ${provider}/${modelId}`,
|
|
authStorage,
|
|
modelRegistry,
|
|
};
|
|
}
|
|
return {
|
|
model: applyProviderModelOverrides(normalizeModelCompat(model)),
|
|
authStorage,
|
|
modelRegistry,
|
|
};
|
|
}
|