lmc/src/config/index.ts

79 lines
2.1 KiB
TypeScript

import fs from "node:fs/promises";
import os from "node:os";
import { autocomplete, intro, isCancel, outro, text } from "@clack/prompts";
import chalk from "chalk";
const home = os.homedir();
const configPath = `${home}/.lmc_config.json`;
export interface AppConfig {
baseURL: string;
model: string;
}
export async function initConfig(old: AppConfig | null): Promise<AppConfig> {
console.log();
intro(chalk.blue("Welcome to LMC. Let's make a new config!"));
const baseURL = await text({
message: "What's your base URL:",
defaultValue: old?.baseURL ?? "http://127.0.0.1:8080/v1",
placeholder: old?.baseURL ?? "http://127.0.0.1:8080/v1",
});
if (isCancel(baseURL)) process.exit(1);
const models = await getModels(baseURL);
const initialValue = models.includes(old?.model ?? "")
? old?.model
: models[0];
const model = await autocomplete({
message: "Choose a default model:",
initialValue,
placeholder: initialValue ?? "Start typing...",
options: models.map((model) => ({ value: model })),
validate: (value) =>
models.includes(typeof value === "string" ? value : "")
? undefined
: `Unable to find model "${value}"`,
});
if (!model || isCancel(model)) process.exit(1);
const config = { baseURL, model } satisfies AppConfig;
await fs.writeFile(configPath, JSON.stringify(config, null, " "));
outro(chalk.green("Configuration saved!"));
return config;
}
type Models = {
data: {
created: number;
id: string;
object: "model";
owned_by: string;
}[];
};
async function getModels(url: string) {
const response = await fetch(`${url}/models`);
const models = (await response.json()) as Models;
return models.data.map((model) => model.id);
}
export async function loadConfig(
configFlag: boolean | undefined,
): Promise<AppConfig | null> {
let config: AppConfig;
try {
const text = await fs.readFile(configPath, "utf8");
config = JSON.parse(text);
} catch {
if (configFlag) return null;
console.error(`Config not found at ${configPath}`);
return null;
}
return config;
}