ruby_todo 1.0.10 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/lib/ruby_todo/ai_assistant/task_creator.rb +23 -2
- data/lib/ruby_todo/commands/ai_assistant.rb +151 -0
- data/lib/ruby_todo/version.rb +1 -1
- metadata +2 -4
- data/sorted_tests.txt +0 -59
- data/test_methods.txt +0 -59
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1ba44da4ec50889bd3ad526d25b43b8157093215303b25874a7038c2d76b1b1d
|
4
|
+
data.tar.gz: eed6527b7f09388a8ad7abae9563f409e497ac06858bc0f39d4c92186cb9902a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b5deb1f7d58a8cb0bd3de5d96ec1bd03fe71f3b0e0c3b3c88f2ade4ce0d980c650cc691e897f63100d6ce83415f364aef436cf8d5d07a747982d0cf8a4afa68f
|
7
|
+
data.tar.gz: 75d18f85223d81795a229bbdca14cfe54d0a8b3536610dbc72e0fba91fb24cbc178d5423211255aedb5296211e3f92c7a89e5524dc40c4bd2545fa4dc78b191a
|
data/CHANGELOG.md
CHANGED
@@ -62,7 +62,7 @@ module RubyTodo
|
|
62
62
|
"action-oriented titles. For example, 'add new relic infra to questions-engine' should become " \
|
63
63
|
"'Integrate New Relic Infrastructure with Questions Engine'\n" \
|
64
64
|
"- description: A detailed description of what the task involves\n" \
|
65
|
-
"- priority: Suggested priority (high, medium, or low)\n" \
|
65
|
+
"- priority: Suggested priority (must be exactly one of: 'high', 'medium', or 'low')\n" \
|
66
66
|
"- tags: Relevant tags as a comma-separated string"
|
67
67
|
end
|
68
68
|
end
|
@@ -87,6 +87,8 @@ module RubyTodo
|
|
87
87
|
- "create a new task to add newrelic to the questions engine app" → "Implement New Relic Monitoring for Questions Engine Application"
|
88
88
|
|
89
89
|
Create concise but descriptive titles that use proper capitalization and professional terminology.
|
90
|
+
|
91
|
+
IMPORTANT: For priority field, you MUST use ONLY one of these exact values: "high", "medium", or "low" (lowercase).
|
90
92
|
PROMPT
|
91
93
|
|
92
94
|
messages = [
|
@@ -145,11 +147,27 @@ module RubyTodo
|
|
145
147
|
{
|
146
148
|
"title" => title_match ? title_match[1] : "Task from #{task_description}",
|
147
149
|
"description" => desc_match ? desc_match[1] : task_description,
|
148
|
-
"priority" => priority_match ? priority_match[1] : "medium",
|
150
|
+
"priority" => priority_match ? normalize_priority(priority_match[1]) : "medium",
|
149
151
|
"tags" => tags_match ? tags_match[1] : ""
|
150
152
|
}
|
151
153
|
end
|
152
154
|
|
155
|
+
# Normalize priority to ensure it matches allowed values
|
156
|
+
def normalize_priority(priority)
|
157
|
+
priority = priority.downcase.strip
|
158
|
+
return priority if %w[high medium low].include?(priority)
|
159
|
+
|
160
|
+
# Map similar terms to valid priorities
|
161
|
+
case priority
|
162
|
+
when /^h/i, "important", "urgent", "critical"
|
163
|
+
"high"
|
164
|
+
when /^l/i, "minor", "trivial"
|
165
|
+
"low"
|
166
|
+
else
|
167
|
+
"medium" # Default fallback
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
153
171
|
# Create a task from the generated details
|
154
172
|
def create_task_from_details(notebook_name, task_details)
|
155
173
|
# Ensure we have a valid notebook
|
@@ -177,6 +195,9 @@ module RubyTodo
|
|
177
195
|
say "✨ Enhanced title: \"#{task_details["title"]}\"", :green
|
178
196
|
end
|
179
197
|
|
198
|
+
# Ensure priority is properly normalized before passing to CLI
|
199
|
+
task_details["priority"] = normalize_priority(task_details["priority"]) if task_details["priority"]
|
200
|
+
|
180
201
|
args = ["task:add", notebook_name, task_details["title"]]
|
181
202
|
args << "--description" << task_details["description"] if task_details["description"]
|
182
203
|
args << "--priority" << task_details["priority"] if task_details["priority"]
|
@@ -705,6 +705,155 @@ module RubyTodo
|
|
705
705
|
include ExportProcessingHelpers
|
706
706
|
end
|
707
707
|
|
708
|
+
# Module for handling task movement-related functionality
|
709
|
+
module TaskMovementHelpers
|
710
|
+
# Handle moving tasks by title or search term
|
711
|
+
def handle_move_task_by_title(prompt, _cli)
|
712
|
+
# Pattern for "move the task about X to status"
|
713
|
+
task_about_pattern = /
|
714
|
+
move\s+(?:the\s+)?(?:task|tasks)\s+
|
715
|
+
(?:about|with|containing|related\s+to)\s+
|
716
|
+
([\w\s\-]+)\s+to\s+
|
717
|
+
(todo|in[\s_-]?progress|done|archived)
|
718
|
+
/ix
|
719
|
+
|
720
|
+
if prompt.match?(task_about_pattern)
|
721
|
+
match = prompt.match(task_about_pattern)
|
722
|
+
search_term = match[1].strip
|
723
|
+
status = match[2].downcase
|
724
|
+
|
725
|
+
# Normalize status (ensure 'in progress' becomes 'in_progress')
|
726
|
+
status = "in_progress" if status.match?(/in.*progress/i)
|
727
|
+
|
728
|
+
# Find tasks that match the search term
|
729
|
+
all_notebooks = RubyTodo::Notebook.all
|
730
|
+
matched_tasks = []
|
731
|
+
|
732
|
+
all_notebooks.each do |notebook|
|
733
|
+
notebook.tasks.each do |task|
|
734
|
+
next unless task.title.downcase.include?(search_term.downcase) ||
|
735
|
+
(task.description && task.description.downcase.include?(search_term.downcase))
|
736
|
+
|
737
|
+
matched_tasks << { notebook: notebook, task: task }
|
738
|
+
end
|
739
|
+
end
|
740
|
+
|
741
|
+
if matched_tasks.empty?
|
742
|
+
say "No tasks found matching '#{search_term}'".yellow
|
743
|
+
return true
|
744
|
+
end
|
745
|
+
|
746
|
+
# Move each matched task
|
747
|
+
moved_count = 0
|
748
|
+
matched_tasks.each do |task_info|
|
749
|
+
if task_info[:task].update(status: status)
|
750
|
+
say "Moved task #{task_info[:task].id}: '#{task_info[:task].title}' to #{status}".green
|
751
|
+
moved_count += 1
|
752
|
+
else
|
753
|
+
say "Error moving task #{task_info[:task].id}: #{task_info[:task].errors.full_messages.join(", ")}".red
|
754
|
+
end
|
755
|
+
end
|
756
|
+
|
757
|
+
say "Moved #{moved_count} task(s) to #{status}".green if moved_count > 0
|
758
|
+
return true
|
759
|
+
end
|
760
|
+
|
761
|
+
# Pattern for direct task title movement - "move [title] to [status]"
|
762
|
+
if prompt.match?(%r{move\s+(?:task\s+)?([\w\s\-/'"]+?)\s+to\s+(todo|in[\s_-]?progress|done|archived)}i)
|
763
|
+
match = prompt.match(%r{move\s+(?:task\s+)?([\w\s\-/'"]+?)\s+to\s+(todo|in[\s_-]?progress|done|archived)}i)
|
764
|
+
title_text = match[1].strip
|
765
|
+
status = match[2].downcase
|
766
|
+
|
767
|
+
# Clean up the title by removing quotes
|
768
|
+
title_text = title_text.gsub(/^['"]|['"]$/, "")
|
769
|
+
|
770
|
+
# Normalize status
|
771
|
+
status = "in_progress" if status.match?(/in.*progress/i)
|
772
|
+
|
773
|
+
# Find tasks that match the title
|
774
|
+
all_notebooks = RubyTodo::Notebook.all
|
775
|
+
matched_tasks = []
|
776
|
+
|
777
|
+
all_notebooks.each do |notebook|
|
778
|
+
notebook.tasks.each do |task|
|
779
|
+
next unless task.title.downcase.include?(title_text.downcase)
|
780
|
+
|
781
|
+
matched_tasks << { notebook: notebook, task: task }
|
782
|
+
end
|
783
|
+
end
|
784
|
+
|
785
|
+
if matched_tasks.empty?
|
786
|
+
say "No tasks found matching '#{title_text}'".yellow
|
787
|
+
return true
|
788
|
+
end
|
789
|
+
|
790
|
+
# Move each matched task
|
791
|
+
moved_count = 0
|
792
|
+
matched_tasks.each do |task_info|
|
793
|
+
if task_info[:task].update(status: status)
|
794
|
+
say "Moved task #{task_info[:task].id}: '#{task_info[:task].title}' to #{status}".green
|
795
|
+
moved_count += 1
|
796
|
+
else
|
797
|
+
say "Error moving task #{task_info[:task].id}: #{task_info[:task].errors.full_messages.join(", ")}".red
|
798
|
+
end
|
799
|
+
end
|
800
|
+
|
801
|
+
say "Moved #{moved_count} task(s) to #{status}".green if moved_count > 0
|
802
|
+
return true
|
803
|
+
end
|
804
|
+
|
805
|
+
# Specific pattern for "move task(s) with title X to status"
|
806
|
+
task_with_title_pattern = /
|
807
|
+
move\s+(?:the\s+)?(?:task|tasks)\s+
|
808
|
+
with\s+(?:title|name)\s+
|
809
|
+
["']([^"']+)["']\s+to\s+
|
810
|
+
(todo|in[\s_-]?progress|done|archived)
|
811
|
+
/ix
|
812
|
+
|
813
|
+
if prompt.match?(task_with_title_pattern)
|
814
|
+
match = prompt.match(task_with_title_pattern)
|
815
|
+
exact_title = match[1]
|
816
|
+
status = match[2].downcase
|
817
|
+
|
818
|
+
# Normalize status
|
819
|
+
status = "in_progress" if status.match?(/in.*progress/i)
|
820
|
+
|
821
|
+
# Find tasks that match the exact title
|
822
|
+
all_notebooks = RubyTodo::Notebook.all
|
823
|
+
matched_tasks = []
|
824
|
+
|
825
|
+
all_notebooks.each do |notebook|
|
826
|
+
notebook.tasks.each do |task|
|
827
|
+
next unless task.title.downcase == exact_title.downcase
|
828
|
+
|
829
|
+
matched_tasks << { notebook: notebook, task: task }
|
830
|
+
end
|
831
|
+
end
|
832
|
+
|
833
|
+
if matched_tasks.empty?
|
834
|
+
say "No tasks found with title '#{exact_title}'".yellow
|
835
|
+
return true
|
836
|
+
end
|
837
|
+
|
838
|
+
# Move each matched task
|
839
|
+
moved_count = 0
|
840
|
+
matched_tasks.each do |task_info|
|
841
|
+
if task_info[:task].update(status: status)
|
842
|
+
say "Moved task #{task_info[:task].id}: '#{task_info[:task].title}' to #{status}".green
|
843
|
+
moved_count += 1
|
844
|
+
else
|
845
|
+
say "Error moving task #{task_info[:task].id}: #{task_info[:task].errors.full_messages.join(", ")}".red
|
846
|
+
end
|
847
|
+
end
|
848
|
+
|
849
|
+
say "Moved #{moved_count} task(s) to #{status}".green if moved_count > 0
|
850
|
+
return true
|
851
|
+
end
|
852
|
+
|
853
|
+
false
|
854
|
+
end
|
855
|
+
end
|
856
|
+
|
708
857
|
# Main AI Assistant command class
|
709
858
|
class AIAssistantCommand < Thor
|
710
859
|
include OpenAIIntegration
|
@@ -714,6 +863,7 @@ module RubyTodo
|
|
714
863
|
include AIAssistantHelpers
|
715
864
|
include StatusFilteringHelpers
|
716
865
|
include ExportHelpers
|
866
|
+
include TaskMovementHelpers
|
717
867
|
|
718
868
|
desc "ask [PROMPT]", "Ask the AI assistant to perform tasks using natural language"
|
719
869
|
method_option :api_key, type: :string, desc: "OpenAI API key"
|
@@ -879,6 +1029,7 @@ module RubyTodo
|
|
879
1029
|
return true if handle_documentation_task_specific_patterns(prompt)
|
880
1030
|
return true if handle_task_creation_patterns(prompt, cli)
|
881
1031
|
return true if handle_task_status_patterns(prompt)
|
1032
|
+
return true if handle_move_task_by_title(prompt, cli)
|
882
1033
|
return true if handle_export_task_patterns(prompt)
|
883
1034
|
return true if handle_notebook_operations(prompt, cli)
|
884
1035
|
return true if handle_task_operations(prompt, cli)
|
data/lib/ruby_todo/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_todo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremiah Parrack
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-04-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -243,8 +243,6 @@ files:
|
|
243
243
|
- progress_ai_test.md
|
244
244
|
- protectors_tasks.json
|
245
245
|
- sig/ruby_todo.rbs
|
246
|
-
- sorted_tests.txt
|
247
|
-
- test_methods.txt
|
248
246
|
- todo_tasks_export_20250331.json
|
249
247
|
homepage: https://github.com/jeremiahlukus/ruby_todo
|
250
248
|
licenses:
|
data/sorted_tests.txt
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
test_ai_ambiguous_notebook_reference
|
2
|
-
test_ai_basic_functionality
|
3
|
-
test_ai_batch_task_update_by_keyword
|
4
|
-
test_ai_batch_task_update_by_tag
|
5
|
-
test_ai_complex_task_creation_with_natural_language
|
6
|
-
test_ai_conversational_export_requests
|
7
|
-
test_ai_conversational_request_for_notebook_contents
|
8
|
-
test_ai_create_default_notebook_for_task
|
9
|
-
test_ai_create_multiple_infrastructure_tasks
|
10
|
-
test_ai_create_notebook
|
11
|
-
test_ai_create_task_with_attributes
|
12
|
-
test_ai_date_based_export_request
|
13
|
-
test_ai_default_notebook_remains_when_adding_new_notebook
|
14
|
-
test_ai_display_in_progress_status_tasks
|
15
|
-
test_ai_display_tasks_that_are_in_progress
|
16
|
-
test_ai_empty_prompt
|
17
|
-
test_ai_explicit_default_notebook_commands
|
18
|
-
test_ai_export_archived_tasks
|
19
|
-
test_ai_export_done_tasks
|
20
|
-
test_ai_export_done_tasks_to_csv
|
21
|
-
test_ai_export_done_tasks_with_custom_filename
|
22
|
-
test_ai_export_in_progress_tasks
|
23
|
-
test_ai_export_nonexistent_status
|
24
|
-
test_ai_export_tasks_to_different_formats
|
25
|
-
test_ai_export_tasks_with_status
|
26
|
-
test_ai_export_todo_tasks
|
27
|
-
test_ai_export_with_custom_parameters
|
28
|
-
test_ai_export_with_different_status_formats
|
29
|
-
test_ai_export_with_no_done_tasks
|
30
|
-
test_ai_handle_multiple_requests_in_one_prompt
|
31
|
-
test_ai_handles_both_normal_and_medium_terms
|
32
|
-
test_ai_invalid_api_key
|
33
|
-
test_ai_invalid_status
|
34
|
-
test_ai_invalid_task_id
|
35
|
-
test_ai_list_tasks_in_notebook
|
36
|
-
test_ai_list_tasks_that_are_in_todo_status
|
37
|
-
test_ai_list_tasks_with_in_progress_hyphenated
|
38
|
-
test_ai_list_tasks_with_in_progress_status
|
39
|
-
test_ai_list_tasks_with_status_in_progress
|
40
|
-
test_ai_list_tasks_with_todo_status
|
41
|
-
test_ai_multiple_specific_task_update
|
42
|
-
test_ai_natural_language_task_creation
|
43
|
-
test_ai_never_uses_normal_priority
|
44
|
-
test_ai_nonexistent_notebook
|
45
|
-
test_ai_notebook_listing
|
46
|
-
test_ai_sets_medium_priority_by_default
|
47
|
-
test_ai_show_in_progress_tasks_alternative_phrasing
|
48
|
-
test_ai_show_tasks_having_in_progress_status
|
49
|
-
test_ai_show_todo_tasks_alternative_phrasing
|
50
|
-
test_ai_statistics_request
|
51
|
-
test_ai_task_creation_suggestion
|
52
|
-
test_ai_task_list
|
53
|
-
test_ai_task_listing
|
54
|
-
test_ai_task_movement_with_natural_language
|
55
|
-
test_ai_task_search
|
56
|
-
test_ai_task_status_update
|
57
|
-
test_ai_task_with_invalid_attributes
|
58
|
-
test_notebook_commands_with_explicit_methods
|
59
|
-
test_template_commands_with_explicit_methods
|
data/test_methods.txt
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
test_ai_basic_functionality
|
2
|
-
test_ai_task_creation_suggestion
|
3
|
-
test_ai_task_listing
|
4
|
-
test_ai_task_status_update
|
5
|
-
test_ai_task_search
|
6
|
-
test_ai_notebook_listing
|
7
|
-
test_ai_create_notebook
|
8
|
-
test_ai_create_task_with_attributes
|
9
|
-
test_ai_list_tasks_in_notebook
|
10
|
-
test_ai_export_done_tasks
|
11
|
-
test_ai_export_done_tasks_to_csv
|
12
|
-
test_ai_export_done_tasks_with_custom_filename
|
13
|
-
test_ai_export_in_progress_tasks
|
14
|
-
test_ai_export_todo_tasks
|
15
|
-
test_ai_export_archived_tasks
|
16
|
-
test_ai_export_tasks_with_status
|
17
|
-
test_ai_export_tasks_to_different_formats
|
18
|
-
test_ai_conversational_export_requests
|
19
|
-
test_ai_export_with_different_status_formats
|
20
|
-
test_ai_export_nonexistent_status
|
21
|
-
test_ai_export_with_custom_parameters
|
22
|
-
test_ai_list_tasks_with_in_progress_status
|
23
|
-
test_ai_show_in_progress_tasks_alternative_phrasing
|
24
|
-
test_ai_list_tasks_with_status_in_progress
|
25
|
-
test_ai_list_tasks_with_todo_status
|
26
|
-
test_ai_show_todo_tasks_alternative_phrasing
|
27
|
-
test_ai_statistics_request
|
28
|
-
test_ai_batch_task_update_by_tag
|
29
|
-
test_ai_batch_task_update_by_keyword
|
30
|
-
test_ai_multiple_specific_task_update
|
31
|
-
test_ai_empty_prompt
|
32
|
-
test_ai_invalid_api_key
|
33
|
-
test_ai_nonexistent_notebook
|
34
|
-
test_ai_invalid_task_id
|
35
|
-
test_ai_invalid_status
|
36
|
-
test_ai_task_with_invalid_attributes
|
37
|
-
test_ai_export_with_no_done_tasks
|
38
|
-
test_ai_ambiguous_notebook_reference
|
39
|
-
test_ai_complex_task_creation_with_natural_language
|
40
|
-
test_ai_conversational_request_for_notebook_contents
|
41
|
-
test_ai_date_based_export_request
|
42
|
-
test_ai_task_movement_with_natural_language
|
43
|
-
test_ai_natural_language_task_creation
|
44
|
-
test_ai_task_list
|
45
|
-
test_notebook_commands_with_explicit_methods
|
46
|
-
test_template_commands_with_explicit_methods
|
47
|
-
test_ai_list_tasks_with_in_progress_hyphenated
|
48
|
-
test_ai_show_tasks_having_in_progress_status
|
49
|
-
test_ai_display_in_progress_status_tasks
|
50
|
-
test_ai_list_tasks_that_are_in_todo_status
|
51
|
-
test_ai_display_tasks_that_are_in_progress
|
52
|
-
test_ai_create_multiple_infrastructure_tasks
|
53
|
-
test_ai_handle_multiple_requests_in_one_prompt
|
54
|
-
test_ai_never_uses_normal_priority
|
55
|
-
test_ai_sets_medium_priority_by_default
|
56
|
-
test_ai_create_default_notebook_for_task
|
57
|
-
test_ai_default_notebook_remains_when_adding_new_notebook
|
58
|
-
test_ai_handles_both_normal_and_medium_terms
|
59
|
-
test_ai_explicit_default_notebook_commands
|