feat: improve tool call clickable links

This commit is contained in:
Carl-Robert Linnupuu 2026-01-16 15:07:06 +00:00
parent 3bc9656196
commit b941a3a19a
3 changed files with 49 additions and 21 deletions

View file

@ -260,19 +260,32 @@ class RollbackPanel(
}
private fun displayPath(path: String, change: FileChange): String {
val originalPath = change.originalPath?.let { toRelativePath(it) }
val truncatedPath = truncatePath(toRelativePath(path))
val truncatedOriginal = originalPath?.let { truncatePath(it) }
return if (change.kind == ChangeKind.MOVED && originalPath != null) {
"$truncatedPath (renamed from $truncatedOriginal)"
} else {
truncatedPath
}
}
private fun toRelativePath(path: String): String {
val base = project.basePath?.replace("\\", "/")
val normalized = path.replace("\\", "/")
val relative = if (base != null && normalized.startsWith(base)) {
return if (base != null && normalized.startsWith(base)) {
normalized.removePrefix(base).trimStart('/')
} else normalized
val original = change.originalPath?.replace("\\", "/")
return if (change.kind == ChangeKind.MOVED && original != null) {
val originalDisplay = if (base != null && original.startsWith(base)) {
original.removePrefix(base).trimStart('/')
} else original
"$relative (renamed from $originalDisplay)"
} else {
relative
normalized
}
}
private fun truncatePath(path: String, maxLength: Int = 80): String {
return if (path.length > maxLength) {
"..." + path.takeLast(maxLength)
} else {
path
}
}

View file

@ -12,14 +12,17 @@ enum class ToolKind {
data class Badge(
val text: String,
val color: JBColor = JBColor.GRAY,
val tooltip: String? = null
val tooltip: String? = null,
val action: (() -> Unit)? = null
)
data class FileLink(
val path: String,
val displayName: String,
val enabled: Boolean = true,
val action: ((Project) -> Unit)? = null
val action: ((Project) -> Unit)? = null,
val line: Int? = null,
val column: Int? = null
)
data class ToolAction(

View file

@ -1,6 +1,8 @@
package ee.carlrobert.codegpt.toolwindow.agent.ui.descriptor
import com.intellij.ide.actions.OpenFileAction
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.fileEditor.OpenFileDescriptor
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.vfs.LocalFileSystem
@ -110,10 +112,26 @@ private class ToolCallHeaderPanel(
val project = getProject()
if (project != null) {
val vf = LocalFileSystem.getInstance().findFileByPath(fileLink.path)
if (vf != null) OpenFileAction.openFile(vf, project)
if (vf != null) {
if (fileLink.line != null) {
val descriptor = OpenFileDescriptor(
project,
vf,
fileLink.line - 1,
fileLink.column ?: 0
)
FileEditorManager.getInstance(project).openTextEditor(descriptor, true)
} else {
OpenFileAction.openFile(vf, project)
}
}
}
}.apply {
toolTipText = fileLink.path
toolTipText = if (fileLink.line != null) {
"${fileLink.path}:${fileLink.line}"
} else {
fileLink.path
}
setExternalLinkIcon()
isEnabled = fileLink.enabled
}
@ -146,15 +164,9 @@ private class ToolCallHeaderPanel(
private fun addSecondaryBadges() {
descriptor.secondaryBadges.forEach { badge ->
val isMatchesBadge = badge.text.contains("matches", ignoreCase = true)
if (isMatchesBadge && descriptor.result != null) {
if (badge.action != null) {
val link = ActionLink(badge.text) {
val content = when (val res = descriptor.result) {
is IntelliJSearchTool.Result -> res.output
is String -> res
else -> null
}
content?.let { showSearchResultsDialog(it) }
badge.action?.invoke()
}.apply {
font = JBUI.Fonts.smallFont()
}