Class: Ace::Idea::Organisms::IdeaManager
- Inherits:
-
Object
- Object
- Ace::Idea::Organisms::IdeaManager
- Defined in:
- lib/ace/idea/organisms/idea_manager.rb
Overview
Orchestrates all idea CRUD operations. Entry point for idea management with config-driven root directory.
Defined Under Namespace
Classes: CreateRetriesExhaustedError
Constant Summary collapse
- CREATE_RETRY_LIMIT =
3
Instance Attribute Summary collapse
-
#last_folder_counts ⇒ Object
readonly
Returns the value of attribute last_folder_counts.
-
#last_list_total ⇒ Object
readonly
Returns the value of attribute last_list_total.
-
#root_dir ⇒ String
readonly
Get the root directory.
Instance Method Summary collapse
-
#create(content = nil, title: nil, tags: [], move_to: nil, clipboard: false, llm_enhance: false) ⇒ Idea
Create a new idea.
-
#create_from_clipboard(llm_enhance: false, move_to: nil) ⇒ Idea
Create an idea from clipboard.
-
#initialize(root_dir: nil, config: nil) ⇒ IdeaManager
constructor
A new instance of IdeaManager.
-
#list(status: nil, in_folder: "next", tags: [], root: nil, filters: nil) ⇒ Array<Idea>
List ideas with optional filtering.
-
#show(ref) ⇒ Idea?
Show (load) a single idea by reference.
-
#update(ref, set: {}, add: {}, remove: {}, move_to: nil) ⇒ Idea?
Update an idea’s fields and optionally move to a folder.
Constructor Details
#initialize(root_dir: nil, config: nil) ⇒ IdeaManager
Returns a new instance of IdeaManager.
25 26 27 28 |
# File 'lib/ace/idea/organisms/idea_manager.rb', line 25 def initialize(root_dir: nil, config: nil) @config = config || load_config @root_dir = root_dir || resolve_root_dir end |
Instance Attribute Details
#last_folder_counts ⇒ Object (readonly)
Returns the value of attribute last_folder_counts.
21 22 23 |
# File 'lib/ace/idea/organisms/idea_manager.rb', line 21 def last_folder_counts @last_folder_counts end |
#last_list_total ⇒ Object (readonly)
Returns the value of attribute last_list_total.
21 22 23 |
# File 'lib/ace/idea/organisms/idea_manager.rb', line 21 def last_list_total @last_list_total end |
#root_dir ⇒ String (readonly)
Get the root directory
175 176 177 |
# File 'lib/ace/idea/organisms/idea_manager.rb', line 175 def root_dir @root_dir end |
Instance Method Details
#create(content = nil, title: nil, tags: [], move_to: nil, clipboard: false, llm_enhance: false) ⇒ Idea
Create a new idea
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/ace/idea/organisms/idea_manager.rb', line 38 def create(content = nil, title: nil, tags: [], move_to: nil, clipboard: false, llm_enhance: false) ensure_root_dir creator = Molecules::IdeaCreator.new(root_dir: @root_dir, config: @config) prepared_payload = creator.prepare_create_payload( content, clipboard: clipboard, llm_enhance: llm_enhance ) attempts = 0 begin attempts += 1 creator.create( nil, title: title, tags: , move_to: move_to, clipboard: false, llm_enhance: false, time: Time.now.utc + ((attempts - 1) * 2), prepared_payload: prepared_payload ) rescue Molecules::IdeaCreator::IdCollisionError retry if attempts < CREATE_RETRY_LIMIT raise CreateRetriesExhaustedError, "Failed to create idea: unable to generate a unique ID after #{CREATE_RETRY_LIMIT} attempts" end end |
#create_from_clipboard(llm_enhance: false, move_to: nil) ⇒ Idea
Create an idea from clipboard
72 73 74 |
# File 'lib/ace/idea/organisms/idea_manager.rb', line 72 def create_from_clipboard(llm_enhance: false, move_to: nil) create(nil, clipboard: true, llm_enhance: llm_enhance, move_to: move_to) end |
#list(status: nil, in_folder: "next", tags: [], root: nil, filters: nil) ⇒ Array<Idea>
List ideas with optional filtering
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/ace/idea/organisms/idea_manager.rb', line 97 def list(status: nil, in_folder: "next", tags: [], root: nil, filters: nil) scan_root = if root candidate = File.(File.join(@root_dir, root)) root_real = File.(@root_dir) unless candidate.start_with?(root_real + File::SEPARATOR) || candidate == root_real raise ArgumentError, "Path traversal detected in --root option" end candidate else @root_dir end scanner = Molecules::IdeaScanner.new(scan_root) scan_results = scanner.scan_in_folder(in_folder) @last_list_total = scanner.last_scan_total @last_folder_counts = scanner.last_folder_counts loader = Molecules::IdeaLoader.new ideas = scan_results.filter_map do |sr| loader.load(sr.dir_path, id: sr.id, special_folder: sr.special_folder) end # Apply legacy filters (backward-compatible) ideas = ideas.select { |i| i.status == status } if status ideas = (ideas, ) if .any? # Apply generic --filter specs via FilterApplier if filters && !filters.empty? filter_specs = Ace::Support::Items::Atoms::FilterParser.parse(filters) ideas = Ace::Support::Items::Molecules::FilterApplier.apply(ideas, filter_specs, value_accessor: method(:idea_value_accessor)) end ideas end |
#show(ref) ⇒ Idea?
Show (load) a single idea by reference
79 80 81 82 83 84 85 86 87 88 |
# File 'lib/ace/idea/organisms/idea_manager.rb', line 79 def show(ref) resolver = Molecules::IdeaResolver.new(@root_dir) scan_result = resolver.resolve(ref) return nil unless scan_result loader = Molecules::IdeaLoader.new loader.load(scan_result.dir_path, id: scan_result.id, special_folder: scan_result.special_folder) end |
#update(ref, set: {}, add: {}, remove: {}, move_to: nil) ⇒ Idea?
Update an idea’s fields and optionally move to a folder.
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/ace/idea/organisms/idea_manager.rb', line 138 def update(ref, set: {}, add: {}, remove: {}, move_to: nil) scan_result = resolve_scan_result(ref) return nil unless scan_result loader = Molecules::IdeaLoader.new idea = loader.load(scan_result.dir_path, id: scan_result.id, special_folder: scan_result.special_folder) return nil unless idea # Apply field updates if any has_field_updates = [set, add, remove].any? { |h| h && !h.empty? } update_idea_file(idea, set: set, add: add, remove: remove) if has_field_updates # Apply move if requested current_path = idea.path current_special = idea.special_folder if move_to mover = Molecules::IdeaMover.new(@root_dir) new_path = if Ace::Support::Items::Atoms::SpecialFolderDetector.move_to_root?(move_to) mover.move_to_root(idea) else archive_date = parse_archive_date(idea) mover.move(idea, to: move_to, date: archive_date) end current_path = new_path current_special = Ace::Support::Items::Atoms::SpecialFolderDetector.detect_in_path( new_path, root: @root_dir ) end # Reload and return updated idea loader.load(current_path, id: idea.id, special_folder: current_special) end |