Skip to content

Commit 377d0c9

Browse files
committed
feat: proxyai agent
1 parent b2a2e90 commit 377d0c9

File tree

130 files changed

+14050
-362
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

130 files changed

+14050
-362
lines changed

build.gradle.kts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ plugins {
3737
id("org.jetbrains.intellij.platform")
3838
alias(libs.plugins.changelog)
3939
alias(libs.plugins.protobuf)
40+
alias(libs.plugins.kotlin.serialization)
4041
}
4142

4243
group = properties("pluginGroup").get()
@@ -72,26 +73,37 @@ dependencies {
7273
implementation(project(":codegpt-telemetry"))
7374
implementation(project(":codegpt-treesitter"))
7475

76+
implementation(platform(libs.okhttp.bom))
77+
implementation(platform(libs.slf4j.bom))
7578
implementation(platform(libs.jackson.bom))
76-
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jdk8")
77-
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")
78-
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
79+
implementation(platform(libs.mcp.sdk.bom))
80+
81+
implementation(libs.jackson.datatype.jdk8)
82+
implementation(libs.jackson.datatype.jsr310)
83+
implementation(libs.jackson.module.kotlin)
84+
7985
implementation(libs.flexmark.all) {
8086
// vulnerable transitive dependency
8187
exclude(group = "org.jsoup", module = "jsoup")
8288
}
83-
implementation(kotlin("stdlib"))
84-
implementation(kotlin("reflect"))
89+
implementation(libs.kotlin.stdlib)
90+
implementation(libs.kotlin.reflect)
91+
implementation(libs.koog.agents) {
92+
exclude(group = "org.jetbrains.kotlinx", module = "kotlinx-coroutines-core")
93+
exclude(group = "org.jetbrains.kotlinx", module = "kotlinx-coroutines-jdk8")
94+
}
8595
implementation(libs.jsoup)
8696
implementation(libs.commons.text)
8797
implementation(libs.jtokkit)
98+
8899
implementation(libs.grpc.protobuf)
89100
implementation(libs.grpc.stub)
90101
implementation(libs.grpc.netty.shaded)
91102
implementation(libs.protobuf.runtime)
92-
implementation(platform(libs.mcp.sdk.bom))
103+
93104
implementation(libs.mcp.sdk)
94-
testImplementation("junit:junit:4.13.2")
105+
106+
testImplementation(libs.junit4)
95107
testImplementation(kotlin("test"))
96108
}
97109

buildSrc/src/main/kotlin/codegpt.java-conventions.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ dependencies {
3535
}
3636

3737
implementation(lib("llm.client"))
38+
implementation(lib("kotlinx.serialization.json"))
3839
constraints {
3940
implementation(lib("okio")) {
4041
because("llm-client 0.7.0 uses okio 3.2.0: https://avd.aquasec.com/nvd/cve-2023-3635")

gradle/libs.versions.toml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,12 @@ jsoup = "1.21.2"
1313
jtokkit = "1.1.0"
1414
junit = "5.13.4"
1515
kotlin = "2.2.10"
16-
llm-client = "0.8.56"
16+
kotlinx-serialization = "1.6.3"
17+
llm-client = "0.8.58"
18+
koog = "0.6.0"
19+
okhttp = "4.12.0"
1720
okio = "3.15.0"
21+
slf4j = "2.0.17"
1822
tree-sitter = "0.24.5"
1923
grpc = "1.73.0"
2024
protobuf = "3.25.1"
@@ -28,14 +32,24 @@ flexmark-all = { module = "com.vladsch.flexmark:flexmark-all", version.ref = "fl
2832
gradle-intellij-plugin = { module = "org.jetbrains.intellij.platform:intellij-platform-gradle-plugin", version.ref = "gradle-intellij-plugin-version" }
2933
gson = { module = "com.google.code.gson:gson", version.ref = "gson" }
3034
jackson-bom = { module = "com.fasterxml.jackson:jackson-bom", version.ref = "jackson" }
35+
jackson-datatype-jdk8 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jdk8", version.ref = "jackson" }
36+
jackson-datatype-jsr310 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", version.ref = "jackson" }
37+
jackson-module-kotlin = { module = "com.fasterxml.jackson.module:jackson-module-kotlin", version.ref = "jackson" }
3138
mcp-sdk = { module = "io.modelcontextprotocol.sdk:mcp", version.ref = "mcp" }
3239
mcp-sdk-bom = { module = "io.modelcontextprotocol.sdk:mcp-bom", version.ref = "mcp" }
3340
jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
3441
jtokkit = { module = "com.knuddels:jtokkit", version.ref = "jtokkit" }
3542
junit-bom = { module = "org.junit:junit-bom", version.ref = "junit" }
43+
junit4 = { module = "junit:junit", version = "4.13.2" }
44+
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
45+
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
46+
koog-agents = { module = "ai.koog:koog-agents", version.ref = "koog" }
3647
kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
48+
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
3749
llm-client = { module = "ee.carlrobert:llm-client", version.ref = "llm-client" }
50+
okhttp-bom = { module = "com.squareup.okhttp3:okhttp-bom", version.ref = "okhttp" }
3851
okio = { module = "com.squareup.okio:okio", version.ref = "okio" }
52+
slf4j-bom = { module = "org.slf4j:slf4j-bom", version.ref = "slf4j" }
3953
tree-sitter = { module = "io.github.bonede:tree-sitter", version.ref = "tree-sitter" }
4054
grpc-protobuf = { module = "io.grpc:grpc-protobuf", version.ref = "grpc" }
4155
grpc-stub = { module = "io.grpc:grpc-stub", version.ref = "grpc" }
@@ -46,4 +60,5 @@ protobuf-runtime = { module = "com.google.protobuf:protobuf-java", version.ref =
4660

4761
[plugins]
4862
changelog = { id = "org.jetbrains.changelog", version.ref = "changelog" }
63+
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
4964
protobuf = { id = "com.google.protobuf", version.ref = "protobuf-plugin" }

src/main/java/ee/carlrobert/codegpt/completions/ToolwindowChatCompletionRequestHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ private EventSource startCall(ChatCompletionParameters callParameters) {
128128
}
129129
} catch (Throwable ex) {
130130
handleCallException(ex);
131-
throw ex;
132131
}
132+
return null;
133133
}
134134

135135
private void handleCallException(Throwable ex) {

src/main/java/ee/carlrobert/codegpt/settings/service/FeatureType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package ee.carlrobert.codegpt.settings.service;
22

33
public enum FeatureType {
4+
AGENT,
45
CHAT,
56
CODE_COMPLETION,
67
AUTO_APPLY,

src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ChatToolWindowTabPanel.java

Lines changed: 72 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import com.intellij.util.concurrency.AppExecutorUtil;
1515
import com.intellij.util.ui.JBUI;
1616
import ee.carlrobert.codegpt.CodeGPTKeys;
17+
import ee.carlrobert.codegpt.CodeGPTBundle;
1718
import ee.carlrobert.codegpt.EncodingManager;
1819
import ee.carlrobert.codegpt.ReferencedFile;
1920
import ee.carlrobert.codegpt.actions.ActionType;
@@ -38,6 +39,7 @@
3839
import ee.carlrobert.codegpt.toolwindow.chat.structure.data.PsiStructureRepository;
3940
import ee.carlrobert.codegpt.toolwindow.chat.structure.data.PsiStructureState;
4041
import ee.carlrobert.codegpt.toolwindow.chat.ui.ChatMessageResponseBody;
42+
import ee.carlrobert.codegpt.toolwindow.chat.editor.header.LoadingPanel;
4143
import ee.carlrobert.codegpt.toolwindow.chat.ui.ChatToolWindowScrollablePanel;
4244
import ee.carlrobert.codegpt.toolwindow.chat.ui.textarea.TotalTokensDetails;
4345
import ee.carlrobert.codegpt.toolwindow.chat.ui.textarea.TotalTokensPanel;
@@ -57,10 +59,10 @@
5759
import ee.carlrobert.codegpt.ui.textarea.header.tag.TagManager;
5860
import ee.carlrobert.codegpt.util.EditorUtil;
5961
import ee.carlrobert.codegpt.util.coroutines.CoroutineDispatchers;
62+
import ee.carlrobert.llm.client.openai.completion.ErrorDetails;
6063
import git4idea.GitCommit;
6164
import java.awt.BorderLayout;
6265
import java.util.ArrayList;
63-
import java.util.Arrays;
6466
import java.util.HashSet;
6567
import java.util.List;
6668
import java.util.Objects;
@@ -93,6 +95,8 @@ public class ChatToolWindowTabPanel implements Disposable {
9395
private final TagManager tagManager;
9496
private final JPanel mcpApprovalContainer;
9597
private @Nullable ToolwindowChatCompletionRequestHandler requestHandler;
98+
private LoadingPanel inputLoadingPanel;
99+
private final JPanel queuedMessageContainer;
96100

97101
public ChatToolWindowTabPanel(@NotNull Project project, @NotNull Conversation conversation) {
98102
this.project = project;
@@ -130,6 +134,11 @@ public ChatToolWindowTabPanel(@NotNull Project project, @NotNull Conversation co
130134
mcpApprovalContainer.setBorder(JBUI.Borders.empty());
131135
mcpApprovalContainer.setOpaque(false);
132136

137+
queuedMessageContainer = new JPanel();
138+
queuedMessageContainer.setLayout(new BoxLayout(queuedMessageContainer, BoxLayout.Y_AXIS));
139+
queuedMessageContainer.setBorder(JBUI.Borders.empty());
140+
queuedMessageContainer.setOpaque(false);
141+
133142
rootPanel = createRootPanel();
134143

135144
if (conversation.getMessages().isEmpty()) {
@@ -414,7 +423,7 @@ private ResponseMessagePanel createResponseMessagePanel(ChatCompletionParameters
414423
false,
415424
message.isWebSearchIncluded(),
416425
fileContextIncluded || message.getDocumentationDetails() != null,
417-
true,
426+
false,
418427
this));
419428
return panel;
420429
}
@@ -481,6 +490,7 @@ private void call(
481490
}
482491

483492
userInputPanel.setSubmitEnabled(false);
493+
userInputPanel.setStopEnabled(true);
484494
userMessagePanel.disableActions(List.of("RELOAD", "DELETE"));
485495
responseMessagePanel.disableActions(List.of("COPY"));
486496

@@ -493,13 +503,37 @@ private void call(
493503
totalTokensPanel,
494504
userInputPanel) {
495505
@Override
506+
public void handleRequestOpen() {
507+
super.handleRequestOpen();
508+
showInputLoading(CodeGPTBundle.get("toolwindow.chat.loading"));
509+
}
510+
511+
@Override
512+
public void handleCompleted(String fullMessage, ChatCompletionParameters callParameters) {
513+
try {
514+
super.handleCompleted(fullMessage, callParameters);
515+
} finally {
516+
hideInputLoading();
517+
}
518+
}
519+
520+
@Override
521+
public void handleError(ErrorDetails error, Throwable ex) {
522+
try {
523+
super.handleError(error, ex);
524+
} finally {
525+
hideInputLoading();
526+
}
527+
}
528+
@Override
496529
public void handleTokensExceededPolicyAccepted() {
497530
call(callParameters, responseMessagePanel, userMessagePanel);
498531
}
499532
},
500533
this);
501534

502535
requestHandler.setResponseMessagePanel(responseMessagePanel);
536+
showInputLoading(CodeGPTBundle.get("toolwindow.chat.loading"));
503537
requestHandler.call(callParameters);
504538
}
505539

@@ -520,7 +554,7 @@ private Unit handleSubmit(String text) {
520554
.filter(TagDetails::getSelected)
521555
.collect(Collectors.toList());
522556

523-
var messageBuilder = new MessageBuilder(project, text).withInlays(appliedTags);
557+
var messageBuilder = new MessageBuilder(project, text).withTags(appliedTags);
524558

525559
List<ReferencedFile> referencedFiles = getReferencedFiles(appliedTags);
526560
if (!referencedFiles.isEmpty()) {
@@ -547,27 +581,15 @@ private Unit handleSubmit(String text) {
547581
private Unit handleCancel() {
548582
if (requestHandler != null) {
549583
requestHandler.cancel();
584+
ApplicationManager.getApplication().invokeLater(() -> {
585+
mcpApprovalContainer.removeAll();
586+
updateUserPromptPanel();
587+
hideInputLoading();
588+
userInputPanel.setSubmitEnabled(true);
589+
CompletionProgressNotifier.update(project, false);
590+
requestHandler = null;
591+
});
550592
}
551-
ApplicationManager.getApplication().invokeLater(() -> {
552-
mcpApprovalContainer.removeAll();
553-
updateUserPromptPanel();
554-
var lastComponent = toolWindowScrollablePanel.getLastComponent();
555-
if (lastComponent != null) {
556-
Arrays.stream(lastComponent.getComponents())
557-
.filter(ResponseMessagePanel.class::isInstance)
558-
.findFirst()
559-
.ifPresent(panel -> {
560-
ResponseMessagePanel responsePanel = (ResponseMessagePanel) panel;
561-
var responseComponent = responsePanel.getResponseComponent();
562-
if (responseComponent != null) {
563-
responseComponent.stopLoading();
564-
}
565-
});
566-
}
567-
userInputPanel.setSubmitEnabled(true);
568-
CompletionProgressNotifier.update(project, false);
569-
});
570-
requestHandler = null;
571593
return Unit.INSTANCE;
572594
}
573595

@@ -581,6 +603,16 @@ private JPanel createUserPromptPanel() {
581603
topContainer.setLayout(new BoxLayout(topContainer, BoxLayout.Y_AXIS));
582604
topContainer.setOpaque(false);
583605

606+
inputLoadingPanel = new LoadingPanel(CodeGPTBundle.get("toolwindow.chat.loading"), null, null);
607+
inputLoadingPanel.setAlignmentX(JComponent.LEFT_ALIGNMENT);
608+
inputLoadingPanel.setVisible(false);
609+
topContainer.add(inputLoadingPanel);
610+
611+
if (queuedMessageContainer.getComponentCount() > 0) {
612+
queuedMessageContainer.setAlignmentX(JComponent.LEFT_ALIGNMENT);
613+
topContainer.add(queuedMessageContainer);
614+
}
615+
584616
if (mcpApprovalContainer.getComponentCount() > 0) {
585617
mcpApprovalContainer.setAlignmentX(JComponent.LEFT_ALIGNMENT);
586618
topContainer.add(mcpApprovalContainer);
@@ -596,6 +628,23 @@ private JPanel createUserPromptPanel() {
596628
return panel;
597629
}
598630

631+
private void showInputLoading(String text) {
632+
if (inputLoadingPanel != null) {
633+
inputLoadingPanel.setText(text);
634+
inputLoadingPanel.setVisible(true);
635+
inputLoadingPanel.revalidate();
636+
inputLoadingPanel.repaint();
637+
}
638+
}
639+
640+
private void hideInputLoading() {
641+
if (inputLoadingPanel != null) {
642+
inputLoadingPanel.setVisible(false);
643+
inputLoadingPanel.revalidate();
644+
inputLoadingPanel.repaint();
645+
}
646+
}
647+
599648
private JComponent getLandingView() {
600649
return new ChatToolWindowLandingPanel((action, locationOnScreen) -> {
601650
var editor = EditorUtil.getSelectedEditor(project);

src/main/java/ee/carlrobert/codegpt/toolwindow/chat/ToolWindowCompletionResponseEventListener.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ abstract class ToolWindowCompletionResponseEventListener implements
3535
private final UserMessagePanel userMessagePanel;
3636
private ChatMessageResponseBody responseContainer;
3737
private final TotalTokensPanel totalTokensPanel;
38-
private final UserInputPanel textArea;
38+
private final UserInputPanel userInputPanel;
3939

4040
private final Timer updateTimer = new Timer(UPDATE_INTERVAL_MS, e -> processBufferedMessages());
4141
private final ConcurrentLinkedQueue<String> messageBuffer = new ConcurrentLinkedQueue<>();
@@ -47,13 +47,13 @@ public ToolWindowCompletionResponseEventListener(
4747
UserMessagePanel userMessagePanel,
4848
ResponseMessagePanel responsePanel,
4949
TotalTokensPanel totalTokensPanel,
50-
UserInputPanel textArea) {
50+
UserInputPanel userInputPanel) {
5151
this.encodingManager = EncodingManager.getInstance();
5252
this.project = project;
5353
this.userMessagePanel = userMessagePanel;
5454
this.responsePanel = responsePanel;
5555
this.totalTokensPanel = totalTokensPanel;
56-
this.textArea = textArea;
56+
this.userInputPanel = userInputPanel;
5757
}
5858

5959
public abstract void handleTokensExceededPolicyAccepted();
@@ -146,7 +146,7 @@ public void handleCompleted(String fullMessage, ChatCompletionParameters callPar
146146
container.withResponse(fullMessage);
147147
}
148148
}
149-
totalTokensPanel.updateUserPromptTokens(textArea.getText());
149+
totalTokensPanel.updateUserPromptTokens(userInputPanel.getText());
150150
totalTokensPanel.updateConversationTokens(callParameters.getConversation());
151151
} finally {
152152
stopStreaming(responseContainer);
@@ -184,11 +184,11 @@ private void processBufferedMessages() {
184184

185185
private void stopStreaming(ChatMessageResponseBody responseContainer) {
186186
stopped = true;
187-
textArea.setSubmitEnabled(true);
187+
userInputPanel.setSubmitEnabled(true);
188+
userInputPanel.setStopEnabled(false);
188189
userMessagePanel.enableAllActions(true);
189190
responsePanel.enableAllActions(true);
190191
if (responseContainer != null) {
191-
responseContainer.stopLoading();
192192
responseContainer.hideCaret();
193193
responseContainer.finishThinking();
194194
}

0 commit comments

Comments
 (0)