-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathCopilotModelInfoProvider.java
More file actions
96 lines (85 loc) · 3.85 KB
/
Copy pathCopilotModelInfoProvider.java
File metadata and controls
96 lines (85 loc) · 3.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package appland.copilotChat;
import appland.cli.AppLandModelInfoProvider;
import appland.copilotChat.copilot.CopilotModelDefinition;
import appland.copilotChat.copilot.GitHubCopilotService;
import appland.settings.AppMapApplicationSettingsService;
import com.intellij.ide.plugins.PluginManagerCore;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class CopilotModelInfoProvider implements AppLandModelInfoProvider {
@Override
public @Nullable List<ModelInfo> getModelInfo() throws IOException {
if (isDisabled()) {
return null;
}
if (!GitHubCopilotService.getInstance().isCopilotAuthenticated()) {
return null;
}
var chatSession = GitHubCopilotService.getInstance().createChatSession();
var filteredModels = withoutDuplicateModels(chatSession != null ? chatSession.loadChatModels() : null);
if (filteredModels.isEmpty()) {
return null;
}
var nameCounts = filteredModels.stream()
.collect(Collectors.groupingBy(CopilotModelDefinition::name, Collectors.counting()));
var baseUrl = NavieCopilotChatRequestHandler.getBaseUrl();
var apiKey = GitHubCopilotService.RandomIdeSessionId;
return filteredModels.stream().map(model -> new ModelInfo(
nameCounts.get(model.name()) > 1
? String.format("%s (%s)", model.name(), model.version())
: model.name(),
model.id(),
"Copilot",
Instant.now().toString(),
baseUrl,
apiKey,
model.capabilities().limits().maxPromptTokens()
)).toList();
}
/**
* @return {@code true} if the integration with GitHub Copilot is unavailable
* because the GitHub Copilot plugin is not installed or the integration was explicitly disabled.
* This method must not evaluate the state of Copilot authentication.
*/
public static boolean isDisabled() {
return isGitHubCopilotDisabled();
}
private static boolean isGitHubCopilotDisabled() {
if (AppMapApplicationSettingsService.getInstance().isCopilotIntegrationDisabled()) {
return true;
}
return !PluginManagerCore.isPluginInstalled(GitHubCopilotService.CopilotPluginId) || PluginManagerCore.isDisabled(GitHubCopilotService.CopilotPluginId);
}
/**
* Remove duplicates, there are models with the same name and version, but with different IDs.
* We're keeping the model with the shortest ID, e.g. gpt-4o instead gpt-4o-preview.
* <p>
* This method returns a mutable list if at least one model is available.
*/
private static @NotNull List<CopilotModelDefinition> withoutDuplicateModels(@Nullable List<CopilotModelDefinition> models) {
if (models == null || models.isEmpty()) {
return List.of();
}
var comparator = Comparator.comparing((CopilotModelDefinition model) -> model.name() + model.version())
.thenComparing(CopilotModelDefinition::id);
final String[] lastClassifier = {null};
return models.stream()
.sorted(comparator)
.filter(model -> {
var classifier = model.name() + model.version();
try {
return lastClassifier[0] == null || !lastClassifier[0].equals(classifier);
} finally {
lastClassifier[0] = classifier;
}
})
.sorted(Comparator.comparing(CopilotModelDefinition::name))
.collect(Collectors.toCollection(ArrayList::new));
}
}