diff --git a/src/integrations/pi.ts b/src/integrations/pi.ts index 2eaf36c..9f13045 100644 --- a/src/integrations/pi.ts +++ b/src/integrations/pi.ts @@ -10,8 +10,10 @@ type PiModelEntry = { contextWindow?: number; name?: string; input?: string[]; - // Preserve arbitrary manual fields (reasoning, thinkingLevelMap, compat, cost, etc.) - [key: string]: unknown; + // Thinking/reasoning config is user-curated and preserved across refreshes. + reasoning?: boolean; + thinkingLevelMap?: Record; + compat?: Record; }; type PiProviderConfig = { @@ -65,29 +67,24 @@ export async function installPiIntegration( return; } - // Preserve any manually-added per-model fields (reasoning, thinkingLevelMap, - // compat, cost, maxTokens, etc.) across refreshes. Only `id` and `contextWindow` - // are managed by routstrd. + // Rebuild every model entry from scratch from the daemon, so the generated + // models.json is always a faithful projection of the daemon's state. The only + // exception is thinking/reasoning config (reasoning, thinkingLevelMap, compat), + // which the daemon does not provide and the user curates by hand — preserve it. const existingModels = new Map( (piConfig.providers["routstr"]?.models ?? []).map((m) => [m.id, m]), ); const providerModels: PiModelEntry[] = models.map((model) => { const previous = existingModels.get(model.id); - const entry: PiModelEntry = previous ? { ...previous } : { id: model.id }; - - entry.id = model.id; + const entry: PiModelEntry = { id: model.id }; if (model.context_length !== undefined && model.context_length > 0) { entry.contextWindow = model.context_length; - } else { - delete entry.contextWindow; } if (model.name) { entry.name = model.name; - } else { - delete entry.name; } // Map the daemon's input modalities to Pi's ["text", "image"] vocabulary. @@ -97,13 +94,16 @@ export async function installPiIntegration( if (mods.includes("image")) input.push("image"); entry.input = input; + // Preserve user-curated thinking fields from the previous entry. + if (previous?.reasoning !== undefined) entry.reasoning = previous.reasoning; + if (previous?.thinkingLevelMap !== undefined) entry.thinkingLevelMap = previous.thinkingLevelMap; + if (previous?.compat !== undefined) entry.compat = previous.compat; + return entry; }); - // Preserve provider-level manual fields (compat, headers, name, etc.); only update - // the routstrd-managed fields below. + // Rebuild provider from scratch too; only write routstrd-managed fields. piConfig.providers["routstr"] = { - ...(piConfig.providers["routstr"] ?? {}), baseUrl, api: "openai-completions", apiKey,