diff --git a/src/Cody.AgentTester/Cody.AgentTester.csproj b/src/Cody.AgentTester/Cody.AgentTester.csproj
index 55c0cc0d..2eab2ae8 100644
--- a/src/Cody.AgentTester/Cody.AgentTester.csproj
+++ b/src/Cody.AgentTester/Cody.AgentTester.csproj
@@ -57,11 +57,10 @@
{9ff2cc40-78e9-46c8-b2ef-30a1f1be82f2}
Cody.Core
-
-
-
- 2.9.85
-
+
+ {3bb34f98-f069-4a38-bc4d-cf407d59b863}
+ Cody.VisualStudio
+
\ No newline at end of file
diff --git a/src/Cody.AgentTester/Program.cs b/src/Cody.AgentTester/Program.cs
index 8c5a3a21..a5678348 100644
--- a/src/Cody.AgentTester/Program.cs
+++ b/src/Cody.AgentTester/Program.cs
@@ -1,7 +1,8 @@
using Cody.Core.Agent;
-using Cody.Core.Agent.Connector;
using Cody.Core.Agent.Protocol;
+using Cody.VisualStudio.Client;
using System;
+using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
@@ -9,29 +10,31 @@ namespace Cody.AgentTester
{
internal class Program
{
- private static AgentConnector connector;
+ private static AgentClient client;
private static ConsoleLogger logger = new ConsoleLogger();
- private static IAgentClient agentClient;
+ private static IAgentService agentService;
static async Task Main(string[] args)
{
// Set the env var to 3113 when running with local agent.
- var portNumber = int.TryParse(Environment.GetEnvironmentVariable("CODY_VS_DEV_PORT"), out int port) ? port : (int?)null;
+ var devPort = Environment.GetEnvironmentVariable("CODY_VS_DEV_PORT");
+ var portNumber = int.TryParse(devPort, out int port) ? port : 3113;
- var options = new AgentConnectorOptions
+ var options = new AgentClientOptions
{
- NotificationsTarget = new NotificationHandlers(),
+ NotificationHandlers = new List { new NotificationHandlers() },
AgentDirectory = "../../../Cody.VisualStudio/Agent",
RestartAgentOnFailure = true,
Debug = true,
- Port = portNumber,
+ ConnectToRemoteAgent = devPort != null,
+ RemoteAgentPort = portNumber,
};
- connector = new AgentConnector(options, logger);
+ client = new AgentClient(options, logger);
- await connector.Connect();
+ client.Start();
- agentClient = connector.CreateClient();
+ agentService = client.CreateAgentService();
await Initialize();
@@ -76,9 +79,9 @@ private static async Task Initialize()
}
};
- await agentClient.Initialize(clientInfo);
+ await agentService.Initialize(clientInfo);
- agentClient.Initialized();
+ agentService.Initialized();
}
diff --git a/src/Cody.Core/Agent/AgentClientFactory.cs b/src/Cody.Core/Agent/AgentClientFactory.cs
deleted file mode 100644
index dfd46f4d..00000000
--- a/src/Cody.Core/Agent/AgentClientFactory.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using Cody.Core.Agent.Connector;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Cody.Core.Agent
-{
- public class AgentClientFactory : IAgentClientFactory
- {
- private AgentConnector connector;
-
- public AgentClientFactory(AgentConnector connector)
- {
- this.connector = connector;
- }
-
- public IAgentClient CreateAgentClient()
- {
- return connector.CreateClient();
- }
- }
-}
diff --git a/src/Cody.Core/Agent/AgentMethodAttribute.cs b/src/Cody.Core/Agent/AgentMethodAttribute.cs
new file mode 100644
index 00000000..e03df2fc
--- /dev/null
+++ b/src/Cody.Core/Agent/AgentMethodAttribute.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Cody.Core.Agent
+{
+ public class AgentMethodAttribute : Attribute
+ {
+ public AgentMethodAttribute(string name)
+ {
+ Name = name;
+ }
+
+ public string Name { get; private set; }
+ }
+}
diff --git a/src/Cody.Core/Agent/AgentNotificationAttribute.cs b/src/Cody.Core/Agent/AgentNotificationAttribute.cs
new file mode 100644
index 00000000..1ec114a0
--- /dev/null
+++ b/src/Cody.Core/Agent/AgentNotificationAttribute.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Cody.Core.Agent
+{
+ public class AgentNotificationAttribute : Attribute
+ {
+ public AgentNotificationAttribute(string name, bool deserializeToSingleObject = false)
+ {
+ Name = name;
+ DeserializeToSingleObject = deserializeToSingleObject;
+ }
+
+ public string Name { get; private set; }
+
+ public bool DeserializeToSingleObject { get; private set; }
+ }
+}
diff --git a/src/Cody.Core/Agent/Connector/AgentConnector.cs b/src/Cody.Core/Agent/Connector/AgentConnector.cs
deleted file mode 100644
index 7aea0230..00000000
--- a/src/Cody.Core/Agent/Connector/AgentConnector.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-using Cody.Core.Logging;
-using Newtonsoft.Json.Converters;
-using Newtonsoft.Json.Serialization;
-using StreamJsonRpc;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Cody.Core.Agent.Connector
-{
- public class AgentConnector
- {
- private IAgentProcess agentProcess;
- private JsonRpc jsonRpc;
- private IAgentClient agentClient;
- private AgentConnectorOptions options;
- private ILog log;
-
- public AgentConnector(AgentConnectorOptions connectorOptions, ILog log)
- {
- if (connectorOptions == null) throw new ArgumentNullException(nameof(connectorOptions));
-
- options = connectorOptions;
- this.log = log;
- }
-
- public bool IsConnected { get; private set; }
-
- public async Task Connect()
- {
- if (IsConnected) return;
-
- if (options.Port != null)
- {
- agentProcess = await RemoteAgent.Connect(options, OnAgentExit);
- }
- else
- {
- agentProcess = AgentProcess.Start(options.AgentDirectory, options.Debug, log, OnAgentExit);
- }
- log.Info("The agent process has started.");
-
- var jsonMessageFormatter = new JsonMessageFormatter();
- jsonMessageFormatter.JsonSerializer.ContractResolver = new DefaultContractResolver()
- {
- NamingStrategy = new CamelCaseNamingStrategy()
- };
- jsonMessageFormatter.JsonSerializer.Converters.Add(new StringEnumConverter(new CamelCaseNamingStrategy()));
-
- var handler = new HeaderDelimitedMessageHandler(agentProcess.SendingStream, agentProcess.ReceivingStream, jsonMessageFormatter);
- jsonRpc = new JsonRpc(handler);
-
- if (options.NotificationsTarget != null) jsonRpc.AddLocalRpcTarget(options.NotificationsTarget);
- agentClient = jsonRpc.Attach();
- options.NotificationsTarget.SetAgentClient(agentClient);
-
- jsonRpc.StartListening();
- IsConnected = true;
- log.Info("A connection with the agent has been established.");
-
- if (options.AfterConnection != null) options.AfterConnection(agentClient);
- }
-
- private void OnAgentExit(int exitCode)
- {
- DisconnectInternal();
- if (exitCode == 0) log.Info("The agent's process has ended.");
- else log.Error($"The agent process unexpectedly ended with code {exitCode}.");
-
- if (options.RestartAgentOnFailure && exitCode != 0)
- {
- log.Info("Restarting the agent.");
- // TODO: Make RemoteAgent wait until there's an agent to reconnect to before failing.
- Connect().Wait();
- }
- }
-
- public void Disconnect()
- {
- if (!IsConnected) return;
-
- DisconnectInternal();
- }
-
- private void DisconnectInternal()
- {
- if (options.BeforeDisconnection != null) options.BeforeDisconnection(agentClient);
-
- jsonRpc.Dispose();
- agentProcess.Dispose();
-
- jsonRpc = null;
- agentProcess = null;
-
- IsConnected = false;
- log.Info("The connection with the agent has been terminated.");
- }
-
- public IAgentClient CreateClient()
- {
- if (!IsConnected) Connect();
-
- return agentClient;
- }
- }
-}
diff --git a/src/Cody.Core/Agent/Connector/AgentConnectorOptions.cs b/src/Cody.Core/Agent/Connector/AgentConnectorOptions.cs
deleted file mode 100644
index 544ccd9d..00000000
--- a/src/Cody.Core/Agent/Connector/AgentConnectorOptions.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Cody.Core.Agent.Connector
-{
- public class AgentConnectorOptions
- {
- public bool Debug { get; set; }
-
- public bool RestartAgentOnFailure { get; set; }
-
- ///
- /// If non-null, the TCP port to connect to an existing Agent instance on.
- ///
- public int? Port { get; set; }
-
- public string AgentDirectory { get; set; }
-
- public Action AfterConnection { get; set; }
-
- public Action BeforeDisconnection { get; set; }
-
- public NotificationHandlers NotificationsTarget { get; set; }
- }
-}
diff --git a/src/Cody.Core/Agent/Connector/AgentProcess.cs b/src/Cody.Core/Agent/Connector/AgentProcess.cs
deleted file mode 100644
index a5e754f2..00000000
--- a/src/Cody.Core/Agent/Connector/AgentProcess.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-using Cody.Core.Logging;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Runtime.InteropServices;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Cody.Core.Agent.Connector
-{
- public class AgentProcess : IAgentProcess
- {
- private readonly Process process = new Process();
- private string agentDirectory;
- private static readonly string workingDirectory = "../../../../../cody/agent/dist";
- private bool debugMode;
- private ILog logger;
- private Action onExit;
-
- private AgentProcess(string agentDirectory, bool debugMode, ILog logger, Action onExit)
- {
- this.agentDirectory = agentDirectory;
- this.debugMode = debugMode;
- this.logger = logger;
- this.onExit = onExit;
- }
-
- public Stream SendingStream => process.StandardInput.BaseStream;
-
- public Stream ReceivingStream => process.StandardOutput.BaseStream;
-
- public static AgentProcess Start(string agentDirectory, bool debugMode, ILog logger, Action onExit)
- {
-
- if (!Directory.Exists(agentDirectory))
- throw new ArgumentException("Directory does not exist", nameof(agentDirectory));
-
- var agentProcess = new AgentProcess(agentDirectory, debugMode, logger, onExit);
- agentProcess.StartInternal();
-
- return agentProcess;
- }
-
-
- private void StartInternal()
- {
- var path = Path.Combine(agentDirectory, GetAgentFileName());
-
- if (!File.Exists(path))
- throw new FileNotFoundException("Agent file not found", path);
-
- var port = Environment.GetEnvironmentVariable("CODY_VS_DEV_PORT");
-
- if (port != null && Directory.Exists(workingDirectory))
- agentDirectory = workingDirectory;
-
- process.StartInfo.FileName = path;
- process.StartInfo.Arguments = GetAgentArguments(debugMode);
- process.StartInfo.WorkingDirectory = agentDirectory;
- process.StartInfo.UseShellExecute = false;
- process.StartInfo.RedirectStandardOutput = true;
- process.StartInfo.RedirectStandardError = true;
- process.StartInfo.RedirectStandardInput = true;
- process.StartInfo.CreateNoWindow = true;
- process.EnableRaisingEvents = true;
- process.Exited += OnProcessExited;
- process.ErrorDataReceived += OnErrorDataReceived;
-
- process.Start();
- process.BeginErrorReadLine();
- }
-
- private void OnErrorDataReceived(object sender, DataReceivedEventArgs e)
- {
- logger.Error(e.Data, "Agent errors");
- }
-
- private void OnProcessExited(object sender, EventArgs e)
- {
- if (onExit != null) onExit(process.ExitCode);
- }
-
- private string GetAgentFileName()
- {
- if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
- return "node-win-arm64.exe";
-
- return "node-win-x64.exe";
- }
-
- private string GetAgentArguments(bool debugMode)
- {
- var argList = new List();
-
- if (debugMode)
- {
- argList.Add("--inspect");
- argList.Add("--enable-source-maps");
- }
-
- argList.Add("index.js api jsonrpc-stdio");
-
- var arguments = string.Join(" ", argList);
- return arguments;
- }
-
- public void Dispose()
- {
- if (!process.HasExited) process.Kill();
-
- process.Dispose();
- }
-
- public bool IsConnected
- {
- get
- {
- return !process.HasExited;
- }
- }
- }
-}
diff --git a/src/Cody.Core/Agent/Connector/IAgentProcess.cs b/src/Cody.Core/Agent/Connector/IAgentProcess.cs
deleted file mode 100644
index e2e03403..00000000
--- a/src/Cody.Core/Agent/Connector/IAgentProcess.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Cody.Core.Agent.Connector
-{
- internal interface IAgentProcess : IDisposable
- {
- bool IsConnected { get; }
- Stream SendingStream { get; }
- Stream ReceivingStream { get; }
- }
-}
diff --git a/src/Cody.Core/Agent/Connector/RemoteAgent.cs b/src/Cody.Core/Agent/Connector/RemoteAgent.cs
deleted file mode 100644
index ee70428c..00000000
--- a/src/Cody.Core/Agent/Connector/RemoteAgent.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using System;
-using System.IO;
-using System.Net;
-using System.Net.Sockets;
-using System.Threading.Tasks;
-
-namespace Cody.Core.Agent.Connector
-{
- class RemoteAgent : IAgentProcess
- {
- internal static async Task Connect(AgentConnectorOptions options, Action onExit)
- {
- TcpClient client = new TcpClient();
- await client.ConnectAsync(IPAddress.Loopback, options.Port ?? 3113);
- return new RemoteAgent(client, onExit);
- }
-
- private TcpClient client;
- private Action onExit;
-
- private RemoteAgent(TcpClient client, Action onExit) {
- this.client = client;
- this.onExit = onExit;
-
- // TODO: Wrap the returned streams and if they fail to read or write, call the onExit callback.
- }
-
- public void Dispose()
- {
- this.client.Dispose();
- }
-
- public bool IsConnected {
- get {
- return this.client.Connected;
- }
- }
-
- public Stream SendingStream => client.GetStream();
- public Stream ReceivingStream => client.GetStream();
- }
-}
diff --git a/src/Cody.Core/Agent/IAgentClient.cs b/src/Cody.Core/Agent/IAgentClient.cs
deleted file mode 100644
index 9250c6a2..00000000
--- a/src/Cody.Core/Agent/IAgentClient.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using Cody.Core.Agent.Protocol;
-using StreamJsonRpc;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Cody.Core.Agent
-{
- public interface IAgentClient
- {
- [JsonRpcMethod("initialize")]
- Task Initialize(ClientInfo clientInfo);
-
- [JsonRpcMethod("graphql/getCurrentUserCodySubscription")]
- Task GetCurrentUserCodySubscription();
-
- [JsonRpcMethod("initialized")]
- void Initialized();
-
- [JsonRpcMethod("git/codebaseName")]
- Task GetGitCodebaseName(string url);
-
- [JsonRpcMethod("webview/resolveWebviewView", UseSingleObjectParameterDeserialization = true)]
- Task ResolveWebviewView(ResolveWebviewViewParams paramValue);
-
- [JsonRpcMethod("webview/receiveMessageStringEncoded")]
- Task ReceiveMessageStringEncoded(ReceiveMessageStringEncodedParams paramValue);
-
- [JsonRpcMethod("env/openExternal")]
- Task OpenExternal(string url);
-
- [JsonRpcMethod("textDocument/didOpen", UseSingleObjectParameterDeserialization = true)]
- void DidOpen(ProtocolTextDocument docState);
-
- [JsonRpcMethod("textDocument/didChange", UseSingleObjectParameterDeserialization = true)]
- void DidChange(ProtocolTextDocument docState);
-
- [JsonRpcMethod("textDocument/didFocus")]
- void DidFocus(string uri);
-
- [JsonRpcMethod("textDocument/didSave")]
- void DidSave(string uri);
-
- [JsonRpcMethod("textDocument/didClose", UseSingleObjectParameterDeserialization = true)]
- void DidClose(ProtocolTextDocument docState);
- }
-}
-
-public class ResolveWebviewViewParams
-{
- public string ViewId { get; set; }
- public string WebviewHandle { get; set; }
-}
-
-public class ReceiveMessageStringEncodedParams
-{
- public string Id { get; set; }
- public string MessageStringEncoded { get; set; }
-}
\ No newline at end of file
diff --git a/src/Cody.Core/Agent/IAgentService.cs b/src/Cody.Core/Agent/IAgentService.cs
new file mode 100644
index 00000000..9cca7356
--- /dev/null
+++ b/src/Cody.Core/Agent/IAgentService.cs
@@ -0,0 +1,49 @@
+using Cody.Core.Agent.Protocol;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Cody.Core.Agent
+{
+ public interface IAgentService
+ {
+ [AgentMethod("initialize")]
+ Task Initialize(ClientInfo clientInfo);
+
+ [AgentMethod("graphql/getCurrentUserCodySubscription")]
+ Task GetCurrentUserCodySubscription();
+
+ [AgentMethod("initialized")]
+ void Initialized();
+
+ [AgentMethod("git/codebaseName")]
+ Task GetGitCodebaseName(string url);
+
+ [AgentMethod("webview/resolveWebviewView")]
+ Task ResolveWebviewView(ResolveWebviewViewParams paramValue);
+
+ [AgentMethod("webview/receiveMessageStringEncoded")]
+ Task ReceiveMessageStringEncoded(ReceiveMessageStringEncodedParams paramValue);
+
+ [AgentMethod("env/openExternal")]
+ Task OpenExternal(string url);
+
+ [AgentMethod("textDocument/didOpen")]
+ void DidOpen(ProtocolTextDocument docState);
+
+ [AgentMethod("textDocument/didChange")]
+ void DidChange(ProtocolTextDocument docState);
+
+ [AgentMethod("textDocument/didFocus")]
+ void DidFocus(string uri);
+
+ [AgentMethod("textDocument/didSave")]
+ void DidSave(string uri);
+
+ [AgentMethod("textDocument/didClose")]
+ void DidClose(ProtocolTextDocument docState);
+ }
+}
+
diff --git a/src/Cody.Core/Agent/IAgentClientFactory.cs b/src/Cody.Core/Agent/INotificationHandler.cs
similarity index 66%
rename from src/Cody.Core/Agent/IAgentClientFactory.cs
rename to src/Cody.Core/Agent/INotificationHandler.cs
index bc8e8301..d59d5802 100644
--- a/src/Cody.Core/Agent/IAgentClientFactory.cs
+++ b/src/Cody.Core/Agent/INotificationHandler.cs
@@ -6,8 +6,7 @@
namespace Cody.Core.Agent
{
- public interface IAgentClientFactory
+ public interface INotificationHandler
{
- IAgentClient CreateAgentClient();
}
}
diff --git a/src/Cody.Core/Agent/Connector/InitializeCallback.cs b/src/Cody.Core/Agent/InitializeCallback.cs
similarity index 97%
rename from src/Cody.Core/Agent/Connector/InitializeCallback.cs
rename to src/Cody.Core/Agent/InitializeCallback.cs
index 25ee06d6..caad707b 100644
--- a/src/Cody.Core/Agent/Connector/InitializeCallback.cs
+++ b/src/Cody.Core/Agent/InitializeCallback.cs
@@ -11,7 +11,7 @@
using System.Text;
using System.Threading.Tasks;
-namespace Cody.Core.Agent.Connector
+namespace Cody.Core.Agent
{
public class InitializeCallback
{
@@ -35,7 +35,7 @@ public InitializeCallback(
this.log = log;
}
- public async Task Initialize(IAgentClient client)
+ public async Task Initialize(IAgentService client)
{
// TODO: Get the solution directory path that the user is working on.
var solutionDirPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
diff --git a/src/Cody.Core/Agent/NotificationHandlers.cs b/src/Cody.Core/Agent/NotificationHandlers.cs
index f76392c1..88f65c4a 100644
--- a/src/Cody.Core/Agent/NotificationHandlers.cs
+++ b/src/Cody.Core/Agent/NotificationHandlers.cs
@@ -1,15 +1,12 @@
-using Cody.Core.Agent.Connector;
-using Cody.Core.Agent.Protocol;
+using Cody.Core.Agent.Protocol;
using Newtonsoft.Json.Linq;
-using StreamJsonRpc;
using System;
-using EnvDTE;
using EnvDTE80;
using System.Threading.Tasks;
namespace Cody.Core.Agent
{
- public class NotificationHandlers
+ public class NotificationHandlers : INotificationHandler
{
public NotificationHandlers()
{
@@ -20,9 +17,9 @@ public NotificationHandlers()
public event EventHandler OnSetHtmlEvent;
public event EventHandler OnPostMessageEvent;
- public IAgentClient agentClient;
+ public IAgentService agentClient;
- public void SetAgentClient(IAgentClient agentClient) => this.agentClient = agentClient;
+ public void SetAgentClient(IAgentService agentClient) => this.agentClient = agentClient;
// Send a message to the host from webview.
public async Task SendWebviewMessage(string handle, string message)
@@ -70,19 +67,19 @@ await agentClient.ReceiveMessageStringEncoded(new ReceiveMessageStringEncodedPar
});
}
- [JsonRpcMethod("debug/message")]
+ [AgentNotification("debug/message")]
public void Debug(string channel, string message)
{
System.Diagnostics.Debug.WriteLine(message, "Agent Debug");
}
- [JsonRpcMethod("webview/registerWebview")]
+ [AgentNotification("webview/registerWebview")]
public void RegisterWebview(string handle)
{
System.Diagnostics.Debug.WriteLine(handle, "Agent registerWebview");
}
- [JsonRpcMethod("webview/registerWebviewViewProvider")]
+ [AgentNotification("webview/registerWebviewViewProvider")]
public async Task RegisterWebviewViewProvider(string viewId, bool retainContextWhenHidden)
{
System.Diagnostics.Debug.WriteLine(viewId, retainContextWhenHidden, "Agent registerWebviewViewProvider");
@@ -95,13 +92,13 @@ await agentClient.ResolveWebviewView(new ResolveWebviewViewParams
});
}
- [JsonRpcMethod("webview/createWebviewPanel", UseSingleObjectParameterDeserialization = true)]
+ [AgentNotification("webview/createWebviewPanel", deserializeToSingleObject: true)]
public void CreateWebviewPanel(CreateWebviewPanelParams panelParams)
{
System.Diagnostics.Debug.WriteLine(panelParams, "Agent createWebviewPanel");
}
- [JsonRpcMethod("webview/setOptions")]
+ [AgentNotification("webview/setOptions")]
public void SetOptions(string handle, DefiniteWebviewOptions options)
{
if (options.EnableCommandUris is bool enableCmd)
@@ -114,67 +111,61 @@ public void SetOptions(string handle, DefiniteWebviewOptions options)
}
}
- [JsonRpcMethod("webview/setHtml")]
+ [AgentNotification("webview/setHtml")]
public void SetHtml(string handle, string html)
{
System.Diagnostics.Debug.WriteLine(html, "Agent setHtml");
OnSetHtmlEvent?.Invoke(this, new SetHtmlEvent() { Handle = handle, Html = html });
}
- [JsonRpcMethod("webview/PostMessage")]
+ [AgentNotification("webview/PostMessage")]
public void PostMessage(string handle, string message)
{
PostMessageStringEncoded(handle, message);
}
- [JsonRpcMethod("webview/postMessageStringEncoded")]
+ [AgentNotification("webview/postMessageStringEncoded")]
public void PostMessageStringEncoded(string id, string stringEncodedMessage)
{
System.Diagnostics.Debug.WriteLine(stringEncodedMessage, "Agent postMessageStringEncoded");
PostWebMessageAsJson?.Invoke(stringEncodedMessage);
}
- [JsonRpcMethod("webview/didDisposeNative")]
+ [AgentNotification("webview/didDisposeNative")]
public void DidDisposeNative(string handle)
{
- ;
+
}
- [JsonRpcMethod("extensionConfiguration/didChange")]
+ [AgentNotification("extensionConfiguration/didChange", deserializeToSingleObject: true)]
public void ExtensionConfigDidChange(ExtensionConfiguration config)
{
System.Diagnostics.Debug.WriteLine(config, "Agent didChange");
}
- [JsonRpcMethod("webview/dispose")]
+ [AgentNotification("webview/dispose")]
public void Dispose(string handle)
{
System.Diagnostics.Debug.WriteLine(handle, "Agent dispose");
}
- [JsonRpcMethod("webview/reveal")]
+ [AgentNotification("webview/reveal")]
public void Reveal(string handle, int viewColumn, bool preserveFocus)
{
System.Diagnostics.Debug.WriteLine(handle, "Agent reveal");
}
- [JsonRpcMethod("webview/setTitle")]
+ [AgentNotification("webview/setTitle")]
public void SetTitle(string handle, string title)
{
System.Diagnostics.Debug.WriteLine(title, "Agent setTitle");
}
- [JsonRpcMethod("webview/setIconPath")]
+ [AgentNotification("webview/setIconPath")]
public void SetIconPath(string handle, string iconPathUri)
{
System.Diagnostics.Debug.WriteLine(iconPathUri, "Agent setIconPath");
}
- [JsonRpcMethod("webview/createWebviewPanel")]
- public void CreateWebviewPanel(string handle, string viewType, string title, ShowOptions showOptions, bool enableScripts, bool enableForms, bool enableCommandUris, bool enableFindWidget, bool retainContextWhenHidden)
- {
- System.Diagnostics.Debug.WriteLine(title, "Agent createWebviewPanel");
- }
-
}
}
diff --git a/src/Cody.Core/Agent/Protocol/ReceiveMessageStringEncodedParams.cs b/src/Cody.Core/Agent/Protocol/ReceiveMessageStringEncodedParams.cs
new file mode 100644
index 00000000..a9c167f9
--- /dev/null
+++ b/src/Cody.Core/Agent/Protocol/ReceiveMessageStringEncodedParams.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Cody.Core.Agent.Protocol
+{
+ public class ReceiveMessageStringEncodedParams
+ {
+ public string Id { get; set; }
+ public string MessageStringEncoded { get; set; }
+ }
+}
diff --git a/src/Cody.Core/Agent/Protocol/ResolveWebviewViewParams.cs b/src/Cody.Core/Agent/Protocol/ResolveWebviewViewParams.cs
new file mode 100644
index 00000000..bf2eff02
--- /dev/null
+++ b/src/Cody.Core/Agent/Protocol/ResolveWebviewViewParams.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Cody.Core.Agent.Protocol
+{
+ public class ResolveWebviewViewParams
+ {
+ public string ViewId { get; set; }
+ public string WebviewHandle { get; set; }
+ }
+}
diff --git a/src/Cody.Core/Cody.Core.csproj b/src/Cody.Core/Cody.Core.csproj
index 6dc512cf..3548634a 100644
--- a/src/Cody.Core/Cody.Core.csproj
+++ b/src/Cody.Core/Cody.Core.csproj
@@ -40,122 +40,10 @@
True
-
- ..\packages\MessagePack.2.5.108\lib\netstandard2.0\MessagePack.dll
-
-
- ..\packages\MessagePack.Annotations.2.5.108\lib\netstandard2.0\MessagePack.Annotations.dll
-
-
- ..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll
-
-
- ..\packages\Microsoft.NET.StringTools.17.4.0\lib\net472\Microsoft.NET.StringTools.dll
-
-
- ..\packages\Microsoft.VisualStudio.Threading.17.9.28\lib\net472\Microsoft.VisualStudio.Threading.dll
-
-
- ..\packages\Microsoft.VisualStudio.Validation.17.8.8\lib\netstandard2.0\Microsoft.VisualStudio.Validation.dll
-
-
- ..\packages\Microsoft.Win32.Registry.5.0.0\lib\net461\Microsoft.Win32.Registry.dll
-
-
- ..\packages\Nerdbank.Streams.2.10.69\lib\netstandard2.0\Nerdbank.Streams.dll
-
-
- ..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll
-
-
- ..\packages\StreamJsonRpc.2.9.85\lib\netstandard2.0\StreamJsonRpc.dll
-
-
- ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
-
-
- ..\packages\System.Collections.Immutable.7.0.0\lib\net462\System.Collections.Immutable.dll
-
-
- ..\packages\System.Diagnostics.DiagnosticSource.8.0.0\lib\net462\System.Diagnostics.DiagnosticSource.dll
-
-
- ..\packages\System.IO.4.3.0\lib\net462\System.IO.dll
- True
- True
-
-
- ..\packages\System.IO.Pipelines.7.0.0\lib\net462\System.IO.Pipelines.dll
-
-
- ..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll
-
-
- ..\packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll
- True
- True
-
-
- ..\packages\System.Net.WebSockets.4.3.0\lib\net46\System.Net.WebSockets.dll
- True
- True
-
-
- ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
-
-
- ..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll
- True
- True
-
-
- ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
-
-
- ..\packages\System.Security.AccessControl.5.0.0\lib\net461\System.Security.AccessControl.dll
-
-
- ..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net463\System.Security.Cryptography.Algorithms.dll
- True
- True
-
-
- ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll
- True
- True
-
-
- ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll
- True
- True
-
-
- ..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll
- True
- True
-
-
- ..\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll
-
-
- ..\packages\System.Text.Encodings.Web.7.0.0\lib\net462\System.Text.Encodings.Web.dll
-
-
- ..\packages\System.Text.Json.7.0.3\lib\net462\System.Text.Json.dll
-
-
- ..\packages\System.Threading.Tasks.Dataflow.7.0.0\lib\net462\System.Threading.Tasks.Dataflow.dll
-
-
- ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
-
-
- ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
-
@@ -167,15 +55,11 @@
Properties\AssemblyVersion.cs
-
-
-
-
-
-
-
-
-
+
+
+
+
+
@@ -189,8 +73,10 @@
+
+
@@ -208,22 +94,9 @@
-
-
-
-
-
-
-
-
-
+
+ 13.0.1
+
-
-
-
- This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
-
-
-
\ No newline at end of file
diff --git a/src/Cody.Core/DocumentSync/DocumentSyncCallback.cs b/src/Cody.Core/DocumentSync/DocumentSyncCallback.cs
index 99620b89..2b8cae94 100644
--- a/src/Cody.Core/DocumentSync/DocumentSyncCallback.cs
+++ b/src/Cody.Core/DocumentSync/DocumentSyncCallback.cs
@@ -7,18 +7,17 @@
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
-using static Nerdbank.Streams.MultiplexingStream;
namespace Cody.Core.DocumentSync
{
public class DocumentSyncCallback : IDocumentSyncActions
{
private ILog logger;
- private IAgentClientFactory agentClientFactory;
+ private IAgentService agentService;
- public DocumentSyncCallback(IAgentClientFactory agentClientFactory, ILog logger)
+ public DocumentSyncCallback(IAgentService agentService, ILog logger)
{
- this.agentClientFactory = agentClientFactory;
+ this.agentService = agentService;
this.logger = logger;
}
@@ -86,7 +85,7 @@ public void OnChanged(string fullPath, DocumentRange visibleRange, DocumentRange
}).ToArray()
};
- agentClientFactory.CreateAgentClient().DidChange(docState);
+ agentService.DidChange(docState);
}
public void OnClosed(string fullPath)
@@ -99,13 +98,13 @@ public void OnClosed(string fullPath)
};
// Only the 'uri' property is required, other properties are ignored.
- agentClientFactory.CreateAgentClient().DidClose(docState);
+ agentService.DidClose(docState);
}
public void OnFocus(string fullPath)
{
logger.Debug($"Sending DidFocus() for '{fullPath}'");
- agentClientFactory.CreateAgentClient().DidFocus(ToUri(fullPath));
+ agentService.DidFocus(ToUri(fullPath));
}
@@ -151,14 +150,14 @@ public void OnOpened(string fullPath, string content, DocumentRange visibleRange
}
};
- agentClientFactory.CreateAgentClient().DidOpen(docState);
+ agentService.DidOpen(docState);
}
public void OnSaved(string fullPath)
{
logger.Debug($"Sending DidSave() for '{fullPath}'");
- agentClientFactory.CreateAgentClient().DidSave(ToUri(fullPath));
+ agentService.DidSave(ToUri(fullPath));
}
}
}
diff --git a/src/Cody.Core/packages.config b/src/Cody.Core/packages.config
deleted file mode 100644
index f9cd0a66..00000000
--- a/src/Cody.Core/packages.config
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Cody.UI/ViewModels/MainViewModel.cs b/src/Cody.UI/ViewModels/MainViewModel.cs
index bded2d78..a02eec51 100644
--- a/src/Cody.UI/ViewModels/MainViewModel.cs
+++ b/src/Cody.UI/ViewModels/MainViewModel.cs
@@ -1,5 +1,4 @@
using Cody.Core.Agent;
-using Cody.Core.Agent.Connector;
using Cody.Core.Logging;
using Cody.UI.MVVM;
using System.Windows.Input;
diff --git a/src/Cody.VisualStudio/Client/AgentClient.cs b/src/Cody.VisualStudio/Client/AgentClient.cs
new file mode 100644
index 00000000..e8d56e08
--- /dev/null
+++ b/src/Cody.VisualStudio/Client/AgentClient.cs
@@ -0,0 +1,124 @@
+using Cody.Core.Logging;
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Serialization;
+using StreamJsonRpc;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Cody.VisualStudio.Client
+{
+ public class AgentClient
+ {
+ private AgentClientOptions options;
+ private ILog log;
+
+ private IAgentConnector connector;
+ private JsonRpc jsonRpc;
+
+ public AgentClient(AgentClientOptions options, ILog log)
+ {
+ this.options = options;
+ this.log = log;
+ }
+
+ public bool IsConnected { get; private set; }
+
+ public void Start()
+ {
+ if (IsConnected) return;
+
+ connector = CreateConnector();
+ connector.ErrorReceived += OnErrorReceived;
+ connector.Disconnected += OnAgentDisconnected;
+
+ connector.Connect(options);
+
+ var jsonMessageFormatter = new JsonMessageFormatter();
+ jsonMessageFormatter.JsonSerializer.ContractResolver = new DefaultContractResolver()
+ {
+ NamingStrategy = new CamelCaseNamingStrategy()
+ };
+ jsonMessageFormatter.JsonSerializer.Converters.Add(new StringEnumConverter(new CamelCaseNamingStrategy()));
+ var handler = new HeaderDelimitedMessageHandler(connector.SendingStream, connector.ReceivingStream, jsonMessageFormatter);
+
+ jsonRpc = new JsonRpc(handler);
+
+ foreach (var target in options.NotificationHandlers)
+ {
+ var methods = NameTransformer.GetNotificationMethods(target.GetType());
+ foreach (var method in methods) jsonRpc.AddLocalRpcMethod(method.Key, target, method.Value);
+ }
+
+ jsonRpc.StartListening();
+ IsConnected = true;
+ log.Info("A connection with the agent has been established.");
+ }
+
+ public T CreateAgentService() where T : class
+ {
+ var proxyOptions = new JsonRpcProxyOptions { MethodNameTransform = NameTransformer.CreateTransformer() };
+ return jsonRpc.Attach(proxyOptions);
+ }
+
+ private void OnErrorReceived(object sender, string error)
+ {
+ log.Error(error, "Agent errors");
+ }
+
+ private IAgentConnector CreateConnector()
+ {
+ IAgentConnector connector;
+ if (options.ConnectToRemoteAgent)
+ {
+ connector = new RemoteAgentConnector();
+ log.Info("Remote agent connector created");
+ }
+ else
+ {
+ connector = new AgentProcessConnector();
+ log.Info("Process agent connector created");
+ }
+
+ return connector;
+ }
+
+ private void OnAgentDisconnected(object sender, int exitCode)
+ {
+ DisconnectInternal();
+ if (exitCode == 0) log.Info("The agent's connection has ended.");
+ else log.Error($"The agent connection unexpectedly ended with code {exitCode}.");
+
+ if (options.RestartAgentOnFailure && exitCode != 0)
+ {
+ log.Info("Restarting the agent.");
+
+ Start();
+ }
+ }
+
+ public void Stop()
+ {
+ if (!IsConnected) return;
+
+ DisconnectInternal();
+ }
+
+ private void DisconnectInternal()
+ {
+ jsonRpc.Dispose();
+ connector.ErrorReceived -= OnErrorReceived;
+ connector.Disconnected -= OnAgentDisconnected;
+ connector.Disconnect();
+
+ jsonRpc = null;
+ connector = null;
+
+ IsConnected = false;
+ log.Info("The connection with the agent has been terminated.");
+ }
+ }
+
+}
diff --git a/src/Cody.VisualStudio/Client/AgentClientOptions.cs b/src/Cody.VisualStudio/Client/AgentClientOptions.cs
new file mode 100644
index 00000000..ee846696
--- /dev/null
+++ b/src/Cody.VisualStudio/Client/AgentClientOptions.cs
@@ -0,0 +1,27 @@
+using Cody.Core.Agent;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Cody.VisualStudio.Client
+{
+ public class AgentClientOptions
+ {
+ public bool Debug { get; set; }
+
+ public bool RestartAgentOnFailure { get; set; } = true;
+
+ public bool ConnectToRemoteAgent { get; set; } = false;
+
+ ///
+ /// If non-null, the TCP port to connect to an existing Agent instance on.
+ ///
+ public int RemoteAgentPort { get; set; } = 3113;
+
+ public string AgentDirectory { get; set; }
+
+ public List NotificationHandlers { get; set; } = new List();
+ }
+}
diff --git a/src/Cody.VisualStudio/Client/AgentProcessConnector.cs b/src/Cody.VisualStudio/Client/AgentProcessConnector.cs
new file mode 100644
index 00000000..9f962666
--- /dev/null
+++ b/src/Cody.VisualStudio/Client/AgentProcessConnector.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Cody.VisualStudio.Client
+{
+ public class AgentProcessConnector : IAgentConnector
+ {
+ private Process process;
+
+ public event EventHandler Disconnected;
+ public event EventHandler ErrorReceived;
+
+ public void Connect(AgentClientOptions options)
+ {
+ var path = Path.Combine(options.AgentDirectory, GetAgentFileName());
+
+ if (!File.Exists(path))
+ throw new FileNotFoundException("Agent file not found", path);
+
+ process = new Process();
+ process.StartInfo.FileName = path;
+ process.StartInfo.Arguments = GetAgentArguments(options.Debug);
+ process.StartInfo.WorkingDirectory = options.AgentDirectory;
+ process.StartInfo.UseShellExecute = false;
+ process.StartInfo.RedirectStandardOutput = true;
+ process.StartInfo.RedirectStandardError = true;
+ process.StartInfo.RedirectStandardInput = true;
+ process.StartInfo.CreateNoWindow = true;
+ process.EnableRaisingEvents = true;
+ process.Exited += OnProcessExited;
+ process.ErrorDataReceived += OnErrorDataReceived;
+
+ process.Start();
+ process.BeginErrorReadLine();
+ }
+
+ private void OnErrorDataReceived(object sender, DataReceivedEventArgs e) => ErrorReceived?.Invoke(this, e.Data);
+
+ private void OnProcessExited(object sender, EventArgs e) => Disconnected?.Invoke(this, process.ExitCode);
+
+ public void Disconnect()
+ {
+ if (process != null && !process.HasExited) process.Kill();
+ }
+
+ public Stream SendingStream => process?.StandardInput?.BaseStream;
+
+ public Stream ReceivingStream => process?.StandardOutput?.BaseStream;
+
+ private string GetAgentFileName()
+ {
+ if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
+ return "node-win-arm64.exe";
+
+ return "node-win-x64.exe";
+ }
+
+ private string GetAgentArguments(bool debugMode)
+ {
+ var argList = new List();
+
+ if (debugMode)
+ {
+ argList.Add("--inspect");
+ argList.Add("--enable-source-maps");
+ }
+
+ argList.Add("index.js api jsonrpc-stdio");
+
+ var arguments = string.Join(" ", argList);
+ return arguments;
+ }
+ }
+}
diff --git a/src/Cody.VisualStudio/Client/IAgentConnector.cs b/src/Cody.VisualStudio/Client/IAgentConnector.cs
new file mode 100644
index 00000000..086c6922
--- /dev/null
+++ b/src/Cody.VisualStudio/Client/IAgentConnector.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Cody.VisualStudio.Client
+{
+ public interface IAgentConnector
+ {
+ void Connect(AgentClientOptions options);
+
+ void Disconnect();
+
+ event EventHandler Disconnected;
+
+ event EventHandler ErrorReceived;
+
+ Stream SendingStream { get; }
+ Stream ReceivingStream { get; }
+ }
+}
diff --git a/src/Cody.VisualStudio/Client/NameTransformer.cs b/src/Cody.VisualStudio/Client/NameTransformer.cs
new file mode 100644
index 00000000..d2c8e096
--- /dev/null
+++ b/src/Cody.VisualStudio/Client/NameTransformer.cs
@@ -0,0 +1,44 @@
+using Cody.Core.Agent;
+using StreamJsonRpc;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Cody.VisualStudio.Client
+{
+ public class NameTransformer
+ {
+ public static Func CreateTransformer(Type type)
+ {
+ var dic = type
+ .GetMethods()
+ .ToDictionary(k => k.Name, v => v.GetCustomAttribute()?.Name ?? v.Name);
+
+ Func func = (x) => dic[x];
+
+ return func;
+ }
+
+ public static Func CreateTransformer() where T : class => CreateTransformer(typeof(T));
+
+ public static IReadOnlyDictionary GetNotificationMethods(Type type)
+ {
+ var dic = type
+ .GetMethods()
+ .Where(x => x.GetCustomAttribute() != null)
+ .ToDictionary(k => k, v =>
+ {
+ var att = v.GetCustomAttribute();
+ return new JsonRpcMethodAttribute(att.Name)
+ {
+ UseSingleObjectParameterDeserialization = att.DeserializeToSingleObject
+ };
+ });
+
+ return dic;
+ }
+ }
+}
diff --git a/src/Cody.VisualStudio/Client/RemoteAgentConnector.cs b/src/Cody.VisualStudio/Client/RemoteAgentConnector.cs
new file mode 100644
index 00000000..6ab579a0
--- /dev/null
+++ b/src/Cody.VisualStudio/Client/RemoteAgentConnector.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net.Sockets;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Cody.VisualStudio.Client
+{
+ public class RemoteAgentConnector : IAgentConnector
+ {
+ private TcpClient client;
+
+ public event EventHandler Disconnected;
+ public event EventHandler ErrorReceived;
+
+ public void Connect(AgentClientOptions options)
+ {
+ client = new TcpClient();
+ client.Connect(IPAddress.Loopback, options.RemoteAgentPort);
+ }
+
+ public void Disconnect()
+ {
+ if (client != null && client.Connected)
+ {
+ client.Close();
+ client = null;
+ Disconnected?.Invoke(this, 0);
+ }
+ }
+
+ public Stream SendingStream => client?.GetStream();
+ public Stream ReceivingStream => client?.GetStream();
+ }
+}
diff --git a/src/Cody.VisualStudio/Cody.VisualStudio.csproj b/src/Cody.VisualStudio/Cody.VisualStudio.csproj
index 5dbe4bb3..25f71551 100644
--- a/src/Cody.VisualStudio/Cody.VisualStudio.csproj
+++ b/src/Cody.VisualStudio/Cody.VisualStudio.csproj
@@ -46,6 +46,12 @@
4
+
+
+
+
+
+
diff --git a/src/Cody.VisualStudio/CodyPackage.cs b/src/Cody.VisualStudio/CodyPackage.cs
index b5f75d5c..47c19c2a 100644
--- a/src/Cody.VisualStudio/CodyPackage.cs
+++ b/src/Cody.VisualStudio/CodyPackage.cs
@@ -20,12 +20,13 @@
using System.IO;
using Cody.Core.Settings;
using Cody.Core.Infrastructure;
-using Cody.Core.Agent.Connector;
using Cody.Core.Agent;
using Cody.Core.DocumentSync;
using Microsoft.VisualStudio.Editor;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Shell.Interop;
+using Cody.VisualStudio.Client;
+using System.Collections.Generic;
namespace Cody.VisualStudio
{
@@ -60,7 +61,8 @@ public sealed class CodyPackage : AsyncPackage
public IVersionService VersionService;
public IVsVersionService VsVersionService;
public MainView MainView;
- public AgentConnector AgentConnector;
+ public AgentClient AgentClient;
+ public IAgentService AgentService;
public IUserSettingsService UserSettingsService;
public InitializeCallback InitializeService;
public IStatusbarService StatusbarService;
@@ -68,7 +70,6 @@ public sealed class CodyPackage : AsyncPackage
public NotificationHandlers NotificationHandlers;
public IVsEditorAdaptersFactoryService VsEditorAdaptersFactoryService;
public IVsUIShell VsUIShell;
- public IAgentClientFactory AgentClientFactory;
public DocumentsSyncService DocumentsSyncService;
protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress progress)
@@ -165,28 +166,34 @@ private async Task InitializeAgent()
var agentDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Agent");
NotificationHandlers = new NotificationHandlers();
- // Set the env var to 3113 when running with local agent.
- var portNumber = int.TryParse(Environment.GetEnvironmentVariable("CODY_VS_DEV_PORT"), out int port) ? port : (int?)null;
- var options = new AgentConnectorOptions
+ var devPort = Environment.GetEnvironmentVariable("CODY_VS_DEV_PORT");
+ var portNumber = int.TryParse(devPort, out int port) ? port : 3113;
+
+ var options = new AgentClientOptions
{
- NotificationsTarget = NotificationHandlers,
+ NotificationHandlers = new List { NotificationHandlers },
AgentDirectory = agentDir,
RestartAgentOnFailure = true,
- AfterConnection = (client) => InitializeService.Initialize(client),
- Port = portNumber,
+ ConnectToRemoteAgent = devPort != null,
+ RemoteAgentPort = portNumber,
};
- AgentConnector = new AgentConnector(options, Logger);
- AgentClientFactory = new AgentClientFactory(AgentConnector);
+ AgentClient = new AgentClient(options, Logger);
WebView2Dev.InitializeController(ThemeService.GetThemingScript());
NotificationHandlers.PostWebMessageAsJson = WebView2Dev.PostWebMessageAsJson;
- _ = Task.Run(() => AgentConnector.Connect())
+ _ = Task.Run(() => AgentClient.Start())
+ .ContinueWith(async x =>
+ {
+ AgentService = AgentClient.CreateAgentService();
+ NotificationHandlers.SetAgentClient(AgentService);
+ await InitializeService.Initialize(AgentService);
+ })
.ContinueWith(x =>
{
- var documentSyncCallback = new DocumentSyncCallback(AgentClientFactory, Logger);
+ var documentSyncCallback = new DocumentSyncCallback(AgentService, Logger);
DocumentsSyncService = new DocumentsSyncService(VsUIShell, documentSyncCallback, VsEditorAdaptersFactoryService);
DocumentsSyncService.Initialize();
})