Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(intellij): impl navigate to file context in chat panel. #3471

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ class CheckIssueDetail : AnAction() {
val server = connectionService.getServerAsync() ?: return@launch
val command = combinedState.state.agentStatus?.command ?: return@launch

server.workspaceFeature.executeCommand(ExecuteCommandParams(
command.command,
command.arguments,
))
server.workspaceFeature.executeCommand(
ExecuteCommandParams(
command.command,
command.arguments,
)
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.tabbyml.intellijtabby.chat
import com.google.gson.Gson
import com.google.gson.annotations.SerializedName
import com.google.gson.reflect.TypeToken
import com.intellij.ide.BrowserUtil
import com.intellij.openapi.application.invokeLater
import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.command.WriteCommandAction
Expand All @@ -14,6 +15,7 @@ import com.intellij.openapi.editor.colors.EditorColorsListener
import com.intellij.openapi.editor.colors.EditorColorsManager
import com.intellij.openapi.editor.colors.EditorFontType
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.fileEditor.OpenFileDescriptor
import com.intellij.openapi.progress.util.BackgroundTaskUtil
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.guessProjectDir
Expand All @@ -22,6 +24,7 @@ import com.intellij.ui.jcef.JBCefBrowser
import com.intellij.ui.jcef.JBCefBrowserBase
import com.intellij.ui.jcef.JBCefJSQuery
import com.tabbyml.intellijtabby.events.CombinedState
import com.tabbyml.intellijtabby.findVirtualFile
import com.tabbyml.intellijtabby.git.GitProvider
import com.tabbyml.intellijtabby.lsp.ConnectionService
import com.tabbyml.intellijtabby.lsp.protocol.Config
Expand All @@ -30,6 +33,7 @@ import com.tabbyml.intellijtabby.lsp.protocol.StatusRequestParams
import io.github.z4kn4fein.semver.Version
import io.github.z4kn4fein.semver.constraints.Constraint
import io.github.z4kn4fein.semver.constraints.satisfiedBy
import io.ktor.http.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -210,12 +214,23 @@ class ChatBrowser(private val project: Project) : JBCefBrowser(
),
filepath = relativePath ?: "",
content = context.first,
gitUrl = gitRepo?.remotes?.firstOrNull()?.url ?: "",
gitUrl = gitRepo?.let { getDefaultRemoteUrl(it) } ?: "",
)
}
}
}

private fun navigateToFileContext(fileContext: FileContext) {
val virtualFile = project.findVirtualFile(fileContext.filepath)
?: gitRemoteUrlToLocalRoot[fileContext.gitUrl]?.let { project.findVirtualFile(it.appendUrlPathSegments(fileContext.filepath)) }
?: project.guessProjectDir()?.url?.let { project.findVirtualFile(it.appendUrlPathSegments(fileContext.filepath)) }
?: return
invokeLater {
val descriptor = OpenFileDescriptor(project, virtualFile, fileContext.range.start, 0)
FileEditorManager.getInstance(project).openTextEditor(descriptor, true)
}
}

private fun handleLoaded() {
jsInjectHandlers()
jsApplyStyle()
Expand Down Expand Up @@ -321,7 +336,15 @@ class ChatBrowser(private val project: Project) : JBCefBrowser(
when (request.method) {
"navigate" -> {
logger.debug("navigate: request: ${request.params}")
// FIXME(@icycodes): not implemented yet
val context = request.params.getOrNull(0)?.let {
gson.fromJson(gson.toJson(it), FileContext::class.java)
} ?: return
val options = request.params.getOrNull(1) as Map<*, *>?
if (options?.get("openInEditor") == true) {
navigateToFileContext(context)
} else {
currentConfig?.let { buildCodeBrowserUrl(it, context) }?.let { BrowserUtil.browse(it) }
}
}

"refresh" -> {
Expand Down Expand Up @@ -601,6 +624,34 @@ class ChatBrowser(private val project: Project) : JBCefBrowser(
return String.format("%.0f, %.0f%%, %.0f%%", h, s, l)
}

private val gitRemoteUrlToLocalRoot = mutableMapOf<String, String>()

private fun getDefaultRemoteUrl(repo: GitProvider.Repository): String? {
if (repo.remotes.isNullOrEmpty()) {
return null
}
val remoteUrl = repo.remotes.firstOrNull { it.name == "origin" }?.url
?: repo.remotes.firstOrNull { it.name == "upstream" }?.url
?: repo.remotes.firstOrNull()?.url
if (remoteUrl != null) {
gitRemoteUrlToLocalRoot[remoteUrl] = repo.root
}
return remoteUrl
}

private fun String.appendUrlPathSegments(path: String): String {
return URLBuilder(this).appendPathSegments(path).toString()
}

private fun buildCodeBrowserUrl(config: Config.ServerConfig, context: FileContext): String {
return URLBuilder(config.endpoint).apply {
appendPathSegments("files")
parameters.append("redirect_git_url", context.gitUrl)
parameters.append("redirect_filepath", context.filepath)
fragment = "L${context.range.start}-L${context.range.end}"
}.buildString()
}

private const val TABBY_CHAT_PANEL_API_VERSION_RANGE = "~0.2.0"
private const val TABBY_SERVER_VERSION_RANGE = ">=0.18.0"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import com.tabbyml.intellijtabby.lsp.protocol.ClientProvidedConfig.Keybindings
import com.tabbyml.intellijtabby.lsp.protocol.EventParams.EventType
import com.tabbyml.intellijtabby.lsp.protocol.EventParams.SelectKind
import com.tabbyml.intellijtabby.lsp.protocol.ReadFileParams.Format
import com.tabbyml.intellijtabby.lsp.protocol.StatusIgnoredIssuesEditParams.Operation
import com.tabbyml.intellijtabby.lsp.protocol.StatusIgnoredIssuesEditParams.StatusIssuesName
import com.tabbyml.intellijtabby.lsp.protocol.StatusInfo.Status
import org.eclipse.lsp4j.*

data class InitializeParams(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ import com.intellij.util.ui.FormBuilder
import com.intellij.util.ui.JBUI
import com.intellij.util.ui.UIUtil
import com.tabbyml.intellijtabby.lsp.ConnectionService
import com.tabbyml.intellijtabby.lsp.protocol.*
import com.tabbyml.intellijtabby.lsp.protocol.StatusIgnoredIssuesEditParams
import com.tabbyml.intellijtabby.lsp.protocol.StatusInfo
import com.tabbyml.intellijtabby.lsp.protocol.StatusRequestParams
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
Expand Down