ruby_todo 1.0.9 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dae18c7aa5f0c69b22d8322958d2bb91dfb44eb69633f0c5f720daa5e10e7dfd
4
- data.tar.gz: f5fcb64983a413d618d4a878d10545d5e7c161387431d71d3a6dc0560a52f262
3
+ metadata.gz: 1ba44da4ec50889bd3ad526d25b43b8157093215303b25874a7038c2d76b1b1d
4
+ data.tar.gz: eed6527b7f09388a8ad7abae9563f409e497ac06858bc0f39d4c92186cb9902a
5
5
  SHA512:
6
- metadata.gz: e3865f71aa4da7b42cecc475b383013f92b6981dbd1c61529b2c4932e6528c3f2a359290f7ee06f34db4c1e3623540158dc1797c675cf36d75f99819ace4af12
7
- data.tar.gz: 8d5a54bfe135dbdb8fe20087db97f779375481954cf7b7bb1f5c380216cd69936c486c95e79ccbf41f1601622fde7eeb23b3e6a10e98783cc5f16ccda7f0f86a
6
+ metadata.gz: b5deb1f7d58a8cb0bd3de5d96ec1bd03fe71f3b0e0c3b3c88f2ade4ce0d980c650cc691e897f63100d6ce83415f364aef436cf8d5d07a747982d0cf8a4afa68f
7
+ data.tar.gz: 75d18f85223d81795a229bbdca14cfe54d0a8b3536610dbc72e0fba91fb24cbc178d5423211255aedb5296211e3f92c7a89e5524dc40c4bd2545fa4dc78b191a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## [1.0.11] - 2025-04-01
2
+
3
+ * Manual release
4
+
5
+
6
+ ## [1.0.10] - 2025-03-31
7
+
8
+ * Manual release
9
+
10
+
1
11
  ## [1.0.9] - 2025-03-31
2
12
 
3
13
  * Manual release
@@ -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
@@ -83,8 +83,12 @@ module RubyTodo
83
83
  - "fix login bug" → "Resolve Authentication Issue in Login System"
84
84
  - "add monitoring to service" → "Implement Comprehensive Monitoring Solution for Service"
85
85
  - "migrate repo to new org" → "Migrate Repository to New Organization Structure"
86
+ - "add newrelic to the questions engine app" → "Integrate New Relic Monitoring with Questions Engine Application"
87
+ - "create a new task to add newrelic to the questions engine app" → "Implement New Relic Monitoring for Questions Engine Application"
86
88
 
87
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).
88
92
  PROMPT
89
93
 
90
94
  messages = [
@@ -143,11 +147,27 @@ module RubyTodo
143
147
  {
144
148
  "title" => title_match ? title_match[1] : "Task from #{task_description}",
145
149
  "description" => desc_match ? desc_match[1] : task_description,
146
- "priority" => priority_match ? priority_match[1] : "medium",
150
+ "priority" => priority_match ? normalize_priority(priority_match[1]) : "medium",
147
151
  "tags" => tags_match ? tags_match[1] : ""
148
152
  }
149
153
  end
150
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
+
151
171
  # Create a task from the generated details
152
172
  def create_task_from_details(notebook_name, task_details)
153
173
  # Ensure we have a valid notebook
@@ -175,6 +195,9 @@ module RubyTodo
175
195
  say "✨ Enhanced title: \"#{task_details["title"]}\"", :green
176
196
  end
177
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
+
178
201
  args = ["task:add", notebook_name, task_details["title"]]
179
202
  args << "--description" << task_details["description"] if task_details["description"]
180
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"
@@ -837,9 +987,10 @@ module RubyTodo
837
987
  # Create a CLI instance for executing commands
838
988
  cli = RubyTodo::CLI.new
839
989
 
840
- # Special case: handling natural language task creation
990
+ # Special case: handling natural language task creation with title enhancement
841
991
  if prompt.match?(/create(?:\s+a)?\s+(?:new\s+)?task\s+(?:to|for|about)\s+(.+)/i)
842
- handle_natural_language_task_creation(prompt, api_key)
992
+ task_description = prompt.match(/create(?:\s+a)?\s+(?:new\s+)?task\s+(?:to|for|about)\s+(.+)/i)[1].strip
993
+ handle_task_creation_with_enhancement(task_description, api_key)
843
994
  return
844
995
  end
845
996
 
@@ -878,6 +1029,7 @@ module RubyTodo
878
1029
  return true if handle_documentation_task_specific_patterns(prompt)
879
1030
  return true if handle_task_creation_patterns(prompt, cli)
880
1031
  return true if handle_task_status_patterns(prompt)
1032
+ return true if handle_move_task_by_title(prompt, cli)
881
1033
  return true if handle_export_task_patterns(prompt)
882
1034
  return true if handle_notebook_operations(prompt, cli)
883
1035
  return true if handle_task_operations(prompt, cli)
@@ -1688,6 +1840,26 @@ module RubyTodo
1688
1840
  end
1689
1841
  end
1690
1842
 
1843
+ # Enhanced task creation that uses AI to improve titles
1844
+ def handle_task_creation_with_enhancement(task_description, api_key)
1845
+ # Get the default notebook
1846
+ notebook_name = default_notebook_name
1847
+
1848
+ # Log the original description if in verbose mode
1849
+ say "Original task description: #{task_description}" if @options[:verbose]
1850
+
1851
+ # Generate task details using AI
1852
+ task_details = generate_task_details(task_description, api_key)
1853
+
1854
+ # Log the enhanced title for better UX
1855
+ if task_details["title"] && task_details["title"] != task_description
1856
+ say "✨ Enhanced title: \"#{task_details["title"]}\"".green
1857
+ end
1858
+
1859
+ # Create the task with the enhanced details
1860
+ create_task_from_details(notebook_name, task_details)
1861
+ end
1862
+
1691
1863
  def handle_natural_language_task_creation(prompt, _api_key)
1692
1864
  # Make sure Ruby Todo is initialized
1693
1865
  initialize_ruby_todo
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyTodo
4
- VERSION = "1.0.9"
4
+ VERSION = "1.0.11"
5
5
  end
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.9
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-03-31 00:00:00.000000000 Z
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