| 1 | using CascadeIDE.Contracts; |
| 2 | using CascadeIDE.Features.WorkspaceNavigation.Application; |
| 3 | |
| 4 | namespace CascadeIDE.Features.IdeMcp.Application; |
| 5 | |
| 6 | /// <summary> |
| 7 | /// Application-level orchestrator helpers for IDE MCP navigation actions. |
| 8 | /// Keeps mode/level normalization and fallback rules out of MainWindowViewModel. |
| 9 | /// </summary> |
| 10 | [ApplicationOrchestrator] |
| 11 | public static class IdeMcpNavigationOrchestrator |
| 12 | { |
| 13 | public static bool TryNormalizeRequestedMode(string mode, out string requestedMode) |
| 14 | { |
| 15 | requestedMode = string.IsNullOrWhiteSpace(mode) ? "related" : mode.Trim().ToLowerInvariant(); |
| 16 | return requestedMode is "related" or "subgraph"; |
| 17 | } |
| 18 | |
| 19 | public static string BuildInvalidModeJson() => |
| 20 | """{"error":"invalid_mode","message":"mode must be related or subgraph."}"""; |
| 21 | |
| 22 | public static (string effectiveLevel, string effectiveMode) ResolveEffectiveLevelAndMode( |
| 23 | string? requestedLevel, |
| 24 | string configuredLevel, |
| 25 | string requestedMode) |
| 26 | { |
| 27 | var effectiveLevel = Models.CodeNavigationMapLevelKind.Normalize( |
| 28 | string.IsNullOrWhiteSpace(requestedLevel) ? configuredLevel : requestedLevel); |
| 29 | var effectiveMode = effectiveLevel == Models.CodeNavigationMapLevelKind.ControlFlow |
| 30 | ? "subgraph" |
| 31 | : requestedMode; |
| 32 | return (effectiveLevel, effectiveMode); |
| 33 | } |
| 34 | |
| 35 | /// <summary>Якорь для control-flow subgraph: производная позиция из текста редактора + fallback по запросу.</summary> |
| 36 | public static (int? line, int? column) ResolveControlFlowLineColumn( |
| 37 | int? requestedLine, |
| 38 | int? requestedColumn, |
| 39 | string? editorText, |
| 40 | int? caretOrSelectionOffset) |
| 41 | { |
| 42 | var (derivedLine, derivedColumn) = WorkspaceNavigationMapOrchestrator.ComputeLineColumn(editorText ?? "", caretOrSelectionOffset); |
| 43 | return ResolveLineColumnForControlFlow(requestedLine, requestedColumn, derivedLine, derivedColumn); |
| 44 | } |
| 45 | |
| 46 | public static (int? line, int? column) ResolveLineColumnForControlFlow( |
| 47 | int? requestedLine, |
| 48 | int? requestedColumn, |
| 49 | int derivedLine, |
| 50 | int derivedColumn) |
| 51 | { |
| 52 | var effectiveLine = requestedLine; |
| 53 | var effectiveColumn = requestedColumn; |
| 54 | |
| 55 | if (effectiveLine is null || effectiveLine <= 0) |
| 56 | effectiveLine = derivedLine; |
| 57 | if (effectiveColumn is null || effectiveColumn <= 0) |
| 58 | effectiveColumn = derivedColumn; |
| 59 | |
| 60 | return (effectiveLine, effectiveColumn); |
| 61 | } |
| 62 | } |
| 63 | |