-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: consolidate Jest config and update Node.js compatibility
Co-Authored-By: Michael Latman <[email protected]>
- Loading branch information
Showing
16 changed files
with
373 additions
and
225 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,72 +1,68 @@ | ||
import { ClientAdapter } from './base-adapter.js'; | ||
import { ServerConfig, ClientConfig } from '../types/client-config.js'; | ||
import * as fs from 'fs'; | ||
import * as fs from 'fs/promises'; | ||
import * as path from 'path'; | ||
import * as os from 'os'; | ||
|
||
export class ClaudeAdapter extends ClientAdapter { | ||
constructor(config: ClientConfig) { | ||
super(config); | ||
} | ||
|
||
getConfigPath(): string { | ||
const platform = os.platform(); | ||
const platform = process.platform; | ||
if (platform === 'win32') { | ||
return path.join(os.homedir(), 'AppData/Roaming/Claude/claude_desktop_config.json'); | ||
return this.resolvePath('AppData/Roaming/Claude/claude_desktop_config.json'); | ||
} | ||
return path.join(os.homedir(), 'Library/Application Support/Claude/claude_desktop_config.json'); | ||
return this.resolvePath('Library/Application Support/Claude/claude_desktop_config.json'); | ||
} | ||
|
||
async isInstalled(): Promise<boolean> { | ||
try { | ||
const configPath = this.getConfigPath(); | ||
return fs.existsSync(configPath); | ||
const platform = process.platform; | ||
const execPath = platform === 'win32' | ||
? this.resolvePath('AppData/Local/Programs/claude-desktop/Claude.exe') | ||
: '/Applications/Claude.app'; | ||
|
||
await fs.access(execPath); | ||
|
||
const configDir = path.dirname(this.getConfigPath()); | ||
await fs.access(configDir); | ||
|
||
return true; | ||
} catch (error) { | ||
return false; | ||
} | ||
} | ||
|
||
async writeConfig(config: ServerConfig): Promise<void> { | ||
try { | ||
const configPath = this.getConfigPath(); | ||
const configDir = path.dirname(configPath); | ||
const configPath = this.getConfigPath(); | ||
await fs.mkdir(path.dirname(configPath), { recursive: true }); | ||
|
||
if (!fs.existsSync(configDir)) { | ||
fs.mkdirSync(configDir, { recursive: true }); | ||
} | ||
let existingConfig = {}; | ||
try { | ||
const content = await fs.readFile(configPath, 'utf-8'); | ||
existingConfig = JSON.parse(content); | ||
} catch (error) { | ||
// File doesn't exist or is invalid, use empty config | ||
} | ||
|
||
let existingConfig = {}; | ||
try { | ||
if (fs.existsSync(configPath)) { | ||
const content = fs.readFileSync(configPath, 'utf-8'); | ||
existingConfig = JSON.parse(content); | ||
const updatedConfig = { | ||
...existingConfig, | ||
mcpServers: { | ||
...(existingConfig as any).mcpServers, | ||
[config.name]: { | ||
runtime: config.runtime, | ||
command: config.command, | ||
args: config.args || [], | ||
env: config.env || {} | ||
} | ||
} catch (error) { | ||
// File doesn't exist or is invalid, use empty config | ||
} | ||
}; | ||
|
||
const updatedConfig = { | ||
...existingConfig, | ||
servers: { | ||
...(existingConfig as any).servers, | ||
[config.name]: { | ||
runtime: config.runtime, | ||
command: config.command, | ||
args: config.args || [], | ||
env: config.env || {}, | ||
transport: config.transport | ||
} | ||
} | ||
}; | ||
|
||
fs.writeFileSync(configPath, JSON.stringify(updatedConfig, null, 2)); | ||
} catch (error) { | ||
throw error; | ||
} | ||
await fs.writeFile(configPath, JSON.stringify(updatedConfig, null, 2)); | ||
} | ||
|
||
async validateConfig(config: ServerConfig): Promise<boolean> { | ||
const validTransports = ['stdio', 'sse', 'websocket'] as const; | ||
return config.transport !== undefined && validTransports.includes(config.transport as typeof validTransports[number]); | ||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,72 +1,74 @@ | ||
import { ClientAdapter } from './base-adapter.js'; | ||
import { ServerConfig, ClientConfig } from '../types/client-config.js'; | ||
import * as fs from 'fs'; | ||
import * as fs from 'fs/promises'; | ||
import * as path from 'path'; | ||
import * as os from 'os'; | ||
import { glob } from 'glob'; | ||
|
||
export class ContinueAdapter extends ClientAdapter { | ||
constructor(config: ClientConfig) { | ||
super(config); | ||
} | ||
|
||
getConfigPath(): string { | ||
const platform = os.platform(); | ||
if (platform === 'win32') { | ||
return path.join(os.homedir(), 'AppData/Roaming/Continue/config.json'); | ||
} | ||
return path.join(os.homedir(), '.config/continue/config.json'); | ||
return this.resolvePath('.continue/config.json'); | ||
} | ||
|
||
async isInstalled(): Promise<boolean> { | ||
try { | ||
const configPath = this.getConfigPath(); | ||
return fs.existsSync(configPath); | ||
// Check for Continue VS Code extension | ||
const vscodePath = this.resolvePath('.vscode/extensions/continue.continue-*'); | ||
const vscodeExists = await this.checkGlobPath(vscodePath); | ||
|
||
// Check for Continue JetBrains plugin | ||
const jetbrainsPath = process.platform === 'win32' | ||
? this.resolvePath('AppData/Roaming/JetBrains/*/plugins/continue') | ||
: this.resolvePath('Library/Application Support/JetBrains/*/plugins/continue'); | ||
const jetbrainsExists = await this.checkGlobPath(jetbrainsPath); | ||
|
||
return vscodeExists || jetbrainsExists; | ||
} catch (error) { | ||
return false; | ||
} | ||
} | ||
|
||
async writeConfig(config: ServerConfig): Promise<void> { | ||
private async checkGlobPath(globPath: string): Promise<boolean> { | ||
try { | ||
const configPath = this.getConfigPath(); | ||
const configDir = path.dirname(configPath); | ||
const matches = await glob(globPath); | ||
return matches.length > 0; | ||
} catch (error) { | ||
return false; | ||
} | ||
} | ||
|
||
if (!fs.existsSync(configDir)) { | ||
fs.mkdirSync(configDir, { recursive: true }); | ||
} | ||
async writeConfig(config: ServerConfig): Promise<void> { | ||
const configPath = this.getConfigPath(); | ||
await fs.mkdir(path.dirname(configPath), { recursive: true }); | ||
|
||
let existingConfig = {}; | ||
try { | ||
if (fs.existsSync(configPath)) { | ||
const content = fs.readFileSync(configPath, 'utf-8'); | ||
existingConfig = JSON.parse(content); | ||
} | ||
} catch (error) { | ||
// File doesn't exist or is invalid, use empty config | ||
} | ||
let existingConfig = {}; | ||
try { | ||
const content = await fs.readFile(configPath, 'utf-8'); | ||
existingConfig = JSON.parse(content); | ||
} catch (error) { | ||
// File doesn't exist or is invalid, use empty config | ||
} | ||
|
||
const updatedConfig = { | ||
...existingConfig, | ||
servers: { | ||
...(existingConfig as any).servers, | ||
[config.name]: { | ||
runtime: config.runtime, | ||
command: config.command, | ||
args: config.args || [], | ||
env: config.env || {}, | ||
transport: config.transport | ||
} | ||
const updatedConfig = { | ||
...existingConfig, | ||
experimental: { | ||
...(existingConfig as any).experimental, | ||
modelContextProtocolServer: { | ||
transport: config.transport || 'stdio', | ||
command: config.command, | ||
args: config.args || [] | ||
} | ||
}; | ||
} | ||
}; | ||
|
||
fs.writeFileSync(configPath, JSON.stringify(updatedConfig, null, 2)); | ||
} catch (error) { | ||
throw error; | ||
} | ||
await fs.writeFile(configPath, JSON.stringify(updatedConfig, null, 2)); | ||
} | ||
|
||
async validateConfig(config: ServerConfig): Promise<boolean> { | ||
const validTransports = ['stdio', 'sse', 'websocket'] as const; | ||
return config.transport !== undefined && validTransports.includes(config.transport as typeof validTransports[number]); | ||
// Continue supports stdio, sse, and websocket transports | ||
return !config.transport || ['stdio', 'sse', 'websocket'].includes(config.transport); | ||
} | ||
} |
Oops, something went wrong.