Forge
csharpdeeb25a2
1using System.Diagnostics;
2using CascadeIDE.Models;
3using CascadeIDE.Models.Forge;
4using CascadeIDE.Services;
5using CascadeIDE.Services.Intercom;
6
7namespace CascadeIDE.Features.Forge.Infrastructure;
8
9/// <summary>Open forge artifact from <c>[FRG:…]</c>; optional code tail → editor (ADR-0159 phase 3).</summary>
10public static class ForgeLensOpenService
11{
12 public static string BuildViewUrl(string baseUrl, ForgeArtifactRef artifact)
13 {
14 var root = baseUrl.TrimEnd('/');
15 return artifact.Kind switch
16 {
17 ForgeArtifactKind.Issue => $"{root}/view/repos/{Uri.EscapeDataString(artifact.Repo)}/issues/{artifact.Number}",
18 ForgeArtifactKind.MergeRequest => $"{root}/view/repos/{Uri.EscapeDataString(artifact.Repo)}/merge-requests/{artifact.Number}",
19 ForgeArtifactKind.Repo => $"{root}/view/repos/{Uri.EscapeDataString(artifact.Repo)}",
20 _ => root + "/view",
21 };
22 }
23
24 public static bool TryOpenExternal(string viewUrl, out string error)
25 {
26 error = "";
27 try
28 {
29 Process.Start(new ProcessStartInfo(viewUrl) { UseShellExecute = true });
30 return true;
31 }
32 catch (Exception ex)
33 {
34 error = ex.Message;
35 return false;
36 }
37 }
38
39 public static bool TryNavigateCodeTail(
40 ForgeArtifactRef artifact,
41 string? workspaceRoot,
42 string? activeFilePath,
43 string? solutionPath,
44 string? indexDirectoryRelative,
45 IIdeMcpActions actions,
46 IntercomSettings settings,
47 bool select,
48 out string error)
49 {
50 error = "";
51 if (string.IsNullOrWhiteSpace(artifact.CodeBracket))
52 return true;
53
54 if (!BracketCodeReferenceParser.TryParse(artifact.CodeBracket, out var reference, out error))
55 return false;
56
57 if (!BracketCodeReferenceParser.TryToAttachmentAnchor(
58 reference,
59 activeFilePath,
60 workspaceRoot,
61 solutionPath,
62 indexDirectoryRelative,
63 out var anchor,
64 out error))
65 {
66 return false;
67 }
68
69 error = IntercomAttachmentNavigator.Apply(
70 actions,
71 settings,
72 workspaceRoot,
73 anchor,
74 selectExplicit: select,
75 shiftSelect: false,
76 durationMs: null,
77 solutionPath);
78 return !error.StartsWith("Error", StringComparison.OrdinalIgnoreCase);
79 }
80}
81
View only · write via MCP/CIDE