Forge
csharpdeeb25a2
1using System.Text.Json;
2using CascadeIDE.Models.Intercom;
3using CascadeIDE.Services;
4using CascadeIDE.Services.Intercom;
5
6namespace CascadeIDE.Features.IdeMcp.Execution;
7
8/// <summary>MCP: Intercom (reveal attachment) и editor bracket navigation (ADR 0131).</summary>
9internal sealed partial class IdeMcpCommandExecutor
10{
11 private void RegisterIntercom(Action<string, Handler> add)
12 {
13 add(Services.IdeCommands.IntercomRevealAttachment, async (args, ct) =>
14 {
15 var a = _actions;
16 if (!IntercomRevealAttachmentMcpArgs.TryParse(args, out var anchor, out var selectExplicit, out var durationMs, out var err))
17 return err;
18
19 var workspaceRoot = TryGetWorkspaceRoot(a);
20 var solutionPath = TryGetAttachSolutionPath();
21 return await Task.FromResult(IntercomAttachmentNavigator.Apply(
22 a,
23 _vm.GetCascadeSettingsForExecutor().Intercom,
24 workspaceRoot,
25 anchor,
26 selectExplicit,
27 shiftSelect: false,
28 durationMs,
29 solutionPath));
30 });
31
32 add(Services.IdeCommands.IntercomAttachSelection, async (_, _) =>
33 await Task.FromResult(_vm.ChatPanel.AttachSelectionToComposer()).ConfigureAwait(false));
34
35 add(Services.IdeCommands.IntercomAttachScope, async (_, _) =>
36 await Task.FromResult(_vm.ChatPanel.AttachScopeToComposer()).ConfigureAwait(false));
37
38 add(Services.IdeCommands.IntercomAttachDiagnostic, async (_, _) =>
39 await Task.FromResult(_vm.ChatPanel.AttachDiagnosticAtCaretToComposer()).ConfigureAwait(false));
40
41 add(Services.IdeCommands.EditorSelectCode, ExecuteEditorCodeRefNavigation(select: true));
42 add(Services.IdeCommands.EditorRevealCode, ExecuteEditorCodeRefNavigation(select: false));
43
44 add(Services.IdeCommands.IntercomMessagesForCode, async (args, _) =>
45 {
46 var a = _actions;
47 return await a.FindIntercomMessagesForCodeAsync(args);
48 });
49
50 add(Services.IdeCommands.IntercomMessageRelate, async (args, _) =>
51 {
52 var a = _actions;
53 return await a.RelateIntercomMessageRangeToCodeAsync(args);
54 });
55
56 add(Services.IdeCommands.IntercomConnectTeam, async (_, ct) =>
57 {
58 var (ok, message) = await _vm.ConnectIntercomTeamTransportAsync(ct).ConfigureAwait(false);
59 return ok ? message : "Error: " + message;
60 });
61
62 add(Services.IdeCommands.IntercomDisconnectTeam, async (_, ct) =>
63 {
64 await _vm.DisconnectIntercomTeamTransportAsync(ct).ConfigureAwait(false);
65 return "Intercom transport disconnected.";
66 });
67
68 add(Services.IdeCommands.IntercomServerStatus, async (_, ct) =>
69 {
70 var result = await _vm.RunIntercomAdminSlashAsync(
71 CascadeIDE.Features.Chat.ChatSlashIntercomHandlers.Ids.ServerStatus,
72 null,
73 ct).ConfigureAwait(false);
74 return result.Message;
75 });
76
77 add(Services.IdeCommands.IntercomServerStart, async (args, ct) =>
78 {
79 var url = args is not null
80 && args.TryGetValue("base_url", out var el)
81 && el.ValueKind == JsonValueKind.String
82 ? el.GetString()
83 : null;
84 var result = await _vm.RunIntercomAdminSlashAsync(
85 CascadeIDE.Features.Chat.ChatSlashIntercomHandlers.Ids.ServerStart,
86 url,
87 ct).ConfigureAwait(false);
88 return result.Message;
89 });
90
91 add(Services.IdeCommands.IntercomServerStop, async (_, ct) =>
92 {
93 var result = await _vm.RunIntercomAdminSlashAsync(
94 CascadeIDE.Features.Chat.ChatSlashIntercomHandlers.Ids.ServerStop,
95 null,
96 ct).ConfigureAwait(false);
97 return result.Message;
98 });
99
100 add(Services.IdeCommands.IntercomTeamMembers, async (_, ct) =>
101 {
102 var result = await _vm.RunIntercomAdminSlashAsync(
103 CascadeIDE.Features.Chat.ChatSlashIntercomHandlers.Ids.TeamMembers,
104 null,
105 ct).ConfigureAwait(false);
106 return result.Message;
107 });
108
109 add(Services.IdeCommands.IntercomAgentProvision, async (args, ct) =>
110 {
111 if (args is null
112 || !args.TryGetValue("display_name", out var nameEl)
113 || nameEl.ValueKind != JsonValueKind.String
114 || string.IsNullOrWhiteSpace(nameEl.GetString()))
115 return "Error: display_name required.";
116
117 var result = await _vm.RunIntercomAdminSlashAsync(
118 CascadeIDE.Features.Chat.ChatSlashIntercomHandlers.Ids.AgentProvision,
119 nameEl.GetString(),
120 ct).ConfigureAwait(false);
121 return result.Message;
122 });
123 }
124
125 private Handler ExecuteEditorCodeRefNavigation(bool select) => async (args, ct) =>
126 {
127 var a = _actions;
128 if (!EditorCodeRefMcpArgs.TryParse(args, out var codeRef, out var activeFile, out var durationMs, out var err))
129 return err;
130
131 if (!BracketCodeReferenceParser.TryParse(codeRef, out var reference, out err))
132 return err;
133
134 var workspaceRoot = TryGetWorkspaceRoot(a);
135 var solutionPath = TryGetAttachSolutionPath();
136 var indexDir = CascadeIDE.Features.HybridIndex.Application.HybridIndexIndexDirectoryRelative.ResolveOrDefault(
137 _vm.GetCascadeSettingsForExecutor().HybridIndex.IndexDir);
138 if (!BracketCodeReferenceParser.TryToAttachmentAnchor(
139 reference,
140 activeFile,
141 workspaceRoot,
142 solutionPath,
143 indexDir,
144 out var anchor,
145 out err))
146 {
147 return err;
148 }
149
150 return await Task.FromResult(IntercomAttachmentNavigator.Apply(
151 a,
152 _vm.GetCascadeSettingsForExecutor().Intercom,
153 workspaceRoot,
154 anchor,
155 selectExplicit: select,
156 shiftSelect: false,
157 durationMs,
158 solutionPath));
159 };
160}
161
View only · write via MCP/CIDE