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
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: afd80be43cbf526411e03bbf7ced8c539b12d81e82d19b2e805dc2a85045aa83
4
+ data.tar.gz: 4ce850bc8e751d2271ea049724bce5ddbf82d55b9d83749e7d06cfb1d0aebb2c
5
+ SHA512:
6
+ metadata.gz: 4fda18b86bf518cfbace011470987b8aa6fb7d1ebbfbb8e95933498736a6792b9c90183a8e820a2868ed8a34dab8cb0a32e194f054315d6bfbbdd4f6c067feb6
7
+ data.tar.gz: 45148c5baac802a9c4c330206724b4e8a867df7886a2fc984b9f5b5854a14d926336492c88c0e0f718f84a3d0b8973373f682eaf20d628929dd03d7bc4c5a9ee
data/CHANGELOG.md ADDED
@@ -0,0 +1,36 @@
1
+ # Changelog
2
+
3
+ All notable changes to the MetaWorkflows engine will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+ - Initial Rails engine structure
12
+ - Configuration system for engine customization
13
+ - Support for Rails 7.2+
14
+ - Integration with Sidekiq for background job processing
15
+ - Integration with ruby_conversations for AI chat functionality
16
+ - ViewComponent support for UI components
17
+ - Turbo and Stimulus integration for frontend interactivity
18
+ - PostgreSQL database support following host application patterns
19
+
20
+ ### Changed
21
+ - Extracted from course-builder monolith into standalone engine
22
+ - Updated dependencies for Rails 7.2 compatibility
23
+ - Switched from SQLite3 to PostgreSQL for database backend
24
+ - Updated dummy application to use PostgreSQL configuration
25
+ - Aligned database setup with host application (course-builder) patterns
26
+
27
+ ## [0.1.0] - 2025-01-XX
28
+
29
+ ### Added
30
+ - Initial release of MetaWorkflows as a Rails engine
31
+ - Core workflow execution framework
32
+ - AI-powered conversation management
33
+ - Human interaction points in workflows
34
+ - Background job processing with Sidekiq
35
+ - Modern UI components with TailwindCSS and Stimulus
36
+ - PostgreSQL database backend for reliability and scalability
data/README.md ADDED
@@ -0,0 +1,498 @@
1
+ # MetaWorkflows
2
+
3
+ <div align="center">
4
+ <img src="spec/dummy/public/icon.svg" alt="MetaWorkflows Logo" width="128" height="128">
5
+ </div>
6
+
7
+ A Rails engine for managing AI-powered meta workflows with human interaction points, extracted from course-builder into a standalone, reusable Rails gem.
8
+
9
+ ## Overview
10
+
11
+ MetaWorkflows provides a flexible framework for creating and executing AI-powered workflows that can include human interaction points, background job processing, and modern UI components. Built as a Rails engine for easy integration into existing applications, it enables sophisticated multi-step processes that combine AI automation with human oversight.
12
+
13
+ Originally developed as part of the course-builder application and extracted to improve modularity and enable reuse across multiple applications. The system orchestrates complex workflows requiring both AI agent and human interactions through a configurable YAML-based workflow definition system.
14
+
15
+ ## Key Features
16
+
17
+ - **AI-Powered Workflows**: Integration with `ruby_conversations` for AI chat functionality and tool calling
18
+ - **Human Interaction Points**: Pause workflows for human input, review, and feedback with built-in UI components
19
+ - **Background Processing**: Sidekiq integration for reliable, asynchronous job execution
20
+ - **Modern UI**: TailwindCSS styling with Turbo and Stimulus for real-time interactivity
21
+ - **Flexible Configuration**: YAML-based workflow definitions with multiple action types
22
+ - **Rails Engine Architecture**: Clean integration as a mountable engine with proper namespacing
23
+ - **Atomic Operations**: Database transactions ensure data integrity during batch operations
24
+ - **Extensible Service Layer**: Pluggable services for record updates and collection creation
25
+
26
+ ## System Architecture
27
+
28
+ ### Core Components
29
+
30
+ The MetaWorkflows system consists of several interconnected components:
31
+
32
+ #### Database Models
33
+ - **MetaWorkflows::Workflow**: Stores workflow definitions with named steps and JSON recipes
34
+ - **MetaWorkflows::WorkflowExecution**: Tracks active workflow instances and their state
35
+ - **MetaWorkflows::WorkflowStep**: Represents individual steps within a workflow execution
36
+ - **MetaWorkflows::Chat**: Manages LLM conversation contexts for workflow steps
37
+ - **MetaWorkflows::Message**: Stores individual messages within workflow conversations
38
+ - **MetaWorkflows::ToolCall**: Records tool calls made during LLM interactions
39
+
40
+ #### Controllers
41
+ - **MetaWorkflows::MetaController**: Base controller with shared workflow functionality
42
+ - **MetaWorkflows::HumansController**: Manages human interactions within workflows
43
+
44
+ #### Background Jobs
45
+ - **MetaWorkflows::MetaWorkflowJob**: Entry point for workflow processing and step coordination
46
+ - **MetaWorkflows::MetaJob**: Base job class for workflow-related processing
47
+ - **MetaWorkflows::HumanInputJob**: Handles human input processing within workflows
48
+ - **MetaWorkflows::RecordRedirectJob**: Manages post-workflow redirections
49
+
50
+ #### Services
51
+ - **Services::MetaWorkflows::MetaWorkflowService**: Central workflow coordinator that processes all workflow steps and actions
52
+ - **Services::MetaWorkflows::Updaters::MetaService**: Generic record update service for modifying model attributes
53
+
54
+ ## Workflow Action Types
55
+
56
+ MetaWorkflows supports several action types for different workflow needs:
57
+
58
+ ### `agent`
59
+ - Executes LLM interactions using specified prompts and tools
60
+ - Requires `prompt_id` configuration
61
+ - Supports tool calling and complex reasoning tasks
62
+ - Output is extracted and stored for subsequent steps
63
+
64
+ ### `human`
65
+ - Presents UI for human interaction and input collection
66
+ - Requires `prompt_id` for context presentation
67
+ - Collects user feedback through forms
68
+ - Workflow pauses until human input is provided
69
+
70
+ ### `collection_create`
71
+ - Creates collections of related records atomically
72
+ - Requires `collection_creator` service class name
73
+ - Handles batch creation operations with all-or-nothing semantics
74
+ - Automatically halts workflow on any creation failure
75
+
76
+ ### `record_update`
77
+ - Updates the associated record with specified attributes
78
+ - Requires `record_updater` service class name and `attributes_to_update` list
79
+ - Uses values from `workflow_params` to update the record
80
+ - Supports both generic and custom updater services
81
+
82
+ ### `record_redirect`
83
+ - Redirects users to specified paths
84
+ - Marks workflow as complete
85
+ - Requires `redirect_path` or `redirect_method` configuration
86
+
87
+ ## Requirements
88
+
89
+ - **Rails 7.2+**: Compatible with modern Rails applications
90
+ - **PostgreSQL**: Database backend (9.3 and up supported)
91
+ - **Sidekiq**: Background job processing with Redis
92
+ - **Ruby 3.2+**: Modern Ruby version
93
+ - **TailwindCSS**: For UI styling (configured automatically)
94
+
95
+ ## Installation
96
+
97
+ Add this line to your application's Gemfile:
98
+
99
+ ```ruby
100
+ gem 'meta_workflows'
101
+ ```
102
+
103
+ And then execute:
104
+
105
+ ```bash
106
+ bundle install
107
+ ```
108
+
109
+ Or install it yourself as:
110
+
111
+ ```bash
112
+ gem install meta_workflows
113
+ ```
114
+
115
+ ## Setup
116
+
117
+ ### 1. Database Setup
118
+
119
+ Ensure PostgreSQL is installed and running on your system. The engine uses PostgreSQL for reliable data storage and supports the same configuration as your host Rails application.
120
+
121
+ ### 2. Environment Configuration
122
+
123
+ For development and testing, configure the required environment variables:
124
+
125
+ ```bash
126
+ # Copy the example environment file
127
+ cp spec/dummy/.env.example spec/dummy/.env
128
+
129
+ # Edit the .env file with your actual values
130
+ ```
131
+
132
+ The following environment variables are required for StrongMind Identity SSO integration:
133
+
134
+ | Variable | Description | Example |
135
+ |:--------:|:----------:|:-------:|
136
+ | `IDENTITY_CLIENT_ID` | Your StrongMind Identity client ID | `course-builder-development` |
137
+ | `IDENTITY_CLIENT_SECRET` | Your StrongMind Identity client secret | `your-secret-key` |
138
+ | `IDENTITY_BASE_URL` | StrongMind Identity service URL | `https://devlogin.strongmind.com` |
139
+
140
+ > 💡 **Tip:** Contact your system administrator for the appropriate values for your environment.
141
+
142
+ ### 3. Install and Run Migrations
143
+
144
+ ```bash
145
+ rails meta_workflows:install:migrations
146
+ rails db:migrate
147
+ ```
148
+
149
+ ### 4. Mount the Engine
150
+
151
+ Add to your `config/routes.rb`:
152
+
153
+ ```ruby
154
+ Rails.application.routes.draw do
155
+ mount MetaWorkflows::Engine, at: '/meta_workflows'
156
+ # ... your other routes
157
+ end
158
+ ```
159
+
160
+ ### 5. Configure Sidekiq
161
+
162
+ Ensure Sidekiq is configured in your application for background job processing:
163
+
164
+ ```ruby
165
+ # config/application.rb or config/initializers/sidekiq.rb
166
+ require 'sidekiq'
167
+
168
+ # Configure Redis connection and other Sidekiq settings
169
+ ```
170
+
171
+ ## Usage
172
+
173
+ ### Creating Workflow Definitions
174
+
175
+ Define workflows in YAML files within your configured workflow definitions path:
176
+
177
+ ```yaml
178
+ # config/workflows/example_workflow.yml
179
+ name: "example_workflow"
180
+ description: "An example workflow demonstrating multiple action types"
181
+ steps:
182
+ - name: "initial_generation"
183
+ action: "agent"
184
+ prompt_id: "generation_prompt"
185
+ step_progress:
186
+ - "Analyzing input parameters..."
187
+ - "Generating initial content..."
188
+ - "Refining results..."
189
+ input:
190
+ title:
191
+ type: "string"
192
+ required: true
193
+ description: "The title for processing"
194
+ output:
195
+ generated_content:
196
+ type: "string"
197
+ description: "The generated content"
198
+
199
+ - name: "human_review"
200
+ action: "human"
201
+ prompt_id: "review_prompt"
202
+ step_progress:
203
+ - "Preparing content for review..."
204
+ input:
205
+ generated_content:
206
+ type: "string"
207
+ from_step: "initial_generation"
208
+ output:
209
+ user_feedback:
210
+ type: "string"
211
+ description: "User feedback on the content"
212
+
213
+ - name: "record_update"
214
+ action: "record_update"
215
+ record_updater: "Services::MetaWorkflows::Updaters::MetaService"
216
+ attributes_to_update:
217
+ - "title"
218
+ - "topic"
219
+ step_progress:
220
+ - "Updating record..."
221
+ - "Saving changes..."
222
+ workflow_params:
223
+ - name: "title"
224
+ type: string
225
+ description: "The new title for the record"
226
+
227
+ - name: "completion_redirect"
228
+ action: "record_redirect"
229
+ redirect_path: "/your/completion/path"
230
+ ```
231
+
232
+ ### Executing Workflows
233
+
234
+ #### From Controller Actions
235
+
236
+ ```ruby
237
+ class YourController < ApplicationController
238
+ def start_workflow
239
+ @record = YourModel.find(params[:id])
240
+
241
+ MetaWorkflows::MetaWorkflowJob.perform_later(
242
+ workflow_name: "example_workflow",
243
+ record_type: @record.class.name,
244
+ record_id: @record.id,
245
+ user_id: current_user.id,
246
+ inputs: {
247
+ title: @record.title,
248
+ # other initial parameters
249
+ }
250
+ )
251
+
252
+ redirect_to workflow_path(@record)
253
+ end
254
+ end
255
+ ```
256
+
257
+ #### Direct Job Execution
258
+
259
+ ```ruby
260
+ # Start a workflow
261
+ MetaWorkflows::MetaWorkflowJob.perform_later(
262
+ 'example_workflow',
263
+ context: {
264
+ user_id: 1,
265
+ record_id: 123,
266
+ record_type: 'YourModel'
267
+ }
268
+ )
269
+ ```
270
+
271
+ ### Using Meta Workflow UI Components
272
+
273
+ Instead of creating custom views from scratch, use the provided Meta Workflow partials:
274
+
275
+ #### Complete View Example
276
+
277
+ ```erb
278
+ <%= turbo_stream_from turbo_stream_name(@record) %>
279
+ <div class="max-w-3xl m-auto flex flex-col p-10 gap-6">
280
+ <!-- Workflow progress and chat messages area -->
281
+ <%= render partial: 'meta_workflows/loader', locals: {
282
+ record: @record,
283
+ step_progress: ["Generating draft content...", "Processing with AI..."]
284
+ } %>
285
+
286
+ <!-- User input area for human interaction steps -->
287
+ <%= render partial: 'meta_workflows/response_form', locals: {
288
+ record: @record,
289
+ response_enabled: false
290
+ } %>
291
+ </div>
292
+ ```
293
+
294
+ ## File Structure Overview
295
+
296
+ The MetaWorkflows gem follows a structured organization:
297
+
298
+ ```
299
+ meta_workflows/
300
+ ├── app/
301
+ │ ├── controllers/meta_workflows/ # Workflow controllers
302
+ │ ├── jobs/meta_workflows/ # Background jobs
303
+ │ ├── models/meta_workflows/ # Database models
304
+ │ └── views/meta_workflows/ # UI partials and templates
305
+ ├── lib/
306
+ │ └── services/meta_workflows/ # Business logic services
307
+ │ ├── updaters/ # Record update services
308
+ │ └── creators/ # Collection creation services
309
+ ├── config/
310
+ │ └── workflows/ # YAML workflow definitions
311
+ └── spec/
312
+ └── dummy/ # Test Rails application
313
+ ```
314
+
315
+ ## Development
316
+
317
+ ### Setting Up Development Environment
318
+
319
+ After checking out the repo, run:
320
+
321
+ ```bash
322
+ bundle install
323
+ ```
324
+
325
+ Set up the test database:
326
+
327
+ ```bash
328
+ cd spec/dummy
329
+ rails db:create
330
+ rails db:migrate
331
+ ```
332
+
333
+ ### Running Tests
334
+
335
+ To run the test suite:
336
+
337
+ ```bash
338
+ bundle exec rspec
339
+ ```
340
+
341
+ ### Dummy Application
342
+
343
+ The gem includes a complete Rails application in `spec/dummy/` for testing and development:
344
+
345
+ ```bash
346
+ # Set up environment variables
347
+ cp spec/dummy/.env.example spec/dummy/.env
348
+ # Edit spec/dummy/.env with your actual values
349
+
350
+ # Start the dummy application
351
+ cd spec/dummy
352
+ rails server
353
+ ```
354
+
355
+ The dummy app demonstrates MetaWorkflows integration with:
356
+ - User authentication (Devise)
357
+ - Post and Comment models with associations
358
+ - Complete CRUD operations
359
+ - MetaWorkflows engine mounted at `/meta_workflows`
360
+ - StrongMind Identity SSO integration
361
+
362
+ ## Extending the System
363
+
364
+ ### Creating Custom Record Updater Services
365
+
366
+ ```ruby
367
+ # lib/services/meta_workflows/updaters/your_model_service.rb
368
+ module Services
369
+ module MetaWorkflows
370
+ module Updaters
371
+ class YourModelService < ApplicationService
372
+ def initialize(record, attributes_to_update, workflow_params)
373
+ @record = record
374
+ @attributes_to_update = attributes_to_update
375
+ @workflow_params = workflow_params
376
+ end
377
+
378
+ def call
379
+ update_attributes = build_update_attributes
380
+ record.update!(update_attributes)
381
+ record
382
+ end
383
+
384
+ private
385
+
386
+ def build_update_attributes
387
+ # Custom logic for building update attributes
388
+ end
389
+ end
390
+ end
391
+ end
392
+ end
393
+ ```
394
+
395
+ ### Creating Custom Collection Creator Services
396
+
397
+ ```ruby
398
+ # lib/services/meta_workflows/creators/your_collection_service.rb
399
+ module Services
400
+ module MetaWorkflows
401
+ module Creators
402
+ class YourCollectionService
403
+ def self.create_collection(parent, items, options = {})
404
+ created_items = []
405
+
406
+ ActiveRecord::Base.transaction do
407
+ items.each do |item_data|
408
+ created_items << create_item(parent, item_data, options)
409
+ end
410
+ end
411
+
412
+ created_items
413
+ end
414
+
415
+ private_class_method
416
+
417
+ def self.create_item(parent, data, options = {})
418
+ YourModel.create!(
419
+ content: data[:content],
420
+ parent: parent,
421
+ organization_id: parent.organization_id
422
+ )
423
+ end
424
+ end
425
+ end
426
+ end
427
+ end
428
+ ```
429
+
430
+ ### Adding New Action Types
431
+
432
+ To add a new action type:
433
+
434
+ 1. Add the action to `ACTIONS_WITHOUT_CONVERSATION` in `Services::MetaWorkflows::MetaWorkflowService` if it doesn't require conversation tracking
435
+ 2. Implement a `process_[action_name]_action` method in the service
436
+ 3. Add the action handling to the `process_action` method
437
+ 4. Create any necessary supporting services
438
+ 5. Add comprehensive tests for the new action type
439
+
440
+ ## Best Practices
441
+
442
+ ### Workflow Design
443
+ - Keep steps focused and single-purpose
444
+ - Design clear input/output schemas
445
+ - Provide meaningful progress messages
446
+ - Handle error cases gracefully
447
+ - Use `record_update` steps to persist intermediate workflow results
448
+
449
+ ### Performance
450
+ - Use background jobs for long-running processes
451
+ - Implement appropriate caching strategies
452
+ - Monitor workflow execution times
453
+ - Set reasonable timeouts for LLM interactions
454
+ - Use bulk operations in collection creators when possible
455
+
456
+ ### UI/UX Considerations
457
+ - Use the provided meta partials for consistent UI
458
+ - Provide meaningful step progress messages in workflow definitions
459
+ - Ensure proper Turbo Stream configuration for real-time updates
460
+ - Handle edge cases and error states appropriately
461
+
462
+ ## Architecture Details
463
+
464
+ ### Engine Isolation
465
+ - All classes properly namespaced under `MetaWorkflows::`
466
+ - Controllers inherit from `MetaWorkflows::ApplicationController`
467
+ - Jobs inherit from `MetaWorkflows::ApplicationJob`
468
+ - Models use engine-specific associations and validations
469
+ - Services organized under `Services::MetaWorkflows::` namespace
470
+
471
+ ### Database Compatibility
472
+ - Migration files include `table_exists?` checks to prevent conflicts
473
+ - Exact schema compatibility maintained with existing applications
474
+ - Proper foreign key references and indexes included
475
+ - Migration timestamps ordered correctly for dependency resolution
476
+
477
+ ## Contributing
478
+
479
+ Bug reports and pull requests are welcome on GitHub at https://github.com/strongmind/meta_workflows.
480
+
481
+ For development contributions:
482
+ 1. Fork the repository
483
+ 2. Create a feature branch
484
+ 3. Add comprehensive tests
485
+ 4. Follow the established code patterns and namespacing
486
+ 5. Update documentation as needed
487
+ 6. Submit a pull request
488
+
489
+ ## Documentation
490
+
491
+ For detailed information about the MetaWorkflows system:
492
+ - [Setup Guide](https://strongmind.atlassian.net/wiki/spaces/MW/pages/3929833507) - Configuration and workflow setup
493
+ - [File Structure Guide](https://strongmind.atlassian.net/wiki/spaces/MW/pages/3930521627) - Complete file organization reference
494
+ - [Dummy App Guide](https://strongmind.atlassian.net/wiki/spaces/MW/pages/3941072927) - Test application documentation
495
+
496
+ ## License
497
+
498
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+
5
+ APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
6
+ load 'rails/tasks/engine.rake'
7
+
8
+ load 'rails/tasks/statistics.rake'
9
+
10
+ require 'bundler/gem_tasks'
@@ -0,0 +1,31 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+
3
+ // Connects to data-controller="loading-phrases"
4
+ export default class extends Controller {
5
+ static targets = ["message"]
6
+ static values = {
7
+ phrases: Array
8
+ }
9
+
10
+ connect() {
11
+ if (!this.hasPhrasesValue || this.phrasesValue.length === 0) {
12
+ this.phrasesValue = ["Talking to the LLM..."]
13
+ }
14
+
15
+ this.currentIndex = 0
16
+ this.startCycling()
17
+ }
18
+
19
+ disconnect() {
20
+ if (this.intervalId) {
21
+ clearInterval(this.intervalId)
22
+ }
23
+ }
24
+
25
+ startCycling() {
26
+ this.intervalId = setInterval(() => {
27
+ this.currentIndex = (this.currentIndex + 1) % this.phrasesValue.length
28
+ this.messageTarget.textContent = this.phrasesValue[this.currentIndex]
29
+ }, 3000) // Change phrase every 3 seconds
30
+ }
31
+ }
@@ -0,0 +1,15 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+
3
+ // Connects to data-controller="redirect"
4
+ export default class extends Controller {
5
+ static values = {
6
+ url: String,
7
+ delay: { type: Number, default: 500 }
8
+ }
9
+
10
+ connect() {
11
+ setTimeout(() => {
12
+ Turbo.visit(this.urlValue)
13
+ }, this.delayValue)
14
+ }
15
+ }
@@ -0,0 +1,67 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+
3
+ export default class extends Controller {
4
+ connect() {
5
+ this.setupObserver()
6
+ this.setupTurboListener()
7
+ this.scrollToBottom()
8
+ }
9
+
10
+ disconnect() {
11
+ if (this.observer) {
12
+ this.observer.disconnect()
13
+ }
14
+ document.removeEventListener("turbo:frame-render", this.handleTurboRender)
15
+ }
16
+
17
+ setupObserver() {
18
+ this.observer = new MutationObserver((mutations) => {
19
+ if (mutations.some(mutation =>
20
+ mutation.type === 'childList' ||
21
+ mutation.type === 'characterData'
22
+ )) {
23
+ setTimeout(() => this.scrollToBottom(), 10)
24
+ }
25
+ })
26
+
27
+ const contentContainer = this.element.closest('#response-content-container')
28
+ if (contentContainer) {
29
+ this.observer.observe(contentContainer, {
30
+ childList: true,
31
+ subtree: true,
32
+ characterData: true,
33
+ attributes: true
34
+ })
35
+ } else {
36
+ this.observer.observe(this.element, {
37
+ childList: true,
38
+ subtree: true,
39
+ characterData: true,
40
+ attributes: true
41
+ })
42
+ }
43
+ }
44
+
45
+ setupTurboListener() {
46
+ this.handleTurboRender = () => {
47
+ setTimeout(() => this.scrollToBottom(), 10)
48
+ }
49
+ document.addEventListener("turbo:frame-render", this.handleTurboRender)
50
+ }
51
+
52
+ scrollToBottom() {
53
+ const mainContainer = document.querySelector('#main-scroll-container')
54
+ if (!mainContainer) return
55
+
56
+ const scrollHeight = mainContainer.scrollHeight
57
+ const clientHeight = mainContainer.clientHeight
58
+ const maxScroll = scrollHeight - clientHeight
59
+
60
+ if (maxScroll > 0) {
61
+ mainContainer.scrollTo({
62
+ top: maxScroll,
63
+ behavior: 'smooth'
64
+ })
65
+ }
66
+ }
67
+ }
@@ -0,0 +1,13 @@
1
+ //= require_tree ./meta_workflows/controllers
2
+
3
+ // MetaWorkflows Stimulus Controllers
4
+ import LoadingPhrasesController from "./meta_workflows/controllers/loading_phrases_controller"
5
+ import ResponseScrollController from "./meta_workflows/controllers/response_scroll_controller"
6
+ import RedirectController from "./meta_workflows/controllers/redirect_controller"
7
+
8
+ // Register controllers with Stimulus
9
+ const application = window.Stimulus || Application.start()
10
+
11
+ application.register("loading-phrases", LoadingPhrasesController)
12
+ application.register("response-scroll", ResponseScrollController)
13
+ application.register("redirect", RedirectController)