@@ -3,20 +3,17 @@ package ai.devchat.cli
33import ai.devchat.common.Log
44import com.alibaba.fastjson.JSON
55import com.alibaba.fastjson.JSONArray
6+ import com.intellij.util.containers.addIfNotNull
67import java.io.BufferedReader
78import java.io.IOException
8- import java.io.InputStream
9- import java.io.InputStreamReader
10- import java.util.*
11- import java.util.function.BiConsumer
12- import java.util.function.Consumer
9+
10+ private const val DEFAULT_LOG_MAX_COUNT = 10000
1311
1412class DevChatWrapper {
1513 private var apiBase: String? = null
1614 private var apiKey: String? = null
1715 private var currentModel: String? = null
1816 private var command: String
19- private val DEFAULT_LOG_MAX_COUNT = " 100"
2017
2118 constructor (command: String ) {
2219 this .command = command
@@ -29,23 +26,27 @@ class DevChatWrapper {
2926 this .command = command
3027 }
3128
32- private fun execCommand (commands : List <String ?>) : String {
29+ private fun execCommand (commands : List <String >, callback : (( String ) -> Unit ) ? ) : String? {
3330 val pb = ProcessBuilder (commands)
34- if (apiBase != null ) {
35- pb.environment()[" OPENAI_API_BASE" ] = apiBase
36- Log .info(" api_base: $apiBase " )
31+ val env = pb.environment()
32+
33+ apiBase?.let {
34+ env[" OPENAI_API_BASE" ] = it
35+ Log .info(" api_base: $it " )
3736 }
38- if (apiKey != null ) {
39- pb.environment()[" OPENAI_API_KEY" ] = apiKey
40- Log .info(
41- " api_key: " + apiKey!! .substring(0 , 5 ) + " ..."
42- + apiKey!! .substring(apiKey!! .length - 4 , apiKey!! .length)
43- )
37+ apiKey?.let {
38+ env[" OPENAI_API_KEY" ] = it
39+ Log .info(" api_key: ${it.substring(0 , 5 )} ...${it.substring(it.length - 4 )} " )
4440 }
4541 return try {
46- Log .info(" Executing command: " + java.lang. String .join (" " , pb.command()) )
42+ Log .info(" Executing command: ${commands.joinToString (" " )} } " )
4743 val process = pb.start()
48- val text = process.inputStream.bufferedReader().use(BufferedReader ::readText)
44+ val text = process.inputStream.bufferedReader().use { reader ->
45+ callback?.let {
46+ reader.forEachLine(it)
47+ null
48+ } ? : reader.readText()
49+ }
4950 val errors = process.errorStream.bufferedReader().use(BufferedReader ::readText)
5051 process.waitFor()
5152 val exitCode = process.exitValue()
@@ -67,143 +68,57 @@ class DevChatWrapper {
6768 }
6869 }
6970
70- private fun execCommand (commands : List <String ?>, callback : Consumer <String >) {
71- val pb = ProcessBuilder (commands)
72- if (apiBase != null ) {
73- pb.environment()[" OPENAI_API_BASE" ] = apiBase
74- Log .info(" api_base: $apiBase " )
75- }
76- if (apiKey != null ) {
77- pb.environment()[" OPENAI_API_KEY" ] = apiKey
78- Log .info(
79- " api_key: " + apiKey!! .substring(0 , 5 ) + " ..."
80- + apiKey!! .substring(apiKey!! .length - 4 , apiKey!! .length)
81- )
82- }
83- try {
84- Log .info(" Executing command: " + java.lang.String .join(" " , pb.command()))
85- val process = pb.start()
86- readOutputByLine(process.inputStream, callback)
87- val exitCode = process.waitFor()
88- if (exitCode != 0 ) {
89- val error = readOutput(process.errorStream)
90- Log .error(
91- " Failed to execute command: " + java.lang.String .join(" " , pb.command()) + " Exit Code: " + exitCode
92- + " Error: " + error
93- )
94- throw RuntimeException (
95- " Failed to execute command: " + java.lang.String .join(" " , pb.command()) + " Exit Code: " + exitCode
96- + " Error: " + error
97- )
98- }
99- } catch (e: IOException ) {
100- Log .error(" Failed to execute command: " + java.lang.String .join(" " , pb.command()))
101- throw RuntimeException (" Failed to execute command: " + java.lang.String .join(" " , pb.command()), e)
102- } catch (e: InterruptedException ) {
103- Log .error(" Failed to execute command: " + java.lang.String .join(" " , pb.command()))
104- throw RuntimeException (" Failed to execute command: " + java.lang.String .join(" " , pb.command()), e)
105- }
71+ val prompt: (MutableList <Pair <String , String ?>>, String , ((String ) -> Unit )? ) -> Unit get() = {
72+ flags: MutableList <Pair <String , String ?>>, message: String , callback: ((String ) -> Unit )? ->
73+ flags.addAll(listOf (" model" to currentModel, " " to message))
74+ subCommand(listOf (" prompt" ))(flags, callback)
10675 }
10776
108- @Throws(IOException ::class )
109- private fun readOutput (inputStream : InputStream ): String {
110- val reader = BufferedReader (InputStreamReader (inputStream))
111- val output = StringBuilder ()
112- reader.forEachLine { line ->
113- output.append(line)
114- output.append(' \n ' )
115- }
116- return output.toString()
77+ val logTopic: (String , Int? ) -> JSONArray get() = {topic: String , maxCount: Int? ->
78+ val num: Int = maxCount ? : DEFAULT_LOG_MAX_COUNT
79+ JSON .parseArray(log(mutableListOf (
80+ " topic" to topic,
81+ " max-count" to num.toString()
82+ ), null ))
11783 }
11884
119- @Throws(IOException ::class )
120- private fun readOutputByLine (inputStream : InputStream , callback : Consumer <String >) {
121- val reader = BufferedReader (InputStreamReader (inputStream))
122- reader.forEachLine { line -> callback.accept(line) }
123- }
85+ val run get() = subCommand(listOf (" run" ))
86+ val log get() = subCommand(listOf (" log" ))
87+ val topic get() = subCommand(listOf (" topic" ))
12488
125- fun runPromptCommand (flags : MutableMap <String , List <String ?>>, message : String? , callback : Consumer <String >) {
126- try {
127- flags[" model" ] = listOf (currentModel)
128- val commands = prepareCommand(" prompt" , flags, message)
129- execCommand(commands, callback)
130- } catch (e: Exception ) {
131- throw RuntimeException (" Fail to run [prompt] command" , e)
132- }
133- }
89+ val topicList: JSONArray get() = JSON .parseArray(topic(mutableListOf (" list" to null ), null ))
90+ val commandList: JSONArray get() = JSON .parseArray(run (mutableListOf (" list" to null ), null ))
13491
135- fun runLogCommand (flags : Map <String , List <String ?>>? ): String {
136- return try {
137- val commands: List <String ?> = prepareCommand(flags, " log" )
138- execCommand(commands)
139- } catch (e: Exception ) {
140- throw RuntimeException (" Failed to run [log] command" , e)
141- }
142- }
14392
144- val commandList: JSONArray
145- get() {
146- val result = runCommand(null , " run" , " --list" )
147- return JSON .parseArray(result)
148- }
149- val commandNamesList: Array <String ?>
150- get() {
151- val commandList = commandList
152- val names = arrayOfNulls<String >(commandList.size)
153- for (i in commandList.indices) {
154- names[i] = commandList.getJSONObject(i).getString(" name" )
155- }
156- return names
93+ fun runCommand (subCommands : List <String >? , flags : List <Pair <String , String ?>>? = null, callback : ((String ) -> Unit )? = null): String? {
94+ val cmd: MutableList <String > = mutableListOf (command)
95+ cmd.addAll(subCommands.orEmpty())
96+ flags?.forEach { (name, value) ->
97+ cmd.add(" --$name " )
98+ cmd.addIfNotNull(value)
15799 }
158-
159- fun listConversationsInOneTopic (topicHash : String ): JSONArray {
160- val result = runLogCommand(
161- java.util.Map .of<String , List <String ?>>(
162- " topic" , listOf (topicHash),
163- " max-count" , listOf (DEFAULT_LOG_MAX_COUNT )
164- )
165- )
166- return JSON .parseArray(result)
167- }
168-
169- fun listTopics (): JSONArray {
170- val result = runCommand(null , " topic" , " --list" )
171- return JSON .parseArray(result)
172- }
173-
174- fun runCommand (flags : Map <String , List <String ?>>? , vararg subCommands : String ): String {
175100 return try {
176- val commands: List <String ?> = prepareCommand(flags, * subCommands)
177- execCommand(commands)
101+ execCommand(cmd, callback)
178102 } catch (e: Exception ) {
179- Log .error(" Failed to run [run] command: " + e.message)
180- throw RuntimeException (" Failed to run [ ${subCommands} ] command" , e)
103+ Log .error(" Failed to run command $cmd : ${ e.message} " )
104+ throw RuntimeException (" Failed to run command $cmd " , e)
181105 }
182106 }
183107
184- private fun prepareCommand (flags : Map <String , List <String ?>>? , vararg subCommands : String ): MutableList <String ?> {
185- val commands: MutableList <String ?> = ArrayList ()
186- commands.add(command)
187- Collections .addAll(commands, * subCommands)
188- if (flags == null ) {
189- return commands
190- }
191- flags.forEach(BiConsumer { flag: String , values: List <String ?> ->
192- for (value in values) {
193- commands.add(" --$flag " )
194- commands.add(value)
108+ private fun subCommand (subCommands : List <String >): (MutableList <Pair <String , String ?>>? , ((String ) -> Unit )? ) -> String? {
109+ val cmd: MutableList <String > = mutableListOf (command)
110+ cmd.addAll(subCommands)
111+ return {flags: List <Pair <String , String ?>>? , callback: ((String ) -> Unit )? ->
112+ flags?.forEach { (name, value) ->
113+ cmd.add(" --$name " )
114+ cmd.addIfNotNull(value)
115+ }
116+ try {
117+ execCommand(cmd, callback)
118+ } catch (e: Exception ) {
119+ Log .error(" Failed to run command $cmd : ${e.message} " )
120+ throw RuntimeException (" Failed to run command $cmd " , e)
195121 }
196- })
197- return commands
198- }
199-
200- private fun prepareCommand (subCommand : String , flags : Map <String , List <String ?>>, message : String? ): List <String ?> {
201- val commands = prepareCommand(flags, subCommand)
202- // Add the message to the command list
203- if (! message.isNullOrEmpty()) {
204- commands.add(" --" )
205- commands.add(message)
206122 }
207- return commands
208123 }
209124}
0 commit comments