-
Notifications
You must be signed in to change notification settings - Fork 241
Add to-do list functionality to QCLI #2533
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
Open
kiran-garre
wants to merge
37
commits into
main
Choose a base branch
from
kiran-garre/todo-list
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
37 commits
Select commit
Hold shift + click to select a range
264c308
feat: update build scripts to build qchat (#2198)
brandonskiser 415624a
feat: Add basic todo list tool
30fc467
Slash command + persistence in progress commit
da54512
feat: Add basic persistence functionality to todo_list
2a09ea9
Add append-only context and "modified files" fields to "complete" com…
398bdb4
refactor: Change to-do lists to use database over filesystem
c000ffb
feat: Add `view` subcommand for /todos
302cecd
feat: Add clear-finished subcommand for /todos
a9501e7
feat: Add `add` and `remove` functionality for to-do lists
814a96a
fix: Add feedback after calling todo_list commands
216ce00
feat: Cleaned up todo list UX and removed /todos show
714474a
feat: Add /todos show
06837f2
trying to merge changes
1a4e7e1
fix: Fix all merge conflicts, back to working state
3299478
chore: Resolve merge conflicts, run formatter and clippy
e31c7ed
chore: Fix real clippy errors (hopefully)
058cc62
Merge branch 'main' of github.com:aws/amazon-q-developer-cli into kir…
12a70b5
chore: Run formatter
ef44517
chore: Remove old/unrelated files
cbbfa20
chore: Remove old/unrelated files again
5ebf87a
refactor: Several changes made to `todo_list` tool
5e76bc1
chore: Fix typo in tool_index.json
7f91788
chore: Remove buildspec files
70423f9
chore: Edit buildspec files to be identical to main
81b1dac
chore: Remove debugging in todos.rs
e7ea8af
chore: Merging changes from main
d7aa647
refactor: Convert from global database store to per-directory filesys…
ee6b932
merge commit
6d00e0f
Merge branch 'main' into kiran-garre/todo-list
4b684f9
fix: Update dependencies to fix slab issue
f2fc3d1
chore: Change variable names, add comments, add file extension to tod…
2fcbe56
Merge commit
9e0b732
Removed merge markers from Cargo.lock
030c79a
Fixed Cargo.lock
cbc8625
fix: Modify system prompt to contain current todo list id
2bf1c40
Merge branch 'main' of github.com:aws/amazon-q-developer-cli
2d9c3b4
Merge branch 'main' into kiran-garre/todo-list
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,4 +44,3 @@ artifacts: | |
# Signatures | ||
- ./*.asc | ||
- ./*.sig | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,4 +38,3 @@ artifacts: | |
- ./*.zip | ||
# Hashes | ||
- ./*.sha256 | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
use clap::Subcommand; | ||
use crossterm::execute; | ||
use crossterm::style::{ | ||
self, | ||
Stylize, | ||
}; | ||
use dialoguer::FuzzySelect; | ||
use eyre::Result; | ||
|
||
use crate::cli::chat::tools::todo::{ | ||
TodoListState, | ||
delete_todo, | ||
get_all_todos, | ||
}; | ||
use crate::cli::chat::{ | ||
ChatError, | ||
ChatSession, | ||
ChatState, | ||
}; | ||
use crate::os::Os; | ||
|
||
/// Defines subcommands that allow users to view and manage todo lists | ||
#[derive(Debug, PartialEq, Subcommand)] | ||
pub enum TodoSubcommand { | ||
/// Delete all completed to-do lists | ||
ClearFinished, | ||
|
||
/// Resume a selected to-do list | ||
Resume, | ||
|
||
/// View a to-do list | ||
View, | ||
|
||
/// Delete a to-do list | ||
Delete { | ||
#[arg(long, short)] | ||
all: bool, | ||
}, | ||
} | ||
|
||
/// Used for displaying completed and in-progress todo lists | ||
pub struct TodoDisplayEntry { | ||
pub num_completed: usize, | ||
pub num_tasks: usize, | ||
pub description: String, | ||
pub id: String, | ||
} | ||
|
||
impl std::fmt::Display for TodoDisplayEntry { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
if self.num_completed == self.num_tasks { | ||
write!(f, "{} {}", "✓".green().bold(), self.description.clone(),) | ||
} else { | ||
write!( | ||
f, | ||
"{} {} ({}/{})", | ||
"✗".red().bold(), | ||
self.description.clone(), | ||
self.num_completed, | ||
self.num_tasks | ||
) | ||
} | ||
} | ||
} | ||
|
||
impl TodoSubcommand { | ||
pub async fn execute(self, os: &mut Os, session: &mut ChatSession) -> Result<ChatState, ChatError> { | ||
match self { | ||
Self::ClearFinished => { | ||
let (todos, errors) = match get_all_todos(os).await { | ||
Ok(res) => res, | ||
Err(e) => return Err(ChatError::Custom(format!("Could not get to-do lists: {e}").into())), | ||
}; | ||
let mut cleared_one = false; | ||
|
||
for todo_status in todos.iter() { | ||
if todo_status.completed.iter().all(|b| *b) { | ||
match delete_todo(os, &todo_status.id).await { | ||
Ok(_) => cleared_one = true, | ||
Err(e) => { | ||
return Err(ChatError::Custom(format!("Could not delete to-do list: {e}").into())); | ||
}, | ||
}; | ||
} | ||
} | ||
if cleared_one { | ||
execute!( | ||
session.stderr, | ||
style::Print("✔ Cleared finished to-do lists!\n".green()) | ||
)?; | ||
} else { | ||
execute!(session.stderr, style::Print("No finished to-do lists to clear!\n"))?; | ||
} | ||
if !errors.is_empty() { | ||
execute!( | ||
session.stderr, | ||
style::Print(format!("* Failed to get {} todo list(s)\n", errors.len()).dark_grey()) | ||
)?; | ||
} | ||
}, | ||
Self::Resume => match Self::get_descriptions_and_statuses(os).await { | ||
Ok(entries) => { | ||
if entries.is_empty() { | ||
execute!(session.stderr, style::Print("No to-do lists to resume!\n"),)?; | ||
} else if let Some(index) = fuzzy_select_todos(&entries, "Select a to-do list to resume:") { | ||
if index < entries.len() { | ||
execute!( | ||
session.stderr, | ||
style::Print(format!( | ||
"{} {}", | ||
"⟳ Resuming:".magenta(), | ||
entries[index].description.clone() | ||
)) | ||
)?; | ||
return session.resume_todo_request(os, &entries[index].id).await; | ||
} | ||
} | ||
}, | ||
Err(e) => return Err(ChatError::Custom(format!("Could not show to-do lists: {e}").into())), | ||
}, | ||
Self::View => match Self::get_descriptions_and_statuses(os).await { | ||
Ok(entries) => { | ||
if entries.is_empty() { | ||
execute!(session.stderr, style::Print("No to-do lists to view!\n"))?; | ||
} else if let Some(index) = fuzzy_select_todos(&entries, "Select a to-do list to view:") { | ||
if index < entries.len() { | ||
let list = TodoListState::load(os, &entries[index].id).await.map_err(|e| { | ||
ChatError::Custom(format!("Could not load current to-do list: {e}").into()) | ||
})?; | ||
execute!( | ||
session.stderr, | ||
style::Print(format!( | ||
"{} {}\n\n", | ||
"Viewing:".magenta(), | ||
entries[index].description.clone() | ||
)) | ||
)?; | ||
if list.display_list(&mut session.stderr).is_err() { | ||
return Err(ChatError::Custom("Could not display the selected to-do list".into())); | ||
} | ||
execute!(session.stderr, style::Print("\n"),)?; | ||
} | ||
} | ||
}, | ||
Err(e) => return Err(ChatError::Custom(format!("Could not show to-do lists: {e}").into())), | ||
}, | ||
Self::Delete { all } => match Self::get_descriptions_and_statuses(os).await { | ||
Ok(entries) => { | ||
if entries.is_empty() { | ||
execute!(session.stderr, style::Print("No to-do lists to delete!\n"))?; | ||
} else if all { | ||
for entry in entries { | ||
delete_todo(os, &entry.id) | ||
.await | ||
.map_err(|_e| ChatError::Custom("Could not delete all to-do lists".into()))?; | ||
} | ||
execute!(session.stderr, style::Print("✔ Deleted all to-do lists!\n".green()),)?; | ||
} else if let Some(index) = fuzzy_select_todos(&entries, "Select a to-do list to delete:") { | ||
if index < entries.len() { | ||
delete_todo(os, &entries[index].id).await.map_err(|e| { | ||
ChatError::Custom(format!("Could not delete the selected to-do list: {e}").into()) | ||
})?; | ||
execute!( | ||
session.stderr, | ||
style::Print("✔ Deleted to-do list: ".green()), | ||
style::Print(format!("{}\n", entries[index].description.clone().dark_grey())) | ||
)?; | ||
} | ||
} | ||
}, | ||
Err(e) => return Err(ChatError::Custom(format!("Could not show to-do lists: {e}").into())), | ||
}, | ||
} | ||
Ok(ChatState::PromptUser { | ||
skip_printing_tools: true, | ||
}) | ||
} | ||
|
||
/// Convert all to-do list state entries to displayable entries | ||
async fn get_descriptions_and_statuses(os: &Os) -> Result<Vec<TodoDisplayEntry>> { | ||
let mut out = Vec::new(); | ||
let (todos, _) = get_all_todos(os).await?; | ||
for todo in todos.iter() { | ||
out.push(TodoDisplayEntry { | ||
num_completed: todo.completed.iter().filter(|b| **b).count(), | ||
num_tasks: todo.completed.len(), | ||
description: todo.description.clone(), | ||
id: todo.id.clone(), | ||
}); | ||
} | ||
Ok(out) | ||
} | ||
} | ||
|
||
fn fuzzy_select_todos(entries: &[TodoDisplayEntry], prompt_str: &str) -> Option<usize> { | ||
FuzzySelect::new() | ||
.with_prompt(prompt_str) | ||
.items(entries) | ||
.report(false) | ||
.interact_opt() | ||
.unwrap_or(None) | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any todo list directory creation should really be happening with the todo list code that depends on it, having it here is error prone should this ever be moved in the future.