meta_workflows 0.7.0

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.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +36 -0
  3. data/README.md +498 -0
  4. data/Rakefile +10 -0
  5. data/app/assets/javascripts/meta_workflows/controllers/loading_phrases_controller.js +31 -0
  6. data/app/assets/javascripts/meta_workflows/controllers/redirect_controller.js +15 -0
  7. data/app/assets/javascripts/meta_workflows/controllers/response_scroll_controller.js +67 -0
  8. data/app/assets/javascripts/meta_workflows_manifest.js +13 -0
  9. data/app/assets/stylesheets/meta_workflows/application.css +161 -0
  10. data/app/controllers/meta_workflows/application_controller.rb +10 -0
  11. data/app/controllers/meta_workflows/debug_controller.rb +101 -0
  12. data/app/controllers/meta_workflows/humans_controller.rb +96 -0
  13. data/app/controllers/meta_workflows/meta_controller.rb +21 -0
  14. data/app/helpers/meta_workflows/application_helper.rb +7 -0
  15. data/app/helpers/meta_workflows/debug_helper.rb +54 -0
  16. data/app/helpers/meta_workflows/execution_helper.rb +77 -0
  17. data/app/helpers/meta_workflows/formatting_helper.rb +30 -0
  18. data/app/helpers/meta_workflows/meta_workflows_helper.rb +41 -0
  19. data/app/helpers/meta_workflows/status_badge_helper.rb +66 -0
  20. data/app/jobs/meta_workflows/application_job.rb +14 -0
  21. data/app/jobs/meta_workflows/human_input_job.rb +35 -0
  22. data/app/jobs/meta_workflows/meta_job.rb +121 -0
  23. data/app/jobs/meta_workflows/meta_workflow_job.rb +20 -0
  24. data/app/jobs/meta_workflows/record_redirect_job.rb +36 -0
  25. data/app/mailers/meta_workflows/application_mailer.rb +8 -0
  26. data/app/models/meta_workflows/application_record.rb +7 -0
  27. data/app/models/meta_workflows/chat.rb +20 -0
  28. data/app/models/meta_workflows/message.rb +11 -0
  29. data/app/models/meta_workflows/tool_call.rb +7 -0
  30. data/app/models/meta_workflows/workflow.rb +32 -0
  31. data/app/models/meta_workflows/workflow_execution.rb +23 -0
  32. data/app/models/meta_workflows/workflow_step.rb +49 -0
  33. data/app/models/meta_workflows.rb +7 -0
  34. data/app/services/meta_workflows/execution_filter_service.rb +80 -0
  35. data/app/sidekiq/meta_workflows/tools/meta_workflow_tool.rb +86 -0
  36. data/app/views/layouts/meta_workflows/application.html.erb +17 -0
  37. data/app/views/layouts/meta_workflows/debug.html.erb +47 -0
  38. data/app/views/meta_workflows/_loader.html.erb +22 -0
  39. data/app/views/meta_workflows/_redirect.html.erb +1 -0
  40. data/app/views/meta_workflows/_response.html.erb +5 -0
  41. data/app/views/meta_workflows/_response_form.html.erb +36 -0
  42. data/app/views/meta_workflows/debug/executions.html.erb +187 -0
  43. data/app/views/meta_workflows/debug/show_execution.html.erb +283 -0
  44. data/app/views/meta_workflows/debug/show_workflow.html.erb +148 -0
  45. data/app/views/meta_workflows/debug/workflows.html.erb +110 -0
  46. data/config/routes.rb +13 -0
  47. data/db/migrate/20250530220618_create_meta_workflows_workflows.rb +16 -0
  48. data/db/migrate/20250530220634_create_meta_workflows_workflow_executions.rb +18 -0
  49. data/db/migrate/20250530220704_create_meta_workflows_chats.rb +16 -0
  50. data/db/migrate/20250530220722_create_meta_workflows_messages.rb +19 -0
  51. data/db/migrate/20250530220737_create_meta_workflows_tool_calls.rb +18 -0
  52. data/db/migrate/20250530220750_create_meta_workflows_workflow_steps.rb +17 -0
  53. data/db/migrate/20250613213159_add_error_fields_to_workflow_steps.rb +8 -0
  54. data/lib/meta_workflows/asset_installer.rb +509 -0
  55. data/lib/meta_workflows/configuration.rb +39 -0
  56. data/lib/meta_workflows/engine.rb +47 -0
  57. data/lib/meta_workflows/export_execution_service.rb +56 -0
  58. data/lib/meta_workflows/version.rb +5 -0
  59. data/lib/meta_workflows.rb +9 -0
  60. data/lib/services/meta_workflows/application_service.rb +11 -0
  61. data/lib/services/meta_workflows/meta_workflow_service.rb +277 -0
  62. data/lib/services/meta_workflows/updaters/meta_service.rb +39 -0
  63. data/lib/tasks/meta_workflows_tasks.rake +153 -0
  64. metadata +219 -0
@@ -0,0 +1,277 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Services
4
+ module MetaWorkflows
5
+ class MetaWorkflowService
6
+ ACTIONS_WITHOUT_CONVERSATION = %w[record_redirect collection_create record_update].freeze
7
+
8
+ attr_reader :record, :workflow_name, :user, :inputs, :workflow_params
9
+
10
+ # TODO: inputs should be a an empty hash by default
11
+ # Once everything is working we can change the default value from nil to {}
12
+ def initialize(record:, workflow_name: nil, user: nil, inputs: nil, workflow_params: nil)
13
+ @record = record
14
+ @workflow_name = workflow_name
15
+ @user = user
16
+ @inputs = inputs
17
+ @workflow_params = workflow_params
18
+ end
19
+
20
+ def call
21
+ validate_workflow_presence
22
+
23
+ workflow, workflow_execution = find_or_create_workflow_execution
24
+ execution_step, execution_output, workflow_step = prepare_workflow_execution(workflow, workflow_execution)
25
+
26
+ if ACTIONS_WITHOUT_CONVERSATION.include?(execution_step['action'])
27
+ process_action(execution_step, nil, workflow_execution, workflow)
28
+ else
29
+ chat = create_and_configure_chat(workflow_step)
30
+ conversation = create_and_configure_conversation(chat, workflow_execution, execution_output, execution_step)
31
+ process_action(execution_step, conversation, workflow_execution, workflow)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def process_action(execution_step, conversation, workflow_execution, workflow)
38
+ case execution_step['action']
39
+ when 'agent'
40
+ process_agent_action(conversation, workflow_execution, workflow)
41
+ when 'human'
42
+ process_human_action(execution_step, workflow_execution)
43
+ when 'record_redirect'
44
+ process_record_redirect_action(workflow_execution, workflow)
45
+ when 'collection_create'
46
+ process_collection_create_action(execution_step, workflow_execution, workflow)
47
+ when 'record_update'
48
+ process_record_update_action(execution_step, workflow_execution, workflow)
49
+ else
50
+ raise ArgumentError, "The action #{execution_step['action']} does not exist"
51
+ end
52
+ end
53
+
54
+ def process_agent_action(conversation, workflow_execution, workflow)
55
+ workflow_step = find_workflow_step(workflow_execution)
56
+
57
+ begin
58
+ clear_previous_errors(workflow_step)
59
+ execute_llm_call(conversation, workflow_execution)
60
+ handle_workflow_continuation(workflow_execution, workflow, conversation)
61
+ rescue StandardError => e
62
+ handle_agent_error(e, workflow_step, workflow, workflow_execution)
63
+ raise
64
+ end
65
+ end
66
+
67
+ def find_workflow_step(workflow_execution)
68
+ workflow_execution.workflow_steps.find_by(step: workflow_execution.current_step)
69
+ end
70
+
71
+ def clear_previous_errors(workflow_step)
72
+ workflow_step&.clear_error if workflow_step&.error?
73
+ end
74
+
75
+ def execute_llm_call(conversation, workflow_execution)
76
+ conversation.call_llm
77
+ workflow_execution.increment_step
78
+ end
79
+
80
+ def handle_workflow_continuation(workflow_execution, workflow, conversation)
81
+ new_inputs = extract_tool_call_inputs(conversation)
82
+
83
+ if workflow_execution.current_step < workflow.total_steps
84
+ schedule_next_workflow_step_with_inputs(new_inputs)
85
+ else
86
+ workflow_execution.update(completed: true)
87
+ end
88
+ end
89
+
90
+ def schedule_next_workflow_step_with_inputs(new_inputs)
91
+ ::MetaWorkflows::MetaWorkflowJob.perform_later(
92
+ record_id: record.id,
93
+ record_type: record.class.name,
94
+ workflow_name: nil,
95
+ user_id: user&.id,
96
+ inputs: new_inputs
97
+ )
98
+ end
99
+
100
+ def handle_agent_error(error, workflow_step, workflow, workflow_execution)
101
+ Rails.logger.error("LLM Error in MetaWorkflowService: #{error.message}")
102
+ Rails.logger.error(error.backtrace.join("\n"))
103
+
104
+ record_error_details(error, workflow_step, workflow, workflow_execution) if workflow_step
105
+ end
106
+
107
+ def record_error_details(error, workflow_step, workflow, workflow_execution)
108
+ workflow_step.record_error(error, additional_details: {
109
+ service_class: self.class.name,
110
+ workflow_id: workflow.id,
111
+ workflow_name: workflow.name,
112
+ current_step: workflow_execution.current_step,
113
+ record_type: record.class.name,
114
+ record_id: record.id
115
+ })
116
+ end
117
+
118
+ def process_human_action(execution_step, workflow_execution)
119
+ ::MetaWorkflows::HumanInputJob.perform_later(
120
+ user_id: user&.id,
121
+ record: workflow_execution.record,
122
+ params: {
123
+ inputs: inputs,
124
+ prompt_id: execution_step['prompt_id']
125
+ }
126
+ )
127
+ # the step advancement is handled in the human input job
128
+ end
129
+
130
+ def process_record_redirect_action(workflow_execution, workflow)
131
+ ::MetaWorkflows::RecordRedirectJob.perform_later(workflow_execution: workflow_execution)
132
+ workflow_execution.increment_step
133
+
134
+ return unless workflow_execution.current_step >= workflow.total_steps
135
+
136
+ workflow_execution.update(completed: true)
137
+ end
138
+
139
+ def process_collection_create_action(execution_step, workflow_execution, workflow)
140
+ service = build_collection_service(execution_step, workflow_execution)
141
+
142
+ begin
143
+ service.call
144
+ workflow_execution.increment_step
145
+ continue_workflow(workflow_execution, workflow)
146
+ rescue StandardError => e
147
+ Rails.logger.error("Error creating collection: #{e.message}")
148
+ # The workflow should halt on error per requirements - do not increment step
149
+ end
150
+ end
151
+
152
+ def process_record_update_action(execution_step, workflow_execution, workflow)
153
+ service = build_record_update_service(execution_step, workflow_execution)
154
+
155
+ begin
156
+ service.call
157
+ workflow_execution.increment_step
158
+ continue_workflow(workflow_execution, workflow)
159
+ rescue StandardError => e
160
+ Rails.logger.error("Error updating record: #{e.message}")
161
+ # Let Sidekiq handle retry - reraise the error
162
+ raise
163
+ end
164
+ end
165
+
166
+ def build_collection_service(execution_step, workflow_execution)
167
+ service_class_name = execution_step['collection_creator']
168
+ service_class = service_class_name.safe_constantize
169
+
170
+ raise ArgumentError, "Invalid collection creator class: #{service_class_name}" unless service_class
171
+
172
+ parent_record = find_parent_record(workflow_execution)
173
+
174
+ service_class.new(
175
+ parent_record: parent_record,
176
+ collection: inputs[:collection]
177
+ )
178
+ end
179
+
180
+ def build_record_update_service(execution_step, workflow_execution)
181
+ service_class_name = execution_step['record_updater']
182
+ service_class = service_class_name.safe_constantize
183
+
184
+ raise ArgumentError, "Invalid record updater class: #{service_class_name}" unless service_class
185
+
186
+ target_record = find_parent_record(workflow_execution)
187
+ attributes_to_update = execution_step['attributes_to_update']
188
+
189
+ service_class.new(target_record, attributes_to_update, workflow_execution.workflow_params)
190
+ end
191
+
192
+ def find_parent_record(workflow_execution)
193
+ record_class = workflow_execution.record.class.name.constantize
194
+ record_class.find(workflow_execution.workflow_params['record_id'])
195
+ end
196
+
197
+ def continue_workflow(workflow_execution, workflow)
198
+ if workflow_execution.current_step < workflow.total_steps
199
+ schedule_next_workflow_step
200
+ else
201
+ workflow_execution.update(completed: true)
202
+ end
203
+ end
204
+
205
+ def schedule_next_workflow_step
206
+ ::MetaWorkflows::MetaWorkflowJob.perform_later(
207
+ record_id: record.id,
208
+ record_type: record.class.name,
209
+ workflow_name: nil,
210
+ user_id: user&.id,
211
+ inputs: {}
212
+ )
213
+ end
214
+
215
+ def create_and_configure_conversation(chat, workflow_execution, execution_output, execution_step)
216
+ conversation = RubyConversations::Conversation.new(chat: chat)
217
+ conversation.tool = ::MetaWorkflows::Tools::MetaWorkflowTool.build(workflow_execution, execution_output)
218
+ conversation.with_prompt(
219
+ execution_step['prompt_id'],
220
+ inputs: inputs,
221
+ description: "Executing step #{workflow_execution.current_step} of " \
222
+ "workflow #{workflow_execution.workflow.name}"
223
+ )
224
+ conversation
225
+ end
226
+
227
+ def create_and_configure_chat(workflow_step)
228
+ workflow_step.chat = ::MetaWorkflows::Chat.new(model_id: RubyConversations.configuration.default_llm_model,
229
+ provider: RubyConversations.configuration.default_llm_provider)
230
+ chat = workflow_step.chat
231
+ chat.user = @user
232
+ chat.save!
233
+ workflow_step.save!
234
+ chat
235
+ end
236
+
237
+ def validate_workflow_presence
238
+ return unless workflow_name.nil? && record.workflow_execution.blank?
239
+
240
+ raise ArgumentError, 'No workflow specified and record has no workflow attached'
241
+ end
242
+
243
+ def find_or_create_workflow_execution
244
+ if workflow_name.present?
245
+ workflow = ::MetaWorkflows::Workflow.find_by(name: workflow_name)
246
+ workflow_execution = ::MetaWorkflows::WorkflowExecution.create(
247
+ record: record,
248
+ workflow: workflow,
249
+ current_step: 0,
250
+ completed: false,
251
+ workflow_params: workflow_params
252
+ )
253
+ else
254
+ workflow_execution = record.workflow_execution
255
+ workflow = workflow_execution.workflow
256
+ end
257
+
258
+ [workflow, workflow_execution]
259
+ end
260
+
261
+ def prepare_workflow_execution(workflow, workflow_execution)
262
+ execution_step = workflow.step_data(workflow_execution.current_step)
263
+ execution_output = workflow.step_output(workflow_execution.current_step)
264
+ workflow_step = workflow_execution.workflow_steps.find_or_create_by(step: workflow_execution.current_step)
265
+
266
+ [execution_step, execution_output, workflow_step]
267
+ end
268
+
269
+ def extract_tool_call_inputs(conversation)
270
+ # the tool call is always the next to last message in the conversation
271
+ tool_call_id = JSON.parse(conversation.messages.first.response)[-2]['tool_call_id']
272
+ tool_call = ::MetaWorkflows::ToolCall.find(tool_call_id)
273
+ tool_call.arguments.deep_symbolize_keys
274
+ end
275
+ end
276
+ end
277
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Services
4
+ module MetaWorkflows
5
+ module Updaters
6
+ class MetaService < Services::MetaWorkflows::ApplicationService
7
+ attr_reader :record, :attributes_to_update, :workflow_params
8
+
9
+ def initialize(record, attributes_to_update, workflow_params)
10
+ super()
11
+ @record = record
12
+ @attributes_to_update = attributes_to_update
13
+ @workflow_params = workflow_params
14
+ end
15
+
16
+ def call
17
+ update_attributes = build_update_attributes
18
+ record.update!(update_attributes)
19
+ record
20
+ end
21
+
22
+ private
23
+
24
+ def build_update_attributes
25
+ attributes_hash = {}
26
+
27
+ attributes_to_update.each do |attribute_name|
28
+ param_value = workflow_params[attribute_name] || workflow_params[attribute_name.to_sym]
29
+ next if param_value.blank?
30
+
31
+ attributes_hash[attribute_name.to_sym] = param_value
32
+ end
33
+
34
+ attributes_hash
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+ require 'fileutils'
5
+ require_relative '../meta_workflows/asset_installer'
6
+
7
+ namespace :meta_workflows do
8
+ desc 'Import workflows from YAML files in the workflows directory'
9
+ task import: :environment do
10
+ MetaWorkflows::WorkflowImporter.new.import_workflows
11
+ end
12
+
13
+ namespace :install do
14
+ desc 'Install meta_workflows assets (JavaScript controllers and stylesheets) into host application'
15
+ task assets: :environment do
16
+ MetaWorkflows::AssetInstallerService.new.install
17
+ end
18
+ end
19
+ end
20
+
21
+ # Service class to handle workflow import logic
22
+ module MetaWorkflows
23
+ class WorkflowImporter
24
+ def initialize
25
+ @workflows_path = Rails.root.join('workflows')
26
+ end
27
+
28
+ def import_workflows
29
+ puts "Importing workflows from #{@workflows_path}..."
30
+
31
+ Dir.glob(File.join(@workflows_path, '*.yml')).each do |file_path|
32
+ import_single_workflow(file_path)
33
+ end
34
+
35
+ puts 'Workflow import completed!'
36
+ end
37
+
38
+ private
39
+
40
+ def import_single_workflow(file_path)
41
+ file_name = File.basename(file_path, '.yml')
42
+ workflow_name = file_name.underscore
43
+
44
+ begin
45
+ yaml_content = YAML.load_file(file_path)
46
+ save_workflow(workflow_name, yaml_content)
47
+ rescue StandardError => e
48
+ puts "Error processing #{file_path}: #{e.message}"
49
+ end
50
+ end
51
+
52
+ def save_workflow(workflow_name, yaml_content)
53
+ workflow = MetaWorkflows::Workflow.find_or_initialize_by(name: workflow_name)
54
+ workflow.recipe = yaml_content
55
+
56
+ if workflow.save
57
+ puts "Successfully imported workflow: #{workflow.name}"
58
+ else
59
+ puts "Failed to import workflow #{workflow_name}: #{workflow.errors.full_messages.join(', ')}"
60
+ end
61
+ end
62
+ end
63
+
64
+ # Service class to handle asset installation
65
+ class AssetInstallerService
66
+ def install
67
+ puts 'Installing meta_workflows assets...'
68
+
69
+ installer = MetaWorkflows::AssetInstaller.new
70
+
71
+ # Pre-installation validation
72
+ unless installer.valid_environment?
73
+ puts 'Installation aborted due to validation errors.'
74
+ return
75
+ end
76
+
77
+ begin
78
+ process_asset_installation(installer)
79
+ rescue MetaWorkflows::AssetInstaller::InstallationError => e
80
+ handle_installation_error(e)
81
+ rescue StandardError => e
82
+ handle_unexpected_error(e)
83
+ end
84
+ end
85
+
86
+ private
87
+
88
+ def process_asset_installation(installer)
89
+ assets = discover_and_validate_assets(installer)
90
+ return if assets.empty?
91
+
92
+ result = installer.install_assets(assets)
93
+ display_installation_results(installer, assets, result)
94
+ end
95
+
96
+ def discover_and_validate_assets(installer)
97
+ assets = installer.discover_assets
98
+
99
+ if assets.empty?
100
+ puts 'No assets found to install.'
101
+ return []
102
+ end
103
+
104
+ puts "Found #{assets.count} asset(s) to install:"
105
+ assets.each { |asset| puts " - #{asset[:relative_path]}" }
106
+ puts
107
+
108
+ assets
109
+ end
110
+
111
+ def display_installation_results(installer, assets, result)
112
+ puts
113
+ if result[:success]
114
+ display_successful_installation(installer, assets, result)
115
+ else
116
+ display_partial_installation(installer, assets, result)
117
+ end
118
+ end
119
+
120
+ def display_successful_installation(installer, assets, result)
121
+ puts 'Installation completed successfully!'
122
+ puts "#{result[:copied]} file(s) copied, #{result[:skipped]} file(s) skipped."
123
+
124
+ return unless result[:copied].positive?
125
+
126
+ puts
127
+ installer.display_integration_instructions(assets, result)
128
+ end
129
+
130
+ def display_partial_installation(installer, assets, result)
131
+ puts 'Installation completed with errors.'
132
+ puts "#{result[:copied]} file(s) copied, #{result[:skipped]} file(s) skipped, " \
133
+ "#{result[:failed]} file(s) failed."
134
+ puts 'Some files may have been partially installed. Please review the output above.'
135
+
136
+ return unless result[:copied].positive?
137
+
138
+ puts
139
+ puts 'For successfully copied files, see integration instructions below:'
140
+ installer.display_integration_instructions(assets, result)
141
+ end
142
+
143
+ def handle_installation_error(error)
144
+ puts "Installation failed: #{error.message}"
145
+ puts 'Installation aborted.'
146
+ end
147
+
148
+ def handle_unexpected_error(error)
149
+ puts "Unexpected error during asset installation: #{error.message}"
150
+ puts 'Installation aborted.'
151
+ end
152
+ end
153
+ end
metadata ADDED
@@ -0,0 +1,219 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: meta_workflows
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.7.0
5
+ platform: ruby
6
+ authors:
7
+ - Leonid Medovyy
8
+ - Sami Tanquary
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2025-06-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: 7.2.0
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: '9.0'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ version: 7.2.0
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: '9.0'
34
+ - !ruby/object:Gem::Dependency
35
+ name: sidekiq
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '6.0'
41
+ type: :runtime
42
+ prerelease: false
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '6.0'
48
+ - !ruby/object:Gem::Dependency
49
+ name: ruby_conversations
50
+ requirement: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: ruby_llm
64
+ requirement: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ type: :runtime
70
+ prerelease: false
71
+ version_requirements: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ - !ruby/object:Gem::Dependency
77
+ name: view_component
78
+ requirement: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ type: :runtime
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ - !ruby/object:Gem::Dependency
91
+ name: stimulus-rails
92
+ requirement: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '1.0'
97
+ type: :runtime
98
+ prerelease: false
99
+ version_requirements: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '1.0'
104
+ - !ruby/object:Gem::Dependency
105
+ name: turbo-rails
106
+ requirement: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '1.0'
111
+ type: :runtime
112
+ prerelease: false
113
+ version_requirements: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '1.0'
118
+ description: MetaWorkflows provides a flexible framework for creating and executing
119
+ AI-powered workflows with human interaction points, built as a Rails engine for
120
+ easy integration into existing applications.
121
+ email:
122
+ - leonid.medovyy@strongmind.com
123
+ - samantha.tanquary@strongmind.com
124
+ executables: []
125
+ extensions: []
126
+ extra_rdoc_files: []
127
+ files:
128
+ - CHANGELOG.md
129
+ - README.md
130
+ - Rakefile
131
+ - app/assets/javascripts/meta_workflows/controllers/loading_phrases_controller.js
132
+ - app/assets/javascripts/meta_workflows/controllers/redirect_controller.js
133
+ - app/assets/javascripts/meta_workflows/controllers/response_scroll_controller.js
134
+ - app/assets/javascripts/meta_workflows_manifest.js
135
+ - app/assets/stylesheets/meta_workflows/application.css
136
+ - app/controllers/meta_workflows/application_controller.rb
137
+ - app/controllers/meta_workflows/debug_controller.rb
138
+ - app/controllers/meta_workflows/humans_controller.rb
139
+ - app/controllers/meta_workflows/meta_controller.rb
140
+ - app/helpers/meta_workflows/application_helper.rb
141
+ - app/helpers/meta_workflows/debug_helper.rb
142
+ - app/helpers/meta_workflows/execution_helper.rb
143
+ - app/helpers/meta_workflows/formatting_helper.rb
144
+ - app/helpers/meta_workflows/meta_workflows_helper.rb
145
+ - app/helpers/meta_workflows/status_badge_helper.rb
146
+ - app/jobs/meta_workflows/application_job.rb
147
+ - app/jobs/meta_workflows/human_input_job.rb
148
+ - app/jobs/meta_workflows/meta_job.rb
149
+ - app/jobs/meta_workflows/meta_workflow_job.rb
150
+ - app/jobs/meta_workflows/record_redirect_job.rb
151
+ - app/mailers/meta_workflows/application_mailer.rb
152
+ - app/models/meta_workflows.rb
153
+ - app/models/meta_workflows/application_record.rb
154
+ - app/models/meta_workflows/chat.rb
155
+ - app/models/meta_workflows/message.rb
156
+ - app/models/meta_workflows/tool_call.rb
157
+ - app/models/meta_workflows/workflow.rb
158
+ - app/models/meta_workflows/workflow_execution.rb
159
+ - app/models/meta_workflows/workflow_step.rb
160
+ - app/services/meta_workflows/execution_filter_service.rb
161
+ - app/sidekiq/meta_workflows/tools/meta_workflow_tool.rb
162
+ - app/views/layouts/meta_workflows/application.html.erb
163
+ - app/views/layouts/meta_workflows/debug.html.erb
164
+ - app/views/meta_workflows/_loader.html.erb
165
+ - app/views/meta_workflows/_redirect.html.erb
166
+ - app/views/meta_workflows/_response.html.erb
167
+ - app/views/meta_workflows/_response_form.html.erb
168
+ - app/views/meta_workflows/debug/executions.html.erb
169
+ - app/views/meta_workflows/debug/show_execution.html.erb
170
+ - app/views/meta_workflows/debug/show_workflow.html.erb
171
+ - app/views/meta_workflows/debug/workflows.html.erb
172
+ - config/routes.rb
173
+ - db/migrate/20250530220618_create_meta_workflows_workflows.rb
174
+ - db/migrate/20250530220634_create_meta_workflows_workflow_executions.rb
175
+ - db/migrate/20250530220704_create_meta_workflows_chats.rb
176
+ - db/migrate/20250530220722_create_meta_workflows_messages.rb
177
+ - db/migrate/20250530220737_create_meta_workflows_tool_calls.rb
178
+ - db/migrate/20250530220750_create_meta_workflows_workflow_steps.rb
179
+ - db/migrate/20250613213159_add_error_fields_to_workflow_steps.rb
180
+ - lib/meta_workflows.rb
181
+ - lib/meta_workflows/asset_installer.rb
182
+ - lib/meta_workflows/configuration.rb
183
+ - lib/meta_workflows/engine.rb
184
+ - lib/meta_workflows/export_execution_service.rb
185
+ - lib/meta_workflows/version.rb
186
+ - lib/services/meta_workflows/application_service.rb
187
+ - lib/services/meta_workflows/meta_workflow_service.rb
188
+ - lib/services/meta_workflows/updaters/meta_service.rb
189
+ - lib/tasks/meta_workflows_tasks.rake
190
+ homepage: https://github.com/strongmind/meta_workflows
191
+ licenses:
192
+ - None
193
+ metadata:
194
+ allowed_push_host: https://rubygems.org
195
+ homepage_uri: https://github.com/strongmind/meta_workflows
196
+ source_code_uri: https://github.com/strongmind/meta_workflows
197
+ changelog_uri: https://github.com/strongmind/meta_workflows/blob/main/CHANGELOG.md
198
+ documentation_uri: https://github.com/strongmind/meta_workflows/blob/main/README.md
199
+ rubygems_mfa_required: 'true'
200
+ post_install_message:
201
+ rdoc_options: []
202
+ require_paths:
203
+ - lib
204
+ required_ruby_version: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: 3.2.0
209
+ required_rubygems_version: !ruby/object:Gem::Requirement
210
+ requirements:
211
+ - - ">="
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ requirements: []
215
+ rubygems_version: 3.5.3
216
+ signing_key:
217
+ specification_version: 4
218
+ summary: A Rails engine for managing AI-powered meta workflows
219
+ test_files: []