Class: RailsConsoleAi::Agent
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- RailsConsoleAi::Agent
- Defined in:
- app/models/rails_console_ai/agent.rb
Constant Summary collapse
- STATUS_PROPOSED =
'proposed'.freeze
- STATUS_APPROVED =
'approved'.freeze
- STATUSES =
[STATUS_PROPOSED, STATUS_APPROVED].freeze
- CONTENT_ATTRIBUTES =
Attributes that, if changed, invalidate the current approval and revert the agent back to “proposed”. Status / approver columns are excluded so that an explicit approve! call doesn’t reset its own approval.
%w[name description body max_rounds model tools].freeze
Class Method Summary collapse
- .connection ⇒ Object
- .decode_json_array(raw) ⇒ Object
- .encode_json_array(value) ⇒ Object
- .record_use!(id) ⇒ Object
Instance Method Summary collapse
- #approve!(approved_by:) ⇒ Object
- #approved? ⇒ Boolean
- #approved_at ⇒ Object
- #approved_by ⇒ Object
- #decode_json_array(raw) ⇒ Object
- #encode_json_array(value) ⇒ Object
- #has_attribute_status? ⇒ Boolean
- #last_used_at ⇒ Object
- #proposed? ⇒ Boolean
-
#status ⇒ Object
Defensive accessors — if ‘ai_db_migrate` hasn’t been run yet, the status / approval columns may be missing on an older table.
- #to_hash ⇒ Object
-
#tools ⇒ Object
Manual JSON accessor for ‘tools` — same approach we use for skill tags, avoids Rails-version-specific `serialize` API.
- #tools=(value) ⇒ Object
-
#update_with_version!(attrs, edited_by: nil, change_note: nil, preserve_approval: false) ⇒ Object
Assigns attrs, saves, and records one AgentVersion snapshot of the post-save state.
- #use_count ⇒ Object
Class Method Details
.connection ⇒ Object
29 30 31 32 33 34 35 36 37 |
# File 'app/models/rails_console_ai/agent.rb', line 29 def self.connection klass = RailsConsoleAi.configuration.connection_class if klass klass = Object.const_get(klass) if klass.is_a?(String) klass.connection else super end end |
.decode_json_array(raw) ⇒ Object
109 110 111 112 113 114 115 |
# File 'app/models/rails_console_ai/agent.rb', line 109 def self.decode_json_array(raw) return [] if raw.nil? || (raw.respond_to?(:empty?) && raw.empty?) return raw if raw.is_a?(Array) JSON.parse(raw) rescue JSON::ParserError [] end |
.encode_json_array(value) ⇒ Object
117 118 119 |
# File 'app/models/rails_console_ai/agent.rb', line 117 def self.encode_json_array(value) JSON.dump(Array(value)) end |
.record_use!(id) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 |
# File 'app/models/rails_console_ai/agent.rb', line 74 def self.record_use!(id) return false unless connection.column_exists?(table_name, :use_count) where(id: id).update_all([ 'use_count = COALESCE(use_count, 0) + 1, last_used_at = ?', Time.now.utc ]) true rescue ::ActiveRecord::ActiveRecordError => e RailsConsoleAi.logger.warn("RailsConsoleAi::Agent.record_use!(#{id.inspect}) failed: #{e.}") false end |
Instance Method Details
#approve!(approved_by:) ⇒ Object
154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'app/models/rails_console_ai/agent.rb', line 154 def approve!(approved_by:) raise ArgumentError, 'approved_by is required' if approved_by.to_s.strip.empty? update_with_version!( { status: STATUS_APPROVED, approved_by: approved_by, approved_at: Time.now.utc }, edited_by: approved_by, change_note: "Approved by #{approved_by}", preserve_approval: true ) end |
#approved? ⇒ Boolean
64 |
# File 'app/models/rails_console_ai/agent.rb', line 64 def approved?; status.to_s == STATUS_APPROVED; end |
#approved_at ⇒ Object
59 60 61 |
# File 'app/models/rails_console_ai/agent.rb', line 59 def approved_at has_attribute?(:approved_at) ? read_attribute(:approved_at) : nil end |
#approved_by ⇒ Object
55 56 57 |
# File 'app/models/rails_console_ai/agent.rb', line 55 def approved_by has_attribute?(:approved_by) ? read_attribute(:approved_by) : nil end |
#decode_json_array(raw) ⇒ Object
121 |
# File 'app/models/rails_console_ai/agent.rb', line 121 def decode_json_array(raw); self.class.decode_json_array(raw); end |
#encode_json_array(value) ⇒ Object
122 |
# File 'app/models/rails_console_ai/agent.rb', line 122 def encode_json_array(value); self.class.encode_json_array(value); end |
#has_attribute_status? ⇒ Boolean
105 106 107 |
# File 'app/models/rails_console_ai/agent.rb', line 105 def has_attribute_status? has_attribute?(:status) end |
#last_used_at ⇒ Object
70 71 72 |
# File 'app/models/rails_console_ai/agent.rb', line 70 def last_used_at has_attribute?(:last_used_at) ? read_attribute(:last_used_at) : nil end |
#proposed? ⇒ Boolean
63 |
# File 'app/models/rails_console_ai/agent.rb', line 63 def proposed?; status.to_s == STATUS_PROPOSED; end |
#status ⇒ Object
Defensive accessors — if ‘ai_db_migrate` hasn’t been run yet, the status / approval columns may be missing on an older table.
51 52 53 |
# File 'app/models/rails_console_ai/agent.rb', line 51 def status has_attribute_status? ? read_attribute(:status) : STATUS_PROPOSED end |
#to_hash ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'app/models/rails_console_ai/agent.rb', line 86 def to_hash { 'id' => id, 'name' => name, 'description' => description, 'body' => body, 'max_rounds' => max_rounds, 'model' => model, 'tools' => tools, 'status' => status, 'approved_by' => approved_by, 'approved_at' => approved_at, 'use_count' => use_count, 'last_used_at' => last_used_at, 'source' => :db, 'updated_at' => updated_at } end |
#tools ⇒ Object
Manual JSON accessor for ‘tools` — same approach we use for skill tags, avoids Rails-version-specific `serialize` API.
41 42 43 |
# File 'app/models/rails_console_ai/agent.rb', line 41 def tools decode_json_array(read_attribute(:tools)) end |
#tools=(value) ⇒ Object
45 46 47 |
# File 'app/models/rails_console_ai/agent.rb', line 45 def tools=(value) write_attribute(:tools, encode_json_array(value)) end |
#update_with_version!(attrs, edited_by: nil, change_note: nil, preserve_approval: false) ⇒ Object
Assigns attrs, saves, and records one AgentVersion snapshot of the post-save state. If ‘preserve_approval` is false (the default), any change to a content attribute reverts the agent back to “proposed” and clears the approver.
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'app/models/rails_console_ai/agent.rb', line 127 def update_with_version!(attrs, edited_by: nil, change_note: nil, preserve_approval: false) transaction do assign_attributes(attrs) if !preserve_approval && approved? && content_dirty? self.status = STATUS_PROPOSED self.approved_by = nil self.approved_at = nil end save! RailsConsoleAi::AgentVersion.create!( agent_id: id, name: name, description: description, body: body, max_rounds: max_rounds, model: model, tools: tools, status: status, edited_by: edited_by, change_note: change_note ) end self end |
#use_count ⇒ Object
66 67 68 |
# File 'app/models/rails_console_ai/agent.rb', line 66 def use_count has_attribute?(:use_count) ? (read_attribute(:use_count) || 0) : 0 end |