meta_workflows 0.8.6 → 0.8.7

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: 6b77a7e4c35c915d045693675b711c52ba87a3eac9ba5f16d2dcff556131ebda
4
- data.tar.gz: 0d519f2f1e2999a52ecb161a20a3761e9acf441b254303f4607fc225cace5b98
3
+ metadata.gz: 20f6cdd2bd711b98e1961eafc5221ae7972df75bda8b5fad2ffe01d376baa7dc
4
+ data.tar.gz: 97b70ce3e211bc1735acd1f40108b13b0700cfe9a1d36d26ca8f4709927339da
5
5
  SHA512:
6
- metadata.gz: c87dee53a2e8c5f3dfb2f2ec96b1888499a2ce850327910a6062c9e1fede1b727846f29e065a274204c7a233c35e67752665cad46c812227b61256d39588fbca
7
- data.tar.gz: 88c0bd57ebc8310bee5dba554672167714159c152dd2952c05566053c6e262b5567c05f04b8ffe5fb22e8bd33e2f15ee5bde8ccd196e2d343fead326b86d5123
6
+ metadata.gz: d682e32e43cb0d06e99fd8dcf7e703eff7bb763fc3f087d5347c98e6365dd340d455fc6de6fe4a5c079de519198888d18bc0076162f773b323238c8492e3d0ec
7
+ data.tar.gz: 534fbd9b1c6282d6615c0eb5261bd2b6477655b678978cc59d86f6c82e25790cc30fb337198680de03e07d25fc5a3566669ef51f10fdfe28a17df3f0e70b3545
@@ -10,16 +10,19 @@ module TrayConfigurable
10
10
  def tray_config
11
11
  @tray_config ||= {
12
12
  beta: {
13
- visible: false,
14
- collapsible: true
13
+ visible: true,
14
+ collapsible: true,
15
+ lexi: false
15
16
  },
16
17
  gamma: {
17
- visible: false,
18
- collapsible: true
18
+ visible: true,
19
+ collapsible: true,
20
+ lexi: false
19
21
  },
20
22
  delta: {
21
- visible: false,
22
- collapsible: true
23
+ visible: true,
24
+ collapsible: true,
25
+ lexi: false
23
26
  }
24
27
  }
25
28
  end
@@ -16,11 +16,11 @@ module MetaWorkflows
16
16
  end
17
17
 
18
18
  def meta_response_form
19
- 'meta_workflows/response_form'
19
+ 'meta_workflows/response_form_lexi'
20
20
  end
21
21
 
22
22
  def meta_response
23
- 'meta_workflows/response'
23
+ 'meta_workflows/response_lexi'
24
24
  end
25
25
 
26
26
  def meta_redirect
@@ -13,10 +13,23 @@ module MetaWorkflows
13
13
 
14
14
  private
15
15
 
16
- def broadcast_response(response)
16
+ def broadcast_response(chat, full_response)
17
+ user_messages = chat.messages.where(role: 'user').order(:created_at)
18
+ messages = chat.messages.order(:created_at)
19
+ last_message = messages.last
20
+ is_streaming = full_response.present?
21
+
17
22
  Turbo::StreamsChannel.broadcast_replace_to(turbo_stream_name(record),
18
23
  target: target_frame_id(record),
19
- locals: { record: record, response: response },
24
+ locals: {
25
+ record: record,
26
+ chat: chat,
27
+ full_response: full_response,
28
+ user_messages: user_messages,
29
+ messages: messages,
30
+ last_message: last_message,
31
+ is_streaming: is_streaming
32
+ },
20
33
  partial: meta_response)
21
34
  end
22
35
 
@@ -9,6 +9,7 @@ module MetaWorkflows
9
9
  def setup(user_id, record)
10
10
  @user_id = user_id
11
11
  @record = record.class.find(record.id)
12
+ @full_response = +''
12
13
  end
13
14
 
14
15
  def initialize_conversation(params)
@@ -26,8 +27,6 @@ module MetaWorkflows
26
27
  current_step = workflow_execution.workflow_steps.find_by(step: workflow_execution.current_step)
27
28
  @chat = current_step&.chat
28
29
 
29
- @full_response = +''
30
-
31
30
  conversation = RubyConversations::Conversation.new(chat:)
32
31
  conversation.with_prompt(params[:prompt_id], inputs: inputs, description: "Running #{params[:prompt_id]} process")
33
32
  end
@@ -35,11 +34,8 @@ module MetaWorkflows
35
34
  def continue_existing_conversation(params)
36
35
  @chat = MetaWorkflows::Chat.find(params[:chat_id])
37
36
  conversation = RubyConversations::Conversation.new(chat:, id: chat.conversation_id)
38
-
39
37
  new_message = params[:inputs]
40
38
  conversation.with_user_message(new_message, description: "Following up on #{params[:prompt_id]} process")
41
- @full_response = chat.messages[1..].map(&:content).join + format_user_message(new_message)
42
-
43
39
  conversation
44
40
  end
45
41
 
@@ -62,14 +58,13 @@ module MetaWorkflows
62
58
 
63
59
  def execute_llm_conversation(conversation)
64
60
  conversation.call_llm do |chunk|
65
- full_response << (chunk.content || '')
66
- broadcast_response(full_response)
61
+ @full_response << (chunk.content || '')
62
+ broadcast_response(chat, full_response)
67
63
  end
68
64
  end
69
65
 
70
66
  def finalize_conversation(conversation)
71
67
  chat.update!(conversation_id: conversation.id) if chat.conversation_id.blank?
72
- broadcast_response(full_response)
73
68
  broadcast_form(chat)
74
69
  end
75
70
 
@@ -101,21 +96,16 @@ module MetaWorkflows
101
96
  end
102
97
 
103
98
  def broadcast_error_response(error)
104
- error_message = "Error occurred during LLM processing: #{error.message}"
105
- broadcast_response(error_message)
106
- end
107
-
108
- def broadcast_response(response)
109
- raise NotImplementedError
99
+ error_message = "Error occured during LLM processing: #{error.message}"
100
+ broadcast_response(chat, error_message)
110
101
  end
111
102
 
112
103
  def broadcast_form(chat)
113
104
  raise NotImplementedError
114
105
  end
115
106
 
116
- def format_user_message(message)
117
- '<div class="flex p-4 border border-slate-300 rounded-xl bg-white text-xl ' \
118
- "font-semibold leading-snug\">#{message}</div>\n\n"
107
+ def broadcast_response(chat, full_response)
108
+ raise NotImplementedError
119
109
  end
120
110
  end
121
111
  end
@@ -0,0 +1,53 @@
1
+ <%= turbo_frame_tag target_frame_id(record, form: true) do %>
2
+ <% if local_assigns[:response_enabled] %>
3
+ <div>
4
+ <%= form_with url: (workflow_execution_id.present? ? meta_workflows.human_path(workflow_execution_id) : "#"), method: :patch do |form| %>
5
+ <%= form.hidden_field :chat_id, value: chat_id %>
6
+ <fieldset>
7
+ <div class="flex flex-col gap-1">
8
+ <!-- Input Container -->
9
+ <div class="flex flex-col max-h-[200px] border border-gray-300 rounded-lg bg-white/80 p-2">
10
+ <!-- Input area with icons -->
11
+ <div class="flex-1 relative">
12
+ <%= form.text_area :message, rows: 1, placeholder: random_chat_placeholder, disabled: local_assigns[:responding], class: "w-full min-h-[50px] border-0 resize-none focus:outline-none focus:ring-0 bg-transparent text-base overflow-y-auto" %>
13
+ </div>
14
+
15
+ <div class="flex justify-between">
16
+ <div class="flex gap-1 items-end justify-end">
17
+ <button type="button" class="p-2 rounded-xl hover:bg-gray-100" disabled>
18
+ <i class="fa-solid fa-microphone text-lg"></i>
19
+ </button>
20
+ <button type="button" class="p-2 rounded-xl hover:bg-gray-100" disabled>
21
+ <i class="fa-solid fa-headphones text-lg"></i>
22
+ </button>
23
+ <button type="button" class="p-2 rounded-xl hover:bg-gray-100" disabled>
24
+ <i class="fa-solid fa-waveform-lines text-lg"></i>
25
+ </button>
26
+ </div>
27
+ <div>
28
+ <!-- Send button -->
29
+ <% if local_assigns[:responding] %>
30
+ <button type="button" class="w-12 h-12 rounded-full flex items-center justify-center text-white transition-colors bg-purple-600 opacity-50 cursor-not-allowed" disabled>
31
+ <i class="fa-solid fa-arrow-up text-lg"></i>
32
+ </button>
33
+ <% else %>
34
+ <%= form.button type: "submit", class: "w-12 h-12 rounded-full flex items-center justify-center text-white bg-purple-600 transition-colors focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2" do %>
35
+ <i class="fa-solid fa-arrow-up text-lg"></i>
36
+ <% end %>
37
+ <% end %>
38
+ </div>
39
+ </div>
40
+ </div>
41
+
42
+ <!-- Next Button (outside input container) -->
43
+ <div class="flex justify-end">
44
+ <%= form.button type: "submit", name: "advance", value: "true", class: "text-xs mb-2 #{local_assigns[:responding] ? 'opacity-50 cursor-not-allowed' : ''}", disabled: local_assigns[:responding] do %>
45
+ <i class="fa-light fa-arrow-right"></i> Next
46
+ <% end %>
47
+ </div>
48
+ </div>
49
+ </fieldset>
50
+ <% end %>
51
+ </div>
52
+ <% end %>
53
+ <% end %>
@@ -0,0 +1,57 @@
1
+ <%= turbo_frame_tag target_frame_id(record) do %>
2
+ <div id="response-content-container" class="space-y-4" data-controller="response-scroll">
3
+ <% if chat.present? && chat.messages.any? %>
4
+
5
+ <!-- Show all saved messages except the first user message -->
6
+ <% messages.each_with_index do |message, index| %>
7
+ <% next if message.role == 'system' %>
8
+ <% next if message.role == 'user' && message == user_messages.first %>
9
+ <% next if is_streaming && message.role == 'assistant' && message == last_message %>
10
+
11
+ <% if message.role == 'user' %>
12
+ <!-- User message bubble (right-aligned, amber background) -->
13
+ <div class="flex justify-end">
14
+ <div class="max-w-[80%] bg-amber-100 rounded-xl px-4 py-2">
15
+ <div class="text-sm">
16
+ <%= simple_format(message.content) %>
17
+ </div>
18
+ </div>
19
+ </div>
20
+
21
+ <% elsif message.role == 'assistant' %>
22
+ <!-- Lexi message bubble (left-aligned with avatar) -->
23
+ <div class="flex items-start space-x-3">
24
+ <!-- Lexi Avatar -->
25
+ <div class="flex-shrink-0">
26
+ <%= image_tag 'lexi-chaticon.png', alt: 'Lexi', class: 'w-auto h-10' %>
27
+ </div>
28
+
29
+ <!-- Message Bubble -->
30
+ <div class="max-w-[80%] bg-slate-100 rounded-xl px-4 py-2">
31
+ <div class="prose prose-sm max-w-none text-sm">
32
+ <%= markdown(message.content) %>
33
+ </div>
34
+ </div>
35
+ </div>
36
+ <% end %>
37
+ <% end %>
38
+
39
+ <!-- Show streaming response -->
40
+ <% if is_streaming %>
41
+ <div class="flex items-start space-x-3">
42
+ <!-- Lexi Avatar -->
43
+ <div class="flex-shrink-0">
44
+ <%= image_tag 'lexi-chaticon.png', alt: 'Lexi', class: 'w-auto h-10' %>
45
+ </div>
46
+
47
+ <!-- Streaming Message Bubble -->
48
+ <div class="max-w-[80%] bg-slate-100 rounded-xl px-4 py-2">
49
+ <div class="prose prose-sm max-w-none text-sm">
50
+ <%= markdown(full_response) %>
51
+ </div>
52
+ </div>
53
+ </div>
54
+ <% end %>
55
+ <% end %>
56
+ </div>
57
+ <% end %>
@@ -3,7 +3,7 @@
3
3
  module MetaWorkflows
4
4
  MAJOR = 0
5
5
  MINOR = 8
6
- PATCH = 6 # this is automatically incremented by the build process
6
+ PATCH = 7 # 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.8.6
4
+ version: 0.8.7
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-06-24 00:00:00.000000000 Z
12
+ date: 2025-06-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -152,8 +152,8 @@ files:
152
152
  - app/views/layouts/meta_workflows/debug.html.erb
153
153
  - app/views/meta_workflows/_loader.html.erb
154
154
  - app/views/meta_workflows/_redirect.html.erb
155
- - app/views/meta_workflows/_response.html.erb
156
- - app/views/meta_workflows/_response_form.html.erb
155
+ - app/views/meta_workflows/_response_form_lexi.html.erb
156
+ - app/views/meta_workflows/_response_lexi.html.erb
157
157
  - app/views/meta_workflows/debug/executions.html.erb
158
158
  - app/views/meta_workflows/debug/show_execution.html.erb
159
159
  - app/views/meta_workflows/debug/show_workflow.html.erb
@@ -1,5 +0,0 @@
1
- <%= turbo_frame_tag target_frame_id(record) do %>
2
- <div id="response-content-container" class="meta-workflows chat" data-controller="response-scroll">
3
- <%= markdown(response) %>
4
- </div>
5
- <% end %>
@@ -1,36 +0,0 @@
1
- <%= turbo_frame_tag target_frame_id(record, form: true) do %>
2
- <% if local_assigns[:response_enabled] %>
3
- <div>
4
- <%= form_with url: meta_workflows.human_path(workflow_execution_id), method: :patch do |form| %>
5
- <%= form.hidden_field :chat_id, value: chat_id %>
6
- <fieldset>
7
- <div class="flex flex-col gap-5">
8
- <div class="flex gap-2">
9
- <%= form.text_area :message, rows: 3, placeholder: random_chat_placeholder, disabled: local_assigns[:responding], class: "flex-1" %>
10
-
11
- <% if local_assigns[:responding] %>
12
- <button type="button" class="sm-btn sm-btn-primary self-start" disabled>
13
- <i class="fa-light fa-spinner fa-spin mr-1"></i> Generating...
14
- </button>
15
- <% else %>
16
- <%= form.button type: "submit", class: "sm-btn sm-btn-outline" do %>
17
- <i class="fa-light fa-paper-plane"></i>
18
- <% end %>
19
- <% end %>
20
- </div>
21
-
22
- <hr/>
23
-
24
- <% unless local_assigns[:responding] %>
25
- <div class="flex justify-end">
26
- <%= form.button type: "submit", name: "advance", value: "true", class: "sm-btn sm-btn-primary sm-btn-large" do %>
27
- <i class="fa-light fa-arrow-right"></i> Next
28
- <% end %>
29
- </div>
30
- <% end %>
31
- </div>
32
- </fieldset>
33
- <% end %>
34
- </div>
35
- <% end %>
36
- <% end %>