Skip to main content
Glama
ChangeManager.ts8.07 kB
import { Change, ChangeStatus, DocumentDiff } from '../types'; import { EventEmitter } from 'events'; import DocumentAdapter from './DocumentAdapter'; /** * 修改管理器 * 管理修改建议的状态和生命周期 */ export class ChangeManager extends EventEmitter { private changes: Map<string, Change> = new Map(); private changeHistory: Change[] = []; private currentDocumentState: string = ''; constructor() { super(); } /** * 添加修改建议 */ addChange(change: Omit<Change, 'id' | 'timestamp' | 'status'>): Change { const newChange: Change = { ...change, id: this.generateChangeId(), timestamp: Date.now(), status: 'pending', }; this.changes.set(newChange.id, newChange); this.changeHistory.push(newChange); // 触发事件 this.emit('change:added', newChange); this.emit('changes:updated', this.getAllChanges()); return newChange; } /** * 批量添加修改建议 */ addChanges(changes: Omit<Change, 'id' | 'timestamp' | 'status'>[]): Change[] { const newChanges = changes.map((change) => this.addChange(change)); return newChanges; } /** * 获取单个修改 */ getChange(id: string): Change | undefined { return this.changes.get(id); } /** * 获取所有修改 */ getAllChanges(): Change[] { return Array.from(this.changes.values()); } /** * 获取待处理的修改 */ getPendingChanges(): Change[] { return this.getAllChanges().filter((c) => c.status === 'pending'); } /** * 获取已接受的修改 */ getAcceptedChanges(): Change[] { return this.getAllChanges().filter((c) => c.status === 'accepted'); } /** * 获取已拒绝的修改 */ getRejectedChanges(): Change[] { return this.getAllChanges().filter((c) => c.status === 'rejected'); } /** * 按类型获取修改 */ getChangesByType(type: Change['type']): Change[] { return this.getAllChanges().filter((c) => c.type === type); } /** * 更新修改状态 */ updateChangeStatus(id: string, status: ChangeStatus): void { const change = this.changes.get(id); if (!change) { throw new Error(`修改不存在: ${id}`); } const oldStatus = change.status; change.status = status; // 触发事件 this.emit('change:updated', change, oldStatus); this.emit('changes:updated', this.getAllChanges()); } /** * 接受修改 */ async acceptChange(id: string): Promise<void> { const change = this.changes.get(id); if (!change) { throw new Error(`修改不存在: ${id}`); } // 更新状态 this.updateChangeStatus(id, 'accepted'); // 应用修改到文档 try { const adapter = DocumentAdapter.getInstance(); await adapter.applyChange(change); this.emit('change:accepted', change); } catch (error) { // 如果应用失败,回滚状态 this.updateChangeStatus(id, 'pending'); throw error; } } /** * 拒绝修改 */ async rejectChange(id: string): Promise<void> { const change = this.changes.get(id); if (!change) { throw new Error(`修改不存在: ${id}`); } // 更新状态 this.updateChangeStatus(id, 'rejected'); // 移除高亮 try { const adapter = DocumentAdapter.getInstance(); await adapter.removeHighlight(id); this.emit('change:rejected', change); } catch (error) { // 如果移除失败,回滚状态 this.updateChangeStatus(id, 'pending'); throw error; } } /** * 批量接受修改 */ async acceptChanges(ids: string[]): Promise<void> { for (const id of ids) { await this.acceptChange(id); } this.emit('changes:batchAccepted', ids); } /** * 接受所有待处理的修改 */ async acceptAll(): Promise<void> { const pendingIds = this.getPendingChanges().map((c) => c.id); await this.acceptChanges(pendingIds); } /** * 批量拒绝修改 */ async rejectChanges(ids: string[]): Promise<void> { for (const id of ids) { await this.rejectChange(id); } this.emit('changes:batchRejected', ids); } /** * 拒绝所有待处理的修改 */ async rejectAll(): Promise<void> { const pendingIds = this.getPendingChanges().map((c) => c.id); await this.rejectChanges(pendingIds); } /** * 删除修改 */ deleteChange(id: string): void { const change = this.changes.get(id); if (change) { this.changes.delete(id); this.emit('change:deleted', change); this.emit('changes:updated', this.getAllChanges()); } } /** * 清空所有修改 */ clearAll(): void { this.changes.clear(); this.emit('changes:cleared'); this.emit('changes:updated', []); } /** * 生成唯一的修改ID */ private generateChangeId(): string { return `change-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; } /** * 获取修改统计信息 */ getStats(): { total: number; pending: number; accepted: number; rejected: number; byType: Record<Change['type'], number>; } { const all = this.getAllChanges(); const stats = { total: all.length, pending: this.getPendingChanges().length, accepted: this.getAcceptedChanges().length, rejected: this.getRejectedChanges().length, byType: { insert: 0, delete: 0, modify: 0, format: 0, } as Record<Change['type'], number>, }; for (const change of all) { stats.byType[change.type]++; } return stats; } /** * 导出修改历史 */ exportHistory(): Change[] { return [...this.changeHistory]; } /** * 导入修改历史 */ importHistory(history: Change[]): void { this.clearAll(); for (const change of history) { this.changes.set(change.id, change); this.changeHistory.push(change); } this.emit('changes:updated', this.getAllChanges()); } /** * 保存当前文档状态 */ async saveDocumentState(): Promise<void> { try { const adapter = DocumentAdapter.getInstance(); this.currentDocumentState = await adapter.getContent(); this.emit('document:stateSaved', this.currentDocumentState); } catch (error) { console.error('保存文档状态失败:', error); throw error; } } /** * 比较文档差异 */ async compareDocuments(original: string, modified: string): Promise<DocumentDiff> { // 简单的差异对比实现 // 实际应用中应该使用更复杂的diff算法 const changes: Change[] = []; if (original !== modified) { changes.push({ id: this.generateChangeId(), type: 'modify', content: modified, originalContent: original, timestamp: Date.now(), status: 'pending', description: '文档内容已修改', }); } return { original, modified, changes, }; } /** * 应用文档差异 */ async applyDocumentDiff(diff: DocumentDiff): Promise<void> { for (const change of diff.changes) { this.addChange(change); } } /** * 获取修改时间线 */ getTimeline(): Change[] { return [...this.changeHistory].sort((a, b) => a.timestamp - b.timestamp); } /** * 撤销最后一个修改 */ async undoLastChange(): Promise<void> { const acceptedChanges = this.getAcceptedChanges(); if (acceptedChanges.length === 0) { throw new Error('没有可撤销的修改'); } const lastChange = acceptedChanges[acceptedChanges.length - 1]; await this.rejectChange(lastChange.id); this.emit('change:undone', lastChange); } /** * 获取修改摘要 */ getSummary(): string { const stats = this.getStats(); return `总计 ${stats.total} 个修改: ${stats.pending} 个待处理, ${stats.accepted} 个已接受, ${stats.rejected} 个已拒绝`; } } // 导出单例 export default new ChangeManager();

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/walkingzzzy/office-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server