Skip to content
Open
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
7 changes: 7 additions & 0 deletions src/main/kotlin/ee/carlrobert/codegpt/agent/AgentFactory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,13 @@ object AgentFactory {
hookManager = hookManager,
)
)
if (SubagentTool.DIAGNOSTICS in selected) tool(
DiagnosticsTool(
project = project,
sessionId = sessionId,
hookManager = hookManager,
)
)
if (SubagentTool.WEB_SEARCH in selected) tool(
WebSearchTool(
workingDirectory = project.basePath ?: System.getProperty("user.dir"),
Expand Down
21 changes: 10 additions & 11 deletions src/main/kotlin/ee/carlrobert/codegpt/agent/ProxyAIAgent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import ee.carlrobert.codegpt.EncodingManager
import ee.carlrobert.codegpt.agent.clients.shouldStream
import ee.carlrobert.codegpt.agent.clients.shouldStreamCustomOpenAI
import ee.carlrobert.codegpt.agent.strategy.CODE_AGENT_COMPRESSION
import ee.carlrobert.codegpt.agent.strategy.HistoryCompressionConfig
import ee.carlrobert.codegpt.agent.strategy.SingleRunStrategyProvider
Expand All @@ -34,7 +35,6 @@ import ee.carlrobert.codegpt.settings.hooks.HookManager
import ee.carlrobert.codegpt.settings.models.ModelSettings
import ee.carlrobert.codegpt.settings.service.FeatureType
import ee.carlrobert.codegpt.settings.service.ServiceType
import ee.carlrobert.codegpt.settings.service.custom.CustomServicesSettings
import ee.carlrobert.codegpt.settings.skills.SkillDiscoveryService
import ee.carlrobert.codegpt.toolwindow.agent.ui.approval.BashPayload
import ee.carlrobert.codegpt.toolwindow.agent.ui.approval.ToolApprovalRequest
Expand Down Expand Up @@ -89,7 +89,7 @@ object ProxyAIAgent {
val modelSelection =
service<ModelSettings>().getModelSelectionForFeature(FeatureType.AGENT)
val skills = project.service<SkillDiscoveryService>().listSkills()
val stream = shouldStreamAgentToolLoop(project, provider)
val stream = shouldStreamAgentToolLoop(provider)
val projectInstructions = loadProjectInstructions(project.basePath)
val executor = AgentFactory.createExecutor(provider, events)
val pendingMessageQueue = pendingMessages.getOrPut(sessionId) { ArrayDeque() }
Expand Down Expand Up @@ -268,18 +268,10 @@ object ProxyAIAgent {
}

private fun shouldStreamAgentToolLoop(
project: Project,
provider: ServiceType,
): Boolean {
return when (provider) {
ServiceType.CUSTOM_OPENAI -> {
val selectedServiceId =
project.service<ModelSettings>().getStoredModelForFeature(FeatureType.AGENT)
project.service<CustomServicesSettings>().state.services
.firstOrNull { it.id == selectedServiceId }?.chatCompletionSettings?.shouldStream()
?: false
}

ServiceType.CUSTOM_OPENAI -> shouldStreamCustomOpenAI(FeatureType.AGENT)
ServiceType.GOOGLE -> false
else -> true
}
Expand Down Expand Up @@ -323,6 +315,13 @@ object ProxyAIAgent {
hookManager = hookManager,
)
)
tool(
DiagnosticsTool(
project = project,
sessionId = sessionId,
hookManager = hookManager,
)
)
tool(
WebSearchTool(
workingDirectory = workingDirectory,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ enum class SubagentTool(val id: String, val displayName: String, val isWrite: Bo
READ("read", "Read", false),
TODO_WRITE("todowrite", "TodoWrite", false),
INTELLIJ_SEARCH("intellijsearch", "IntelliJSearch", false),
DIAGNOSTICS("diagnostics", "Diagnostics", false),
WEB_SEARCH("websearch", "WebSearch", false),
WEB_FETCH("webfetch", "WebFetch", false),
MCP("MCP", "MCP", false),
Expand Down
47 changes: 47 additions & 0 deletions src/main/kotlin/ee/carlrobert/codegpt/agent/ToolArgumentsJson.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package ee.carlrobert.codegpt.agent

import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.contentOrNull

private val toolArgumentsJson = Json {
ignoreUnknownKeys = true
}

internal fun normalizeToolArgumentsJson(rawArgs: String?): String? {
val payload = rawArgs?.trim().orEmpty()
if (payload.isBlank()) {
return null
}

val element = runCatching {
toolArgumentsJson.parseToJsonElement(payload)
}.getOrNull() ?: return null

return normalizeToolArgumentsElement(element)?.toString()
}

private tailrec fun normalizeToolArgumentsElement(element: JsonElement): JsonObject? {
return when (element) {
is JsonObject -> element
is JsonPrimitive -> {
if (!element.isString) {
null
} else {
val nestedPayload = element.contentOrNull?.trim().orEmpty()
if (nestedPayload.isBlank()) {
null
} else {
val nested = runCatching {
toolArgumentsJson.parseToJsonElement(nestedPayload)
}.getOrNull() ?: return null
normalizeToolArgumentsElement(nested)
}
}
}

else -> null
}
}
14 changes: 13 additions & 1 deletion src/main/kotlin/ee/carlrobert/codegpt/agent/ToolSpecs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ enum class ToolName(val id: String, val aliases: Set<String> = emptySet()) {
BASH_OUTPUT("BashOutput"),
KILL_SHELL("KillShell"),
INTELLIJ_SEARCH("IntelliJSearch"),
DIAGNOSTICS("Diagnostics"),
WEB_SEARCH("WebSearch"),
WEB_FETCH("WebFetch"),
MCP("MCP"),
Expand Down Expand Up @@ -94,6 +95,13 @@ object ToolSpecs {
IntelliJSearchTool.Result.serializer()
)
)
register(
ToolSpec(
ToolName.DIAGNOSTICS,
DiagnosticsTool.Args.serializer(),
DiagnosticsTool.Result.serializer()
)
)
register(
ToolSpec(
ToolName.WEB_SEARCH,
Expand Down Expand Up @@ -193,8 +201,12 @@ object ToolSpecs {
if (serializer == null || payload.isBlank()) {
return null
}
val typedSerializer = serializer as KSerializer<Any>
return runCatching {
json.decodeFromString(serializer as KSerializer<Any>, payload)
json.decodeFromString(typedSerializer, payload)
}.recoverCatching {
val normalized = normalizeToolArgumentsJson(payload) ?: throw it
json.decodeFromString(typedSerializer, normalized)
}.getOrNull()
}
}
Loading