Files
ai-terminal-assistant/packages/ui/src/api/client.ts
T
kurihada 250d2cb4b5 feat(ui): 添加 IDE 组件(文件浏览器 + 代码编辑器)
- 新增 CodeEditor 组件,基于 CodeMirror 实现多标签代码编辑
- 新增 FileExplorer 组件,支持文件树展开/折叠和文件选择
- 新增 IDE 组件,整合文件浏览器和代码编辑器
- 新增 SessionPanel 组件,用于会话管理
- 添加文件写入 API(PUT /api/files/write)
- 优化布局:IDE 始终显示,移除文件切换按钮
- 工作目录路径显示在文件浏览器标题栏,支持悬浮显示完整路径
2025-12-17 16:55:22 +08:00

1116 lines
24 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Configurable API Client
*/
import type {
Session,
Message,
HealthStatus,
FileListResponse,
FileReadResponse,
FileTreeResponse,
ServerConfig,
CommandInfo,
CommandSearchResult,
CommandExecuteResult,
CommandListResponse,
CreateCommandInput,
UpdateCommandInput,
CommandContent,
MCPServerStatus,
MCPToolInfo,
MCPConfig,
HookConfig,
FileHookConfig,
ShellCommandConfig,
HookTestResult,
AgentListItem,
AgentDetail,
AgentInput,
AgentDefaults,
CheckpointListItem,
CheckpointDetail,
CheckpointStats,
DiffInfo,
FileDiffDetail,
RestoreOptions,
RestoreResult,
SafetyCheckResult,
UnrevertStatus,
UnrevertResult,
// Provider types
ProviderListItem,
ProviderDetail,
ModelInfo,
CustomProviderDefinition,
ProviderConfig,
ConnectionTestResult,
// Context types
ContextUsageInfo,
CompressionResult,
// File search types
FileSearchResponse,
// LSP types
LSPServer,
DiagnosticsResponse,
} from './types.js';
// Re-export types
export type {
Session,
Message,
HealthStatus,
FileInfo,
FileListResponse,
FileReadResponse,
FileTreeNode,
FileTreeResponse,
ServerConfig,
CommandInfo,
CommandSearchResult,
CommandExecuteResult,
CommandListResponse,
CreateCommandInput,
UpdateCommandInput,
CommandContent,
MCPServerStatus,
MCPServerStatusType,
MCPToolInfo,
MCPConfig,
MCPServerConfigInfo,
// Hooks types
HookConfig,
FileHookConfig,
ShellCommandConfig,
HookTestResult,
// Agent types
AgentMode,
AgentModelConfig,
AgentToolConfig,
PermissionRule,
AgentBashPermission,
AgentFilePermission,
AgentGitPermission,
AgentPermission,
AgentListItem,
AgentDetail,
AgentInput,
AgentDefaults,
// Checkpoint types
CheckpointTrigger,
FileChangeType,
CheckpointListItem,
CheckpointDetail,
FileChange,
DiffInfo,
FileDiffDetail,
RestoreMode,
RestoreOptions,
RestoreResult,
SafetyCheckResult,
CheckpointStats,
UnrevertStatus,
UnrevertResult,
// Provider types
BuiltinProviderType,
ProviderType,
ModelCapabilities,
ModelInfo,
ProviderListItem,
ProviderDetail,
CustomProviderDefinition,
ProviderConfig,
ConnectionTestResult,
// Context compression types
TokenUsage,
ContextUsageInfo,
CompressionStatus,
CompressionType,
CompressionResult,
// WebSocket error types
ConfigErrorPayload,
// File search types
FileSearchResult,
FileSearchResponse,
// Agent mode types
AgentModeType,
// Question types (for ask_user_question tool)
QuestionOption,
Question,
QuestionMessagePart,
// LSP types
LSPServer,
FileDiagnostic,
DiagnosticsSummary,
SingleFileDiagnosticsResponse,
AllFilesDiagnosticsResponse,
DiagnosticsResponse,
} from './types.js';
// API Configuration
interface ApiConfig {
baseUrl: string;
wsBaseUrl: () => string;
healthUrl: () => string;
}
let apiConfig: ApiConfig = {
baseUrl: '/api',
wsBaseUrl: () => {
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
return `${protocol}//${window.location.host}/api`;
},
healthUrl: () => '/health',
};
/**
* Configure API client for different environments
*/
export function configureApiClient(config: {
baseUrl: string;
wsBaseUrl: string | (() => string);
healthUrl?: string | (() => string);
}) {
apiConfig = {
baseUrl: config.baseUrl,
wsBaseUrl:
typeof config.wsBaseUrl === 'function'
? config.wsBaseUrl
: () => config.wsBaseUrl as string,
healthUrl: config.healthUrl
? typeof config.healthUrl === 'function'
? config.healthUrl
: () => config.healthUrl as string
: () => '/health',
};
}
async function request<T>(method: string, path: string, body?: unknown): Promise<T> {
const response = await fetch(`${apiConfig.baseUrl}${path}`, {
method,
headers: {
'Content-Type': 'application/json',
},
body: body ? JSON.stringify(body) : undefined,
});
if (!response.ok) {
const error = await response.json().catch(() => ({ error: response.statusText }));
throw new Error(error.error || `HTTP ${response.status}`);
}
return response.json();
}
// Health
export async function getHealth(): Promise<HealthStatus> {
const healthUrl = apiConfig.healthUrl();
const response = await fetch(healthUrl);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.json();
}
// Sessions
export async function listSessions(): Promise<{ success: boolean; data: Session[] }> {
return request('GET', '/sessions');
}
export async function createSession(name?: string): Promise<{ success: boolean; data: Session }> {
return request('POST', '/sessions', { name });
}
export async function getSession(id: string): Promise<{ success: boolean; data: Session }> {
return request('GET', `/sessions/${id}`);
}
export async function deleteSession(id: string): Promise<{ success: boolean }> {
return request('DELETE', `/sessions/${id}`);
}
// Messages
export async function getMessages(
sessionId: string
): Promise<{ success: boolean; data: Message[] }> {
return request('GET', `/sessions/${sessionId}/messages`);
}
export async function sendMessage(
sessionId: string,
content: string
): Promise<{ success: boolean; data: Message }> {
return request('POST', `/sessions/${sessionId}/messages`, { content });
}
// WebSocket
export function createWebSocket(sessionId: string): WebSocket {
const wsBase = apiConfig.wsBaseUrl();
return new WebSocket(`${wsBase}/ws/${sessionId}`);
}
// Files
export async function getWorkingDirectory(): Promise<{
success: boolean;
data: { workingDirectory: string; separator: string };
}> {
return request('GET', '/files');
}
export async function listFiles(
path: string = '.',
showHidden: boolean = false
): Promise<FileListResponse> {
const params = new URLSearchParams({ path });
if (showHidden) params.set('hidden', 'true');
return request('GET', `/files/list?${params}`);
}
export async function readFile(path: string): Promise<FileReadResponse> {
return request('GET', `/files/read?path=${encodeURIComponent(path)}`);
}
export interface FileWriteResponse {
success: boolean;
data: {
path: string;
name: string;
size: number;
modified: string;
};
}
export async function writeFile(path: string, content: string): Promise<FileWriteResponse> {
return request('PUT', '/files/write', { path, content });
}
export async function getFileTree(path: string = '.', depth: number = 3): Promise<FileTreeResponse> {
const params = new URLSearchParams({ path, depth: String(depth) });
return request('GET', `/files/tree?${params}`);
}
// Config
export async function getConfig(): Promise<{ success: boolean; data: ServerConfig }> {
return request('GET', '/config');
}
export async function updateConfig(
config: Partial<ServerConfig>
): Promise<{ success: boolean; data: ServerConfig }> {
return request('PATCH', '/config', config);
}
// Commands
export async function listCommands(): Promise<{ success: boolean; data: CommandListResponse }> {
return request('GET', '/commands');
}
export async function getCommand(name: string): Promise<{ success: boolean; data: CommandInfo }> {
return request('GET', `/commands/${encodeURIComponent(name)}`);
}
export async function executeCommand(
name: string,
args: string = ''
): Promise<{ success: boolean; data?: CommandExecuteResult; error?: string }> {
return request('POST', `/commands/${encodeURIComponent(name)}/execute`, {
arguments: args,
});
}
export async function searchCommands(
query: string,
limit: number = 10
): Promise<{ success: boolean; data: CommandSearchResult[] }> {
return request('POST', '/commands/search', { query, limit });
}
export async function reloadCommands(): Promise<{
success: boolean;
data: { message: string; stats: { total: number; bySource: Record<string, number> } };
}> {
return request('POST', '/commands/reload');
}
// Commands CRUD
export async function createCommand(
input: CreateCommandInput
): Promise<{ success: boolean; data?: { name: string; path: string }; error?: string }> {
return request('POST', '/commands', input);
}
export async function getCommandContent(
name: string
): Promise<{ success: boolean; data?: CommandContent; error?: string }> {
return request('GET', `/commands/${encodeURIComponent(name)}/content`);
}
export async function updateCommand(
name: string,
input: UpdateCommandInput
): Promise<{ success: boolean; data?: { name: string; path: string }; error?: string }> {
return request('PUT', `/commands/${encodeURIComponent(name)}`, input);
}
export async function deleteCommand(
name: string
): Promise<{ success: boolean; data?: { name: string; path: string }; error?: string }> {
return request('DELETE', `/commands/${encodeURIComponent(name)}`);
}
// ============ MCP API ============
/**
* 获取所有 MCP 服务器状态
*/
export async function listMCPServers(): Promise<{
success: boolean;
data: MCPServerStatus[];
error?: string;
}> {
return request('GET', '/mcp/servers');
}
/**
* 获取单个 MCP 服务器详情
*/
export async function getMCPServer(name: string): Promise<{
success: boolean;
data?: MCPServerStatus;
error?: string;
}> {
return request('GET', `/mcp/servers/${encodeURIComponent(name)}`);
}
/**
* 连接 MCP 服务器
*/
export async function connectMCPServer(name: string): Promise<{
success: boolean;
data?: { message: string; status: MCPServerStatus };
error?: string;
}> {
return request('POST', `/mcp/servers/${encodeURIComponent(name)}/connect`);
}
/**
* 断开 MCP 服务器
*/
export async function disconnectMCPServer(name: string): Promise<{
success: boolean;
data?: { message: string; status: MCPServerStatus };
error?: string;
}> {
return request('POST', `/mcp/servers/${encodeURIComponent(name)}/disconnect`);
}
/**
* 启用 MCP 服务器
*/
export async function enableMCPServer(name: string): Promise<{
success: boolean;
data?: { message: string; status: MCPServerStatus };
error?: string;
}> {
return request('POST', `/mcp/servers/${encodeURIComponent(name)}/enable`);
}
/**
* 禁用 MCP 服务器
*/
export async function disableMCPServer(name: string): Promise<{
success: boolean;
data?: { message: string; status: MCPServerStatus };
error?: string;
}> {
return request('POST', `/mcp/servers/${encodeURIComponent(name)}/disable`);
}
/**
* 获取所有 MCP 工具
*/
export async function listMCPTools(): Promise<{
success: boolean;
data: MCPToolInfo[];
error?: string;
}> {
return request('GET', '/mcp/tools');
}
/**
* 获取单个 MCP 工具详情
*/
export async function getMCPTool(name: string): Promise<{
success: boolean;
data?: MCPToolInfo;
error?: string;
}> {
return request('GET', `/mcp/tools/${encodeURIComponent(name)}`);
}
/**
* 获取 MCP 配置
*/
export async function getMCPConfig(): Promise<{
success: boolean;
data?: MCPConfig;
error?: string;
}> {
return request('GET', '/mcp/config');
}
// ============ Hooks API ============
/**
* 获取完整钩子配置
*/
export async function getHooksConfig(): Promise<{
success: boolean;
data: HookConfig;
error?: string;
}> {
return request('GET', '/hooks/config');
}
/**
* 更新完整钩子配置
*/
export async function updateHooksConfig(config: HookConfig): Promise<{
success: boolean;
data: HookConfig;
error?: string;
}> {
return request('PUT', '/hooks/config', config);
}
/**
* 获取 file_edited 钩子配置
*/
export async function getFileEditedHooks(): Promise<{
success: boolean;
data: FileHookConfig;
error?: string;
}> {
return request('GET', '/hooks/file-edited');
}
/**
* 更新 file_edited 钩子配置
*/
export async function updateFileEditedHooks(hooks: FileHookConfig): Promise<{
success: boolean;
data: FileHookConfig;
error?: string;
}> {
return request('PUT', '/hooks/file-edited', hooks);
}
/**
* 获取 file_created 钩子配置
*/
export async function getFileCreatedHooks(): Promise<{
success: boolean;
data: FileHookConfig;
error?: string;
}> {
return request('GET', '/hooks/file-created');
}
/**
* 更新 file_created 钩子配置
*/
export async function updateFileCreatedHooks(hooks: FileHookConfig): Promise<{
success: boolean;
data: FileHookConfig;
error?: string;
}> {
return request('PUT', '/hooks/file-created', hooks);
}
/**
* 获取 file_deleted 钩子配置
*/
export async function getFileDeletedHooks(): Promise<{
success: boolean;
data: FileHookConfig;
error?: string;
}> {
return request('GET', '/hooks/file-deleted');
}
/**
* 更新 file_deleted 钩子配置
*/
export async function updateFileDeletedHooks(hooks: FileHookConfig): Promise<{
success: boolean;
data: FileHookConfig;
error?: string;
}> {
return request('PUT', '/hooks/file-deleted', hooks);
}
/**
* 获取 session_completed 钩子配置
*/
export async function getSessionCompletedHooks(): Promise<{
success: boolean;
data: ShellCommandConfig[];
error?: string;
}> {
return request('GET', '/hooks/session-completed');
}
/**
* 更新 session_completed 钩子配置
*/
export async function updateSessionCompletedHooks(hooks: ShellCommandConfig[]): Promise<{
success: boolean;
data: ShellCommandConfig[];
error?: string;
}> {
return request('PUT', '/hooks/session-completed', hooks);
}
/**
* 测试执行钩子命令
*/
export async function testHookCommand(command: ShellCommandConfig): Promise<{
success: boolean;
data?: HookTestResult;
error?: string;
}> {
return request('POST', '/hooks/test', command);
}
// ============ Agents API ============
/**
* 获取所有 Agent 列表
*/
export async function listAgents(): Promise<{
success: boolean;
data: AgentListItem[];
error?: string;
}> {
return request('GET', '/agents');
}
/**
* 获取单个 Agent 详情
*/
export async function getAgent(name: string): Promise<{
success: boolean;
data?: AgentDetail;
error?: string;
}> {
return request('GET', `/agents/${encodeURIComponent(name)}`);
}
/**
* 创建新 Agent
*/
export async function createAgent(
name: string,
config: AgentInput
): Promise<{
success: boolean;
data?: AgentDetail;
error?: string;
}> {
return request('POST', '/agents', { name, ...config });
}
/**
* 更新 Agent
*/
export async function updateAgent(
name: string,
config: AgentInput
): Promise<{
success: boolean;
data?: AgentDetail;
error?: string;
}> {
return request('PUT', `/agents/${encodeURIComponent(name)}`, config);
}
/**
* 删除 Agent
*/
export async function deleteAgent(name: string): Promise<{
success: boolean;
error?: string;
}> {
return request('DELETE', `/agents/${encodeURIComponent(name)}`);
}
/**
* 获取预设 Agent 列表
*/
export async function listPresetAgents(): Promise<{
success: boolean;
data: AgentListItem[];
error?: string;
}> {
return request('GET', '/agents/presets');
}
/**
* 获取全局默认配置
*/
export async function getAgentDefaults(): Promise<{
success: boolean;
data: AgentDefaults;
error?: string;
}> {
return request('GET', '/agents/defaults');
}
/**
* 更新全局默认配置
*/
export async function updateAgentDefaults(defaults: AgentDefaults): Promise<{
success: boolean;
data: AgentDefaults;
error?: string;
}> {
return request('PUT', '/agents/defaults', defaults);
}
// ============ Checkpoints API ============
/**
* 获取所有检查点列表
*/
export async function listCheckpoints(): Promise<{
success: boolean;
data: CheckpointListItem[];
error?: string;
}> {
return request('GET', '/checkpoints');
}
/**
* 获取检查点统计信息
*/
export async function getCheckpointStats(): Promise<{
success: boolean;
data: CheckpointStats;
error?: string;
}> {
return request('GET', '/checkpoints/stats');
}
/**
* 获取最新检查点
*/
export async function getLatestCheckpoint(): Promise<{
success: boolean;
data: CheckpointDetail | null;
error?: string;
}> {
return request('GET', '/checkpoints/latest');
}
/**
* 获取单个检查点详情
*/
export async function getCheckpoint(id: string): Promise<{
success: boolean;
data?: CheckpointDetail;
error?: string;
}> {
return request('GET', `/checkpoints/${encodeURIComponent(id)}`);
}
/**
* 创建手动检查点
*/
export async function createCheckpoint(options?: {
name?: string;
description?: string;
}): Promise<{
success: boolean;
data?: CheckpointDetail;
error?: string;
}> {
return request('POST', '/checkpoints', options || {});
}
/**
* 删除检查点
*/
export async function deleteCheckpoint(id: string): Promise<{
success: boolean;
data?: { deleted: boolean };
error?: string;
}> {
return request('DELETE', `/checkpoints/${encodeURIComponent(id)}`);
}
/**
* 获取检查点与当前工作区的差异
*/
export async function getCheckpointDiff(id: string): Promise<{
success: boolean;
data?: DiffInfo;
error?: string;
}> {
return request('GET', `/checkpoints/${encodeURIComponent(id)}/diff`);
}
/**
* 获取单个文件的详细差异
*/
export async function getFileDiff(checkpointId: string, filePath: string): Promise<{
success: boolean;
data?: FileDiffDetail;
error?: string;
}> {
const params = new URLSearchParams({ path: filePath });
return request('GET', `/checkpoints/${encodeURIComponent(checkpointId)}/file-diff?${params}`);
}
/**
* 回滚到检查点
*/
export async function restoreCheckpoint(
id: string,
options?: RestoreOptions
): Promise<{
success: boolean;
data?: RestoreResult;
error?: string;
}> {
return request('POST', `/checkpoints/${encodeURIComponent(id)}/restore`, options || {});
}
/**
* 预览回滚(dry run
*/
export async function previewRestore(
id: string,
options?: { mode?: RestoreOptions['mode']; files?: string[] }
): Promise<{
success: boolean;
data?: RestoreResult;
error?: string;
}> {
const params = new URLSearchParams();
if (options?.mode) params.set('mode', options.mode);
if (options?.files) params.set('files', options.files.join(','));
return request('GET', `/checkpoints/${encodeURIComponent(id)}/restore/preview?${params}`);
}
/**
* 撤销最近一次回滚
*/
export async function unrevert(): Promise<{
success: boolean;
data?: UnrevertResult;
error?: string;
}> {
return request('POST', '/checkpoints/unrevert');
}
/**
* 检查是否可撤销回滚
*/
export async function getUnrevertStatus(): Promise<{
success: boolean;
data?: UnrevertStatus;
error?: string;
}> {
return request('GET', '/checkpoints/unrevert/status');
}
/**
* 执行安全检查
*/
export async function checkSafety(id: string): Promise<{
success: boolean;
data?: SafetyCheckResult;
error?: string;
}> {
return request('GET', `/checkpoints/${encodeURIComponent(id)}/safety-check`);
}
/**
* 清理过期检查点
*/
export async function cleanupCheckpoints(): Promise<{
success: boolean;
data?: { deleted: number };
error?: string;
}> {
return request('POST', '/checkpoints/cleanup');
}
/**
* 获取会话的所有检查点
*/
export async function getSessionCheckpoints(sessionId: string): Promise<{
success: boolean;
data: CheckpointListItem[];
error?: string;
}> {
return request('GET', `/checkpoints/sessions/${encodeURIComponent(sessionId)}`);
}
/**
* 获取消息关联的检查点
*/
export async function getMessageCheckpoints(messageId: string): Promise<{
success: boolean;
data: CheckpointListItem[];
error?: string;
}> {
return request('GET', `/checkpoints/messages/${encodeURIComponent(messageId)}`);
}
// ============ Providers API ============
/**
* 获取所有提供商列表
*/
export async function listProviders(): Promise<{
success: boolean;
data: ProviderListItem[];
error?: string;
}> {
return request('GET', '/providers');
}
/**
* 获取单个提供商详情
*/
export async function getProvider(id: string): Promise<{
success: boolean;
data?: ProviderDetail;
error?: string;
}> {
return request('GET', `/providers/${encodeURIComponent(id)}`);
}
/**
* 获取提供商的模型列表
*/
export async function getProviderModels(id: string): Promise<{
success: boolean;
data: ModelInfo[];
error?: string;
}> {
return request('GET', `/providers/${encodeURIComponent(id)}/models`);
}
/**
* 测试提供商连接
*/
export async function testProviderConnection(
id: string,
apiKey?: string
): Promise<{
success: boolean;
data: ConnectionTestResult;
error?: string;
}> {
return request('POST', `/providers/${encodeURIComponent(id)}/test`, apiKey ? { apiKey } : {});
}
/**
* 注册自定义提供商
*/
export async function registerProvider(
definition: CustomProviderDefinition
): Promise<{
success: boolean;
message?: string;
error?: string;
}> {
return request('POST', '/providers', definition);
}
/**
* 更新提供商配置
*/
export async function updateProviderConfig(
id: string,
config: ProviderConfig
): Promise<{
success: boolean;
message?: string;
error?: string;
}> {
return request('PUT', `/providers/${encodeURIComponent(id)}`, config);
}
/**
* 删除自定义提供商
*/
export async function deleteProvider(id: string): Promise<{
success: boolean;
message?: string;
error?: string;
}> {
return request('DELETE', `/providers/${encodeURIComponent(id)}`);
}
/**
* 添加自定义模型
*/
export async function addProviderModel(
providerId: string,
model: ModelInfo
): Promise<{
success: boolean;
message?: string;
error?: string;
}> {
return request('POST', `/providers/${encodeURIComponent(providerId)}/models`, model);
}
/**
* 删除自定义模型
*/
export async function deleteProviderModel(
providerId: string,
modelId: string
): Promise<{
success: boolean;
message?: string;
error?: string;
}> {
return request('DELETE', `/providers/${encodeURIComponent(providerId)}/models/${encodeURIComponent(modelId)}`);
}
// ============ Context Compression API ============
/**
* 获取会话上下文使用情况
*/
export async function getContextUsage(sessionId: string): Promise<{
success: boolean;
data?: ContextUsageInfo;
error?: string;
}> {
return request('GET', `/sessions/${encodeURIComponent(sessionId)}/context`);
}
/**
* 触发上下文压缩
*/
export async function compressContext(
sessionId: string,
options?: { force?: boolean }
): Promise<{
success: boolean;
data?: CompressionResult;
error?: string;
}> {
return request('POST', `/sessions/${encodeURIComponent(sessionId)}/compress`, options || {});
}
// ============ File Search API ============
/**
* 模糊搜索项目文件
*/
export async function searchFiles(
query: string = '',
limit: number = 10,
type: 'file' | 'directory' | 'all' = 'file'
): Promise<FileSearchResponse> {
const params = new URLSearchParams({
query,
limit: String(limit),
type,
});
return request('GET', `/files/search?${params}`);
}
// ============ LSP API ============
/**
* 获取所有语言服务器列表
*/
export async function listLSPServers(): Promise<{
success: boolean;
data: LSPServer[];
error?: string;
}> {
return request('GET', '/lsp/servers');
}
/**
* 获取单个语言服务器详情
*/
export async function getLSPServer(id: string): Promise<{
success: boolean;
data?: LSPServer;
error?: string;
}> {
return request('GET', `/lsp/servers/${encodeURIComponent(id)}`);
}
/**
* 安装语言服务器
*/
export async function installLSPServer(id: string): Promise<{
success: boolean;
data?: { message: string; server: LSPServer };
error?: string;
}> {
return request('POST', `/lsp/servers/${encodeURIComponent(id)}/install`);
}
/**
* 启动语言服务器
* @param id 服务器 ID
* @param filePath 需要提供一个文件路径来触发对应语言的服务器
*/
export async function startLSPServer(
id: string,
filePath: string
): Promise<{
success: boolean;
data?: { message: string; isFirstStart: boolean; runningServers: string[] };
error?: string;
}> {
return request('POST', `/lsp/servers/${encodeURIComponent(id)}/start`, { filePath });
}
/**
* 停止语言服务器
*/
export async function stopLSPServer(id: string): Promise<{
success: boolean;
data?: { message: string; runningServers: string[] };
error?: string;
}> {
return request('POST', `/lsp/servers/${encodeURIComponent(id)}/stop`);
}
/**
* 获取正在运行的语言服务器列表
*/
export async function getRunningLSPServers(): Promise<{
success: boolean;
data: string[];
error?: string;
}> {
return request('GET', '/lsp/running');
}
/**
* 获取诊断信息
* @param file 可选,指定文件路径获取单个文件的诊断
*/
export async function getLSPDiagnostics(file?: string): Promise<{
success: boolean;
data: DiagnosticsResponse;
error?: string;
}> {
const params = file ? `?file=${encodeURIComponent(file)}` : '';
return request('GET', `/lsp/diagnostics${params}`);
}