Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

extensions/web/settings.ts

Raw
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
import {
	resolveSetting,
	type SettingDeclaration,
	type SettingResult,
} from "./src/pi-ext-settings.ts";

export type SettingsContext = Pick<
	ExtensionContext,
	"cwd" | "isProjectTrusted"
>;
export type ZaiSearchFreshness = "day" | "week" | "month" | "year";

// No web setting has a CLI flag.
const NO_FLAGS = { getFlag: () => undefined };
const NO_FRESHNESS = new Set(["", "none", "nolimit", "no_limit"]);
const FRESHNESS = new Set(["day", "week", "month", "year"]);

function parseText(raw: unknown): string {
	const value = typeof raw === "string" ? raw.trim() : "";
	if (!value) throw new Error("expected a non-empty string");
	return value;
}

function parseFreshness(raw: unknown): ZaiSearchFreshness | null {
	const value = typeof raw === "string" ? raw.trim().toLowerCase() : undefined;
	if (value !== undefined && NO_FRESHNESS.has(value)) return null;
	if (value !== undefined && FRESHNESS.has(value))
		return value as ZaiSearchFreshness;
	throw new Error("expected day, week, month, year, or none");
}

const ZAI_FRESHNESS: SettingDeclaration<ZaiSearchFreshness | null> = {
	key: "web.zai.freshness",
	env: "ZAI_SEARCH_FRESHNESS",
	parse: parseFreshness,
	default: null,
};
const ZAI_MCP_URL: SettingDeclaration<string> = {
	key: "web.zai.mcpUrl",
	env: "ZAI_SEARCH_MCP_URL",
	parse: parseText,
	default: "https://api.z.ai/api/mcp/web_search_prime/mcp",
};
// Older alias env var, below ZAI_SEARCH_MCP_URL.
const ZAI_BASE_URL = { ...ZAI_MCP_URL, env: "ZAI_SEARCH_BASE_URL" };
const ZAI_CONTENT_SIZE: SettingDeclaration<string> = {
	key: "web.zai.contentSize",
	env: "ZAI_SEARCH_CONTENT_SIZE",
	parse: parseText,
	default: "medium",
};
const ZAI_LOCATION: SettingDeclaration<string> = {
	key: "web.zai.location",
	env: "ZAI_SEARCH_LOCATION",
	parse: parseText,
	default: "us",
};
const MINIMAX_API_HOST: SettingDeclaration<string> = {
	key: "web.minimax.apiHost",
	env: "MINIMAX_API_HOST",
	parse: parseText,
	default: "https://api.minimax.io",
};

function unwrap<T>(result: SettingResult<T>): T {
	if (!result.ok) throw new Error(result.error);
	return result.value;
}

function read<T>(ctx: SettingsContext, declaration: SettingDeclaration<T>): T {
	return unwrap(resolveSetting(NO_FLAGS, ctx, declaration));
}

export const zaiFreshness = (ctx: SettingsContext) => read(ctx, ZAI_FRESHNESS);
export const zaiContentSize = (ctx: SettingsContext) =>
	read(ctx, ZAI_CONTENT_SIZE);
export const zaiLocation = (ctx: SettingsContext) => read(ctx, ZAI_LOCATION);
export const minimaxApiHost = (ctx: SettingsContext) =>
	read(ctx, MINIMAX_API_HOST);

export function zaiMcpUrl(ctx: SettingsContext): string {
	const primary = resolveSetting(NO_FLAGS, ctx, ZAI_MCP_URL);
	return unwrap(
		primary.source === "env"
			? primary
			: resolveSetting(NO_FLAGS, ctx, ZAI_BASE_URL),
	);
}

/** Every web setting reader; each throws its invalid-value error. */
export const SETTING_READERS = [
	zaiFreshness,
	zaiMcpUrl,
	zaiContentSize,
	zaiLocation,
	minimaxApiHost,
];