Skip to content

Commit

Permalink
refactor(core): stage changes for core files and update Cargo.toml
Browse files Browse the repository at this point in the history
  • Loading branch information
omarabid committed Dec 21, 2023
1 parent 69476ce commit 0595d1d
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 41 deletions.
1 change: 1 addition & 0 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ async-openai = "0.17.0"
reqwest = "0.11.22"
comfy-table = "7.1.0"
spinners = "4.1.1"
shlex = "1.2.0"
71 changes: 31 additions & 40 deletions core/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ use comfy_table::Table;
use spinners::{Spinner, Spinners};

use crate::db;
use crate::git;
use crate::decode::{GPTResponse, GPTResult};
use crate::git::{self, execute_gptresponse};

/// Show the configuration file
pub fn config() -> Result<()> {
Expand Down Expand Up @@ -54,8 +55,6 @@ pub fn undo() -> Result<()> {
.replace("{git_status}", &git_status)
.replace("{git_log}", &git_log);

println!("{}", &prompt);

let request = async_openai::types::CreateChatCompletionRequestArgs::default()
.model("gpt-4")
.messages([
Expand All @@ -77,8 +76,6 @@ pub fn undo() -> Result<()> {
.create(request), // Make the API call in that "group"
)?;

//println!("{:#?}", response);

spinner.stop();
println!("");

Expand All @@ -91,27 +88,27 @@ pub fn undo() -> Result<()> {
.as_ref()
.ok_or_else(|| Error::new("No content returned"))?;

println!("Suggested Command: \n$ {}", returned_command);
println!(":: Prooced with Command?: \n [Y/n]");

let mut input = String::new();
std::io::stdin().read_line(&mut input)?;
let decoded_command = crate::decode::decode_gpt_response(returned_command.to_string())?;

if input.trim() == "Y" {
println!("yes");
println!("{}", &decoded_command);

let trimmed_command = returned_command.replace("git ", "");
let gpt_response: GPTResponse = match decoded_command {
GPTResult::Success(gpt_response) => gpt_response,
GPTResult::Failure(msg) => {
println!("Giton failed. You can try again. \n {}", &msg);

let mut output = Command::new("git");
trimmed_command.split_whitespace().for_each(|arg| {
output.arg(arg);
});
return Ok(());
}
};

let output_stdout = output.output().expect("failed to execute process").stdout;
println!(":: Prooced with Command(s)?: \n [Y/n]");

let output = String::from_utf8(output_stdout)?;
let mut input = String::new();
std::io::stdin().read_line(&mut input)?;

println!("{}", output);
if input.trim() == "Y" {
// execute GPTResponse
execute_gptresponse(gpt_response)?;
}

Ok(())
Expand All @@ -120,7 +117,6 @@ pub fn undo() -> Result<()> {
pub fn helpme() -> Result<()> {
let mut spinner = Spinner::new(Spinners::Dots2, "Communicating with Open AI".into());

let last_command = db::get_last_command()?;
let git_status = git::get_status()?;
let git_log = git::get_log()?;

Expand All @@ -133,8 +129,6 @@ pub fn helpme() -> Result<()> {
.replace("{git_status}", &git_status)
.replace("{git_log}", &git_log);

println!("{}", &prompt);

let request = async_openai::types::CreateChatCompletionRequestArgs::default()
.model("gpt-4")
.messages([ChatCompletionRequestSystemMessageArgs::default()
Expand All @@ -150,8 +144,6 @@ pub fn helpme() -> Result<()> {
.create(request), // Make the API call in that "group"
)?;

//println!("{:#?}", response);

spinner.stop();
println!("");

Expand All @@ -164,27 +156,26 @@ pub fn helpme() -> Result<()> {
.as_ref()
.ok_or_else(|| Error::new("No content returned"))?;

println!("Suggested Command: \n$ {}", returned_command);
println!(":: Prooced with Command?: \n [Y/n]");
let decoded_command = crate::decode::decode_gpt_response(returned_command.to_string())?;

let mut input = String::new();
std::io::stdin().read_line(&mut input)?;
println!("{}", &decoded_command);

if input.trim() == "Y" {
println!("yes");
let gpt_response: GPTResponse = match decoded_command {
GPTResult::Success(gpt_response) => gpt_response,
GPTResult::Failure(msg) => {
println!("Giton failed. You can try again. \n {}", &msg);

let trimmed_command = returned_command.replace("git ", "");
return Ok(());
}
};

let mut output = Command::new("git");
trimmed_command.split_whitespace().for_each(|arg| {
output.arg(arg);
});
println!(":: Prooced with Command(s)?: \n [Y/n]");

let output_stdout = output.output().expect("failed to execute process").stdout;

let output = String::from_utf8(output_stdout)?;
let mut input = String::new();
std::io::stdin().read_line(&mut input)?;

println!("{}", output);
if input.trim() == "Y" {
execute_gptresponse(gpt_response)?;
}

Ok(())
Expand Down
93 changes: 93 additions & 0 deletions core/src/decode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use comfy_table::Table;
use utils::error::{Error, Result};

#[derive(Debug)]
pub enum GPTResult {
Success(GPTResponse),
Failure(String),
}

#[derive(Debug)]
pub struct GPTResponse {
pub status: ResponseStatus,
pub explanation: String,
pub commands: Vec<String>,
}

#[derive(Debug)]
pub enum ResponseStatus {
Success,
NotValid,
NotPossible,
}

pub fn decode_gpt_response(response: String) -> Result<GPTResult> {
let response = response.trim();

if response.starts_with("NOT_VALID:") {
let explanation = response.replace("NOT_VALID:", "");

return Ok(GPTResult::Success(GPTResponse {
status: ResponseStatus::NotValid,
explanation,
commands: vec![],
}));
}

if response.starts_with("NOT_POSSIBLE:") {
let explanation = response.replace("NOT_POSSIBLE:", "");

return Ok(GPTResult::Success(GPTResponse {
status: ResponseStatus::NotPossible,
explanation,
commands: vec![],
}));
}

if response.starts_with("git") {
// Sanitize commands
let commands: Vec<String> = response
.split("&&")
.map(|command| {
if command.trim().starts_with("git") {
Ok(command.trim().replace("git ", ""))
} else {
Err(Error::new("One or more commands do not start with 'git'"))
}
})
.collect::<Result<Vec<String>>>()?;

return Ok(GPTResult::Success(GPTResponse {
status: ResponseStatus::Success,
explanation: String::from(""),
commands,
}));
}

Err(Error::new("Could not decode GPT response"))
}

// implement display for GPTResult
// use comfy_table::Table to display the commands
impl std::fmt::Display for GPTResult {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
GPTResult::Success(response) => {
let mut table = Table::new();

table.set_header(vec!["#", "Command"]);

response
.commands
.iter()
.enumerate()
.for_each(|(i, command)| {
table.add_row(vec![i.to_string(), format!("git {}", command.to_string())]);
});

write!(f, "{}", table)
}
GPTResult::Failure(error) => write!(f, "{}", error),
}
}
}
39 changes: 38 additions & 1 deletion core/src/git.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::process::Command;
use utils::error::Result;
use utils::error::{Error, Result};

use crate::decode::{GPTResponse, ResponseStatus};

// Get Git status and return it as a String
pub fn get_status() -> Result<String> {
Expand Down Expand Up @@ -29,3 +31,38 @@ pub fn get_log() -> Result<String> {

Ok(lines_string)
}

pub fn execute_command(command: String) -> Result<()> {
dbg!(&command);

let mut output = Command::new("git");

shlex::split(&command).unwrap().iter().for_each(|arg| {
output.arg(arg);
});

dbg!(&output);

let output_stdout = output.output().expect("failed to execute process").stdout;

let output = String::from_utf8(output_stdout)?;

println!("{}", output);

Ok(())
}

pub fn execute_gptresponse(response: GPTResponse) -> Result<()> {
match response.status {
ResponseStatus::Success => {
response.commands.iter().for_each(|command| {
execute_command(command.to_string()).unwrap();
});

return Ok(());
}
_ => {
return Err(Error::new("GPTResponse cannot be executed"));
}
}
}
1 change: 1 addition & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ extern crate log;

pub mod commands;
pub mod db;
pub mod decode;
pub mod git;

use utils::error::Result;
Expand Down

0 comments on commit 0595d1d

Please sign in to comment.