Skip to content

Commit

Permalink
Switch to web UI (#2022)
Browse files Browse the repository at this point in the history
Let's merge what we have for now and resolve the rest of the blockers in
the follow up PRs. That will help us keeping the other PRs in smaller
batches that are easier to review and work with.

## Test plan
- CI (unit tests and it)
- dogfooding

<!-- All pull requests REQUIRE a test plan:
https://sourcegraph.com/docs/dev/background-information/testing_principles

Why does it matter?

These test plans are there to demonstrate that are following industry
standards which are important or critical for our customers.
They might be read by customers or an auditor. There are meant be simple
and easy to read. Simply explain what you did to ensure
your changes are correct!

Here are a non exhaustive list of test plan examples to help you:

- Making changes on a given feature or component:
- "Covered by existing tests" or "CI" for the shortest possible plan if
there is zero ambiguity
  - "Added new tests"
- "Manually tested" (if non trivial, share some output, logs, or
screenshot)
- Updating docs:
  - "previewed locally"
  - share a screenshot if you want to be thorough
- Updating deps, that would typically fail immediately in CI if
incorrect
  - "CI"
  - "locally tested"
-->

---------

Co-authored-by: Dominic Cooney <[email protected]>
  • Loading branch information
mkondratek and dominiccooney authored Aug 12, 2024
1 parent cf1af08 commit 1eb2580
Show file tree
Hide file tree
Showing 253 changed files with 1,833 additions and 3,355 deletions.
11 changes: 11 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,17 @@ You should build everything in PowerShell. Git Bash, Ubuntu and MinGW all offer
$env:SKIP_CODE_SEARCH_BUILD="true"
```
### Web UI Development
The fastest way to develop the Web UI is to use Storybook. However for some tasks loading the webview in JetBrains is
unavoidable. The process to do this is:
1. Use the "Run the plugin locally with fresh build of a local clone of Cody" setup (see above.) Specifically, you must have `CODY_DIR` set.
2. After changing the Web UI, in `$CODY_DIR` run `pnpm -C agent build:webviews`
3. Start a new chat to load the new webview bundle.
For changes in the TypeScript extension outside of the webview bundle, you must use one of the agent workflows described above.
## Using Nightly/Experimental channel releases
- Open "Sourcegraph & Cody" settings
Expand Down
8 changes: 5 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -339,13 +339,12 @@ tasks {
val agentDir = codyDir.resolve("agent")
exec {
workingDir(agentDir)
commandLine(pnpmPath, "run", "build:agent")
commandLine(pnpmPath, "run", "build")
}
copy {
from(agentDir.resolve("dist"))
into(buildCodyDir)
}

copy {
from(downloadNodeBinaries())
into(buildCodyDir)
Expand Down Expand Up @@ -473,7 +472,10 @@ tasks {
buildPlugin {
dependsOn(project.tasks.getByPath("buildCody"))
from(
fileTree(buildCodyDir) { include("*") },
fileTree(buildCodyDir) {
include("*")
include("webviews/**")
},
) {
into("agent/")
}
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ kotlin.stdlib.default.dependency=false
nodeBinaries.commit=8755ae4c05fd476cd23f2972049111ba436c86d4
nodeBinaries.version=v20.12.2
cody.autocomplete.enableFormatting=true
cody.commit=a7ba4e4d5d8273508eafd46d626e04c383e5588d
cody.commit=a7ba3c987888439299edb6c215bb8b3ed4765d1d
118 changes: 0 additions & 118 deletions src/main/java/com/sourcegraph/cody/MyAccountTabPanel.kt

This file was deleted.

78 changes: 74 additions & 4 deletions src/main/java/com/sourcegraph/cody/agent/CodyAgentClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.sourcegraph.cody.agent.protocol.*;
import com.sourcegraph.cody.agent.protocol_generated.DisplayCodeLensParams;
import com.sourcegraph.cody.agent.protocol_generated.EditTask;
import com.sourcegraph.cody.ui.NativeWebviewProvider;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.function.Function;
Expand All @@ -19,9 +20,15 @@
*/
@SuppressWarnings("unused")
public class CodyAgentClient {

private static final Logger logger = Logger.getInstance(CodyAgentClient.class);

@NotNull NativeWebviewProvider webview;

CodyAgentClient(@NotNull NativeWebviewProvider webviewProvider) {
this.webview = webviewProvider;
}

// TODO: Remove this once we stop sniffing postMessage.
// Callback that is invoked when the agent sends a "chat/updateMessageInProgress" notification.
@Nullable Consumer<WebviewPostMessageParams> onNewMessage;

Expand All @@ -30,7 +37,7 @@ public class CodyAgentClient {

// Callback that is invoked on webview messages which aren't handled by onNewMessage or
// onSetConfigFeatures
@Nullable Consumer<WebviewPostMessageParams> onReceivedWebviewMessage;
@Nullable Consumer<WebviewPostMessageParams> onReceivedWebviewMessageTODODeleteThis;

// Callback for the "editTask/didUpdate" notification from the agent.
@Nullable Consumer<EditTask> onEditTaskDidUpdate;
Expand Down Expand Up @@ -70,6 +77,13 @@ public void codeLensesDisplay(DisplayCodeLensParams params) {
acceptOnEventThread("codeLenses/display", onCodeLensesDisplay, params);
}

@Nullable Function<OpenExternalParams, Boolean> onOpenExternal;

@JsonRequest("env/openExternal")
public CompletableFuture<Boolean> ignoreTest(@NotNull OpenExternalParams params) {
return acceptOnEventThread("env/openExternal", onOpenExternal, params);
}

@Nullable Consumer<Void> onRemoteRepoDidChange;

@JsonNotification("remoteRepo/didChange")
Expand Down Expand Up @@ -158,6 +172,7 @@ public CompletableFuture<Boolean> workspaceEdit(WorkspaceEditParams params) {
return acceptOnEventThread(name, fun, params);
}

// TODO: Delete this
// Webviews
@JsonRequest("webview/create")
public CompletableFuture<Void> webviewCreate(WebviewCreateParams params) {
Expand All @@ -177,6 +192,61 @@ public void debugMessage(@NotNull DebugMessage msg) {
}
}

// ================================================
// Webviews, forwarded to the NativeWebviewProvider
// ================================================

@JsonNotification("webview/createWebviewPanel")
public void webviewCreateWebviewPanel(@NotNull WebviewCreateWebviewPanelParams params) {
this.webview.createPanel(params);
}

@JsonNotification("webview/postMessageStringEncoded")
public void webviewPostMessageStringEncoded(
@NotNull WebviewPostMessageStringEncodedParams params) {
this.webview.receivedPostMessage(params);
}

@JsonNotification("webview/registerWebviewViewProvider")
public void webviewRegisterWebviewViewProvider(
@NotNull WebviewRegisterWebviewViewProviderParams params) {
this.webview.registerViewProvider(params);
}

@JsonNotification("webview/setHtml")
public void webviewTitle(@NotNull WebviewSetHtmlParams params) {
this.webview.setHtml(params);
}

@JsonNotification("webview/setIconPath")
public void webviewSetIconPath(@NotNull WebviewSetIconPathParams params) {
// TODO: Implement this.
System.out.println("TODO, implement webview/setIconPath");
}

@JsonNotification("webview/setOptions")
public void webviewTitle(@NotNull WebviewSetOptionsParams params) {
this.webview.setOptions(params);
}

@JsonNotification("webview/setTitle")
public void webviewTitle(@NotNull WebviewSetTitleParams params) {
this.webview.setTitle(params);
}

@JsonNotification("webview/reveal")
public void webviewReveal(@NotNull WebviewRevealParams params) {
// TODO: Implement this.
System.out.println("TODO, implement webview/reveal");
}

@JsonNotification("webview/dispose")
public void webviewDispose(@NotNull WebviewDisposeParams params) {
// TODO: Implement this.
System.out.println("TODO, implement webview/dispose");
}

// TODO: Remove this
@JsonNotification("webview/postMessage")
public void webviewPostMessage(@NotNull WebviewPostMessageParams params) {
ExtensionMessage extensionMessage = params.getMessage();
Expand All @@ -194,9 +264,9 @@ public void webviewPostMessage(@NotNull WebviewPostMessageParams params) {
return;
}

if (onReceivedWebviewMessage != null) {
if (onReceivedWebviewMessageTODODeleteThis != null) {
ApplicationManager.getApplication()
.invokeLater(() -> onReceivedWebviewMessage.accept(params));
.invokeLater(() -> onReceivedWebviewMessageTODODeleteThis.accept(params));
return;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package com.sourcegraph.cody.agent

data class CommandExecuteParams(val command: String, val arguments: List<String>)
data class CommandExecuteParams(val command: String, val arguments: List<Any>)
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package com.sourcegraph.cody.agent

import com.sourcegraph.cody.agent.protocol.ChatError
import com.sourcegraph.cody.agent.protocol.ChatMessage
import com.sourcegraph.cody.agent.protocol.ContextItem
import com.sourcegraph.cody.agent.protocol.Repo
import com.sourcegraph.cody.agent.protocol.*

/**
* A message sent from the webview to the extension host. See vscode/src/chat/protocol.ts for the
Expand Down Expand Up @@ -53,6 +50,34 @@ data class ExtensionMessage(

data class WebviewPostMessageParams(val id: String, val message: ExtensionMessage)

data class WebviewRegisterWebviewViewProviderParams(
val viewId: String,
val retainContextWhenHidden: Boolean
)

data class WebviewResolveWebviewViewParams(val viewId: String, val webviewHandle: String)

data class WebviewPostMessageStringEncodedParams(val id: String, val stringEncodedMessage: String)

data class WebviewReceiveMessageStringEncodedParams(
val id: String,
val messageStringEncoded: String
)

data class WebviewSetHtmlParams(val handle: String, val html: String)

data class WebviewSetIconPathParams(val handle: String, val iconPathUri: String?)

data class WebviewSetOptionsParams(val handle: String, val options: WebviewOptions)

data class WebviewSetTitleParams(val handle: String, val title: String)

data class WebviewRevealParams(val handle: String, val viewColumn: Int, val preserveFocus: Boolean)
// When the server initiates dispose, this is sent to the client.
data class WebviewDisposeParams(val handle: String)
// When the client initiates dispose, this is sent to the server.
data class WebviewDidDisposeParams(val handle: String)

data class ConfigFeatures(val attribution: Boolean, val serverSentModels: Boolean)

data class EnhancedContextContextT(val groups: List<ContextGroup>)
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/sourcegraph/config/ThemeUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public static boolean isDarkTheme() {
}

@Nullable
private static String getHexString(@Nullable Color color) {
public static String getHexString(@Nullable Color color) {
if (color != null) {
String colorString = Integer.toHexString(color.getRGB());
if (colorString.length() > 2) {
Expand Down
Loading

0 comments on commit 1eb2580

Please sign in to comment.