meta_workflows 0.9.20 → 0.9.22
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 +4 -4
- data/app/assets/javascripts/meta_workflows/controllers/lexi_form_submit_controller.js +12 -1
- data/app/assets/javascripts/meta_workflows/controllers/structured_form_submit_controller.js +36 -1
- data/app/assets/stylesheets/meta_workflows/application.css +7 -0
- data/app/controllers/concerns/meta_workflows/streamable.rb +59 -19
- data/app/controllers/meta_workflows/humans_controller.rb +4 -30
- data/app/controllers/meta_workflows/meta_controller.rb +33 -0
- data/app/controllers/meta_workflows/structured_humans_controller.rb +14 -38
- data/app/helpers/meta_workflows/application_helper.rb +1 -0
- data/app/helpers/meta_workflows/meta_workflows_helper.rb +14 -4
- data/app/jobs/meta_workflows/human_input_job.rb +7 -24
- data/app/jobs/meta_workflows/meta_job.rb +2 -2
- data/app/views/meta_workflows/_chat_history.html.erb +23 -0
- data/app/views/meta_workflows/_checkbox_input.html.erb +17 -1
- data/app/views/meta_workflows/_lexi_chat_alpha_tray.html.erb +7 -7
- data/app/views/meta_workflows/_lexi_chat_right_tray.html.erb +7 -5
- data/app/views/meta_workflows/_response_form_lexi.html.erb +1 -1
- data/app/views/meta_workflows/_response_lexi.html.erb +15 -42
- data/app/views/meta_workflows/_streaming_response.html.erb +17 -0
- data/app/views/meta_workflows/_structured_input.html.erb +5 -1
- data/lib/meta_workflows/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1404f6e59d744f270e2363b7a81860281c9b27c866b3cf9187e7fe7bf278005f
|
4
|
+
data.tar.gz: 767e829444443ca93c84dad56693a9cfc01bdae12e3a69bae66dff1259c3a4fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ce0f15c4e087743fdc3c70bb184f378af3ffc34e34863ceca30dbf8b68b0f35ead1605f4f8707149e2eb9496a97d6b96fd823a6f7ea686199af91c68bffc359
|
7
|
+
data.tar.gz: fc5d22929e95d6785ea16583167184ec378b9d2dfaf1784c051012b46ecc29287f1858647811d595df4dab4305fe839a95f3efe532deb409897bf4a4e049077d
|
@@ -1,12 +1,16 @@
|
|
1
1
|
import { Controller } from '@hotwired/stimulus';
|
2
2
|
|
3
3
|
export default class extends Controller {
|
4
|
-
static targets = ['textarea', 'form'];
|
4
|
+
static targets = ['textarea', 'form', 'structuredInputForm'];
|
5
5
|
|
6
6
|
connect() {
|
7
7
|
this.submitted = false;
|
8
8
|
}
|
9
9
|
|
10
|
+
textareaTargetConnected() {
|
11
|
+
this.submitted = false;
|
12
|
+
}
|
13
|
+
|
10
14
|
handleKeyDown(event) {
|
11
15
|
if (event.key === 'Enter' && !event.shiftKey) {
|
12
16
|
event.preventDefault();
|
@@ -25,6 +29,13 @@ export default class extends Controller {
|
|
25
29
|
}
|
26
30
|
|
27
31
|
this.submitted = true;
|
32
|
+
this.hideStructuredInputForm();
|
28
33
|
this.formTarget.requestSubmit();
|
29
34
|
}
|
35
|
+
|
36
|
+
hideStructuredInputForm() {
|
37
|
+
if (this.hasStructuredInputFormTarget) {
|
38
|
+
this.structuredInputFormTarget.style.display = 'none';
|
39
|
+
}
|
40
|
+
}
|
30
41
|
}
|
@@ -1,18 +1,53 @@
|
|
1
1
|
import { Controller } from '@hotwired/stimulus';
|
2
2
|
|
3
3
|
export default class extends Controller {
|
4
|
-
static targets = ['form', '
|
4
|
+
static targets = ['form', 'submitButton', 'checkbox'];
|
5
5
|
|
6
6
|
connect() {
|
7
7
|
this.submitted = false;
|
8
8
|
}
|
9
9
|
|
10
|
+
checkboxTargetConnected() {
|
11
|
+
this.updateSubmitButtonState();
|
12
|
+
}
|
13
|
+
|
14
|
+
checkboxTargetDisconnected() {
|
15
|
+
this.updateSubmitButtonState();
|
16
|
+
}
|
17
|
+
|
18
|
+
updateSubmitButtonState() {
|
19
|
+
if (!this.hasSubmitButtonTarget) return;
|
20
|
+
|
21
|
+
const hasSelection = this.checkboxTargets.some(checkbox => checkbox.checked);
|
22
|
+
this.submitButtonTarget.disabled = !hasSelection;
|
23
|
+
}
|
24
|
+
|
25
|
+
handleCheckboxChange() {
|
26
|
+
this.updateSubmitButtonState();
|
27
|
+
}
|
28
|
+
|
10
29
|
handleSubmit() {
|
11
30
|
if (this.submitted) {
|
12
31
|
return;
|
13
32
|
}
|
14
33
|
|
15
34
|
this.submitted = true;
|
35
|
+
this.hideFormAndSubmit();
|
36
|
+
}
|
37
|
+
|
38
|
+
handleCheckboxSubmit(event) {
|
39
|
+
event.preventDefault();
|
40
|
+
|
41
|
+
if (this.submitted) {
|
42
|
+
return;
|
43
|
+
}
|
44
|
+
|
45
|
+
this.submitted = true;
|
46
|
+
this.hideFormAndSubmit();
|
47
|
+
}
|
48
|
+
|
49
|
+
hideFormAndSubmit() {
|
50
|
+
this.formTarget.style.display = 'none';
|
16
51
|
this.formTarget.requestSubmit();
|
17
52
|
}
|
18
53
|
}
|
@@ -992,6 +992,13 @@
|
|
992
992
|
border: 1px solid var(--purple-200);
|
993
993
|
}
|
994
994
|
|
995
|
+
/* Structured Input Submit Container */
|
996
|
+
.structured-submit-container {
|
997
|
+
display: flex;
|
998
|
+
justify-content: flex-end;
|
999
|
+
margin-top: 1rem;
|
1000
|
+
}
|
1001
|
+
|
995
1002
|
/* Structured Input Submit Button */
|
996
1003
|
.structured-submit-button {
|
997
1004
|
width: 3rem;
|
@@ -17,9 +17,14 @@ module MetaWorkflows
|
|
17
17
|
|
18
18
|
Turbo::StreamsChannel.broadcast_replace_to(
|
19
19
|
turbo_stream_name(record),
|
20
|
-
target: target_frame_id(record,
|
21
|
-
partial:
|
22
|
-
locals: {
|
20
|
+
target: target_frame_id(record, streaming: true),
|
21
|
+
partial: meta_streaming_response,
|
22
|
+
locals: {
|
23
|
+
record: record,
|
24
|
+
show_loader: true,
|
25
|
+
step_progress: step_progress,
|
26
|
+
full_response: nil
|
27
|
+
}
|
23
28
|
)
|
24
29
|
end
|
25
30
|
|
@@ -27,22 +32,11 @@ module MetaWorkflows
|
|
27
32
|
def broadcast_error_response(workflow_execution)
|
28
33
|
record = workflow_execution.record
|
29
34
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
)
|
36
|
-
end
|
37
|
-
|
38
|
-
# Builds loader stream for direct response
|
39
|
-
def build_loader_stream(record:, workflow_execution:)
|
40
|
-
step_progress = workflow_execution.step_progress(workflow_execution.current_step) || default_step_progress
|
41
|
-
|
42
|
-
turbo_stream.replace(
|
43
|
-
target_frame_id(record, loader: true),
|
44
|
-
partial: meta_loader_message,
|
45
|
-
locals: { record: record, step_progress: step_progress }
|
35
|
+
broadcast_streaming_response(
|
36
|
+
record: record,
|
37
|
+
full_response: nil,
|
38
|
+
show_loader: false,
|
39
|
+
show_error: true
|
46
40
|
)
|
47
41
|
end
|
48
42
|
|
@@ -66,5 +60,51 @@ module MetaWorkflows
|
|
66
60
|
step_has_repetitions: current_step_has_repetitions?(workflow_execution)
|
67
61
|
}
|
68
62
|
end
|
63
|
+
|
64
|
+
# Builds chat history stream for instant user message display
|
65
|
+
def build_chat_history_stream(record:, workflow_execution:)
|
66
|
+
chat_history = workflow_execution.execution_chat_history
|
67
|
+
|
68
|
+
turbo_stream.replace(
|
69
|
+
target_frame_id(record, chat_history: true),
|
70
|
+
partial: meta_chat_history,
|
71
|
+
locals: {
|
72
|
+
record: record,
|
73
|
+
chat_history: chat_history,
|
74
|
+
current_user_messages: []
|
75
|
+
}
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Builds streaming response stream for loader display
|
80
|
+
def build_streaming_response_stream(record:, show_loader: false, step_progress: nil)
|
81
|
+
turbo_stream.replace(
|
82
|
+
target_frame_id(record, streaming: true),
|
83
|
+
partial: meta_streaming_response,
|
84
|
+
locals: {
|
85
|
+
record: record,
|
86
|
+
show_loader: show_loader,
|
87
|
+
step_progress: step_progress || default_step_progress,
|
88
|
+
full_response: nil
|
89
|
+
}
|
90
|
+
)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Broadcasts streaming response to the streaming frame
|
94
|
+
def broadcast_streaming_response(record:, full_response: nil, show_loader: false,
|
95
|
+
show_error: false, error_message: nil)
|
96
|
+
Turbo::StreamsChannel.broadcast_replace_to(
|
97
|
+
turbo_stream_name(record),
|
98
|
+
target: target_frame_id(record, streaming: true),
|
99
|
+
partial: meta_streaming_response,
|
100
|
+
locals: {
|
101
|
+
record: record,
|
102
|
+
full_response: full_response,
|
103
|
+
show_loader: show_loader,
|
104
|
+
show_error: show_error,
|
105
|
+
error_message: error_message
|
106
|
+
}
|
107
|
+
)
|
108
|
+
end
|
69
109
|
end
|
70
110
|
end
|
@@ -2,19 +2,19 @@
|
|
2
2
|
|
3
3
|
module MetaWorkflows
|
4
4
|
class HumansController < MetaController
|
5
|
-
include MetaWorkflows::MetaWorkflowsHelper
|
6
|
-
include MetaWorkflows::Streamable
|
7
5
|
before_action :set_workflow_data, only: [:update]
|
8
6
|
|
9
7
|
def update
|
8
|
+
append_user_message_to_history(params[:message]) if params[:message].present?
|
9
|
+
|
10
10
|
auto_advancing = should_auto_advance?
|
11
11
|
|
12
12
|
if params[:manual_advance].present? || auto_advancing
|
13
13
|
@workflow_execution.increment_step
|
14
|
-
|
14
|
+
render_processing_state_stream
|
15
15
|
process_human_input(auto_advancing:, manual_advancing: params[:manual_advance].present?)
|
16
16
|
else
|
17
|
-
|
17
|
+
render_processing_state_stream
|
18
18
|
process_human_input
|
19
19
|
end
|
20
20
|
end
|
@@ -44,31 +44,5 @@ module MetaWorkflows
|
|
44
44
|
}
|
45
45
|
)
|
46
46
|
end
|
47
|
-
|
48
|
-
def render_loader_stream
|
49
|
-
respond_to do |format|
|
50
|
-
format.turbo_stream do
|
51
|
-
render turbo_stream: [
|
52
|
-
build_loader_stream(record: @record, workflow_execution: @workflow_execution),
|
53
|
-
build_response_form_stream(record: @record, workflow_execution: @workflow_execution,
|
54
|
-
response_enabled: false, responding: false, chat_id: params[:chat_id])
|
55
|
-
]
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def render_response_form_stream
|
61
|
-
respond_to do |format|
|
62
|
-
format.turbo_stream do
|
63
|
-
render turbo_stream: build_response_form_stream(
|
64
|
-
record: @record,
|
65
|
-
workflow_execution: @workflow_execution,
|
66
|
-
response_enabled: true,
|
67
|
-
responding: true,
|
68
|
-
chat_id: params[:chat_id]
|
69
|
-
)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
47
|
end
|
74
48
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module MetaWorkflows
|
4
4
|
class MetaController < MetaWorkflows::ApplicationController
|
5
5
|
include MetaWorkflows::MetaWorkflowsHelper
|
6
|
+
include MetaWorkflows::Streamable
|
6
7
|
|
7
8
|
def set_workflow_data
|
8
9
|
@workflow_execution = MetaWorkflows::WorkflowExecution.includes(:record, :workflow,
|
@@ -21,5 +22,37 @@ module MetaWorkflows
|
|
21
22
|
def current_step_repetitions
|
22
23
|
@workflow_execution.step_repetitions(@workflow_execution.current_step)
|
23
24
|
end
|
25
|
+
|
26
|
+
def append_user_message_to_history(user_message)
|
27
|
+
message_data = {
|
28
|
+
role: 'user',
|
29
|
+
content: user_message,
|
30
|
+
model_id: nil,
|
31
|
+
input_tokens: nil,
|
32
|
+
output_tokens: nil,
|
33
|
+
created_at: Time.current.iso8601,
|
34
|
+
step: @workflow_execution.current_step
|
35
|
+
}
|
36
|
+
|
37
|
+
# Ensure ExecutionChatHistory exists
|
38
|
+
chat_history = @workflow_execution.execution_chat_history ||
|
39
|
+
@workflow_execution.create_execution_chat_history!
|
40
|
+
|
41
|
+
# Append the user message to the history
|
42
|
+
chat_history.append_message(message_data)
|
43
|
+
end
|
44
|
+
|
45
|
+
def render_processing_state_stream
|
46
|
+
respond_to do |format|
|
47
|
+
format.turbo_stream do
|
48
|
+
render turbo_stream: [
|
49
|
+
build_chat_history_stream(record: @record, workflow_execution: @workflow_execution),
|
50
|
+
build_streaming_response_stream(record: @record, show_loader: true),
|
51
|
+
build_response_form_stream(record: @record, workflow_execution: @workflow_execution,
|
52
|
+
response_enabled: false, responding: false, chat_id: params[:chat_id])
|
53
|
+
]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
24
57
|
end
|
25
58
|
end
|
@@ -2,72 +2,48 @@
|
|
2
2
|
|
3
3
|
module MetaWorkflows
|
4
4
|
class StructuredHumansController < MetaController
|
5
|
-
include MetaWorkflows::MetaWorkflowsHelper
|
6
|
-
include MetaWorkflows::Streamable
|
7
5
|
before_action :set_workflow_data, only: [:update]
|
8
6
|
|
9
7
|
def update
|
10
|
-
|
11
|
-
|
8
|
+
formatted_input = extract_and_format_structured_input
|
9
|
+
|
10
|
+
append_user_message_to_history(formatted_input) if formatted_input.present?
|
11
|
+
render_processing_state_stream
|
12
|
+
process_structured_human_input(formatted_input)
|
12
13
|
@workflow_execution.increment_step
|
13
14
|
end
|
14
15
|
|
15
16
|
private
|
16
17
|
|
17
|
-
def process_structured_human_input
|
18
|
+
def process_structured_human_input(formatted_input)
|
18
19
|
MetaWorkflows::HumanInputJob.perform_later(
|
19
20
|
user_id: current_user.id,
|
20
21
|
record: @record,
|
21
22
|
auto_advancing: true,
|
22
23
|
manual_advancing: false,
|
23
24
|
params: {
|
24
|
-
inputs:
|
25
|
+
inputs: formatted_input,
|
25
26
|
chat_id: params[:chat_id],
|
26
27
|
prompt_id: @prompt_id
|
27
28
|
}
|
28
29
|
)
|
29
30
|
end
|
30
31
|
|
31
|
-
def
|
32
|
+
def extract_and_format_structured_input
|
32
33
|
step_data = @workflow_execution.step_data(@workflow_execution.current_step)
|
33
34
|
structured_input_config = step_data&.dig('structured_input')
|
34
|
-
|
35
|
+
|
36
|
+
return params[:message].to_s unless structured_input_config
|
35
37
|
|
36
38
|
case structured_input_config['type']
|
37
39
|
when 'single_choice'
|
38
|
-
params[:single_choice_selection]
|
40
|
+
params[:single_choice_selection].to_s
|
39
41
|
when 'multiple_choice'
|
40
|
-
params[:multiple_choice_selections]
|
42
|
+
Array(params[:multiple_choice_selections]).join(', ')
|
41
43
|
when 'range'
|
42
|
-
params[:range_value]
|
44
|
+
params[:range_value].to_s
|
43
45
|
else
|
44
|
-
params[:message]
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def render_loader_stream
|
49
|
-
respond_to do |format|
|
50
|
-
format.turbo_stream do
|
51
|
-
render turbo_stream: [
|
52
|
-
build_loader_stream(record: @record, workflow_execution: @workflow_execution),
|
53
|
-
build_response_form_stream(record: @record, workflow_execution: @workflow_execution,
|
54
|
-
response_enabled: false, responding: false, chat_id: params[:chat_id])
|
55
|
-
]
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def render_response_form_stream
|
61
|
-
respond_to do |format|
|
62
|
-
format.turbo_stream do
|
63
|
-
render turbo_stream: build_response_form_stream(
|
64
|
-
record: @record,
|
65
|
-
workflow_execution: @workflow_execution,
|
66
|
-
response_enabled: true,
|
67
|
-
responding: true,
|
68
|
-
chat_id: params[:chat_id]
|
69
|
-
)
|
70
|
-
end
|
46
|
+
params[:message].to_s
|
71
47
|
end
|
72
48
|
end
|
73
49
|
end
|
@@ -2,12 +2,14 @@
|
|
2
2
|
|
3
3
|
module MetaWorkflows
|
4
4
|
module MetaWorkflowsHelper
|
5
|
-
def target_frame_id(record,
|
5
|
+
def target_frame_id(record, **options)
|
6
6
|
base_id = "#{record.class.name.downcase}_#{record.id}"
|
7
7
|
|
8
|
-
return "#{base_id}_loader" if loader
|
9
|
-
return "#{base_id}_form" if form
|
10
|
-
return "#{base_id}_structured_input" if structured_input
|
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]
|
11
13
|
|
12
14
|
base_id
|
13
15
|
end
|
@@ -36,6 +38,14 @@ module MetaWorkflows
|
|
36
38
|
'meta_workflows/response_lexi'
|
37
39
|
end
|
38
40
|
|
41
|
+
def meta_chat_history
|
42
|
+
'meta_workflows/chat_history'
|
43
|
+
end
|
44
|
+
|
45
|
+
def meta_streaming_response
|
46
|
+
'meta_workflows/streaming_response'
|
47
|
+
end
|
48
|
+
|
39
49
|
def meta_redirect
|
40
50
|
'meta_workflows/redirect'
|
41
51
|
end
|
@@ -23,31 +23,14 @@ module MetaWorkflows
|
|
23
23
|
@is_structured_input = structured_input_config.present? && current_step_data&.dig('action') == 'structured_human'
|
24
24
|
end
|
25
25
|
|
26
|
-
def broadcast_response(
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
Turbo::StreamsChannel.broadcast_remove_to(
|
34
|
-
turbo_stream_name(record),
|
35
|
-
target: target_frame_id(record, loader: true)
|
26
|
+
def broadcast_response(full_response)
|
27
|
+
# Update streaming response frame with LLM content
|
28
|
+
broadcast_streaming_response(
|
29
|
+
record: record,
|
30
|
+
full_response: full_response,
|
31
|
+
show_loader: false,
|
32
|
+
show_error: false
|
36
33
|
)
|
37
|
-
|
38
|
-
# Update main chat content
|
39
|
-
Turbo::StreamsChannel.broadcast_replace_to(turbo_stream_name(record),
|
40
|
-
target: target_frame_id(record),
|
41
|
-
locals: {
|
42
|
-
record: record,
|
43
|
-
chat: chat,
|
44
|
-
full_response: full_response,
|
45
|
-
user_messages: user_messages,
|
46
|
-
messages: messages,
|
47
|
-
last_message: last_message,
|
48
|
-
is_streaming: is_streaming
|
49
|
-
},
|
50
|
-
partial: meta_response)
|
51
34
|
end
|
52
35
|
|
53
36
|
def broadcast_form(chat)
|
@@ -65,7 +65,7 @@ module MetaWorkflows
|
|
65
65
|
def execute_llm_conversation(conversation)
|
66
66
|
conversation.call_llm do |chunk|
|
67
67
|
@full_response << (chunk.content || '')
|
68
|
-
broadcast_response(
|
68
|
+
broadcast_response(full_response) unless auto_advancing
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
@@ -99,7 +99,7 @@ module MetaWorkflows
|
|
99
99
|
raise NotImplementedError
|
100
100
|
end
|
101
101
|
|
102
|
-
def broadcast_response(
|
102
|
+
def broadcast_response(full_response)
|
103
103
|
raise NotImplementedError
|
104
104
|
end
|
105
105
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<%= turbo_frame_tag target_frame_id(record, chat_history: true) do %>
|
2
|
+
<div class="lexi-chat-history">
|
3
|
+
<!-- Show historical messages from ExecutionChatHistory -->
|
4
|
+
<% if local_assigns[:chat_history]&.history&.any? %>
|
5
|
+
<% local_assigns[:chat_history].history.each do |historical_message| %>
|
6
|
+
<% next if historical_message['role'] == 'system' %>
|
7
|
+
|
8
|
+
<% if historical_message['role'] == 'user' %>
|
9
|
+
<%= render 'meta_workflows/user_message_bubble', content: historical_message['content'] %>
|
10
|
+
<% elsif historical_message['role'] == 'assistant' %>
|
11
|
+
<%= render 'meta_workflows/assistant_message_bubble', content: historical_message['content'] %>
|
12
|
+
<% end %>
|
13
|
+
<% end %>
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
<!-- Show current user messages (for instant display) -->
|
17
|
+
<% if local_assigns[:current_user_messages]&.any? %>
|
18
|
+
<% local_assigns[:current_user_messages].each do |user_message| %>
|
19
|
+
<%= render 'meta_workflows/user_message_bubble', content: user_message %>
|
20
|
+
<% end %>
|
21
|
+
<% end %>
|
22
|
+
</div>
|
23
|
+
<% end %>
|
@@ -11,7 +11,8 @@
|
|
11
11
|
name="multiple_choice_selections[]"
|
12
12
|
value="<%= option['value'] %>"
|
13
13
|
class="structured-checkbox-input"
|
14
|
-
data-
|
14
|
+
data-meta-workflows--structured-form-submit-target="checkbox"
|
15
|
+
data-action="change->meta-workflows--structured-form-submit#handleCheckboxChange"
|
15
16
|
aria-describedby="structured-checkbox-help"
|
16
17
|
>
|
17
18
|
<label for="multiple_choice_<%= index %>" class="structured-checkbox-label">
|
@@ -21,4 +22,19 @@
|
|
21
22
|
<% end %>
|
22
23
|
</div>
|
23
24
|
<div id="structured-checkbox-help" class="sr-only">Use space to select/deselect options</div>
|
25
|
+
|
26
|
+
<div class="structured-submit-container">
|
27
|
+
<button
|
28
|
+
type="submit"
|
29
|
+
class="structured-submit-button"
|
30
|
+
data-meta-workflows--structured-form-submit-target="submitButton"
|
31
|
+
data-action="click->meta-workflows--structured-form-submit#handleCheckboxSubmit"
|
32
|
+
disabled
|
33
|
+
aria-describedby="structured-submit-help"
|
34
|
+
aria-label="Submit your selections"
|
35
|
+
>
|
36
|
+
<i class="fa-solid fa-arrow-up"></i>
|
37
|
+
</button>
|
38
|
+
<div id="structured-submit-help" class="sr-only">Submit your selections. Button is disabled until at least one option is selected.</div>
|
39
|
+
</div>
|
24
40
|
</div>
|
@@ -30,19 +30,19 @@
|
|
30
30
|
<div id="main-scroll-container" class="lexi-chat-alpha-messages">
|
31
31
|
<%= render partial: meta_response, locals: {
|
32
32
|
record: local_assigns[:record],
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
chat_history: chat_history,
|
34
|
+
current_user_messages: [],
|
35
|
+
show_loader: false,
|
36
|
+
show_error: false,
|
37
|
+
step_progress: nil,
|
37
38
|
full_response: nil,
|
38
|
-
|
39
|
-
chat_history: chat_history
|
39
|
+
error_message: nil
|
40
40
|
} %>
|
41
41
|
</div>
|
42
42
|
|
43
43
|
<%# Input area (fixed at bottom) %>
|
44
44
|
<div class="lexi-chat-alpha-input-area">
|
45
|
-
<div class="lexi-chat-alpha-input-container">
|
45
|
+
<div class="lexi-chat-alpha-input-container" data-controller="meta-workflows--lexi-form-submit">
|
46
46
|
<!-- Structured Input (always rendered, conditionally displays content) -->
|
47
47
|
<%= render meta_structured_input, record: local_assigns[:record], structured_input_config: false, is_structured_input: false %>
|
48
48
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
<%# Lexi Chat Tray %>
|
2
2
|
<% active_execution = local_assigns[:record]&.workflow_executions&.order(created_at: :desc)&.first %>
|
3
3
|
<% active_chat = active_execution&.workflow_steps&.last&.chat %>
|
4
|
+
<% chat_history = active_execution&.execution_chat_history %>
|
4
5
|
|
5
6
|
<div class="lexi-chat-tray lexi-chat-container-full">
|
6
7
|
<!-- Header with Lexi logo and action icons -->
|
@@ -22,12 +23,13 @@
|
|
22
23
|
<div id="main-scroll-container" class="lexi-chat-messages">
|
23
24
|
<%= render partial: meta_response, locals: {
|
24
25
|
record: local_assigns[:record],
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
chat_history: chat_history,
|
27
|
+
current_user_messages: [],
|
28
|
+
show_loader: false,
|
29
|
+
show_error: false,
|
30
|
+
step_progress: nil,
|
29
31
|
full_response: nil,
|
30
|
-
|
32
|
+
error_message: nil
|
31
33
|
} %>
|
32
34
|
</div>
|
33
35
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
<%= form_with url: workflow_execution_id.present? ? meta_workflows.human_path(workflow_execution_id) : "#",
|
4
4
|
method: :patch,
|
5
5
|
id: "#{target_frame_id(record, form: true)}_lexi",
|
6
|
-
data: {
|
6
|
+
data: { "meta-workflows--lexi-form-submit-target": "form" } do |form| %>
|
7
7
|
<%= form.hidden_field :chat_id, value: chat_id %>
|
8
8
|
<% if local_assigns[:is_structured_input] %>
|
9
9
|
<%= form.hidden_field :auto_advance, value: true %>
|
@@ -1,49 +1,22 @@
|
|
1
1
|
<%= turbo_frame_tag target_frame_id(record) do %>
|
2
2
|
<div id="response-content-container" class="lexi-response-container" data-controller="response-scroll">
|
3
3
|
|
4
|
-
<!--
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
<%= render 'meta_workflows/user_message_bubble', content: historical_message['content'] %>
|
11
|
-
<% elsif historical_message['role'] == 'assistant' %>
|
12
|
-
<%= render 'meta_workflows/assistant_message_bubble', content: historical_message['content'] %>
|
13
|
-
<% end %>
|
14
|
-
<% end %>
|
15
|
-
<% end %>
|
4
|
+
<!-- Persistent Chat History Frame -->
|
5
|
+
<%= render partial: meta_chat_history, locals: {
|
6
|
+
record: record,
|
7
|
+
chat_history: local_assigns[:chat_history],
|
8
|
+
current_user_messages: local_assigns[:current_user_messages] || []
|
9
|
+
} %>
|
16
10
|
|
17
|
-
|
18
|
-
|
19
|
-
|
11
|
+
<!-- Streaming Response Frame -->
|
12
|
+
<%= render partial: meta_streaming_response, locals: {
|
13
|
+
record: record,
|
14
|
+
show_loader: local_assigns[:show_loader] || false,
|
15
|
+
show_error: local_assigns[:show_error] || false,
|
16
|
+
step_progress: local_assigns[:step_progress],
|
17
|
+
full_response: local_assigns[:full_response],
|
18
|
+
error_message: local_assigns[:error_message]
|
19
|
+
} %>
|
20
20
|
|
21
|
-
<!-- Show all saved messages except the first user message -->
|
22
|
-
<% messages.each_with_index do |message, index| %>
|
23
|
-
<% next if message.role == 'system' %>
|
24
|
-
<% next if message.role == 'user' && message == user_messages.first %>
|
25
|
-
<% next if is_streaming && message.role == 'assistant' && message == last_message %>
|
26
|
-
|
27
|
-
<% if message.role == 'user' %>
|
28
|
-
<%= render 'meta_workflows/user_message_bubble', content: message.content %>
|
29
|
-
<% elsif message.role == 'assistant' %>
|
30
|
-
<%= render 'meta_workflows/assistant_message_bubble', content: message.content %>
|
31
|
-
<% end %>
|
32
|
-
<% end %>
|
33
|
-
|
34
|
-
<%= render 'meta_workflows/assistant_message_bubble', content: full_response %>
|
35
|
-
<% end %>
|
36
|
-
<% end %>
|
37
|
-
|
38
|
-
<div class="lexi-loader-container">
|
39
|
-
<%= turbo_frame_tag target_frame_id(record, loader: true) do %>
|
40
|
-
<% if chat.blank? || chat.messages.empty? %>
|
41
|
-
<%= render partial: meta_loader_message, locals: {
|
42
|
-
record: local_assigns[:record],
|
43
|
-
step_progress: default_step_progress
|
44
|
-
} %>
|
45
|
-
<% end %>
|
46
|
-
<% end %>
|
47
|
-
</div>
|
48
21
|
</div>
|
49
22
|
<% end %>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<%= turbo_frame_tag target_frame_id(record, streaming: true) do %>
|
2
|
+
<div class="lexi-streaming-response">
|
3
|
+
<% if local_assigns[:show_loader] %>
|
4
|
+
<!-- Show loader message -->
|
5
|
+
<%= render partial: meta_loader_message, locals: {
|
6
|
+
record: record,
|
7
|
+
step_progress: local_assigns[:step_progress] || default_step_progress
|
8
|
+
} %>
|
9
|
+
<% elsif local_assigns[:show_error] %>
|
10
|
+
<!-- Show error message -->
|
11
|
+
<%= render partial: meta_error_message, locals: { record: record } %>
|
12
|
+
<% elsif local_assigns[:full_response].present? %>
|
13
|
+
<!-- Show streaming LLM response -->
|
14
|
+
<%= render 'meta_workflows/assistant_message_bubble', content: local_assigns[:full_response] %>
|
15
|
+
<% end %>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
@@ -10,7 +10,11 @@
|
|
10
10
|
<%= form_with url: form_url,
|
11
11
|
method: :patch,
|
12
12
|
id: "#{target_frame_id(record, structured_input: true)}_form",
|
13
|
-
data: {
|
13
|
+
data: {
|
14
|
+
controller: "meta-workflows--structured-form-submit",
|
15
|
+
"meta-workflows--structured-form-submit-target": "form",
|
16
|
+
"meta-workflows--lexi-form-submit-target": "structuredInputForm"
|
17
|
+
} do |form| %>
|
14
18
|
<%= form.hidden_field :chat_id, value: chat_id %>
|
15
19
|
|
16
20
|
<div class="structured-input-wrapper">
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module MetaWorkflows
|
4
4
|
MAJOR = 0
|
5
5
|
MINOR = 9
|
6
|
-
PATCH =
|
6
|
+
PATCH = 22 # 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.
|
4
|
+
version: 0.9.22
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leonid Medovyy
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2025-07-
|
12
|
+
date: 2025-07-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -168,6 +168,7 @@ files:
|
|
168
168
|
- app/sidekiq/meta_workflows/tools/meta_workflow_tool.rb
|
169
169
|
- app/views/layouts/meta_workflows/application.html.erb
|
170
170
|
- app/views/meta_workflows/_assistant_message_bubble.html.erb
|
171
|
+
- app/views/meta_workflows/_chat_history.html.erb
|
171
172
|
- app/views/meta_workflows/_checkbox_input.html.erb
|
172
173
|
- app/views/meta_workflows/_error_message.html.erb
|
173
174
|
- app/views/meta_workflows/_lexi_chat_alpha_tray.html.erb
|
@@ -178,6 +179,7 @@ files:
|
|
178
179
|
- app/views/meta_workflows/_response_form_lexi.html.erb
|
179
180
|
- app/views/meta_workflows/_response_lexi.html.erb
|
180
181
|
- app/views/meta_workflows/_slider_input.html.erb
|
182
|
+
- app/views/meta_workflows/_streaming_response.html.erb
|
181
183
|
- app/views/meta_workflows/_structured_input.html.erb
|
182
184
|
- app/views/meta_workflows/_user_message_bubble.html.erb
|
183
185
|
- app/views/meta_workflows/debug/executions.html.erb
|