Skip to content

Commit 4ea41d1

Browse files
authored
1.8.1 (#195)
* 1.8.1 * Help! They are comming! * 1.8.1 * rm tests
1 parent 1196e02 commit 4ea41d1

25 files changed

+288
-200
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ code!
3636
* 🔄 **Diff Windows**: Easily compare and review code changes.
3737

3838

39-
## **Installation & Setup**
39+
## 📥 Installation & Setup
4040

4141
Getting started with AI Coding Assistant is a breeze:
4242

@@ -101,4 +101,4 @@ plugin for developers. 🌟
101101
organization. The plugin is provided free of charge, as-is, with no warranty or guarantee of any kind, and is the work
102102
of a sole developer working on a hobby project.*
103103

104-
<!-- Plugin description end -->
104+
<!-- Plugin description end -->

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ repositories {
2828

2929
val jetty_version = "11.0.24"
3030
val slf4j_version = "2.0.16"
31-
val skyenet_version = "1.2.12"
31+
val skyenet_version = "1.2.13"
3232
val remoterobot_version = "0.11.23"
3333
val jackson_version = "2.17.2"
3434

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
pluginName=intellij-aicoder
22
pluginRepositoryUrl=https://github.com/SimiaCryptus/intellij-aicoder
3-
pluginVersion=1.8.0
3+
pluginVersion=1.8.1
44
jvmArgs=-Xmx8g
55
org.gradle.jvmargs=-Xmx8g -XX:MaxMetaspaceSize=1g
66
# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html

src/main/kotlin/com/github/simiacryptus/aicoder/actions/ApplyPatchAction.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class ApplyPatchAction : BaseAction(
1717

1818
override fun handle(event: AnActionEvent) {
1919
val project = event.project ?: return
20-
val virtualFile = UITools.getSelectedFile(event) ?: return
20+
val virtualFiles = UITools.getSelectedFiles(event) ?: return
2121

2222
// Prompt user to input patch content
2323
val patchContent = Messages.showMultilineInputDialog(
@@ -28,8 +28,9 @@ class ApplyPatchAction : BaseAction(
2828
null,
2929
null
3030
) ?: return
31-
32-
applyPatch(virtualFile, patchContent, project)
31+
virtualFiles.forEach { virtualFile ->
32+
applyPatch(virtualFile, patchContent, project)
33+
}
3334
}
3435

3536
private fun applyPatch(file: VirtualFile, patchContent: String, project: com.intellij.openapi.project.Project) {

src/main/kotlin/com/github/simiacryptus/aicoder/actions/FileContextAction.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.github.simiacryptus.aicoder.util.UITools
55
import com.intellij.openapi.actionSystem.AnActionEvent
66
import com.intellij.openapi.application.ApplicationManager
77
import com.intellij.openapi.fileEditor.FileEditorManager
8+
import com.intellij.openapi.progress.ProgressIndicator
89
import com.intellij.openapi.project.Project
910
import com.intellij.openapi.vfs.LocalFileSystem
1011
import com.intellij.openapi.vfs.VirtualFile
@@ -23,7 +24,7 @@ abstract class FileContextAction<T : Any>(
2324
val projectRoot: File,
2425
)
2526

26-
abstract fun processSelection(state: SelectionState, config: T?): Array<File>
27+
abstract fun processSelection(state: SelectionState, config: T?, progress: ProgressIndicator): Array<File>
2728

2829
final override fun handle(e: AnActionEvent) {
2930
val config = getConfig(e.project, e)
@@ -37,16 +38,16 @@ abstract class FileContextAction<T : Any>(
3738
Thread {
3839
try {
3940
UITools.redoableTask(e) {
40-
UITools.run(e.project, templateText!!, true) {
41+
UITools.run(e.project, templateText!!, true) { progress ->
4142
val newFiles = try {
4243
processSelection(
4344
SelectionState(
4445
selectedFile = virtualFile.toNioPath().toFile(),
4546
projectRoot = projectRoot.toFile(),
46-
), config
47+
), config, progress
4748
)
4849
} finally {
49-
if (it.isCanceled) throw InterruptedException()
50+
if (progress.isCanceled) throw InterruptedException()
5051
}
5152
val start = System.currentTimeMillis()
5253
val fileSystem = LocalFileSystem.getInstance()
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package com.github.simiacryptus.aicoder.actions.generic
2+
3+
import com.github.simiacryptus.aicoder.AppServer
4+
import com.github.simiacryptus.aicoder.actions.BaseAction
5+
import com.github.simiacryptus.aicoder.actions.generic.SimpleCommandAction.Companion.tripleTilde
6+
import com.github.simiacryptus.aicoder.config.AppSettingsState
7+
import com.github.simiacryptus.aicoder.util.BrowseUtil.browse
8+
import com.github.simiacryptus.aicoder.util.UITools
9+
import com.intellij.openapi.actionSystem.ActionUpdateThread
10+
import com.intellij.openapi.actionSystem.AnActionEvent
11+
import com.intellij.openapi.vfs.VirtualFile
12+
import com.simiacryptus.diff.FileValidationUtils
13+
import com.simiacryptus.jopenai.models.chatModel
14+
import com.simiacryptus.skyenet.apps.general.AutoPlanChatApp
15+
import com.simiacryptus.skyenet.apps.plan.PlanSettings
16+
import com.simiacryptus.skyenet.apps.plan.PlanUtil.isWindows
17+
import com.simiacryptus.skyenet.core.platform.Session
18+
import com.simiacryptus.skyenet.core.platform.file.DataStorage
19+
import com.simiacryptus.skyenet.core.util.getModuleRootForFile
20+
import com.simiacryptus.skyenet.webui.application.AppInfoData
21+
import com.simiacryptus.skyenet.webui.application.ApplicationServer
22+
import org.slf4j.LoggerFactory
23+
import java.io.File
24+
import java.nio.file.Path
25+
26+
class AutoPlanChatAction : BaseAction() {
27+
28+
override fun getActionUpdateThread() = ActionUpdateThread.BGT
29+
30+
override fun handle(e: AnActionEvent) {
31+
val dialog = PlanAheadConfigDialog(
32+
e.project, PlanSettings(
33+
defaultModel = AppSettingsState.instance.smartModel.chatModel(),
34+
parsingModel = AppSettingsState.instance.fastModel.chatModel(),
35+
command = listOf(
36+
if (System.getProperty("os.name").lowercase().contains("win")) "powershell" else "bash"
37+
),
38+
temperature = AppSettingsState.instance.temperature,
39+
workingDir = UITools.getSelectedFolder(e)?.toFile?.absolutePath ?: "",
40+
env = mapOf()
41+
)
42+
)
43+
if (dialog.showAndGet()) {
44+
// Settings are applied only if the user clicks OK
45+
val session = Session.newGlobalID()
46+
val folder = UITools.getSelectedFolder(e)
47+
val root = folder?.toFile ?: getModuleRootForFile(
48+
UITools.getSelectedFile(e)?.parent?.toFile ?: throw RuntimeException("")
49+
)
50+
DataStorage.sessionPaths[session] = root
51+
SessionProxyServer.chats[session] = object : AutoPlanChatApp(
52+
planSettings = dialog.settings.copy(
53+
env = mapOf(),
54+
workingDir = root.absolutePath,
55+
language = if (isWindows) "powershell" else "bash",
56+
command = listOf(
57+
if (System.getProperty("os.name").lowercase().contains("win")) "powershell" else "bash"
58+
),
59+
parsingModel = AppSettingsState.instance.fastModel.chatModel(),
60+
),
61+
model = AppSettingsState.instance.smartModel.chatModel(),
62+
parsingModel = AppSettingsState.instance.fastModel.chatModel(),
63+
showMenubar = false,
64+
api = api,
65+
) {
66+
fun codeFiles() = (UITools.getSelectedFiles(e).toTypedArray()?.toList()?.flatMap<VirtualFile, File> {
67+
FileValidationUtils.expandFileList(it.toFile).toList<File>()
68+
}?.map<File, Path> { it.toPath() }?.toSet<Path>()?.toMutableSet<Path>() ?: mutableSetOf<Path>())
69+
.filter { it.toFile().exists() }
70+
.filter { it.toFile().length() < 1024 * 1024 / 2 }
71+
.map { root.toPath().relativize(it) ?: it }.toSet()
72+
73+
fun codeSummary() = codeFiles()
74+
.joinToString("\n\n") { path ->
75+
"""
76+
|# ${path}
77+
|$tripleTilde${path.toString().split('.').lastOrNull()}
78+
|${root.resolve(path.toFile()).readText(Charsets.UTF_8)}
79+
|$tripleTilde
80+
""".trimMargin()
81+
}
82+
83+
fun projectSummary() = codeFiles()
84+
.asSequence().distinct().sorted()
85+
.joinToString("\n") { path ->
86+
"* ${path} - ${root.resolve(path.toFile()).length()} bytes"
87+
}
88+
89+
override fun contextData(): List<String> = listOf(
90+
if (codeFiles().size < 4) {
91+
"Files:\n" + codeSummary()
92+
} else {
93+
"Files:\n" + projectSummary()
94+
},
95+
)
96+
}
97+
ApplicationServer.appInfoMap[session] = AppInfoData(
98+
applicationName = "Auto Plan Chat",
99+
singleInput = false,
100+
stickyInput = true,
101+
loadImages = false,
102+
showMenubar = false
103+
)
104+
val server = AppServer.getServer(e.project)
105+
openBrowser(server, session.toString())
106+
}
107+
}
108+
109+
private fun openBrowser(server: AppServer, session: String) {
110+
Thread {
111+
Thread.sleep(500)
112+
try {
113+
val uri = server.server.uri.resolve("/#$session")
114+
log.info("Opening browser to $uri")
115+
browse(uri)
116+
} catch (e: Throwable) {
117+
log.warn("Error opening browser", e)
118+
}
119+
}.start()
120+
}
121+
122+
companion object {
123+
private val log = LoggerFactory.getLogger(AutoPlanChatAction::class.java)
124+
}
125+
}

src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/CreateFileFromDescriptionAction.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import com.github.simiacryptus.aicoder.config.Name
66
import com.github.simiacryptus.aicoder.util.UITools
77
import com.intellij.openapi.actionSystem.ActionUpdateThread
88
import com.intellij.openapi.actionSystem.AnActionEvent
9+
import com.intellij.openapi.progress.ProgressIndicator
910
import com.intellij.openapi.project.Project
1011
import com.simiacryptus.jopenai.models.ApiModel.*
1112
import com.simiacryptus.jopenai.models.chatModel
@@ -46,7 +47,8 @@ class CreateFileFromDescriptionAction : FileContextAction<CreateFileFromDescript
4647

4748
override fun processSelection(
4849
state: SelectionState,
49-
config: Settings?
50+
config: Settings?,
51+
progress: ProgressIndicator
5052
): Array<File> {
5153
val projectRoot = state.projectRoot.toPath()
5254
val inputPath = projectRoot.relativize(state.selectedFile.toPath()).toString()

src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/DocumentDataExtractorAction.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import com.github.simiacryptus.aicoder.util.UITools
88
import com.intellij.openapi.actionSystem.ActionUpdateThread
99
import com.intellij.openapi.actionSystem.AnActionEvent
1010
import com.simiacryptus.jopenai.models.chatModel
11-
import com.simiacryptus.skyenet.apps.parsers.CodeParsingModel
12-
import com.simiacryptus.skyenet.apps.parsers.DocumentParserApp
13-
import com.simiacryptus.skyenet.apps.parsers.DocumentParsingModel
11+
import com.simiacryptus.skyenet.apps.parse.CodeParsingModel
12+
import com.simiacryptus.skyenet.apps.parse.DocumentParserApp
13+
import com.simiacryptus.skyenet.apps.parse.DocumentParsingModel
1414
import com.simiacryptus.skyenet.core.platform.Session
1515
import com.simiacryptus.skyenet.core.platform.file.DataStorage
1616
import com.simiacryptus.skyenet.webui.application.AppInfoData

src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/DocumentDataExtractorConfigDialog.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import com.intellij.openapi.project.Project
44
import com.intellij.openapi.ui.DialogWrapper
55
import com.intellij.ui.components.JBCheckBox
66
import com.intellij.ui.components.JBTextField
7-
import com.simiacryptus.skyenet.apps.parsers.DocumentParserApp
7+
import com.simiacryptus.skyenet.apps.parse.DocumentParserApp
88
import javax.swing.*
99

1010
class DocumentDataExtractorConfigDialog(

src/main/kotlin/com/github/simiacryptus/aicoder/actions/generic/GenerateDocumentationAction.kt

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.intellij.openapi.actionSystem.ActionUpdateThread
1010
import com.intellij.openapi.actionSystem.AnActionEvent
1111
import com.intellij.openapi.application.ApplicationManager
1212
import com.intellij.openapi.fileEditor.FileEditorManager
13+
import com.intellij.openapi.progress.ProgressIndicator
1314
import com.intellij.openapi.project.Project
1415
import com.intellij.openapi.ui.DialogWrapper
1516
import com.intellij.openapi.ui.Messages
@@ -33,7 +34,6 @@ import java.util.concurrent.Executors
3334
import java.util.concurrent.Future
3435
import java.util.concurrent.TimeUnit
3536
import java.util.concurrent.TimeoutException
36-
import java.util.concurrent.atomic.AtomicReference
3737
import javax.swing.*
3838
import javax.swing.JComboBox
3939

@@ -130,20 +130,22 @@ class GenerateDocumentationAction : FileContextAction<GenerateDocumentationActio
130130
}
131131
}
132132

133-
override fun processSelection(state: SelectionState, config: Settings?): Array<File> {
133+
override fun processSelection(state: SelectionState, config: Settings?, progress: ProgressIndicator): Array<File> {
134+
progress.fraction = 0.0
134135
if (config?.settings == null) {
135136
// Dialog was cancelled, return empty array
136137
return emptyArray<File>().also {
137138
// Ensure we don't attempt to open any files when dialog is cancelled
138139
return@also
139140
}
140141
}
142+
progress.text = "Initializing documentation generation..."
141143

142144
val selectedFolder = state.selectedFile.toPath()
143145
val gitRoot = TestResultAutofixAction.findGitRoot(selectedFolder) ?: selectedFolder
144-
val outputDirectory = config?.settings?.outputDirectory ?: "docs/"
146+
val outputDirectory = config.settings.outputDirectory
145147
var outputPath =
146-
selectedFolder.resolve(config?.settings?.outputFilename ?: "compiled_documentation.md")
148+
selectedFolder.resolve(config.settings.outputFilename)
147149
val relativePath = gitRoot.relativize(outputPath)
148150
outputPath = gitRoot.resolve(outputDirectory).resolve(relativePath)
149151
if (outputPath.toFile().exists()) {
@@ -155,13 +157,15 @@ class GenerateDocumentationAction : FileContextAction<GenerateDocumentationActio
155157
outputPath = selectedFolder.resolve("$name.$fileIndex.$extension")
156158
}
157159
val executorService = Executors.newFixedThreadPool(4)
158-
val transformationMessage = config?.settings?.transformationMessage ?: "Create user documentation"
160+
val transformationMessage = config.settings.transformationMessage
159161
val markdownContent = TreeMap<String, String>()
160162
try {
161-
val selectedPaths = (config?.settings?.filesToProcess ?: listOf()).sortedBy { it.toString() }
163+
val selectedPaths = config.settings.filesToProcess.sortedBy { it.toString() }
162164
val partitionedPaths = Files.walk(selectedFolder)
163165
.filter { Files.isRegularFile(it) && !Files.isDirectory(it) }
164166
.toList().sortedBy { it.toString() }.groupBy { selectedPaths.contains(it) }
167+
val totalFiles = partitionedPaths[true]?.size ?: 0
168+
var processedFiles = 0
165169
val pathList = partitionedPaths[true]
166170
?.toList()?.filterNotNull()
167171
?.map<Path, Future<Path>> { path ->
@@ -183,6 +187,11 @@ class GenerateDocumentationAction : FileContextAction<GenerateDocumentationActio
183187
outputPath,
184188
markdownContent
185189
)
190+
synchronized(progress) {
191+
processedFiles++
192+
progress.fraction = processedFiles.toDouble() / totalFiles
193+
progress.text = "Processing file ${processedFiles} of ${totalFiles}"
194+
}
186195
return@submit path
187196
} catch (e: Exception) {
188197
retries++
@@ -207,7 +216,7 @@ class GenerateDocumentationAction : FileContextAction<GenerateDocumentationActio
207216
null
208217
}
209218
}?.filterNotNull() ?: listOf()
210-
if (config?.settings?.singleOutputFile == true) {
219+
if (config.settings.singleOutputFile == true) {
211220
val sortedContent = markdownContent.entries.joinToString("\n\n") { (path, content) ->
212221
"# $path\n\n$content"
213222
}
@@ -219,7 +228,7 @@ class GenerateDocumentationAction : FileContextAction<GenerateDocumentationActio
219228
} else {
220229
val outputDir = selectedFolder.resolve(outputDirectory)
221230
outputDir.toFile().mkdirs()
222-
open(config?.project!!, selectedFolder.resolve(outputDirectory))
231+
open(config.project!!, selectedFolder.resolve(outputDirectory))
223232
return pathList.map { it.toFile() }.toTypedArray()
224233
}
225234
} finally {
@@ -325,7 +334,6 @@ class GenerateDocumentationAction : FileContextAction<GenerateDocumentationActio
325334

326335
inner class DocumentationCompilerDialog(project: Project?, private val settingsUI: SettingsUI) : DialogWrapper(project) {
327336
val userSettings = UserSettings()
328-
private val selectedInstruction = AtomicReference<String>()
329337

330338
init {
331339
title = "Compile Documentation"

0 commit comments

Comments
 (0)