UNPKG

decocms

Version:

CLI for managing deco.chat apps & projects

158 lines 5.96 kB
/** * Prompts the user to make their IDE sentient about the project by installing MCP configurations. * * This function: * 1. Asks the user if they want to make their IDE sentient * 2. If yes, prompts them to select their IDE (Cursor, VSCode, or Windsurf) * 3. Returns the appropriate MCP configuration and target path for the selected IDE * * @param mcpConfig - The MCP configuration object * @param projectRoot - The root path of the project where the config should be written * @returns Promise<{ config: any; targetPath: string } | null> - The MCP config and target path, or null if user declines */ import inquirer from "inquirer"; import { promises as fs } from "fs"; import { dirname, join } from "path"; import { ensureDir } from "./fs.js"; import { getAppUUID, getMCPConfig, getMCPConfigVersion, getRulesConfig, } from "./config.js"; import process from "node:process"; const IDE_SUPPORT = { cursor: { name: "Cursor", createConfig: async (mcpConfig, projectRoot) => { const outDir = join(projectRoot, ".cursor"); const configs = []; const configPath = join(outDir, "mcp.json"); const existingConfig = await fs .readFile(configPath, "utf-8") .then(JSON.parse) .catch(() => ({ mcpServers: {} })); const config = { mcpServers: { ...(existingConfig.mcpServers || {}), ...mcpConfig.mcpServers, }, }; configs.push({ content: JSON.stringify(config, null, 2), path: join(outDir, "mcp.json"), }); const rules = Object.entries(await getRulesConfig()); for (const [path, content] of rules) { configs.push({ content, path: join(outDir, "rules", path) }); } return configs; }, }, vscode: { name: "VS Code", createConfig: async (mcpConfig, projectRoot) => { const outDir = join(projectRoot, ".vscode"); const configs = []; const configPath = join(outDir, "mcp.json"); const existingConfig = await fs .readFile(configPath, "utf-8") .then(JSON.parse) .catch(() => ({ mcpServers: {} })); const config = { mcpServers: { ...(existingConfig.mcpServers || {}), ...mcpConfig.mcpServers, }, }; configs.push({ content: JSON.stringify(config, null, 2), path: join(outDir, "mcp.json"), }); const rules = Object.entries(await getRulesConfig()); for (const [path, content] of rules) { configs.push({ content, path: join(outDir, "rules", path) }); } return configs; }, }, }; export async function writeIDEConfig(configs) { const targetDir = dirname(configs[0]?.path ?? ""); // Write all configuration files in parallel await Promise.all(configs.map(async ({ content, path }) => { await ensureDir(dirname(path)); await fs.writeFile(path, content); })); console.log(`✅ IDE configuration written to: ${targetDir}`); } export const hasMCPPreferences = async (workspace, app) => { const [appUUID, currentVersion] = await Promise.all([ getAppUUID(workspace, app), getMCPConfigVersion(), ]); // Use a simple file-based storage instead of localStorage for Node.js const prefsPath = join(process.cwd(), ".deco", "preferences.json"); try { const prefs = JSON.parse(await fs.readFile(prefsPath, "utf-8")); const storedVersion = prefs[`mcp-install-version-${appUUID}`]; return storedVersion === currentVersion; } catch { return false; } }; export const setMCPPreferences = async (workspace, app) => { const [appUUID, currentVersion] = await Promise.all([ getAppUUID(workspace, app), getMCPConfigVersion(), ]); const prefsPath = join(process.cwd(), ".deco", "preferences.json"); try { await ensureDir(dirname(prefsPath)); let prefs = {}; try { prefs = JSON.parse(await fs.readFile(prefsPath, "utf-8")); } catch { // File doesn't exist, start with empty prefs } prefs[`mcp-install-version-${appUUID}`] = currentVersion; await fs.writeFile(prefsPath, JSON.stringify(prefs, null, 2)); } catch (error) { console.warn("Failed to save MCP preferences:", error); } }; export async function promptIDESetup(cfg, projectRoot = process.cwd()) { await setMCPPreferences(cfg.workspace, cfg.app); const mcpConfig = getMCPConfig(cfg.workspace, cfg.app); // Ask if user wants to make IDE sentient const { wantsSentientIDE } = await inquirer.prompt([ { type: "confirm", name: "wantsSentientIDE", message: "Would you like to configure your IDE to use this project?", default: true, }, ]); if (!wantsSentientIDE) { return null; } // Prompt user to select their IDE const { selectedIDE } = await inquirer.prompt([ { type: "list", name: "selectedIDE", message: "Select your preferred IDE:", choices: [ { name: "Cursor", value: "cursor" }, { name: "VS Code", value: "vscode" }, { name: "None", value: "none" }, ], }, ]); const ideSupport = IDE_SUPPORT[selectedIDE]; if (selectedIDE === "none") { return null; } // Create the IDE-specific configuration const configs = await ideSupport.createConfig(mcpConfig, projectRoot); return configs; } //# sourceMappingURL=prompt-ide-setup.js.map