| 1 | using CascadeIDE.Models.Editor; |
| 2 | |
| 3 | namespace CascadeIDE.Features.IdeMcp.Execution; |
| 4 | |
| 5 | /// <summary>MCP: правка текста и переход к позиции в файле.</summary> |
| 6 | internal sealed partial class IdeMcpCommandExecutor |
| 7 | { |
| 8 | private void RegisterEditAndNavigation(Action<string, Handler> add) |
| 9 | { |
| 10 | add(Services.IdeCommands.ApplyEdit, async (args, ct) => |
| 11 | { |
| 12 | var a = _actions; |
| 13 | if (args is null || !args.TryGetValue("new_text", out _)) return "Missing arguments"; |
| 14 | if (!EditorTextSpan.TryParse(args, out var span, out var errSpan)) |
| 15 | return errSpan; |
| 16 | return await a.ApplyEditAsync( |
| 17 | span.File.Value, |
| 18 | span.StartLine.Value, |
| 19 | span.StartColumn.Value, |
| 20 | span.EndLine.Value, |
| 21 | span.EndColumn.Value, |
| 22 | McpCommandJsonArgs.String(args, "new_text") ?? ""); |
| 23 | }); |
| 24 | add(Services.IdeCommands.GoToPosition, async (args, ct) => |
| 25 | { |
| 26 | var a = _actions; |
| 27 | if (!EditorGoToPositionMcpArgs.TryParse(args, out var file, out var line, out var column, out var endLine, out var endColumn, out var err)) |
| 28 | return err; |
| 29 | a.GoToPosition(file.Value, line.Value, column.Value, endLine?.Value, endColumn?.Value); |
| 30 | return await Task.FromResult("OK"); |
| 31 | }); |
| 32 | add(Services.IdeCommands.RevealEditorRange, async (args, ct) => |
| 33 | { |
| 34 | var a = _actions; |
| 35 | if (!EditorRevealRangeMcpArgs.TryParse(args, out var request, out var err)) |
| 36 | return err; |
| 37 | |
| 38 | var workspaceRoot = TryGetWorkspaceRoot(a); |
| 39 | var solutionPath = TryGetAttachSolutionPath(); |
| 40 | if (!EditorRevealRangeResolution.TryResolveLines( |
| 41 | request, |
| 42 | workspaceRoot, |
| 43 | out var lines, |
| 44 | out var detail, |
| 45 | out var usedFallback, |
| 46 | solutionPath)) |
| 47 | return $"reveal failed: {detail}"; |
| 48 | |
| 49 | a.RevealEditorRange(request.File.Value, lines.Start.Value, lines.End.Value, request.DurationMs); |
| 50 | var suffix = usedFallback ? $" (fallback: {detail})" : string.IsNullOrEmpty(detail) ? "" : $" ({detail})"; |
| 51 | return await Task.FromResult($"OK lines={lines.Start.Value}-{lines.End.Value}{suffix}"); |
| 52 | }); |
| 53 | } |
| 54 | } |
| 55 | |