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

1.5.7 #169

Merged
merged 1 commit into from
May 31, 2024
Merged

1.5.7 #169

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
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ dependencies {
exclude(group = "org.jetbrains.kotlin", module = "")
}

implementation(group = "com.simiacryptus", name = "jo-penai", version = "1.0.57")
implementation(group = "com.simiacryptus", name = "jo-penai", version = "1.0.59")
{
exclude(group = "org.jetbrains.kotlin", module = "")
}
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pluginName=intellij-aicoder
pluginRepositoryUrl=https://github.com/SimiaCryptus/intellij-aicoder
pluginVersion=1.5.6
pluginVersion=1.5.7

jvmArgs=-Xmx8g
org.gradle.jvmargs=-Xmx8g
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package com.github.simiacryptus.aicoder.actions.generic

import com.github.simiacryptus.aicoder.actions.BaseAction
import com.github.simiacryptus.aicoder.AppServer
import com.github.simiacryptus.aicoder.actions.BaseAction.Companion
import com.github.simiacryptus.aicoder.actions.BaseAction
import com.github.simiacryptus.aicoder.config.AppSettingsState
import com.github.simiacryptus.aicoder.config.AppSettingsState.Companion.chatModel
import com.github.simiacryptus.aicoder.util.CodeChatSocketManager
Expand All @@ -20,13 +19,11 @@ import java.awt.Desktop
class CodeChatAction : BaseAction() {
override fun getActionUpdateThread() = ActionUpdateThread.BGT

val path = "/codeChat"

override fun handle(e: AnActionEvent) {
val editor = e.getData(CommonDataKeys.EDITOR) ?: return

val session = StorageInterface.newGlobalID()
val language = ComputerLanguage.getComputerLanguage(e)?.name ?: return
val language = ComputerLanguage.getComputerLanguage(e)?.name ?: ""
val filename = FileDocumentManager.getInstance().getFile(editor.document)?.name ?: return
SessionProxyServer.agents[session] = CodeChatSocketManager(
session = session,
Expand All @@ -50,7 +47,6 @@ class CodeChatAction : BaseAction() {
Thread {
Thread.sleep(500)
try {

val uri = server.server.uri.resolve("/#$session")
BaseAction.log.info("Opening browser to $uri")
Desktop.getDesktop().browse(uri)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
package com.github.simiacryptus.aicoder.actions.generic

import com.github.simiacryptus.aicoder.AppServer
import com.github.simiacryptus.aicoder.actions.BaseAction
import com.github.simiacryptus.aicoder.actions.BaseAction.Companion
import com.github.simiacryptus.aicoder.actions.generic.MultiStepPatchAction.AutoDevApp.Settings
import com.github.simiacryptus.aicoder.config.AppSettingsState
import com.github.simiacryptus.aicoder.util.UITools
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.PlatformDataKeys
import com.intellij.openapi.vfs.VirtualFile
import com.simiacryptus.diff.addApplyFileDiffLinks
import com.simiacryptus.diff.addSaveLinks
import com.simiacryptus.jopenai.API
import com.simiacryptus.jopenai.ApiModel
import com.simiacryptus.jopenai.ApiModel.Role
import com.simiacryptus.jopenai.GPT4Tokenizer
import com.simiacryptus.jopenai.util.ClientUtil.toContentList
import com.simiacryptus.skyenet.Discussable
import com.simiacryptus.skyenet.core.actors.SimpleActor
import com.simiacryptus.skyenet.core.platform.ClientManager
import com.simiacryptus.skyenet.core.platform.Session
import com.simiacryptus.skyenet.core.platform.StorageInterface
import com.simiacryptus.skyenet.core.platform.User
import com.simiacryptus.skyenet.webui.application.ApplicationInterface
import com.simiacryptus.skyenet.webui.application.ApplicationServer
import com.simiacryptus.skyenet.webui.util.MarkdownUtil.renderMarkdown
import org.slf4j.LoggerFactory
import java.awt.Desktop
import java.io.File
import java.nio.file.Path
import java.util.concurrent.Semaphore
import java.util.concurrent.atomic.AtomicReference

class MultiCodeChatAction : BaseAction() {
override fun getActionUpdateThread() = ActionUpdateThread.BGT

override fun handle(event: AnActionEvent) {
var root: Path? = null
val codeFiles: MutableSet<Path> = mutableSetOf()
fun codeSummary() = codeFiles.filter {
root!!.resolve(it).toFile().exists()
}.associateWith { root!!.resolve(it).toFile().readText(Charsets.UTF_8) }
.entries.joinToString("\n\n") { (path, code) ->
val extension = path.toString().split('.').lastOrNull()?.let { /*escapeHtml4*/(it)/*.indent(" ")*/ }
"""
|# $path
|```$extension
|${code}
|```
""".trimMargin()
}

val dataContext = event.dataContext
val virtualFiles = PlatformDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext)
val folder = UITools.getSelectedFolder(event)
root = if (null != folder) {
folder.toFile.toPath()
} else {
getModuleRootForFile(UITools.getSelectedFile(event)?.parent?.toFile ?: throw RuntimeException("")).toPath()
}
val files = getFiles(virtualFiles, root!!)
codeFiles.addAll(files)

val session = StorageInterface.newGlobalID()
SessionProxyServer.chats[session] = PatchApp(root!!.toFile(), { codeSummary() }, codeFiles)
val server = AppServer.getServer(event.project)

Thread {
Thread.sleep(500)
try {

val uri = server.server.uri.resolve("/#$session")
BaseAction.log.info("Opening browser to $uri")
Desktop.getDesktop().browse(uri)
} catch (e: Throwable) {
log.warn("Error opening browser", e)
}
}.start()
}

inner class PatchApp(
override val root: File,
val codeSummary: () -> String,
val codeFiles: Set<Path> = setOf(),
) : ApplicationServer(
applicationName = "Multi-file Patch Chat",
path = "/patchChat",
showMenubar = false,
) {
override val singleInput = false
override val stickyInput = true
private val mainActor: SimpleActor
get() = SimpleActor(
prompt = """
|You are a helpful AI that helps people with coding.
|
|You will be answering questions about the following code:
|
|${codeSummary()}
|
""".trimMargin(),
model = AppSettingsState.instance.defaultSmartModel()
)

override fun userMessage(
session: Session,
user: User?,
userMessage: String,
ui: ApplicationInterface,
api: API
) {
val settings = getSettings(session, user) ?: Settings()
if (api is ClientManager.MonitoredClient) api.budget = settings.budget ?: 2.00

val task = ui.newTask()
val codex = GPT4Tokenizer()
task.header(renderMarkdown(codeFiles.joinToString("\n") { path ->
"* $path - ${codex.estimateTokenCount(root.resolve(path.toFile()).readText())} tokens"
}))
val toInput = { it: String -> listOf(codeSummary(), it) }
Discussable(
task = task,
userMessage = { userMessage },
heading = renderMarkdown(userMessage),
initialResponse = { it: String -> mainActor.answer(toInput(it), api = api) },
outputFn = { design: String ->
var markdown = ui.socketManager?.addApplyFileDiffLinks(
root = root.toPath(),
code = { codeFiles.associateWith { root.resolve(it.toFile()).readText(Charsets.UTF_8) } },
response = design,
handle = { newCodeMap ->
newCodeMap.forEach { (path, newCode) ->
task.complete("<a href='${"fileIndex/$session/$path"}'>$path</a> Updated")
}
},
ui = ui,
)
markdown = ui.socketManager?.addSaveLinks(
response = markdown!!,
task = task,
ui = ui,
handle = { path, newCode ->
root.resolve(path.toFile()).writeText(newCode, Charsets.UTF_8)
},
)
"""<div>${renderMarkdown(markdown!!)}</div>"""
},
ui = ui,
reviseResponse = { userMessages: List<Pair<String, Role>> ->
mainActor.respond(
messages = (userMessages.map { ApiModel.ChatMessage(it.second, it.first.toContentList()) }
.toTypedArray<ApiModel.ChatMessage>()),
input = toInput(userMessage),
api = api
)
},
atomicRef = AtomicReference(),
semaphore = Semaphore(0),
).call()
}
}


private fun getFiles(
virtualFiles: Array<out VirtualFile>?,
root: Path
): MutableSet<Path> {
val codeFiles = mutableSetOf<Path>()
virtualFiles?.forEach { file ->
if (file.isDirectory) {
getFiles(file.children, root)
} else {
codeFiles.add(root.relativize(file.toNioPath()))
}
}
return codeFiles
}

override fun isEnabled(event: AnActionEvent) = true

companion object {
private val log = LoggerFactory.getLogger(MultiDiffChatAction::class.java)

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.intellij.openapi.vfs.VirtualFileManager
import com.simiacryptus.skyenet.core.OutputInterceptor
import com.simiacryptus.skyenet.core.platform.*
import com.simiacryptus.skyenet.core.platform.ApplicationServicesConfig.isLocked
import com.simiacryptus.skyenet.core.platform.file.DataStorage
import com.simiacryptus.skyenet.core.platform.file.UsageManager
import java.io.File
import java.util.concurrent.atomic.AtomicBoolean
Expand Down Expand Up @@ -84,6 +85,7 @@ class PluginStartupActivity : ProjectActivity {

private fun init() {
if (isInitialized.getAndSet(true)) return
ApplicationServicesConfig.dataStorageRoot = AppSettingsState.instance.pluginHome.resolve(".skyenet")
OutputInterceptor.setupInterceptor()
ApplicationServices.clientManager = object : ClientManager() {
override fun createClient(session: Session, user: User?) =
Expand All @@ -103,7 +105,6 @@ class PluginStartupActivity : ProjectActivity {
override fun logout(accessToken: String, user: User) {}
}
isLocked = true
val resolve = AppSettingsState.instance.pluginHome.resolve(".skyenet")
}


Expand Down
6 changes: 6 additions & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@

<add-to-group group-id="com.github.simiacryptus.aicoder.ui.ProjectMenu" anchor="last"/>
</action>
<action class="com.github.simiacryptus.aicoder.actions.generic.MultiCodeChatAction"
text="Code Chat"
description="Open a chat session with multiple files">

<add-to-group group-id="com.github.simiacryptus.aicoder.ui.ProjectMenu" anchor="last"/>
</action>
<action class="com.github.simiacryptus.aicoder.actions.generic.CreateImageAction"
text="Create Image"
description="Create an image file based on the selected code">
Expand Down
Loading