Forge
csharpdeeb25a2
1using CascadeIDE.ViewModels;
2using CascadeIDE.Features.IdeMcp.Application;
3using CascadeIDE.Features.Workspace.DataAcquisition;
4using CascadeIDE.Models;
5using CascadeIDE.Features.Editor.Application.Monaco;
6using CascadeIDE.Services;
7
8namespace CascadeIDE.Features.IdeMcp.Application;
9
10internal sealed partial class MainWindowIdeMcpHost
11{
12
13 public void OpenFile(string path) =>
14 IdeMcpEditorDocumentOrchestrator.ScheduleOpenFile(
15 UiScheduler.Default,
16 path,
17 normalizedPath =>
18 {
19 _host.IsLoadingCurrentFile = true;
20 try
21 {
22 _host.Documents.OpenOrActivateDocument(normalizedPath);
23 }
24 finally
25 {
26 _host.IsLoadingCurrentFile = false;
27 }
28 });
29
30 public void LoadSolution(string path) =>
31 IdeMcpEditorDocumentOrchestrator.ScheduleLoadSolution(UiScheduler.Default, path, LoadSolution);
32
33 public async Task<string> LoadSolutionAndWaitAsync(string path, CancellationToken cancellationToken)
34 {
35 cancellationToken.ThrowIfCancellationRequested();
36 await _host.LoadSolutionAsync(path).ConfigureAwait(false);
37 cancellationToken.ThrowIfCancellationRequested();
38 return await UiScheduler.Default.InvokeAsync(() =>
39 {
40 if (!string.IsNullOrWhiteSpace(_host.Workspace.SolutionLoadError))
41 return _host.Workspace.SolutionLoadError.Trim();
42 if (string.IsNullOrWhiteSpace(_host.Workspace.SolutionPath) || _host.Workspace.SolutionRoots.Count == 0)
43 return "Не удалось загрузить решение.";
44 return "OK";
45 }).ConfigureAwait(false);
46 }
47
48 public void SelectInEditor(string? filePath, int startLine, int startColumn, int endLine, int endColumn)
49 {
50 UiScheduler.Default.Post(() =>
51 {
52 if (!string.IsNullOrEmpty(filePath))
53 {
54 var normalized = CanonicalFilePath.Normalize(filePath);
55 if (!CanonicalFilePath.Equals(_host.CurrentFilePath, normalized) && File.Exists(normalized))
56 {
57 _host.IsLoadingCurrentFile = true;
58 try
59 {
60 _host.Documents.OpenOrActivateDocument(normalized);
61 }
62 finally { _host.IsLoadingCurrentFile = false; }
63 }
64 }
65 var text = _host.EditorText ?? "";
66 if (!IdeMcpEditorOrchestrator.TryComputeSelectionSpan(
67 text, startLine, startColumn, endLine, endColumn, out var start, out var len))
68 return;
69 _host.EditorSelectionStart = start;
70 _host.EditorSelectionLength = len;
71 });
72 }
73
74 public async Task<string> GetEditorStateAsync(int? maxPreviewChars)
75 {
76 var preview = maxPreviewChars ?? 2000;
77 return await UiScheduler.Default.InvokeAsync(() =>
78 IdeMcpEditorOrchestrator.SerializeEditorState(
79 _host.McpEditorStateProvider?.Invoke(preview) ?? new Services.EditorStateDto()))
80 .ConfigureAwait(false);
81 }
82
83 public async Task<string> GetEditorContentRangeAsync(int startLine, int endLine)
84 {
85 return await UiScheduler.Default.InvokeAsync(() =>
86 {
87 var content = _host.McpEditorContentRangeProvider?.Invoke(startLine, endLine);
88 return IdeMcpEditorOrchestrator.SerializeEditorContentRange(
89 _host.CurrentFilePath, startLine, endLine, content);
90 })
91 .ConfigureAwait(false);
92 }
93
94 public async Task<string> GetOpenDocumentTextAsync(string? filePath, int? maxChars)
95 {
96 return await UiScheduler.Default.InvokeAsync(() =>
97 {
98 var tabs = _host.Documents.CollectIdeMcpOpenDocumentTabSnapshots();
99 return IdeMcpEditorOrchestrator.BuildGetOpenDocumentTextResponse(
100 filePath, _host.CurrentFilePath, tabs, maxChars);
101 })
102 .ConfigureAwait(false);
103 }
104
105 public Task<string> ApplyEditAsync(string filePath, int startLine, int startColumn, int endLine, int endColumn, string newText) =>
106 UiScheduler.Default.InvokeAsync(() =>
107 _host.Documents.ApplyMcpEditToDocument(filePath, startLine, startColumn, endLine, endColumn, newText));
108
109 public Task<string> ReadWorkspaceFileAsync(string filePath, int? offset, int? limit, int? maxChars) =>
110 UiScheduler.Default.InvokeAsync(() =>
111 {
112 var workspace = _host.McpGetWorkspacePath();
113 if (!WorkspaceDocumentFileIo.TryResolvePath(workspace, null, filePath, out var full, out var resolveError))
114 return System.Text.Json.JsonSerializer.Serialize(new { error = "resolve_failed", message = resolveError });
115
116 if (!WorkspaceDocumentFileIo.TryReadText(full, offset, limit, maxChars, out var json, out var readError))
117 return System.Text.Json.JsonSerializer.Serialize(new { error = "read_failed", message = readError, file_path = full });
118
119 return json;
120 });
121
122 public Task<string> SaveDocumentAsync(string? filePath, string? content) =>
123 UiScheduler.Default.InvokeAsync(() => _host.Documents.SaveDocumentToDisk(filePath, content));
124
125 public void GoToPosition(string? filePath, int line, int column, int? endLine, int? endColumn)
126 {
127 _host.EditorNavigation.TryNavigateGoTo(filePath, line, column, endLine, endColumn, EditorNavigationSource.Mcp);
128 }
129
130 public void RevealEditorRange(string? filePath, int startLine, int endLine, int? durationMs)
131 {
132 _host.EditorNavigation.TryNavigateReveal(
133 filePath,
134 startLine,
135 endLine,
136 durationMs,
137 EditorNavigationSource.Mcp);
138 }
139
140}
141
View only · write via MCP/CIDE