feat: 重构为 Monorepo 架构并实现 HTTP Server

架构变更:
- 采用 pnpm workspaces 实现 Monorepo 结构
- 将现有代码迁移到 packages/core
- 新增 packages/server HTTP 服务层

Server 功能:
- REST API: 会话管理、工具管理、配置管理
- WebSocket: 实时双向通信支持
- SSE: 服务端事件推送
- Hono + Bun 作为运行时

API 端点:
- GET/POST /api/sessions - 会话 CRUD
- GET/POST /api/sessions/:id/messages - 消息管理
- GET /api/sessions/:id/events - SSE 事件流
- WS /api/ws/:sessionId - WebSocket 连接
- GET/POST /api/tools - 工具管理
- GET/PUT /api/config - 配置管理
This commit is contained in:
2025-12-12 10:42:20 +08:00
parent 59dbed926e
commit 5e32375f0e
301 changed files with 3281 additions and 43 deletions
+284
View File
@@ -0,0 +1,284 @@
/**
* LSP CLI 命令
* 提供语言服务器的查询和安装功能
*/
import { execSync, spawnSync } from 'child_process';
import { getUniqueServers, type ServerConfig, type InstallConfig } from './server.js';
import type { LanguageId } from './language.js';
// 服务器状态
export interface ServerStatus {
id: string;
displayName: string;
description: string;
command: string;
installed: boolean;
languages: LanguageId[];
install: InstallConfig;
}
/**
* 检查命令是否存在
*/
function commandExists(command: string): boolean {
try {
execSync(`which ${command}`, { stdio: 'ignore' });
return true;
} catch {
return false;
}
}
/**
* 检查包管理器是否可用
*/
function hasPackageManager(manager: string): boolean {
return commandExists(manager);
}
/**
* 获取所有服务器状态
*/
export function listServers(): ServerStatus[] {
const servers = getUniqueServers();
return servers.map((server) => ({
id: server.id,
displayName: server.config.displayName,
description: server.config.description,
command: server.config.command,
installed: commandExists(server.config.command),
languages: server.languages,
install: server.config.install,
}));
}
/**
* 打印服务器列表
*/
export function printServerList(): void {
const servers = listServers();
console.log('\n语言服务器状态:\n');
console.log(' 状态 | 服务器 | 支持语言');
console.log(' ------+--------------------------------+------------------');
for (const server of servers) {
const status = server.installed ? ' ✓ ' : ' ✗ ';
const statusColor = server.installed ? '\x1b[32m' : '\x1b[31m';
const reset = '\x1b[0m';
const name = server.displayName.padEnd(30);
const langs = server.languages.slice(0, 3).join(', ') + (server.languages.length > 3 ? '...' : '');
console.log(` ${statusColor}${status}${reset} | ${name} | ${langs}`);
}
const installed = servers.filter((s) => s.installed).length;
console.log(`\n 已安装: ${installed}/${servers.length}\n`);
}
/**
* 获取安装命令
*/
function getInstallCommand(install: InstallConfig): { command: string; description: string } | null {
// 优先使用 npm
if (install.npm && hasPackageManager('npm')) {
return {
command: `npm install -g ${install.npm}`,
description: 'npm',
};
}
// pip
if (install.pip && hasPackageManager('pip3')) {
return {
command: `pip3 install ${install.pip}`,
description: 'pip3',
};
}
if (install.pip && hasPackageManager('pip')) {
return {
command: `pip install ${install.pip}`,
description: 'pip',
};
}
// go
if (install.go && hasPackageManager('go')) {
return {
command: `go install ${install.go}`,
description: 'go install',
};
}
// rustup
if (install.rustup && hasPackageManager('rustup')) {
return {
command: `rustup component add ${install.rustup}`,
description: 'rustup',
};
}
// cargo
if (install.cargo && hasPackageManager('cargo')) {
return {
command: `cargo install ${install.cargo}`,
description: 'cargo',
};
}
// brew
if (install.brew && hasPackageManager('brew')) {
return {
command: `brew install ${install.brew}`,
description: 'Homebrew',
};
}
// gem
if (install.gem && hasPackageManager('gem')) {
return {
command: `gem install ${install.gem}`,
description: 'RubyGems',
};
}
// custom
if (install.custom) {
return {
command: install.custom,
description: '自定义命令',
};
}
return null;
}
/**
* 安装服务器
*/
export async function installServer(serverId: string): Promise<boolean> {
const servers = listServers();
const server = servers.find(
(s) => s.id === serverId || s.displayName.toLowerCase() === serverId.toLowerCase()
);
if (!server) {
console.error(`\x1b[31m错误: 未找到服务器 "${serverId}"\x1b[0m`);
console.log('\n可用的服务器:');
servers.forEach((s) => console.log(` - ${s.displayName} (${s.id})`));
return false;
}
if (server.installed) {
console.log(`\x1b[32m✓ ${server.displayName} 已安装\x1b[0m`);
return true;
}
const installCmd = getInstallCommand(server.install);
if (!installCmd) {
console.error(`\x1b[31m无法自动安装 ${server.displayName}\x1b[0m`);
if (server.install.manual) {
console.log('\n手动安装说明:');
console.log(server.install.manual);
}
return false;
}
console.log(`\n正在安装 ${server.displayName}...`);
console.log(`使用 ${installCmd.description}: ${installCmd.command}\n`);
try {
const result = spawnSync(installCmd.command, {
shell: true,
stdio: 'inherit',
});
if (result.status === 0) {
console.log(`\n\x1b[32m✓ ${server.displayName} 安装成功\x1b[0m`);
return true;
} else {
console.error(`\n\x1b[31m✗ ${server.displayName} 安装失败\x1b[0m`);
if (server.install.manual) {
console.log('\n手动安装说明:');
console.log(server.install.manual);
}
return false;
}
} catch (error) {
console.error(`\n\x1b[31m安装出错: ${error}\x1b[0m`);
return false;
}
}
/**
* 安装所有服务器
*/
export async function installAllServers(): Promise<void> {
const servers = listServers();
const notInstalled = servers.filter((s) => !s.installed);
if (notInstalled.length === 0) {
console.log('\x1b[32m所有语言服务器都已安装\x1b[0m');
return;
}
console.log(`\n将安装 ${notInstalled.length} 个语言服务器:\n`);
notInstalled.forEach((s) => console.log(` - ${s.displayName}`));
console.log('');
let success = 0;
let failed = 0;
for (const server of notInstalled) {
const result = await installServer(server.id);
if (result) {
success++;
} else {
failed++;
}
console.log('');
}
console.log(`\n安装完成: ${success} 成功, ${failed} 失败`);
}
/**
* 显示服务器详细信息
*/
export function showServerInfo(serverId: string): void {
const servers = listServers();
const server = servers.find(
(s) => s.id === serverId || s.displayName.toLowerCase() === serverId.toLowerCase()
);
if (!server) {
console.error(`\x1b[31m错误: 未找到服务器 "${serverId}"\x1b[0m`);
return;
}
const status = server.installed ? '\x1b[32m已安装\x1b[0m' : '\x1b[31m未安装\x1b[0m';
console.log(`\n${server.displayName}`);
console.log('='.repeat(40));
console.log(`状态: ${status}`);
console.log(`命令: ${server.command}`);
console.log(`描述: ${server.description}`);
console.log(`支持语言: ${server.languages.join(', ')}`);
if (!server.installed) {
const installCmd = getInstallCommand(server.install);
if (installCmd) {
console.log(`\n安装命令 (${installCmd.description}):`);
console.log(` ${installCmd.command}`);
}
if (server.install.manual) {
console.log('\n手动安装说明:');
console.log(server.install.manual);
}
}
console.log('');
}