Skip to content

Commit

Permalink
feat: add platform-specific config path resolution for Zed
Browse files Browse the repository at this point in the history
Co-Authored-By: Michael Latman <[email protected]>
  • Loading branch information
devin-ai-integration[bot] and michaellatman committed Dec 11, 2024
1 parent bccd226 commit bf06619
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 9 deletions.
9 changes: 8 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"glob": "^10.3.10",
"inquirer": "^8.2.4",
"inquirer-autocomplete-prompt": "^2.0.0",
"jsonc-parser": "^3.3.1",
"open": "^10.1.0",
"string-width": "^4.2.3",
"typescript": "^4.0.0"
Expand Down
91 changes: 83 additions & 8 deletions src/clients/zed-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,66 @@ import { ServerConfig, ClientConfig } from '../types/client-config.js';
import * as fs from 'fs/promises';
import * as path from 'path';
import * as TOML from '@iarna/toml';
import { parse as parseJsonc } from 'jsonc-parser';
import * as os from 'os';

interface ZedSettings {
mcp?: ServerConfig;
[key: string]: any;
}

interface ZedConfigPaths {
extension: string;
settings: string;
projectSettings?: string;
}

export class ZedAdapter extends ClientAdapter {
constructor(config: ClientConfig) {
super(config);
}

private async getConfigPaths(): Promise<ZedConfigPaths> {
const home = os.homedir();
const xdgConfig = process.env.XDG_CONFIG_HOME || path.join(home, '.config');

const settingsPath = process.platform === 'linux'
? path.join(xdgConfig, 'zed', 'settings.json')
: path.join(home, '.config', 'zed', 'settings.json');

const paths: ZedConfigPaths = {
extension: this.resolvePath('.zed/extensions/mcp-server/extension.toml'),
settings: settingsPath
};

const projectSettings = path.join(process.cwd(), '.zed', 'settings.json');
try {
await fs.access(projectSettings);
paths.projectSettings = projectSettings;
} catch (err) {
// No project settings found, ignore
}

return paths;
}

getConfigPath(): string {
// Zed extensions are typically in the .zed directory
return this.resolvePath('.zed/extensions/mcp-server/extension.toml');
}

private async parseConfig(content: string, isExtension: boolean = false): Promise<ZedSettings | any> {
try {
return isExtension ?
TOML.parse(content) :
parseJsonc(content);
} catch (err) {
const error = err as Error;
throw new Error(`Failed to parse Zed config: ${error.message}`);
}
}

async isInstalled(): Promise<boolean> {
try {
// Check for Zed installation
const platform = process.platform;
const zedPath = platform === 'win32'
? this.resolvePath('AppData/Local/Programs/Zed/Zed.exe')
Expand All @@ -26,19 +72,17 @@ export class ZedAdapter extends ClientAdapter {

await fs.access(zedPath);

// Check for Zed extensions directory
const extensionsDir = this.resolvePath('.zed/extensions');
await fs.access(extensionsDir);

return true;
} catch (error) {
} catch (err) {
return false;
}
}

async writeConfig(config: ServerConfig): Promise<void> {
const configPath = this.getConfigPath();
await fs.mkdir(path.dirname(configPath), { recursive: true });
const paths = await this.getConfigPaths();

const tomlConfig = {
context_server: {
Expand All @@ -48,11 +92,42 @@ export class ZedAdapter extends ClientAdapter {
}
};

await fs.writeFile(configPath, TOML.stringify(tomlConfig));
await fs.mkdir(path.dirname(paths.extension), { recursive: true });
await fs.writeFile(paths.extension, TOML.stringify(tomlConfig));

try {
let settings: ZedSettings = {};
try {
const settingsContent = await fs.readFile(paths.settings, 'utf8');
settings = await this.parseConfig(settingsContent, false) as ZedSettings;
} catch (err) {
// Ignore if settings file doesn't exist
}

settings.mcp = { ...settings.mcp, ...config };
await fs.mkdir(path.dirname(paths.settings), { recursive: true });
await fs.writeFile(paths.settings, JSON.stringify(settings, null, 2));

if (paths.projectSettings) {
let projectSettings: ZedSettings = {};
try {
const projectContent = await fs.readFile(paths.projectSettings, 'utf8');
projectSettings = await this.parseConfig(projectContent, false) as ZedSettings;
} catch (err) {
// Ignore if project settings file doesn't exist
}

projectSettings.mcp = { ...projectSettings.mcp, ...config };
await fs.mkdir(path.dirname(paths.projectSettings), { recursive: true });
await fs.writeFile(paths.projectSettings, JSON.stringify(projectSettings, null, 2));
}
} catch (err) {
const error = err as Error;
throw new Error(`Failed to update Zed settings: ${error.message}`);
}
}

async validateConfig(config: ServerConfig): Promise<boolean> {
// Zed currently only supports stdio transport
return !config.transport || config.transport === 'stdio';
}
}

0 comments on commit bf06619

Please sign in to comment.