meta_workflows 0.9.32 → 0.9.34

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: 3b6e5652802f3f166ea4d2bc4860e7c3967f5be1b39fb92858dacceb7ce59990
4
- data.tar.gz: d4ccc1608e8683b73d5a7f38e9a49fc2c7511820bd03abacb3bbacb487722313
3
+ metadata.gz: 67144b3aeb77208203f906c27dcf0a98014f4fb7648334cd2232ad6e4619d18b
4
+ data.tar.gz: 216250d9732a3cea86b147b7ed5720629c3cd146d42c231ac726333775943296
5
5
  SHA512:
6
- metadata.gz: c7ea1140103f59aa5667044d9000eb483c06fd5624ed7b761777d3b51e57e7971d040cf5295eee9e2a64a6e0f36d960f6953b65e8440b535520e0155dfd49260
7
- data.tar.gz: 54a7458c7905680b5cb8a56dfb8a985d8bde3878cc7a7e6e3b745023c8571d6e4a6381d70b5e48668df77cd2eaf8fe2dedaf811b9dd79f551df196bb8851cdf4
6
+ metadata.gz: e36e367f6849c449e0b5e854ea53a924a191fe94d698b6eba350ee6afa99ef5730e70c143bac3ff63134f38ff10e508a605eadec8a7415049a30868958c6e0ca
7
+ data.tar.gz: 1e66b674c6157851eb3f4be73767def3d732ba2cbb379ae6d0bd22de8a6cdd8584c4b89b2778779c00269fafa9151bdf0ea4e27ab1368f93bd8cb92ff233be85
@@ -19,22 +19,24 @@ function chevronDirection(tray, expanded) {
19
19
  }
20
20
 
21
21
  export default class extends Controller {
22
- static values = { name: String }
23
- static targets = ["content", "chevron"]
22
+ static targets = ["content", "chevron", "gammaTray", "betaTray", "deltaTray"]
24
23
 
25
24
  connect() {
25
+ const trayName = this.getTrayName();
26
+
26
27
  // Load state from cookies
27
- const savedState = getCookie(`tray_${this.nameValue}`);
28
+ const savedState = getCookie(`tray_${trayName}`);
28
29
  if (savedState === "collapsed") {
29
30
  this.expanded = false;
30
31
  } else {
31
32
  this.expanded = true;
32
33
  }
33
34
  this.updateTray();
35
+
34
36
  // Set chevron direction from cookie if present
35
37
  const chevron = this.hasChevronTarget ? this.chevronTarget : null;
36
38
  if (chevron) {
37
- const chevronCookie = getCookie(`chevron_${this.nameValue}`);
39
+ const chevronCookie = getCookie(`chevron_${trayName}`);
38
40
  if (chevronCookie) {
39
41
  chevron.classList.remove("fa-chevron-left", "fa-chevron-right", "fa-chevron-up", "fa-chevron-down");
40
42
  chevron.classList.add(chevronCookie);
@@ -42,65 +44,108 @@ export default class extends Controller {
42
44
  }
43
45
  }
44
46
 
45
- toggle() {
47
+ toggle(trayType = null) {
48
+ if (!trayType) {
49
+ trayType = this.getTrayName();
50
+ }
51
+
52
+ const trayTargetName = `${trayType}TrayTarget`;
53
+ const hasTrayTarget = `has${trayType.charAt(0).toUpperCase() + trayType.slice(1)}TrayTarget`;
54
+
55
+ if (!this[hasTrayTarget]) {
56
+ return;
57
+ }
58
+
46
59
  this.expanded = !this.expanded;
47
- // Save state to cookies
48
- setCookie(`tray_${this.nameValue}`, this.expanded ? "expanded" : "collapsed");
49
- // Save chevron direction to cookies
50
- setCookie(`chevron_${this.nameValue}`, chevronDirection(this.nameValue, this.expanded));
51
- this.updateTray();
60
+
61
+ setCookie(`tray_${trayType}`, this.expanded ? "expanded" : "collapsed");
62
+ setCookie(`chevron_${trayType}`, chevronDirection(trayType, this.expanded));
63
+
64
+ const updateMethod = `update${trayType.charAt(0).toUpperCase() + trayType.slice(1)}Tray`;
65
+ this[updateMethod](this.hasChevronTarget, this[trayTargetName]);
66
+ }
67
+
68
+ toggleGamma() {
69
+ this.toggle("gamma");
70
+ }
71
+
72
+ toggleBeta() {
73
+ this.toggle("beta");
74
+ }
75
+
76
+ toggleDelta() {
77
+ this.toggle("delta");
78
+ }
79
+
80
+ getTrayName() {
81
+ if (this.hasGammaTrayTarget) return "gamma";
82
+ if (this.hasBetaTrayTarget) return "beta";
83
+ if (this.hasDeltaTrayTarget) return "delta";
84
+ return "unknown";
85
+ }
86
+
87
+ getCurrentTrayElement() {
88
+ if (this.hasGammaTrayTarget) return this.gammaTrayTarget;
89
+ if (this.hasBetaTrayTarget) return this.betaTrayTarget;
90
+ if (this.hasDeltaTrayTarget) return this.deltaTrayTarget;
91
+ return this.element;
52
92
  }
53
93
 
54
94
  updateTray() {
95
+ const trayName = this.getTrayName();
55
96
  const hasChevron = this.hasChevronTarget;
97
+ const trayElement = this.getCurrentTrayElement();
56
98
 
57
- switch (this.nameValue) {
99
+ switch (trayName) {
58
100
  case "delta":
59
- this.updateDeltaTray(hasChevron);
101
+ this.updateDeltaTray(hasChevron, trayElement);
60
102
  break;
61
103
  case "beta":
62
- this.updateBetaTray(hasChevron);
104
+ this.updateBetaTray(hasChevron, trayElement);
63
105
  break;
64
106
  case "gamma":
65
- this.updateGammaTray(hasChevron);
107
+ this.updateGammaTray(hasChevron, trayElement);
66
108
  break;
67
109
  }
68
110
  }
69
111
 
70
- updateDeltaTray(hasChevron) {
112
+ updateDeltaTray(hasChevron, trayElement) {
71
113
  if (this.expanded) {
72
- this.element.classList.remove("collapsed");
73
- this.element.classList.add("h-[200px]");
114
+ trayElement.classList.remove("collapsed");
115
+ trayElement.classList.add("h-[200px]");
74
116
  this.updateChevronClasses(hasChevron, "fa-chevron-up", "fa-chevron-down");
75
117
  } else {
76
- this.element.classList.remove("h-[200px]");
77
- this.element.classList.add("collapsed");
118
+ trayElement.classList.remove("h-[200px]");
119
+ trayElement.classList.add("collapsed");
78
120
  this.updateChevronClasses(hasChevron, "fa-chevron-down", "fa-chevron-up");
79
121
  }
80
122
  }
81
123
 
82
- updateBetaTray(hasChevron) {
124
+ updateBetaTray(hasChevron, trayElement) {
83
125
  // Beta: open=left, collapsed=right
84
126
  if (this.expanded) {
85
- this.element.classList.remove("collapsed");
86
- this.element.classList.add("w-[300px]");
127
+ trayElement.classList.remove("collapsed");
128
+ trayElement.classList.add("w-[300px]");
87
129
  this.updateChevronClasses(hasChevron, "fa-chevron-right", "fa-chevron-left");
88
130
  } else {
89
- this.element.classList.remove("w-[300px]");
90
- this.element.classList.add("collapsed");
131
+ trayElement.classList.remove("w-[300px]");
132
+ trayElement.classList.add("collapsed");
91
133
  this.updateChevronClasses(hasChevron, "fa-chevron-left", "fa-chevron-right");
92
134
  }
93
135
  }
94
136
 
95
- updateGammaTray(hasChevron) {
137
+ updateGammaTray(hasChevron, trayElement) {
138
+ console.log(`Updating gamma tray - expanded: ${this.expanded}`);
96
139
  // Gamma: open=right, collapsed=left
97
140
  if (this.expanded) {
98
- this.element.classList.remove("collapsed");
99
- this.element.classList.add("w-[300px]");
141
+ console.log('Expanding gamma tray');
142
+ trayElement.classList.remove("collapsed");
143
+ trayElement.classList.add("w-[300px]");
100
144
  this.updateChevronClasses(hasChevron, "fa-chevron-left", "fa-chevron-right");
101
145
  } else {
102
- this.element.classList.remove("w-[300px]");
103
- this.element.classList.add("collapsed");
146
+ console.log('Collapsing gamma tray');
147
+ trayElement.classList.remove("w-[300px]");
148
+ trayElement.classList.add("collapsed");
104
149
  this.updateChevronClasses(hasChevron, "fa-chevron-right", "fa-chevron-left");
105
150
  }
106
151
  }
@@ -653,7 +653,7 @@
653
653
 
654
654
  /* Hide standard collapse button when Lexi tray is collapsed */
655
655
  .gamma-tray.lexi-tray.collapsed
656
- > button[data-action='click->tray#toggle']:not(.lexi-floating-avatar) {
656
+ > button[data-action='click->tray#toggleGamma']:not(.lexi-floating-avatar) {
657
657
  display: none;
658
658
  }
659
659
 
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MetaWorkflows
4
+ module FrameIdHelper
5
+ def target_frame_id(record, **options)
6
+ base_id = "#{record.class.name.downcase}_#{record.id}"
7
+
8
+ return "#{base_id}_loader" if options[:loader]
9
+ return "#{base_id}_form" if options[:form]
10
+ return "#{base_id}_structured_input" if options[:structured_input]
11
+ return "#{base_id}_chat_history" if options[:chat_history]
12
+ return "#{base_id}_streaming" if options[:streaming]
13
+
14
+ base_id
15
+ end
16
+
17
+ def turbo_stream_name(record)
18
+ [record.class.name.downcase, record.id]
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MetaWorkflows
4
+ module PartialPathsHelper
5
+ def meta_loader_message
6
+ 'meta_workflows/loader_message'
7
+ end
8
+
9
+ def meta_error_message
10
+ 'meta_workflows/error_message'
11
+ end
12
+
13
+ def meta_response_form
14
+ 'meta_workflows/response_form_lexi'
15
+ end
16
+
17
+ def meta_structured_input
18
+ 'meta_workflows/structured_input'
19
+ end
20
+
21
+ def meta_response
22
+ 'meta_workflows/response_lexi'
23
+ end
24
+
25
+ def meta_chat_history
26
+ 'meta_workflows/chat_history'
27
+ end
28
+
29
+ def meta_streaming_response
30
+ 'meta_workflows/streaming_response'
31
+ end
32
+
33
+ def meta_redirect
34
+ 'meta_workflows/redirect'
35
+ end
36
+
37
+ def meta_lexi_chat_right_tray
38
+ 'meta_workflows/lexi_chat_right_tray'
39
+ end
40
+
41
+ def meta_lexi_chat_alpha_tray
42
+ 'meta_workflows/lexi_chat_alpha_tray'
43
+ end
44
+
45
+ def meta_lexi_chat_messages
46
+ 'meta_workflows/lexi_chat_messages'
47
+ end
48
+
49
+ def meta_lexi_chat_input_area
50
+ 'meta_workflows/lexi_chat_input_area'
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MetaWorkflows
4
+ module UiStateHelper
5
+ def random_chat_placeholder
6
+ [
7
+ 'What would you like to improve?',
8
+ 'Suggest an edit or ask for changes...',
9
+ 'Let me know how I can improve this.',
10
+ 'Not quite right? Let me know.',
11
+ 'Edit, clarify, or request a change.',
12
+ 'Happy with this, or want changes?'
13
+ ].sample
14
+ end
15
+
16
+ def tray_state(tray)
17
+ (cookies['tray_'] && cookies['tray_'][tray.to_s]) || cookies["tray_#{tray}"] || 'expanded'
18
+ end
19
+
20
+ def chevron_direction(tray)
21
+ state = tray_state(tray)
22
+ case tray.to_s
23
+ when 'beta'
24
+ state == 'collapsed' ? 'fa-chevron-right' : 'fa-chevron-left'
25
+ when 'gamma'
26
+ state == 'collapsed' ? 'fa-chevron-left' : 'fa-chevron-right'
27
+ when 'delta'
28
+ state == 'collapsed' ? 'fa-chevron-up' : 'fa-chevron-down'
29
+ else
30
+ ''
31
+ end
32
+ end
33
+
34
+ def default_step_progress
35
+ ['Thinking']
36
+ end
37
+ end
38
+ end
@@ -2,98 +2,72 @@
2
2
 
3
3
  module MetaWorkflows
4
4
  module MetaWorkflowsHelper
5
- def target_frame_id(record, **options)
6
- base_id = "#{record.class.name.downcase}_#{record.id}"
5
+ include MetaWorkflows::FrameIdHelper
6
+ include MetaWorkflows::PartialPathsHelper
7
+ include MetaWorkflows::UiStateHelper
7
8
 
8
- return "#{base_id}_loader" if options[:loader]
9
- return "#{base_id}_form" if options[:form]
10
- return "#{base_id}_structured_input" if options[:structured_input]
11
- return "#{base_id}_chat_history" if options[:chat_history]
12
- return "#{base_id}_streaming" if options[:streaming]
13
-
14
- base_id
15
- end
16
-
17
- def turbo_stream_name(record)
18
- [record.class.name.downcase, record.id]
19
- end
20
-
21
- def meta_loader_message
22
- 'meta_workflows/loader_message'
23
- end
24
-
25
- def meta_error_message
26
- 'meta_workflows/error_message'
27
- end
28
-
29
- def meta_response_form
30
- 'meta_workflows/response_form_lexi'
31
- end
32
-
33
- def meta_structured_input
34
- 'meta_workflows/structured_input'
9
+ def current_step_has_repetitions?(workflow_execution)
10
+ workflow_execution.step_repetitions(workflow_execution.current_step).present?
35
11
  end
36
12
 
37
- def meta_response
38
- 'meta_workflows/response_lexi'
39
- end
13
+ def show_next_button?(workflow_execution)
14
+ return false if current_step_has_repetitions?(workflow_execution)
40
15
 
41
- def meta_chat_history
42
- 'meta_workflows/chat_history'
16
+ workflow_execution.step_advanceable?(workflow_execution.current_step)
43
17
  end
44
18
 
45
- def meta_streaming_response
46
- 'meta_workflows/streaming_response'
47
- end
19
+ def show_skip_button?(workflow_execution)
20
+ return false if current_step_has_repetitions?(workflow_execution)
48
21
 
49
- def meta_redirect
50
- 'meta_workflows/redirect'
22
+ workflow_execution.step_skippable?(workflow_execution.current_step)
51
23
  end
52
24
 
53
- def meta_lexi_chat_right_tray
54
- 'meta_workflows/lexi_chat_right_tray'
25
+ def default_step_progress
26
+ ['Thinking']
55
27
  end
56
28
 
57
- def meta_lexi_chat_alpha_tray
58
- 'meta_workflows/lexi_chat_alpha_tray'
59
- end
29
+ def show_structured_input?(local_assigns, structured_input_config)
30
+ current_step = local_assigns[:current_step]
60
31
 
61
- def tray_state(tray)
62
- (cookies['tray_'] && cookies['tray_'][tray.to_s]) || cookies["tray_#{tray}"] || 'expanded'
32
+ (structured_input_config.present? && !local_assigns[:initial_load]) ||
33
+ (local_assigns[:initial_load] && !current_step&.initial_execution?)
63
34
  end
64
35
 
65
- def chevron_direction(tray)
66
- state = tray_state(tray)
67
- case tray.to_s
68
- when 'beta'
69
- state == 'collapsed' ? 'fa-chevron-right' : 'fa-chevron-left'
70
- when 'gamma'
71
- state == 'collapsed' ? 'fa-chevron-left' : 'fa-chevron-right'
72
- when 'delta'
73
- state == 'collapsed' ? 'fa-chevron-up' : 'fa-chevron-down'
36
+ def current_step_and_config(active_execution, step_structured_input_config)
37
+ if active_execution.present?
38
+ [
39
+ active_execution.workflow_steps.order(:step).last,
40
+ step_structured_input_config
41
+ ]
74
42
  else
75
- ''
43
+ [nil, {}]
76
44
  end
77
45
  end
78
46
 
79
- def current_step_has_repetitions?(workflow_execution)
80
- workflow_execution.step_repetitions(workflow_execution.current_step).present?
47
+ # Consolidates all data fetching for the Lexi chat tray using service object
48
+ def lexi_chat_data(record)
49
+ LexiChatDataService.new(record).call
81
50
  end
82
51
 
83
- def show_next_button?(workflow_execution)
84
- return false if current_step_has_repetitions?(workflow_execution)
85
-
86
- workflow_execution.step_advanceable?(workflow_execution.current_step)
52
+ def structured_form_url(workflow_execution)
53
+ workflow_execution ? meta_workflows.structured_human_path(workflow_execution.id) : '#'
87
54
  end
88
55
 
89
- def show_skip_button?(workflow_execution)
90
- return false if current_step_has_repetitions?(workflow_execution)
91
-
92
- workflow_execution.step_skippable?(workflow_execution.current_step)
56
+ def structured_chat_id(local_assigns)
57
+ local_assigns[:chat_id] || local_assigns[:current_step]&.chat&.id
93
58
  end
94
59
 
95
- def default_step_progress
96
- ['Thinking']
60
+ # Common locals for lexi chat input area
61
+ def lexi_chat_input_locals(record, chat_data, wrapper_class)
62
+ {
63
+ record: record,
64
+ workflow_execution: chat_data[:active_execution],
65
+ current_step: chat_data[:current_step],
66
+ structured_input_config: chat_data[:structured_input_config],
67
+ chat_id: chat_data[:active_chat]&.id,
68
+ is_structured_input: chat_data[:is_structured_input],
69
+ wrapper_class: wrapper_class
70
+ }
97
71
  end
98
72
  end
99
73
  end
@@ -57,8 +57,9 @@ module MetaWorkflows
57
57
  locals: {
58
58
  record: record,
59
59
  chat_id: chat.id,
60
- structured_input_config: structured_input_config,
61
- is_structured_input: is_structured_input
60
+ workflow_execution: workflow_execution,
61
+ current_step: workflow_execution.workflow_steps&.order(:step)&.last,
62
+ structured_input_config: structured_input_config
62
63
  }
63
64
  )
64
65
  end
@@ -21,5 +21,15 @@ module MetaWorkflows
21
21
  def increment_step
22
22
  update(current_step: current_step + 1)
23
23
  end
24
+
25
+ # Get the latest workflow step with its chat (optimized for preloaded data)
26
+ def latest_workflow_step
27
+ workflow_steps.max_by(&:step)
28
+ end
29
+
30
+ # Get the chat from the latest step (optimized for preloaded data)
31
+ def latest_chat
32
+ latest_workflow_step&.chat
33
+ end
24
34
  end
25
35
  end
@@ -11,10 +11,18 @@ module MetaWorkflows
11
11
 
12
12
  has_one :workflow, through: :workflow_execution, class_name: 'MetaWorkflows::Workflow'
13
13
 
14
+ # Callbacks
15
+ before_save :mark_execution_started_if_chat_assigned
16
+
14
17
  # Scopes for error handling
15
18
  scope :with_errors, -> { where.not(error_message: nil) }
16
19
  scope :without_errors, -> { where(error_message: nil) }
17
20
 
21
+ # Initial execution methods
22
+ def initial_execution?
23
+ initial_execution
24
+ end
25
+
18
26
  # Error handling methods
19
27
  def error?
20
28
  error_message.present?
@@ -57,5 +65,13 @@ module MetaWorkflows
57
65
  update!(repetition: new_repetition)
58
66
  new_repetition
59
67
  end
68
+
69
+ private
70
+
71
+ def mark_execution_started_if_chat_assigned
72
+ return unless chat_id_changed? && chat_id.present? && initial_execution?
73
+
74
+ self.initial_execution = false
75
+ end
60
76
  end
61
77
  end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MetaWorkflows
4
+ class LexiChatDataService < ApplicationService
5
+ def initialize(record)
6
+ super()
7
+ @record = record
8
+ end
9
+
10
+ def call
11
+ executions = @record&.workflow_executions
12
+ active_execution = executions&.order(created_at: :desc)&.first
13
+
14
+ if active_execution
15
+ build_active_execution_data(active_execution)
16
+ else
17
+ build_empty_data
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :record
24
+
25
+ def build_active_execution_data(active_execution)
26
+ current_step = active_execution.latest_workflow_step
27
+ active_chat = active_execution.latest_chat
28
+ chat_history = active_execution.execution_chat_history
29
+ current_step_data = active_execution.step_data(active_execution.current_step)
30
+ step_structured_input_config = current_step_data&.dig('structured_input')
31
+ is_structured_input = step_structured_input_config.present? &&
32
+ current_step_data&.dig('action') == 'structured_human'
33
+
34
+ {
35
+ active_execution: active_execution,
36
+ current_step: current_step,
37
+ active_chat: active_chat,
38
+ chat_history: chat_history,
39
+ current_step_data: current_step_data,
40
+ step_structured_input_config: step_structured_input_config,
41
+ is_structured_input: is_structured_input,
42
+ structured_input_config: step_structured_input_config || {}
43
+ }
44
+ end
45
+
46
+ def build_empty_data
47
+ {
48
+ active_execution: nil,
49
+ current_step: nil,
50
+ active_chat: nil,
51
+ chat_history: nil,
52
+ current_step_data: nil,
53
+ step_structured_input_config: nil,
54
+ is_structured_input: false,
55
+ structured_input_config: {}
56
+ }
57
+ end
58
+ end
59
+ end
@@ -1,10 +1,5 @@
1
1
  <%# Lexi Chat Alpha Tray (Center Display) %>
2
- <% active_execution = local_assigns[:record]&.workflow_executions&.order(created_at: :desc)&.first %>
3
- <% active_chat = active_execution&.workflow_steps&.last&.chat %>
4
- <% chat_history = active_execution&.execution_chat_history %>
5
- <% current_step_data = active_execution&.step_data(active_execution&.current_step) %>
6
- <% step_structured_input_config = current_step_data&.dig('structured_input') %>
7
- <% is_structured_input = step_structured_input_config.present? && current_step_data&.dig('action') == 'structured_human' %>
2
+ <% chat_data = lexi_chat_data(local_assigns[:record]) %>
8
3
 
9
4
 
10
5
  <div class="lexi-chat-alpha-tray">
@@ -31,30 +26,15 @@
31
26
  <%# Right column - Chat and Input %>
32
27
  <div class="lexi-chat-alpha-right-column">
33
28
  <%# Scrollable chat messages area %>
34
- <div id="main-scroll-container" class="lexi-chat-alpha-messages">
35
- <%= render partial: meta_response, locals: {
36
- record: local_assigns[:record],
37
- chat_history: chat_history,
38
- current_user_messages: [],
39
- show_loader: false,
40
- show_error: false,
41
- step_progress: nil,
42
- full_response: nil,
43
- error_message: nil
44
- } %>
45
- </div>
29
+ <%= render partial: meta_lexi_chat_messages, locals: {
30
+ record: local_assigns[:record],
31
+ chat_history: chat_data[:chat_history],
32
+ container_class: 'lexi-chat-alpha-messages'
33
+ } %>
46
34
 
47
35
  <%# Input area (fixed at bottom) %>
48
36
  <div class="lexi-chat-alpha-input-area">
49
- <div class="lexi-chat-alpha-input-container" data-controller="meta-workflows--lexi-form-submit">
50
- <!-- Structured Input (always rendered, conditionally displays content) -->
51
- <%= render meta_structured_input, record: local_assigns[:record], structured_input_config: false, is_structured_input: false %>
52
-
53
- <!-- Regular Form Input (always present) -->
54
- <%= render partial: meta_response_form, locals: {record: local_assigns[:record], response_enabled: true,
55
- workflow_execution_id: active_execution&.id, chat_id: active_execution&.workflow_steps&.last&.chat&.id,
56
- workflow_execution: active_execution, is_structured_input: is_structured_input, show_skip_button: false, show_next_button: false } %>
57
- </div>
37
+ <%= render partial: meta_lexi_chat_input_area, locals: lexi_chat_input_locals(local_assigns[:record], chat_data, 'lexi-chat-alpha-input-container') %>
58
38
  </div>
59
39
  </div>
60
40
  </div>
@@ -0,0 +1,20 @@
1
+ <%# Shared input area %>
2
+ <div class="<%= local_assigns[:wrapper_class] || 'lexi-input-wrapper' %>" data-controller="meta-workflows--lexi-form-submit">
3
+ <%= render meta_structured_input,
4
+ record: local_assigns[:record],
5
+ workflow_execution: local_assigns[:workflow_execution],
6
+ current_step: local_assigns[:current_step],
7
+ structured_input_config: local_assigns[:structured_input_config],
8
+ initial_load: true %>
9
+
10
+ <%= render partial: meta_response_form, locals: {
11
+ record: local_assigns[:record],
12
+ response_enabled: true,
13
+ workflow_execution_id: local_assigns[:workflow_execution]&.id,
14
+ chat_id: local_assigns[:chat_id],
15
+ step_has_repetitions: true,
16
+ is_structured_input: local_assigns[:is_structured_input],
17
+ show_skip_button: false,
18
+ show_next_button: false
19
+ } %>
20
+ </div>
@@ -0,0 +1,13 @@
1
+ <%# Shared chat messages area %>
2
+ <div id="main-scroll-container" class="<%= local_assigns[:container_class] || 'lexi-chat-messages' %>">
3
+ <%= render partial: meta_response, locals: {
4
+ record: local_assigns[:record],
5
+ chat_history: local_assigns[:chat_history],
6
+ current_user_messages: [],
7
+ show_loader: false,
8
+ show_error: false,
9
+ step_progress: nil,
10
+ full_response: nil,
11
+ error_message: nil
12
+ } %>
13
+ </div>
@@ -1,10 +1,6 @@
1
- <%# Lexi Chat Tray %>
2
- <% active_execution = local_assigns[:record]&.workflow_executions&.order(created_at: :desc)&.first %>
3
- <% active_chat = active_execution&.workflow_steps&.last&.chat %>
4
- <% chat_history = active_execution&.execution_chat_history %>
5
- <% current_step_data = active_execution&.step_data(active_execution&.current_step) %>
6
- <% step_structured_input_config = current_step_data&.dig('structured_input') %>
7
- <% is_structured_input = step_structured_input_config.present? && current_step_data&.dig('action') == 'structured_human' %>
1
+ <%# Lexi Chat Tray (Right Side) %>
2
+ <% chat_data = lexi_chat_data(local_assigns[:record]) %>
3
+
8
4
 
9
5
  <div class="lexi-chat-tray lexi-chat-container-full">
10
6
  <!-- Header with Lexi logo and action icons -->
@@ -23,18 +19,11 @@
23
19
  </div>
24
20
 
25
21
  <!-- Chat messages area -->
26
- <div id="main-scroll-container" class="lexi-chat-messages">
27
- <%= render partial: meta_response, locals: {
28
- record: local_assigns[:record],
29
- chat_history: chat_history,
30
- current_user_messages: [],
31
- show_loader: false,
32
- show_error: false,
33
- step_progress: nil,
34
- full_response: nil,
35
- error_message: nil
36
- } %>
37
- </div>
22
+ <%= render partial: meta_lexi_chat_messages, locals: {
23
+ record: local_assigns[:record],
24
+ chat_history: chat_data[:chat_history],
25
+ container_class: 'lexi-chat-messages'
26
+ } %>
38
27
 
39
28
  <!-- Structured inputs area (above avatar) -->
40
29
  <div class="structured-input-area" data-controller="meta-workflows--lexi-form-submit">
@@ -44,9 +33,6 @@
44
33
  <!-- Avatar and input area pinned to bottom -->
45
34
  <div class="lexi-chat-bottom">
46
35
  <%= image_tag("lexi-expanded.png", alt: "Lexi Avatar", class: "lexi-avatar") %>
47
- <div class="lexi-input-wrapper">
48
- <%= render partial: meta_response_form, locals: {record: local_assigns[:record], response_enabled: true, workflow_execution_id: active_execution&.id,
49
- chat_id: active_execution&.workflow_steps&.last&.chat&.id, workflow_execution: active_execution, is_structured_input: is_structured_input } %>
50
- </div>
36
+ <%= render partial: meta_lexi_chat_input_area, locals: lexi_chat_input_locals(local_assigns[:record], chat_data, 'lexi-input-wrapper') %>
51
37
  </div>
52
38
  </div>
@@ -1,13 +1,8 @@
1
1
  <%= turbo_frame_tag target_frame_id(record, structured_input: true) do %>
2
- <% if local_assigns[:is_structured_input] && structured_input_config.present? %>
3
- <%
4
- # Get workflow execution for form submission
5
- workflow_execution = record.workflow_executions.order(created_at: :desc).first
6
- form_url = workflow_execution ? meta_workflows.structured_human_path(workflow_execution.id) : "#"
7
- chat_id = local_assigns[:chat_id] || workflow_execution&.workflow_steps&.last&.chat&.id
8
- %>
2
+
3
+ <% if show_structured_input?(local_assigns, structured_input_config) %>
9
4
 
10
- <%= form_with url: form_url,
5
+ <%= form_with url: structured_form_url(local_assigns[:workflow_execution]),
11
6
  method: :patch,
12
7
  id: "#{target_frame_id(record, structured_input: true)}_form",
13
8
  data: {
@@ -15,7 +10,7 @@
15
10
  "meta-workflows--structured-form-submit-target": "form",
16
11
  "meta-workflows--lexi-form-submit-target": "structuredInputForm"
17
12
  } do |form| %>
18
- <%= form.hidden_field :chat_id, value: chat_id %>
13
+ <%= form.hidden_field :chat_id, value: structured_chat_id(local_assigns) %>
19
14
 
20
15
  <div class="structured-input-wrapper">
21
16
  <% case structured_input_config['type'] %>
@@ -0,0 +1,5 @@
1
+ class AddInitialExecutionToMetaWorkflowsWorkflowSteps < ActiveRecord::Migration[7.2]
2
+ def change
3
+ add_column :meta_workflows_workflow_steps, :initial_execution, :boolean, default: true, null: false
4
+ end
5
+ end
@@ -3,7 +3,7 @@
3
3
  module MetaWorkflows
4
4
  MAJOR = 0
5
5
  MINOR = 9
6
- PATCH = 32 # this is automatically incremented by the build process
6
+ PATCH = 34 # this is automatically incremented by the build process
7
7
 
8
8
  VERSION = "#{MetaWorkflows::MAJOR}.#{MetaWorkflows::MINOR}.#{MetaWorkflows::PATCH}".freeze
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meta_workflows
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.32
4
+ version: 0.9.34
5
5
  platform: ruby
6
6
  authors:
7
7
  - Leonid Medovyy
@@ -138,6 +138,9 @@ files:
138
138
  - app/controllers/meta_workflows/meta_controller.rb
139
139
  - app/controllers/meta_workflows/structured_humans_controller.rb
140
140
  - app/controllers/meta_workflows/workflow_imports_controller.rb
141
+ - app/helpers/concerns/meta_workflows/frame_id_helper.rb
142
+ - app/helpers/concerns/meta_workflows/partial_paths_helper.rb
143
+ - app/helpers/concerns/meta_workflows/ui_state_helper.rb
141
144
  - app/helpers/meta_workflows/application_helper.rb
142
145
  - app/helpers/meta_workflows/debug_helper.rb
143
146
  - app/helpers/meta_workflows/execution_helper.rb
@@ -164,6 +167,7 @@ files:
164
167
  - app/models/meta_workflows/workflow_step.rb
165
168
  - app/services/meta_workflows/application_service.rb
166
169
  - app/services/meta_workflows/execution_filter_service.rb
170
+ - app/services/meta_workflows/lexi_chat_data_service.rb
167
171
  - app/services/meta_workflows/message_history_service.rb
168
172
  - app/services/meta_workflows/workflow_import_service.rb
169
173
  - app/sidekiq/meta_workflows/tools/meta_workflow_tool.rb
@@ -173,6 +177,8 @@ files:
173
177
  - app/views/meta_workflows/_checkbox_input.html.erb
174
178
  - app/views/meta_workflows/_error_message.html.erb
175
179
  - app/views/meta_workflows/_lexi_chat_alpha_tray.html.erb
180
+ - app/views/meta_workflows/_lexi_chat_input_area.html.erb
181
+ - app/views/meta_workflows/_lexi_chat_messages.html.erb
176
182
  - app/views/meta_workflows/_lexi_chat_right_tray.html.erb
177
183
  - app/views/meta_workflows/_loader_message.html.erb
178
184
  - app/views/meta_workflows/_radio_input.html.erb
@@ -201,6 +207,7 @@ files:
201
207
  - db/migrate/20250626211926_add_repetition_to_meta_workflows_workflow_steps.rb
202
208
  - db/migrate/20250709153017_add_recipe_to_meta_workflows_workflow_executions.rb
203
209
  - db/migrate/20250714192853_create_meta_workflows_execution_chat_histories.rb
210
+ - db/migrate/20250721195735_add_initial_execution_to_meta_workflows_workflow_steps.rb
204
211
  - lib/meta_workflows.rb
205
212
  - lib/meta_workflows/asset_installer.rb
206
213
  - lib/meta_workflows/configuration.rb