Skip to main content
Glama
Dazlarus
by Dazlarus
configLoader.ts6.5 kB
import * as fs from "fs"; import * as path from "path"; import * as os from "os"; import type { AppConfig, Platform } from "../types.js"; import { getLogger } from "./logging.js"; const CONFIG_DIR_NAME = ".chatgpt-escalation"; const CONFIG_FILE_NAME = "config.json"; /** * Get the user-level config directory path */ export function getConfigDir(): string { const homeDir = os.homedir(); return path.join(homeDir, CONFIG_DIR_NAME); } /** * Get the full path to the config file */ export function getConfigPath(): string { return path.join(getConfigDir(), CONFIG_FILE_NAME); } /** * Detect the current platform */ export function detectPlatform(): Platform { const platform = os.platform(); if (platform === "win32") return "win"; if (platform === "darwin") return "mac"; // Default to win, but warn return "win"; } /** * Load default configuration */ function loadDefaultConfig(): AppConfig { return { chatgpt: { platform: detectPlatform(), // Default to 10 minutes to accommodate long, complex responses responseTimeout: 600000, projects: {}, }, logging: { level: "info", }, }; } /** * Deep merge configuration objects */ function deepMerge(target: AppConfig, source: Partial<AppConfig>): AppConfig { const result: AppConfig = { chatgpt: { ...target.chatgpt }, logging: { ...target.logging }, }; if (source.chatgpt) { result.chatgpt = { ...target.chatgpt, ...source.chatgpt, projects: { ...target.chatgpt.projects, ...(source.chatgpt.projects || {}), }, }; } if (source.logging) { result.logging = { ...target.logging, ...source.logging, }; } return result; } /** * Load user configuration, merged with defaults */ export function loadConfig(): AppConfig { const logger = getLogger("config"); const defaultConfig = loadDefaultConfig(); const configPath = getConfigPath(); if (!fs.existsSync(configPath)) { logger.debug("No user config found, using defaults"); return defaultConfig; } try { const userConfigRaw = fs.readFileSync(configPath, "utf-8"); const userConfig = JSON.parse(userConfigRaw) as Partial<AppConfig>; logger.debug("Loaded user config", { path: configPath }); return deepMerge(defaultConfig, userConfig); } catch (error) { logger.error("Failed to load user config, using defaults", { error }); return defaultConfig; } } /** * Save configuration to the user config file */ export function saveConfig(config: AppConfig): void { const logger = getLogger("config"); const configDir = getConfigDir(); const configPath = getConfigPath(); // Ensure config directory exists with proper permissions if (!fs.existsSync(configDir)) { fs.mkdirSync(configDir, { recursive: true, mode: 0o700 }); // Owner read/write/execute only } try { fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8"); logger.info("Configuration saved", { path: configPath }); } catch (error) { logger.error("Failed to save config", { error }); throw new Error(`Failed to save configuration: ${error}`); } } /** * Validate the configuration */ export interface ConfigValidationResult { valid: boolean; errors: string[]; warnings: string[]; } export function validateConfig(config: AppConfig): ConfigValidationResult { const errors: string[] = []; const warnings: string[] = []; // Validate chatgpt section if (!config.chatgpt) { errors.push("Missing 'chatgpt' configuration section"); } else { // Check platform if (!["win", "mac"].includes(config.chatgpt.platform)) { errors.push(`Invalid platform: ${config.chatgpt.platform}. Must be 'win' or 'mac'`); } // Check projects if (!config.chatgpt.projects || Object.keys(config.chatgpt.projects).length === 0) { errors.push("No projects configured. Run 'chatgpt-escalation-mcp init' to set up projects."); } else { // Validate each project for (const [projectId, entry] of Object.entries(config.chatgpt.projects)) { const conversationTitle = typeof entry === 'string' ? entry : entry?.conversation; if (!conversationTitle || conversationTitle.trim() === "") { errors.push(`Project '${projectId}' has no conversation title configured`); } } } // Check timeout if (config.chatgpt.responseTimeout && config.chatgpt.responseTimeout < 60000) { warnings.push("Timeout is very low (< 60s), ChatGPT responses may take longer"); } } return { valid: errors.length === 0, errors, warnings, }; } /** * Get the conversation title for a specific project */ export function getProjectConversation(config: AppConfig, projectId: string): string | null { const entry = config.chatgpt.projects[projectId]; if (!entry) return null; // Handle both string and object formats if (typeof entry === 'string') { return entry; } return entry.conversation; } /** * Get the project folder for a specific project (if configured) */ export function getProjectFolder(config: AppConfig, projectId: string): string | null { const entry = config.chatgpt.projects[projectId]; if (!entry) return null; // Only object format has folder if (typeof entry === 'string') { return null; } return entry.folder || null; } /** * Check if config directory and file exist */ export function configExists(): boolean { return fs.existsSync(getConfigPath()); } /** * Initialize config directory structure */ export function initConfigDir(): void { const configDir = getConfigDir(); if (!fs.existsSync(configDir)) { fs.mkdirSync(configDir, { recursive: true }); } } /** * Get config summary for display */ export function getConfigSummary(config: AppConfig): string { const projectCount = Object.keys(config.chatgpt.projects).length; const projectList = Object.entries(config.chatgpt.projects) .map(([id, entry]) => { if (typeof entry === 'string') { return ` ${id}: "${entry}"`; } return ` ${id}: "${entry.conversation}"${entry.folder ? ` (in folder: ${entry.folder})` : ''}`; }) .join("\n") || " none"; return ` Configuration Summary: Config path: ${getConfigPath()} Platform: ${config.chatgpt.platform} Response timeout: ${config.chatgpt.responseTimeout}ms Log level: ${config.logging.level} Projects (${projectCount}): ${projectList} `.trim(); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Dazlarus/chatgpt-escalation-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server