mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-08-29 03:44:06 +08:00
Merge pull request #11616 from Kilo-Org/jetbrains-prompt-usage-telemetry
feat(jetbrains): track prompt slash and mention usage
This commit is contained in:
+4
-1
@@ -642,7 +642,10 @@ class SessionUi(
|
||||
spec.name,
|
||||
KiloBundle.message(spec.descriptionKey),
|
||||
spec.hints,
|
||||
action,
|
||||
{
|
||||
Telemetry.send("Slash Command Used", mapOf("slashCommandType" to "client", "command" to spec.name))
|
||||
action()
|
||||
},
|
||||
)
|
||||
|
||||
private fun mentionActions(): List<MentionAction> = MentionAction.ALL.map(::bind)
|
||||
|
||||
+13
-2
@@ -268,18 +268,19 @@ class SessionController(
|
||||
|
||||
private fun dispatch(data: Dispatch, send: suspend (String) -> Unit) {
|
||||
assertEdt()
|
||||
val props = data.props + if (data.kind == "command") slashProps() else emptyMap()
|
||||
capture("Conversation Send Clicked", sessionProps(sid ?: ref?.key) + mapOf(
|
||||
"source" to data.source,
|
||||
"hasExistingSession" to data.exists.toString(),
|
||||
"textLength" to bucket(data.text),
|
||||
) + data.props)
|
||||
) + props)
|
||||
showSession()
|
||||
val pending = sid?.let { CompletableDeferred(it) } ?: session()
|
||||
cs.launch {
|
||||
try {
|
||||
val id = pending.await() ?: return@launch
|
||||
send(id)
|
||||
capture("Conversation Message", sessionProps(id) + mapOf("source" to data.source, "hasExistingSession" to data.exists.toString()) + data.props)
|
||||
capture("Conversation Message", sessionProps(id) + mapOf("source" to data.source, "hasExistingSession" to data.exists.toString()) + props)
|
||||
LOG.debug { "${ChatLogSummary.sid(id)} kind=${data.kind} dispatched=true" }
|
||||
} catch (e: Exception) {
|
||||
capture("Session Error", sessionProps(sid ?: ref?.key ?: data.start) + mapOf("context" to data.kind, "errorClass" to e::class.java.name))
|
||||
@@ -1531,8 +1532,18 @@ class SessionController(
|
||||
put("attachmentCount", files.size.toString())
|
||||
put("mediaAttachmentCount", files.count { it.mime?.startsWith("image/") == true || it.mime == "application/pdf" }.toString())
|
||||
}
|
||||
val mentions = files.filter { it.source?.text?.value?.startsWith("@") == true }
|
||||
if (mentions.isNotEmpty()) {
|
||||
val resources = mentions.count { it.source?.path == "git-changes" }
|
||||
put("hasMentions", "true")
|
||||
put("mentionCount", mentions.size.toString())
|
||||
put("fileMentionCount", (mentions.size - resources).toString())
|
||||
put("resourceMentionCount", resources.toString())
|
||||
}
|
||||
}
|
||||
|
||||
private fun slashProps() = mapOf("hasSlashCommand" to "true", "slashCommandType" to "server")
|
||||
|
||||
private fun bucket(text: String): String = when (text.length) {
|
||||
0 -> "empty"
|
||||
in 1..80 -> "short"
|
||||
|
||||
+4
@@ -48,8 +48,12 @@ class CommandLifecycleTest : SessionControllerTestBase() {
|
||||
|
||||
val sent = appRpc.telemetry.single { it.event == "Conversation Send Clicked" }
|
||||
assertEquals("command", sent.properties["source"])
|
||||
assertEquals("true", sent.properties["hasSlashCommand"])
|
||||
assertEquals("server", sent.properties["slashCommandType"])
|
||||
val message = appRpc.telemetry.single { it.event == "Conversation Message" }
|
||||
assertEquals("command", message.properties["source"])
|
||||
assertEquals("true", message.properties["hasSlashCommand"])
|
||||
assertEquals("server", message.properties["slashCommandType"])
|
||||
}
|
||||
|
||||
fun `test command errors set state and telemetry`() {
|
||||
|
||||
+48
@@ -9,11 +9,14 @@ import ai.kilocode.rpc.dto.AgentDto
|
||||
import ai.kilocode.rpc.dto.ChatEventDto
|
||||
import ai.kilocode.rpc.dto.ModelDto
|
||||
import ai.kilocode.rpc.dto.PartDto
|
||||
import ai.kilocode.rpc.dto.PartSourceDto
|
||||
import ai.kilocode.rpc.dto.PartSourceTextDto
|
||||
import ai.kilocode.rpc.dto.PermissionAlwaysRulesDto
|
||||
import ai.kilocode.rpc.dto.PermissionFileDiffDto
|
||||
import ai.kilocode.rpc.dto.PermissionReplyDto
|
||||
import ai.kilocode.rpc.dto.PermissionRequestDto
|
||||
import ai.kilocode.rpc.dto.ProviderDto
|
||||
import ai.kilocode.rpc.dto.PromptPartDto
|
||||
import ai.kilocode.rpc.dto.QuestionInfoDto
|
||||
import ai.kilocode.rpc.dto.QuestionOptionDto
|
||||
import ai.kilocode.rpc.dto.QuestionReplyDto
|
||||
@@ -45,6 +48,51 @@ class PromptLifecycleTest : SessionControllerTestBase() {
|
||||
assertEquals("short", event.properties["textLength"])
|
||||
}
|
||||
|
||||
fun `test prompt records aggregate mention telemetry`() {
|
||||
appRpc.state.value = ai.kilocode.rpc.dto.KiloAppStateDto(ai.kilocode.rpc.dto.KiloAppStatusDto.READY, config = ai.kilocode.rpc.dto.ConfigDto(model = "kilo/gpt-5"))
|
||||
projectRpc.state.value = workspaceReady()
|
||||
val m = controller()
|
||||
val files = listOf(
|
||||
PromptPartDto(
|
||||
type = "file",
|
||||
mime = "text/plain",
|
||||
url = "file:///repo/src/A.kt",
|
||||
source = PartSourceDto("file", PartSourceTextDto("@src/A.kt", 0.0, 9.0), path = "src/A.kt"),
|
||||
),
|
||||
PromptPartDto(
|
||||
type = "file",
|
||||
mime = "text/plain",
|
||||
url = "file:///repo/src/B.kt",
|
||||
source = PartSourceDto("file", PartSourceTextDto("@src/B.kt", 10.0, 19.0), path = "/repo/src/B.kt"),
|
||||
),
|
||||
PromptPartDto(
|
||||
type = "text",
|
||||
text = "diff",
|
||||
source = PartSourceDto("resource", PartSourceTextDto("@git-changes", 20.0, 32.0), path = "git-changes"),
|
||||
),
|
||||
)
|
||||
|
||||
flush()
|
||||
edt { m.prompt("review", files) }
|
||||
flush()
|
||||
|
||||
val sent = appRpc.telemetry.single { it.event == "Conversation Send Clicked" }
|
||||
assertEquals("true", sent.properties["hasMentions"])
|
||||
assertEquals("3", sent.properties["mentionCount"])
|
||||
assertEquals("2", sent.properties["fileMentionCount"])
|
||||
assertEquals("1", sent.properties["resourceMentionCount"])
|
||||
assertFalse(sent.properties.containsValue("@src/A.kt"))
|
||||
assertFalse(sent.properties.containsValue("src/A.kt"))
|
||||
assertFalse(sent.properties.containsValue("/repo/src/B.kt"))
|
||||
val message = appRpc.telemetry.single { it.event == "Conversation Message" }
|
||||
assertEquals("true", message.properties["hasMentions"])
|
||||
assertEquals("3", message.properties["mentionCount"])
|
||||
assertEquals("2", message.properties["fileMentionCount"])
|
||||
assertEquals("1", message.properties["resourceMentionCount"])
|
||||
assertFalse(message.properties.containsValue("@git-changes"))
|
||||
assertFalse(message.properties.containsValue("git-changes"))
|
||||
}
|
||||
|
||||
fun `test PermissionAsked moves state to AwaitingPermission`() {
|
||||
val (m, _, _) = prompted()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user