Determine Extension Architecture #792
Replies: 52 comments 25 replies
-
First swift, then js. Swift is the easiest for us to implement. |
Beta Was this translation helpful? Give feedback.
-
I would prefer using Swift for extensions, but having JavaScript API would be nice to have also, considering that the app may be ported to iPadOS later. So, I think we need to provide Swift Extension API and prioritize it right now, but also export it to JavaScript. |
Beta Was this translation helpful? Give feedback.
-
I'd imagine more Javascript devs would be using this than Swift devs because they would use Xcode for Swift development for the most part correct? I think both are important and I agree with our current path. |
Beta Was this translation helpful? Give feedback.
-
May I propose Lua as another option? Lua is small, portable, and fast. Actually neovim has a quite mature plugin ecosystem in Lua (see nvim-lua-guide). We can attract those plugin developers if we provide a Lua plugin interface. |
Beta Was this translation helpful? Give feedback.
-
That's an interesting option @henryhchchc. I think at this point we are probably best sticking with Swift and/or JavaScript as our primary focus. In my opinion, considering the large VS Code user base, most extensions developers are going to be looking to develop using JavaScript/TypeScript. Initially it will be important to encourage as many of those developers as possible to contribute and add features that aren't in the core application. I believe extensions are key to making CodeEdit usable for the majority of developers. Since this is a Mac-centric application, it would be really cool to have Swift as an option, but as @austincondiff mentioned, I don't think that is what most extension developers be looking to use. However, if that what is practical to begin, I'm all for it! Ultimately, I wish we could design this in a way that lets extension developers use whatever language they feel most comfortable. I don't want to discourage anyone from contributing. But, it probably isn't realistic without providing some form of language conversion. Additional extension language support is something we could maybe revisit further down the road? |
Beta Was this translation helpful? Give feedback.
-
To the Swift developers, @pkasila, @MarcoCarnevali, @underthestars-zhy, and any others, how could we go about writing this API in Swift and then packaging/compiling/submitting the extensions in an approachable way? Please correct me if I am wrong, VS Code uses the command line I think. Nova just takes care of everything via the GUI. There is a menu option to "Submit extension" and everything simply happens in the background. Not all developers like working in the command line, so it be nice to provide the ability for developers to build/submit the extensions from the GUI. Maybe we could require advanced builds to be performed from the command line? |
Beta Was this translation helpful? Give feedback.
-
So, in my opinion, Swift Extension Architecture can be implemented the way described below. Swift APISo, let's say we have a Loading extensionsAll extensions are loaded using Each dynamic library should have @_cdecl("createExtension")
public func createExtension() -> UnsafeMutableRawPointer {
return Unmanaged.passRetained(HelloWorldExtensionBuilder()).toOpaque()
} The API object is passed to the More information about plugin system using dynamic libraries in Swift can be found here Compiling and packaging extensionExtensions should be compiled as dynamic libraries ( The minimal extension's package structure should be as follows:
Submitting extensionsI think there are 2 ways:
Other languages
|
Beta Was this translation helpful? Give feedback.
-
Awesome @pkasila! |
Beta Was this translation helpful? Give feedback.
-
Are we able to automate and simplify this process from the extension developers perspective through CodeEdit? Maybe a "Package and Submit Extension…" menu item? |
Beta Was this translation helpful? Give feedback.
-
I am in favor of this option if we can make it work. I understand there will be costs involved and it probably depends on community support. I think it's the most reliable choice. If extension developers provide their own storage, whether it be GitHub or something else, there is the possibility that these services might be down, causing some extensions to work and some other not, which could cause confusion to users. Our storage might go down too, but I would think it would likely be the entire extension library and we would at least have the ability to troubleshoot and/or explain the outage. We also run the risk of extensions being deleted, but still appearing in the extension library. |
Beta Was this translation helpful? Give feedback.
-
I think we can determine whether an extension project is open. Any extension's project can be a Swift Package (with a dynamic library) with
I think that I'll try to play around with how API for the extensions store and the store itself can be implemented a little bit. And I'll write about what I think suits our needs better later. |
Beta Was this translation helpful? Give feedback.
-
Thanks @pkasila. Sounds to me like a solid starting point. I know there will be details to figure out and a lot of trial and error as we go. |
Beta Was this translation helpful? Give feedback.
-
Could I suggest to look at how Raycast is handling extensions? It's a delightful experience and it's attracting many developers. |
Beta Was this translation helpful? Give feedback.
-
Good suggestion @FezVrasta! For references: |
Beta Was this translation helpful? Give feedback.
-
Yeah, thanks @FezVrasta. This is great. I'd never heard of it before. |
Beta Was this translation helpful? Give feedback.
-
Adding to my earlier comment of a server / client architecture: It usually makes more sense that the "server" is the extension host and the editor instance is a client of that server - that the user will only need to be able to access the extension host, but the machine the user is editing on doesn't have to be accessible in the network. |
Beta Was this translation helpful? Give feedback.
-
The main issue of Electron apps is not node, it's the rendering, and the huge amount of resources needed by each app. Having a node process run in background of a native app would be totally fine in my opinion. |
Beta Was this translation helpful? Give feedback.
-
It's the same in Nova too. I mentioned this briefly in issue #76 in the "Extension Entry Point" section. Both VS Code and Nova also include activation information in the extension manifest. |
Beta Was this translation helpful? Give feedback.
-
Based on a prior conversation on Discord with @josephschmitt @mattmassicotte @jasonplatts @pkasila @avdept and a few others, with the announcement of ExtensionKit in the latest WWDC which has been written about here, we have arrived at the following conclusion. We will use ExtensionKit and expose a Swift API with the goal of later exposing a Javascript API later on. This will allow us to move fast and remain true to our overall mission statement which is to create something as native as possible to create a more performant editor. I invite anyone who cares to add to this or to explore specifics around this chosen path to do so. I feel like we can close this issue once all the kinks have been ironed out as long as nobody objects to it as I feel like we have arrived at a conclusion here. |
Beta Was this translation helpful? Give feedback.
-
I just wanted to leave a quick update in our progress. We've been taking this real slow because we really need to get this right to begin with because it will affect everything we do going forward. Our idea to execute on this is relatively simple. We will end up exposing a Swift API and JS API in parallel, Swift to start because we will obviously need Swift functions to do anything. Then either as we go or shortly after we will expose a JS API To get JS and Swift to play nicely we'd have a server/client model. We'd use Bun instead of Node for faster execution especially because it is based on JSCore rather than Chromium's JavaScript v8 engine. JavaScript execution using Bun can reach near-native speeds which is what we are looking for. Bun also supports modern JS and TypeScript out-of-the box. We would spin up a JavaScript service on Bun on application start that houses all of the users installed extensions. The app and each installed extension would communicate via XPC and/or JSON-RPC. I also found this project that can reconcile React JSX into JSON so that we can offer React components to render out our Swift views. We need to prove out this theory before we bring any of this to CodeEdit by creating a simple POC. That might look like a simple "hello world" Swift application. We might change the text or enter a name with an input and a button that a Javascript extension tells our Swift application to render, then when clicked, our JS extension will tell our Swift application to execute a specific function with a certain set of arguments in will provide. Once we get this POC done, we can start putting it into CodeEdit. We can tell it to add a new navigator, inspector, or debugger. We can tell it to add autosuggestions under certain conditions, add snippets, and add commands. Then we build from there. Before we begin putting a POC together, does anyone have any feedback on this approach? We also need to figure out the communication protocol. We have mentioned gRPC, JSON-RPC, and XPC. Any preference? Pros and cons? |
Beta Was this translation helpful? Give feedback.
-
This is what I know of the topic, so people, please correct me if I'm wrong. JSON-RPC (Personally never used it)
Cons:
gRPC (Tinkered with this)
Cons:
XPC (Personally never used it, actually never heard of it prior) gRPC has my personal preference, but on whether to use it would kind of depend on how many people in our community know how it works and/or want to learn how it works. As far as I know, it's mainly used in backend development and I assume most of the CodeEdit community are frontend developers. |
Beta Was this translation helpful? Give feedback.
-
I've worked with grpc for last few years and its really good tool to communicate between 2 servers. We don't really need human-readability, since there's nobody in between to read request/response data. Also I can't say it has steep curve. It has some issues if you compile it from sources for specific platform, but if you use prebuilt binaries then IDE should provide code completion for generated code. I have app that makes you to use UI to compile your proto files into specific language. https://github.com/avdept/Protobuf-GUI-Compiler |
Beta Was this translation helpful? Give feedback.
-
Perhaps we should discuss this topic in the next meeting because I think we should make a decision on this, because of the high priority. |
Beta Was this translation helpful? Give feedback.
-
I know there has been a lot of discussion on this topic in the past with little progress other than the POC by @pkasila. We want to take our time and really get this right because we understand the repercussion in getting this wrong. However, @thecoolwinter, @matthijseikelenboom, and I just met and had a really good conversation in which we nailed down a firmer plan for extensions moving forward. Here is what we discussed and the conclusions that we came to. JS or Swift Extensions API? How will the JS API work when it comes time to build it? How do we run Extensions? What does this look like for our architecture? What kinds of things will extensions be able to do?
Please let me know if you see more to add to this list. Where do we plan to start? If you have any additions, questions, concerns, or objections, please feel free to speak up here. Thanks to everyone involved in this massive effort. I think we are on the right track to creating something really special that will have a great impact in the dev community! |
Beta Was this translation helpful? Give feedback.
-
As web dev I would be very excited to have JS plug-in system so I could easily contribute extensions. However as a macOS user I scream in panic when I read “we will spawn NodeJS process”. I thought the whole idea of the application was to be native and fast. If I have to choose from both things I would prefer the later, I don’t want to install another electron like app, that calls hundred bloated node extensions. In other words please don’t trade speed for convenience. Thanks for your hard work so far! |
Beta Was this translation helpful? Give feedback.
-
I think worth considering using react native macos for composing ui of extensions avoiding inventing some of the wheel, can reduce a lot of complexities |
Beta Was this translation helpful? Give feedback.
-
So about the manifest file, how do we plan to store that and how do we access it. I think it's clear that it should be a JSON file. My question is where is it stored, inside the
Or do we store it next to the extension, like so:
(I hope I described it in a clear way) |
Beta Was this translation helpful? Give feedback.
-
Quick update: There has been a lot of discussion on Discord regarding extensions that I wanted to summarize here. @mattmassicotte has recently pushed out ChimeKit that uses ExtensionKit. Hats off to him and his hard work on this. It is something that we've been discussing for some time. So we are now also considering (again) using ExtensionKit. Several things to consider about ExtensionKit:
So this would require that we set the target of CodeEdit to macOS 13.0+. We figure that by the time CodeEdit is out of beta, most users will be on Ventura if not the next version of macOS. We don't want to rush into this decision though. In order to see if it will work for us, a POC using ExtensionKit needs to be created to ensure that it will work for our use-case. This POC would:
Other things to consider:
Ultimately, ExtensionKit is Apple's path forward for Extensions. Deviating from this path should require a pretty compelling case. If we can retain the amount of control we need and we can prove out that that this will work with a POC, I think we should go with ExtensionKit. |
Beta Was this translation helpful? Give feedback.
-
I've published a small POC which demonstrates some use cases of ExtensionKit. It lacks lots of options, butit should suffice to get an idea how things could work. It doesn't meet all the requirements of the above post, but I don't have a lot of free time left this week. The repos are available here: Host Guest The package CodeEditKit is embedded in ExtensionKitHost. Xcode will complain that is is missing in ExtensionKitGuest, it should be added by adding a package in xcode → add a local package → select it in the ExtensionKitHost folder Also, I've some thoughts after developing this POC:
Lastly, for the text transformers I chose to use the same |
Beta Was this translation helpful? Give feedback.
-
Has making an API similar to VSCode's or allowing VSCode extensions to run in CodeEdit (somehow) been discussed? Having something like that brings millions of extensions right to CodeEdit on launch. This is especially nice when it comes to niche extensions. |
Beta Was this translation helpful? Give feedback.
-
Before moving too far forward with the Extension API and marketplace, we need to decide what type of environment will be used to run extensions.
JavaScript Core, https://developer.apple.com/documentation/javascriptcore, is an option. It does not support ESM, but as some have mentioned, there are ways to work around these limitations using build tools.Initially, a Swift extension API is being developed.
However, we ultimately plan to take an approach similar to Raycast that was described by mathieudutour here, #180 (comment). The architecture involves using node and communicating with the CodeEdit application using JSON-RPC. A react-reconciler will allow extensions to create a custom UI with React components.
Thank you to everyone who contributed to the conversation! Please feel free to continue to add feedback and/or suggestions.
Beta Was this translation helpful? Give feedback.
All reactions