Auto-select default model and clean package conflicts

This commit is contained in:
Advait Paliwal
2026-03-20 11:29:21 -07:00
parent 389baf06f2
commit 4bb1823a20
3 changed files with 86 additions and 13 deletions

View File

@@ -101,6 +101,80 @@ function patchEmbeddedPiBranding(piPackageRoot: string): void {
}
}
function choosePreferredModel(
availableModels: Array<{ provider: string; id: string }>,
): { provider: string; id: string } | undefined {
const preferences = [
{ provider: "anthropic", id: "claude-opus-4-6" },
{ provider: "anthropic", id: "claude-opus-4-5" },
{ provider: "anthropic", id: "claude-sonnet-4-5" },
{ provider: "openai", id: "gpt-5.4" },
{ provider: "openai", id: "gpt-5" },
];
for (const preferred of preferences) {
const match = availableModels.find(
(model) => model.provider === preferred.provider && model.id === preferred.id,
);
if (match) {
return match;
}
}
return availableModels[0];
}
function normalizeFeynmanSettings(
settingsPath: string,
bundledSettingsPath: string,
defaultThinkingLevel: ThinkingLevel,
authPath: string,
): void {
let settings: Record<string, unknown> = {};
if (existsSync(settingsPath)) {
try {
settings = JSON.parse(readFileSync(settingsPath, "utf8"));
} catch {
settings = {};
}
}
else if (existsSync(bundledSettingsPath)) {
try {
settings = JSON.parse(readFileSync(bundledSettingsPath, "utf8"));
} catch {
settings = {};
}
}
if (Array.isArray(settings.packages)) {
settings.packages = settings.packages.filter(
(entry) => entry !== "npm:@kaiserlich-dev/pi-session-search",
);
}
if (!settings.defaultThinkingLevel) {
settings.defaultThinkingLevel = defaultThinkingLevel;
}
const authStorage = AuthStorage.create(authPath);
const modelRegistry = new ModelRegistry(authStorage);
const availableModels = modelRegistry.getAvailable().map((model) => ({
provider: model.provider,
id: model.id,
}));
if ((!settings.defaultProvider || !settings.defaultModel) && availableModels.length > 0) {
const preferredModel = choosePreferredModel(availableModels);
if (preferredModel) {
settings.defaultProvider = preferredModel.provider;
settings.defaultModel = preferredModel.id;
}
}
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
}
async function main(): Promise<void> {
const here = dirname(fileURLToPath(import.meta.url));
const appRoot = resolve(here, "..");
@@ -131,8 +205,18 @@ async function main(): Promise<void> {
return;
}
const workingDir = resolve(values.cwd ?? process.cwd());
const sessionDir = resolve(values["session-dir"] ?? resolve(homedir(), ".feynman", "sessions"));
mkdirSync(sessionDir, { recursive: true });
mkdirSync(feynmanAgentDir, { recursive: true });
const feynmanSettingsPath = resolve(feynmanAgentDir, "settings.json");
const feynmanAuthPath = resolve(feynmanAgentDir, "auth.json");
const thinkingLevel = normalizeThinkingLevel(values.thinking ?? process.env.FEYNMAN_THINKING) ?? "medium";
normalizeFeynmanSettings(feynmanSettingsPath, bundledSettingsPath, thinkingLevel, feynmanAuthPath);
if (values["alpha-login"]) {
const result = await loginAlpha();
normalizeFeynmanSettings(feynmanSettingsPath, bundledSettingsPath, thinkingLevel, feynmanAuthPath);
const name =
(result.userInfo &&
typeof result.userInfo === "object" &&
@@ -160,25 +244,14 @@ async function main(): Promise<void> {
return;
}
const workingDir = resolve(values.cwd ?? process.cwd());
const sessionDir = resolve(values["session-dir"] ?? resolve(homedir(), ".feynman", "sessions"));
mkdirSync(sessionDir, { recursive: true });
mkdirSync(feynmanAgentDir, { recursive: true });
const feynmanSettingsPath = resolve(feynmanAgentDir, "settings.json");
if (!existsSync(feynmanSettingsPath) && existsSync(bundledSettingsPath)) {
writeFileSync(feynmanSettingsPath, readFileSync(bundledSettingsPath, "utf8"), "utf8");
}
const explicitModelSpec = values.model ?? process.env.FEYNMAN_MODEL;
if (explicitModelSpec) {
const modelRegistry = new ModelRegistry(AuthStorage.create());
const modelRegistry = new ModelRegistry(AuthStorage.create(feynmanAuthPath));
const explicitModel = parseModelSpec(explicitModelSpec, modelRegistry);
if (!explicitModel) {
throw new Error(`Unknown model: ${explicitModelSpec}`);
}
}
const thinkingLevel = normalizeThinkingLevel(values.thinking ?? process.env.FEYNMAN_THINKING) ?? "medium";
const oneShotPrompt = values.prompt;
const initialPrompt = oneShotPrompt ?? (positionals.length > 0 ? positionals.join(" ") : undefined);