feat(intellij): Add dont-show-again for warnings. Add more online help links. (#823)
parent
2cc751766f
commit
5e7ca4f569
|
|
@ -1,21 +1,23 @@
|
|||
package com.tabbyml.intellijtabby.actions
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.*
|
||||
import com.intellij.openapi.application.invokeLater
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory
|
||||
import com.tabbyml.intellijtabby.agent.Agent
|
||||
import com.tabbyml.intellijtabby.agent.AgentService
|
||||
import com.tabbyml.intellijtabby.settings.ApplicationSettingsState
|
||||
import kotlinx.coroutines.launch
|
||||
import java.net.URL
|
||||
|
||||
|
||||
class CheckIssueDetail : AnAction() {
|
||||
private val logger = Logger.getInstance(CheckIssueDetail::class.java)
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val settings = service<ApplicationSettingsState>()
|
||||
val agentService = service<AgentService>()
|
||||
agentService.issueNotification?.expire()
|
||||
|
||||
|
|
@ -24,7 +26,23 @@ class CheckIssueDetail : AnAction() {
|
|||
if (detail["name"] == "connectionFailed") {
|
||||
invokeLater {
|
||||
val messages = "<html>" + (detail["message"] as String?)?.replace("\n", "<br/>") + "</html>"
|
||||
Messages.showErrorDialog(messages, "Cannot Connect to Tabby Server")
|
||||
val selected = Messages.showDialog(
|
||||
messages,
|
||||
"Cannot Connect to Tabby Server",
|
||||
arrayOf("OK", "Online Help"),
|
||||
0,
|
||||
Messages.getErrorIcon(),
|
||||
)
|
||||
when (selected) {
|
||||
0 -> {
|
||||
// OK
|
||||
}
|
||||
|
||||
1 -> {
|
||||
// Online Help
|
||||
showOnlineHelp(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
return@launch
|
||||
} else {
|
||||
|
|
@ -38,12 +56,51 @@ class CheckIssueDetail : AnAction() {
|
|||
}
|
||||
val message = buildDetailMessage(detail, serverHealthState, agentConfig)
|
||||
invokeLater {
|
||||
Messages.showInfoMessage(message, title)
|
||||
val selected = Messages.showDialog(
|
||||
message,
|
||||
title,
|
||||
arrayOf("OK", "Online Help", "Don't Show Again"),
|
||||
0,
|
||||
Messages.getWarningIcon(),
|
||||
)
|
||||
when (selected) {
|
||||
0 -> {
|
||||
// OK
|
||||
}
|
||||
|
||||
1 -> {
|
||||
// Online Help
|
||||
showOnlineHelp(e)
|
||||
}
|
||||
|
||||
2 -> {
|
||||
// Don't Show Again
|
||||
settings.notificationsMuted += listOf("completionResponseTimeIssues")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun showOnlineHelp(e: AnActionEvent) {
|
||||
e.project?.let {
|
||||
invokeLater {
|
||||
val actionManager = ActionManager.getInstance()
|
||||
val actionGroup = actionManager.getAction("Tabby.OpenOnlineHelp") as? ActionGroup ?: return@invokeLater
|
||||
val popup = JBPopupFactory.getInstance().createActionGroupPopup(
|
||||
"Online Help",
|
||||
actionGroup,
|
||||
e.dataContext,
|
||||
false,
|
||||
null,
|
||||
10,
|
||||
)
|
||||
popup.showCenteredInCurrentWindow(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDetailMessage(
|
||||
detail: Map<String, Any>,
|
||||
serverHealthState: Map<String, Any>?,
|
||||
|
|
@ -76,7 +133,7 @@ class CheckIssueDetail : AnAction() {
|
|||
"""
|
||||
Your Tabby server is running model <i>$model</i> on CPU.
|
||||
This model may be performing poorly due to its large parameter size, please consider trying smaller models or switch to GPU.
|
||||
You can find a list of supported models in the <a href='https://tabby.tabbyml.com/docs/models/'>model directory</a>.
|
||||
You can find a list of recommend models in the <a href='https://tabby.tabbyml.com/docs/models/'>model registry</a>.
|
||||
""".trimIndent()
|
||||
} else {
|
||||
""
|
||||
|
|
@ -85,7 +142,7 @@ class CheckIssueDetail : AnAction() {
|
|||
val host = URL(agentConfig.server?.endpoint).host
|
||||
if (helpMessageForRunningLargeModelOnCPU.isEmpty()) {
|
||||
commonHelpMessage += "<li>The running model <i>$model</i> may be performing poorly due to its large parameter size.<br/>"
|
||||
commonHelpMessage += "Please consider trying smaller models. You can find a list of supported models in the <a href='https://tabby.tabbyml.com/docs/models/'>model directory</a>.</li>"
|
||||
commonHelpMessage += "Please consider trying smaller models. You can find a list of recommend models in the <a href='https://tabby.tabbyml.com/docs/models/'>model registry</a>.</li>"
|
||||
}
|
||||
if (!(host.startsWith("localhost") || host.startsWith("127.0.0.1"))) {
|
||||
commonHelpMessage += "<li>A poor network connection. Please check your network and proxy settings.</li>"
|
||||
|
|
@ -106,8 +163,13 @@ class CheckIssueDetail : AnAction() {
|
|||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
val settings = service<ApplicationSettingsState>()
|
||||
val agentService = service<AgentService>()
|
||||
e.presentation.isVisible = agentService.currentIssue.value != null
|
||||
val muted = mutableListOf<String>()
|
||||
if (settings.notificationsMuted.contains("completionResponseTimeIssues")) {
|
||||
muted += listOf("slowCompletionResponseTime", "highCompletionTimeoutRate")
|
||||
}
|
||||
e.presentation.isVisible = agentService.currentIssue.value != null && agentService.currentIssue.value !in muted
|
||||
}
|
||||
|
||||
override fun getActionUpdateThread(): ActionUpdateThread {
|
||||
|
|
|
|||
11
clients/intellij/src/main/kotlin/com/tabbyml/intellijtabby/actions/JoinTabbySlackCommunity.kt
vendored
Normal file
11
clients/intellij/src/main/kotlin/com/tabbyml/intellijtabby/actions/JoinTabbySlackCommunity.kt
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
package com.tabbyml.intellijtabby.actions
|
||||
|
||||
import com.intellij.ide.BrowserUtil
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
|
||||
class JoinTabbySlackCommunity: AnAction() {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
BrowserUtil.browse("https://join.slack.com/t/tabbycommunity/shared_invite/zt-1xeiddizp-bciR2RtFTaJ37RBxr8VxpA")
|
||||
}
|
||||
}
|
||||
|
|
@ -4,8 +4,8 @@ import com.intellij.ide.BrowserUtil
|
|||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
|
||||
class OpenOnlineDocs: AnAction() {
|
||||
class OpenModelRegistry: AnAction() {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
BrowserUtil.browse("https://tabby.tabbyml.com/docs/extensions/")
|
||||
BrowserUtil.browse("https://tabby.tabbyml.com/docs/models/")
|
||||
}
|
||||
}
|
||||
11
clients/intellij/src/main/kotlin/com/tabbyml/intellijtabby/actions/OpenOnlineDocumentation.kt
vendored
Normal file
11
clients/intellij/src/main/kotlin/com/tabbyml/intellijtabby/actions/OpenOnlineDocumentation.kt
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
package com.tabbyml.intellijtabby.actions
|
||||
|
||||
import com.intellij.ide.BrowserUtil
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
|
||||
class OpenOnlineDocumentation: AnAction() {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
BrowserUtil.browse("https://tabby.tabbyml.com/")
|
||||
}
|
||||
}
|
||||
11
clients/intellij/src/main/kotlin/com/tabbyml/intellijtabby/actions/OpenTabbyGithubRepo.kt
vendored
Normal file
11
clients/intellij/src/main/kotlin/com/tabbyml/intellijtabby/actions/OpenTabbyGithubRepo.kt
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
package com.tabbyml.intellijtabby.actions
|
||||
|
||||
import com.intellij.ide.BrowserUtil
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
|
||||
class OpenTabbyGithubRepo : AnAction() {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
BrowserUtil.browse("https://github.com/tabbyml/tabby")
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,8 @@ import com.intellij.notification.NotificationType
|
|||
import com.intellij.notification.Notifications
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.actionSystem.ActionManager
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.application.ApplicationInfo
|
||||
import com.intellij.openapi.application.ReadAction
|
||||
import com.intellij.openapi.application.invokeLater
|
||||
|
|
@ -76,7 +78,13 @@ class AgentService : Disposable {
|
|||
"${e.message}",
|
||||
NotificationType.ERROR,
|
||||
)
|
||||
notification.addAction(ActionManager.getInstance().getAction("Tabby.OpenOnlineDocs"))
|
||||
notification.addAction(
|
||||
object : AnAction("Open Online Documentation") {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
BrowserUtil.browse("https://tabby.tabbyml.com/docs/extensions/troubleshooting/#tabby-initialization-failed")
|
||||
}
|
||||
}
|
||||
)
|
||||
invokeLater {
|
||||
initFailedNotification?.expire()
|
||||
initFailedNotification = notification
|
||||
|
|
@ -131,16 +139,18 @@ class AgentService : Disposable {
|
|||
|
||||
scope.launch {
|
||||
agent.currentIssue.collect { issueName ->
|
||||
val showCompletionResponseWarnings = !completionResponseWarningShown &&
|
||||
!settings.notificationsMuted.contains("completionResponseTimeIssues")
|
||||
val message = when (issueName) {
|
||||
"connectionFailed" -> "Cannot connect to Tabby server"
|
||||
"slowCompletionResponseTime" -> if (!completionResponseWarningShown) {
|
||||
"slowCompletionResponseTime" -> if (showCompletionResponseWarnings) {
|
||||
completionResponseWarningShown = true
|
||||
"Completion requests appear to take too much time"
|
||||
} else {
|
||||
return@collect
|
||||
}
|
||||
|
||||
"highCompletionTimeoutRate" -> if (!completionResponseWarningShown) {
|
||||
"highCompletionTimeoutRate" -> if (showCompletionResponseWarnings) {
|
||||
completionResponseWarningShown = true
|
||||
"Most completion requests timed out"
|
||||
} else {
|
||||
|
|
@ -160,6 +170,16 @@ class AgentService : Disposable {
|
|||
NotificationType.WARNING,
|
||||
)
|
||||
notification.addAction(ActionManager.getInstance().getAction("Tabby.CheckIssueDetail"))
|
||||
if (issueName in listOf("slowCompletionResponseTime", "highCompletionTimeoutRate")) {
|
||||
notification.addAction(
|
||||
object : AnAction("Don't Show Again") {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
issueNotification?.expire()
|
||||
settings.notificationsMuted += listOf("completionResponseTimeIssues")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
invokeLater {
|
||||
issueNotification?.expire()
|
||||
issueNotification = notification
|
||||
|
|
|
|||
|
|
@ -168,6 +168,19 @@ class ApplicationSettingsPanel {
|
|||
)
|
||||
.panel
|
||||
|
||||
private val resetMutedNotificationsButton = JButton("Reset \"Don't Show Again\" Notifications").apply {
|
||||
addActionListener {
|
||||
val settings = service<ApplicationSettingsState>()
|
||||
settings.notificationsMuted = listOf()
|
||||
invokeLater(ModalityState.stateForComponent(this@ApplicationSettingsPanel.mainPanel)) {
|
||||
Messages.showInfoMessage("Reset \"Don't Show Again\" notifications successfully.", "Reset Notifications")
|
||||
}
|
||||
}
|
||||
}
|
||||
private val resetMutedNotificationsPanel: JPanel = FormBuilder.createFormBuilder()
|
||||
.addComponent(resetMutedNotificationsButton)
|
||||
.panel
|
||||
|
||||
val mainPanel: JPanel = FormBuilder.createFormBuilder()
|
||||
.addLabeledComponent("Server endpoint", serverEndpointPanel, 5, false)
|
||||
.addSeparator(5)
|
||||
|
|
@ -176,6 +189,12 @@ class ApplicationSettingsPanel {
|
|||
.addLabeledComponent("<html>Node binary<br/>(Requires restart IDE)</html>", nodeBinaryPanel, 5, false)
|
||||
.addSeparator(5)
|
||||
.addLabeledComponent("Anonymous usage tracking", isAnonymousUsageTrackingPanel, 5, false)
|
||||
.apply {
|
||||
if (service<ApplicationSettingsState>().notificationsMuted.isNotEmpty()) {
|
||||
addSeparator(5)
|
||||
addLabeledComponent("Notifications", resetMutedNotificationsPanel, 5, false)
|
||||
}
|
||||
}
|
||||
.addComponentFillVertically(JPanel(), 0)
|
||||
.panel
|
||||
|
||||
|
|
|
|||
|
|
@ -56,11 +56,20 @@ class ApplicationSettingsState : PersistentStateComponent<ApplicationSettingsSta
|
|||
isAnonymousUsageTrackingDisabledFlow.value = value
|
||||
}
|
||||
|
||||
private val notificationsMutedFlow = MutableStateFlow(listOf<String>())
|
||||
val notificationsMutedState = notificationsMutedFlow.asStateFlow()
|
||||
var notificationsMuted: List<String> = listOf()
|
||||
set(value) {
|
||||
field = value
|
||||
notificationsMutedFlow.value = value
|
||||
}
|
||||
|
||||
data class State(
|
||||
val completionTriggerMode: TriggerMode,
|
||||
val serverEndpoint: String,
|
||||
val nodeBinary: String,
|
||||
val isAnonymousUsageTrackingDisabled: Boolean,
|
||||
val notificationsMuted: List<String>,
|
||||
)
|
||||
|
||||
val data: State
|
||||
|
|
@ -69,6 +78,7 @@ class ApplicationSettingsState : PersistentStateComponent<ApplicationSettingsSta
|
|||
serverEndpoint = serverEndpoint,
|
||||
nodeBinary = nodeBinary,
|
||||
isAnonymousUsageTrackingDisabled = isAnonymousUsageTrackingDisabled,
|
||||
notificationsMuted = notificationsMuted,
|
||||
)
|
||||
|
||||
val state = combine(
|
||||
|
|
@ -76,12 +86,14 @@ class ApplicationSettingsState : PersistentStateComponent<ApplicationSettingsSta
|
|||
serverEndpointState,
|
||||
nodeBinaryState,
|
||||
isAnonymousUsageTrackingDisabledState,
|
||||
) { completionTriggerMode, serverEndpoint, nodeBinary, isAnonymousUsageTrackingDisabled ->
|
||||
notificationsMutedState,
|
||||
) { completionTriggerMode, serverEndpoint, nodeBinary, isAnonymousUsageTrackingDisabled, notificationsMuted ->
|
||||
State(
|
||||
completionTriggerMode = completionTriggerMode,
|
||||
serverEndpoint = serverEndpoint,
|
||||
nodeBinary = nodeBinary,
|
||||
isAnonymousUsageTrackingDisabled = isAnonymousUsageTrackingDisabled,
|
||||
notificationsMuted = notificationsMuted,
|
||||
)
|
||||
}.stateIn(CoroutineScope(Dispatchers.IO), SharingStarted.Eagerly, this.data)
|
||||
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ class StatusBarWidgetFactory : StatusBarEditorBasedWidgetFactory() {
|
|||
actionManager.getAction("Tabby.CheckIssueDetail"),
|
||||
actionManager.getAction("Tabby.ToggleInlineCompletionTriggerMode"),
|
||||
actionManager.getAction("Tabby.OpenSettings"),
|
||||
actionManager.getAction("Tabby.OpenOnlineDocs"),
|
||||
actionManager.getAction("Tabby.OpenOnlineHelp"),
|
||||
)
|
||||
}
|
||||
},
|
||||
|
|
@ -109,7 +109,11 @@ class StatusBarWidgetFactory : StatusBarEditorBasedWidgetFactory() {
|
|||
tooltip = "Tabby: Initialization failed"
|
||||
}
|
||||
Agent.Status.READY -> {
|
||||
if (state.currentIssue != null) {
|
||||
val muted = mutableListOf<String>()
|
||||
if (state.settings.notificationsMuted.contains("completionResponseTimeIssues")) {
|
||||
muted += listOf("slowCompletionResponseTime", "highCompletionTimeoutRate")
|
||||
}
|
||||
if (state.currentIssue != null && state.currentIssue !in muted) {
|
||||
icon = AllIcons.General.Warning
|
||||
tooltip = when(state.currentIssue) {
|
||||
"slowCompletionResponseTime" -> "Tabby: Completion requests appear to take too much time"
|
||||
|
|
|
|||
|
|
@ -93,11 +93,31 @@
|
|||
text="Open Settings..."
|
||||
description="Show settings for Tabby.">
|
||||
</action>
|
||||
<action id="Tabby.OpenOnlineDocs"
|
||||
class="com.tabbyml.intellijtabby.actions.OpenOnlineDocs"
|
||||
text="Open Online Help..."
|
||||
description="Open the online docs in your web browser.">
|
||||
</action>
|
||||
<group id="Tabby.OpenOnlineHelp"
|
||||
popup="true"
|
||||
text="Open Online Help"
|
||||
description="View useful links for online help.">
|
||||
<action id="Tabby.OpenOnlineHelp.OpenOnlineDocumentation"
|
||||
class="com.tabbyml.intellijtabby.actions.OpenOnlineDocumentation"
|
||||
text="Online Documentation..."
|
||||
description="Open the documentation page in your web browser.">
|
||||
</action>
|
||||
<action id="Tabby.OpenOnlineHelp.OpenModelRegistry"
|
||||
class="com.tabbyml.intellijtabby.actions.OpenModelRegistry"
|
||||
text="Model Registry..."
|
||||
description="Explore more recommend models from Tabby's model registry.">
|
||||
</action>
|
||||
<action id="Tabby.OpenOnlineHelp.JoinTabbySlackCommunity"
|
||||
class="com.tabbyml.intellijtabby.actions.JoinTabbySlackCommunity"
|
||||
text="Tabby Slack Community..."
|
||||
description="Join Tabby's Slack community to get help or feed back.">
|
||||
</action>
|
||||
<action id="Tabby.OpenOnlineHelp.OpenTabbyGithubRepo"
|
||||
class="com.tabbyml.intellijtabby.actions.OpenTabbyGithubRepo"
|
||||
text="Tabby GitHub Repository..."
|
||||
description="View the source code for Tabby, and open issues.">
|
||||
</action>
|
||||
</group>
|
||||
</group>
|
||||
</actions>
|
||||
</idea-plugin>
|
||||
Loading…
Reference in New Issue