collavre 0.5.0 → 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.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/collavre/comment_versions.css +76 -0
- data/app/assets/stylesheets/collavre/comments_popup.css +347 -37
- data/app/assets/stylesheets/collavre/creatives.css +73 -1
- data/app/assets/stylesheets/collavre/org_chart.css +319 -0
- data/app/assets/stylesheets/collavre/popup.css +68 -1
- data/app/controllers/collavre/application_controller.rb +13 -0
- data/app/controllers/collavre/comments/versions_controller.rb +82 -0
- data/app/controllers/collavre/comments_controller.rb +14 -153
- data/app/controllers/collavre/concerns/exportable.rb +30 -0
- data/app/controllers/collavre/concerns/shareable.rb +28 -0
- data/app/controllers/collavre/concerns/slide_viewable.rb +37 -0
- data/app/controllers/collavre/concerns/tree_manageable.rb +141 -0
- data/app/controllers/collavre/creative_imports_controller.rb +6 -0
- data/app/controllers/collavre/creative_invitations_controller.rb +46 -0
- data/app/controllers/collavre/creative_plans_controller.rb +1 -1
- data/app/controllers/collavre/creative_shares_controller.rb +84 -14
- data/app/controllers/collavre/creatives_controller.rb +70 -194
- data/app/controllers/collavre/google_auth_controller.rb +3 -0
- data/app/controllers/collavre/invites_controller.rb +2 -1
- data/app/controllers/collavre/sessions_controller.rb +3 -0
- data/app/controllers/collavre/topics_controller.rb +39 -2
- data/app/controllers/collavre/users_controller.rb +5 -404
- data/app/controllers/concerns/collavre/comments/approval_actions.rb +108 -0
- data/app/controllers/concerns/collavre/comments/batch_operations.rb +55 -0
- data/app/controllers/concerns/collavre/comments/conversion.rb +46 -0
- data/app/controllers/concerns/collavre/users_controller/admin_operations.rb +74 -0
- data/app/controllers/concerns/collavre/users_controller/ai_user_management.rb +119 -0
- data/app/controllers/concerns/collavre/users_controller/contact_management.rb +166 -0
- data/app/controllers/concerns/collavre/users_controller/profile_and_settings.rb +102 -0
- data/app/controllers/concerns/collavre/users_controller/registration.rb +63 -0
- data/app/helpers/collavre/application_helper.rb +1 -0
- data/app/helpers/collavre/creatives_helper.rb +12 -9
- data/app/helpers/collavre/navigation_helper.rb +1 -1
- data/app/javascript/collavre.js +0 -1
- data/app/javascript/controllers/comment_controller.js +33 -70
- data/app/javascript/controllers/comment_version_controller.js +164 -0
- data/app/javascript/controllers/comments/__tests__/form_controller_review.test.js +305 -0
- data/app/javascript/controllers/comments/__tests__/list_controller_selection.test.js +103 -0
- data/app/javascript/controllers/comments/__tests__/review_quotes_store.test.js +113 -0
- data/app/javascript/controllers/comments/contexts_controller.js +363 -0
- data/app/javascript/controllers/comments/form_controller.js +304 -13
- data/app/javascript/controllers/comments/list_controller.js +151 -62
- data/app/javascript/controllers/comments/popup_controller.js +66 -38
- data/app/javascript/controllers/comments/presence_controller.js +2 -10
- data/app/javascript/controllers/comments/review_quotes_store.js +189 -0
- data/app/javascript/controllers/comments/topics_controller.js +34 -10
- data/app/javascript/controllers/index.js +15 -1
- data/app/javascript/controllers/org_chart_controller.js +46 -0
- data/app/javascript/controllers/share_modal_controller.js +369 -0
- data/app/javascript/controllers/topic_search_controller.js +103 -0
- data/app/javascript/creatives/drag_drop/event_handlers.js +42 -1
- data/app/javascript/lib/api/creatives.js +12 -0
- data/app/javascript/lib/api/csrf_fetch.js +35 -0
- data/app/javascript/lib/api/drag_drop.js +17 -0
- data/app/javascript/modules/command_menu.js +40 -0
- data/app/javascript/modules/creative_row_editor.js +88 -0
- data/app/javascript/modules/slide_view.js +2 -1
- data/app/jobs/collavre/ai_agent_job.rb +42 -30
- data/app/jobs/collavre/compress_job.rb +92 -0
- data/app/models/collavre/comment.rb +36 -1
- data/app/models/collavre/comment_version.rb +15 -0
- data/app/models/collavre/creative/describable.rb +1 -1
- data/app/models/collavre/creative.rb +51 -0
- data/app/models/collavre/task.rb +30 -2
- data/app/models/collavre/user.rb +20 -3
- data/app/services/collavre/ai_agent/a2a_dispatcher.rb +68 -0
- data/app/services/collavre/ai_agent/agent_lifecycle_manager.rb +89 -0
- data/app/services/collavre/ai_agent/message_builder.rb +85 -6
- data/app/services/collavre/ai_agent/response_finalizer.rb +97 -0
- data/app/services/collavre/ai_agent/response_streamer.rb +56 -0
- data/app/services/collavre/ai_agent/review_handler.rb +18 -1
- data/app/services/collavre/ai_agent_service.rb +130 -183
- data/app/services/collavre/ai_client.rb +6 -0
- data/app/services/collavre/auto_theme_generator.rb +1 -1
- data/app/services/collavre/command_menu_service.rb +19 -0
- data/app/services/collavre/comments/command_processor.rb +3 -1
- data/app/services/collavre/comments/compress_command.rb +75 -0
- data/app/services/collavre/comments/concerns/workflow_support.rb +115 -0
- data/app/services/collavre/comments/work_command.rb +161 -0
- data/app/services/collavre/comments/workflow_executor.rb +276 -0
- data/app/services/collavre/creatives/plan_tagger.rb +14 -3
- data/app/services/collavre/creatives/tree_formatter.rb +53 -13
- data/app/services/collavre/gemini_parent_recommender.rb +4 -4
- data/app/services/collavre/orchestration/agent_context_builder.rb +1 -3
- data/app/services/collavre/orchestration/agent_orchestrator.rb +15 -4
- data/app/services/collavre/orchestration/policy_resolver.rb +0 -19
- data/app/services/collavre/orchestration/scheduler.rb +3 -2
- data/app/services/collavre/orchestration/stuck_detector.rb +1 -1
- data/app/services/collavre/system_events/dispatcher.rb +9 -0
- data/app/services/collavre/tools/creative_create_service.rb +1 -8
- data/app/services/collavre/tools/creative_import_service.rb +46 -0
- data/app/services/collavre/tools/creative_retrieval_service.rb +157 -96
- data/app/services/collavre/tools/creative_update_service.rb +1 -8
- data/app/services/collavre/tools/cron_list_service.rb +1 -1
- data/app/services/collavre/tools/description_normalizable.rb +16 -0
- data/app/views/collavre/comments/_comment.html.erb +25 -8
- data/app/views/collavre/comments/_comments_popup.html.erb +32 -5
- data/app/views/collavre/creatives/_inline_edit_form.html.erb +13 -0
- data/app/views/collavre/creatives/_share_button.html.erb +4 -1
- data/app/views/collavre/creatives/_share_modal.html.erb +31 -1
- data/app/views/collavre/creatives/index.html.erb +5 -5
- data/app/views/collavre/creatives/slide_view.html.erb +1 -1
- data/app/views/collavre/users/{_contact_management.html.erb → _contact_list.html.erb} +4 -8
- data/app/views/collavre/users/_org_chart.html.erb +68 -0
- data/app/views/collavre/users/_org_chart_node.html.erb +169 -0
- data/app/views/collavre/users/new_ai.html.erb +9 -0
- data/app/views/collavre/users/show.html.erb +32 -8
- data/config/locales/comments.en.yml +57 -2
- data/config/locales/comments.ko.yml +57 -2
- data/config/locales/contacts.en.yml +31 -0
- data/config/locales/contacts.ko.yml +31 -0
- data/config/locales/contexts.en.yml +8 -0
- data/config/locales/contexts.ko.yml +8 -0
- data/config/locales/creatives.en.yml +6 -0
- data/config/locales/creatives.ko.yml +6 -0
- data/config/locales/users.en.yml +1 -0
- data/config/locales/users.ko.yml +1 -0
- data/config/routes.rb +14 -1
- data/db/migrate/20260220072200_add_workflow_fields_to_tasks.rb +12 -0
- data/db/migrate/20260223173533_add_review_type_to_comments.rb +5 -0
- data/db/migrate/20260225065200_create_comment_versions.rb +14 -0
- data/db/migrate/20260225074416_add_selected_version_id_to_comments.rb +7 -0
- data/lib/collavre/version.rb +1 -1
- metadata +47 -10
- data/app/javascript/lib/lexical/__tests__/action_text_attachment_node.test.jsx +0 -91
- data/app/javascript/lib/lexical/action_text_attachment_node.js +0 -459
- data/app/javascript/lib/lexical/dom_attachment_utils.js +0 -66
- data/app/javascript/modules/share_modal.js +0 -76
- data/app/javascript/modules/share_user_popup.js +0 -77
- data/app/services/collavre/orchestration/self_reflection_evaluator.rb +0 -231
- data/app/views/collavre/comments/_presence_avatars.html.erb +0 -8
- data/app/views/collavre/creatives/_delete_button.html.erb +0 -12
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Collavre
|
|
4
|
-
module Orchestration
|
|
5
|
-
# SelfReflectionEvaluator evaluates an agent's response and determines
|
|
6
|
-
# whether the agent should retry, escalate, or mark the task as done.
|
|
7
|
-
#
|
|
8
|
-
# It parses confidence signals from the response and compares against
|
|
9
|
-
# policy-configured thresholds.
|
|
10
|
-
#
|
|
11
|
-
# Usage:
|
|
12
|
-
# evaluator = SelfReflectionEvaluator.new(task)
|
|
13
|
-
# result = evaluator.evaluate
|
|
14
|
-
# case result.action
|
|
15
|
-
# when :done then task.update!(status: "done")
|
|
16
|
-
# when :retry then schedule_retry(result.delay)
|
|
17
|
-
# when :escalate then notify_admin(result.reason)
|
|
18
|
-
# end
|
|
19
|
-
#
|
|
20
|
-
class SelfReflectionEvaluator
|
|
21
|
-
Result = Struct.new(:action, :delay, :reason, :confidence, keyword_init: true)
|
|
22
|
-
|
|
23
|
-
# Patterns to extract confidence from agent response
|
|
24
|
-
CONFIDENCE_PATTERNS = [
|
|
25
|
-
/확신도[:\s]*(\d+)/i,
|
|
26
|
-
/confidence[:\s]*(\d+)/i,
|
|
27
|
-
/\[confidence[:\s]*(\d+)\]/i,
|
|
28
|
-
/확신[:\s]*(\d+)%?/i
|
|
29
|
-
].freeze
|
|
30
|
-
|
|
31
|
-
# Patterns that indicate the agent is stuck or uncertain
|
|
32
|
-
UNCERTAINTY_PATTERNS = [
|
|
33
|
-
/잘\s*모르겠/,
|
|
34
|
-
/확실하지\s*않/,
|
|
35
|
-
/불확실/,
|
|
36
|
-
/도움이?\s*필요/,
|
|
37
|
-
/막혔/,
|
|
38
|
-
/I('m| am)\s*(not sure|uncertain|stuck)/i,
|
|
39
|
-
/need(s)?\s*help/i,
|
|
40
|
-
/cannot\s*(proceed|continue)/i
|
|
41
|
-
].freeze
|
|
42
|
-
|
|
43
|
-
def initialize(task, response_content: nil, policy_resolver: nil)
|
|
44
|
-
@task = task
|
|
45
|
-
@response_content = response_content || ""
|
|
46
|
-
@policy_resolver = policy_resolver ||
|
|
47
|
-
PolicyResolver.new(task.trigger_event_payload || {})
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
# Evaluate the task's response and return a Result
|
|
51
|
-
# @return [Result] with :action (:done, :retry, :escalate), :delay, :reason, :confidence
|
|
52
|
-
def evaluate
|
|
53
|
-
return Result.new(action: :done, reason: "self_reflection_disabled") unless enabled?
|
|
54
|
-
|
|
55
|
-
confidence = parse_confidence
|
|
56
|
-
uncertainty_detected = detect_uncertainty
|
|
57
|
-
|
|
58
|
-
if confidence.nil? && !uncertainty_detected
|
|
59
|
-
# No confidence signal and no uncertainty - assume done
|
|
60
|
-
Result.new(action: :done, confidence: nil, reason: "no_signal")
|
|
61
|
-
elsif confidence && confidence >= threshold
|
|
62
|
-
# Confidence meets threshold - done
|
|
63
|
-
Result.new(action: :done, confidence: confidence, reason: "threshold_met")
|
|
64
|
-
elsif @task.retry_count >= max_retries
|
|
65
|
-
# Max retries exceeded - escalate
|
|
66
|
-
Result.new(
|
|
67
|
-
action: :escalate,
|
|
68
|
-
confidence: confidence,
|
|
69
|
-
reason: "max_retries_exceeded"
|
|
70
|
-
)
|
|
71
|
-
else
|
|
72
|
-
# Below threshold or uncertainty detected - retry
|
|
73
|
-
Result.new(
|
|
74
|
-
action: :retry,
|
|
75
|
-
delay: retry_delay,
|
|
76
|
-
confidence: confidence,
|
|
77
|
-
reason: uncertainty_detected ? "uncertainty_detected" : "below_threshold"
|
|
78
|
-
)
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
# Schedule a retry by creating a system message and re-triggering
|
|
83
|
-
# @param result [Result] pre-computed result from evaluate
|
|
84
|
-
def schedule_retry!(result)
|
|
85
|
-
return result unless result.action == :retry
|
|
86
|
-
|
|
87
|
-
# Increment retry count
|
|
88
|
-
@task.increment!(:retry_count)
|
|
89
|
-
|
|
90
|
-
# Create self-reflection prompt as a new comment
|
|
91
|
-
create_reflection_prompt
|
|
92
|
-
|
|
93
|
-
# Schedule the retry job
|
|
94
|
-
if result.delay.positive?
|
|
95
|
-
AiAgentJob.set(wait: result.delay.seconds).perform_later(@task)
|
|
96
|
-
else
|
|
97
|
-
AiAgentJob.perform_later(@task)
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
result
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
# Escalate to admin users
|
|
104
|
-
# @param result [Result] pre-computed result from evaluate
|
|
105
|
-
def escalate!(result)
|
|
106
|
-
return result unless result.action == :escalate
|
|
107
|
-
|
|
108
|
-
@task.update!(status: "escalated")
|
|
109
|
-
create_escalation_notice
|
|
110
|
-
notify_admins
|
|
111
|
-
|
|
112
|
-
result
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
private
|
|
116
|
-
|
|
117
|
-
def config
|
|
118
|
-
@config ||= @policy_resolver.self_reflection_config
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def enabled?
|
|
122
|
-
config["enabled"] == true
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
def threshold
|
|
126
|
-
config["confidence_threshold"] || 70
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def max_retries
|
|
130
|
-
config["max_retries"] || 3
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
def retry_delay
|
|
134
|
-
config["retry_delay_seconds"] || 5
|
|
135
|
-
end
|
|
136
|
-
|
|
137
|
-
def response_content
|
|
138
|
-
@response_content
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
def parse_confidence
|
|
142
|
-
CONFIDENCE_PATTERNS.each do |pattern|
|
|
143
|
-
match = response_content.match(pattern)
|
|
144
|
-
return match[1].to_i if match
|
|
145
|
-
end
|
|
146
|
-
nil
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
def detect_uncertainty
|
|
150
|
-
UNCERTAINTY_PATTERNS.any? { |pattern| response_content.match?(pattern) }
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
def create_reflection_prompt
|
|
154
|
-
creative_id = @task.trigger_event_payload&.dig("creative", "id")
|
|
155
|
-
return unless creative_id && @task.topic_id
|
|
156
|
-
|
|
157
|
-
creative = Creative.find_by(id: creative_id)
|
|
158
|
-
return unless creative
|
|
159
|
-
|
|
160
|
-
# Create a system message prompting self-reflection
|
|
161
|
-
creative.comments.create!(
|
|
162
|
-
content: reflection_prompt_content,
|
|
163
|
-
user: system_user,
|
|
164
|
-
topic_id: @task.topic_id,
|
|
165
|
-
private: false
|
|
166
|
-
)
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
def reflection_prompt_content
|
|
170
|
-
<<~PROMPT.strip
|
|
171
|
-
[시스템] 확신도가 낮습니다 (#{@task.retry_count + 1}/#{max_retries} 재시도).
|
|
172
|
-
|
|
173
|
-
다시 검토해주세요:
|
|
174
|
-
- 다른 접근법이 있나요?
|
|
175
|
-
- 부족한 정보가 있다면 @멘션으로 다른 Agent에게 요청하세요.
|
|
176
|
-
- 그래도 해결이 어려우면 상위로 에스컬레이션하세요.
|
|
177
|
-
|
|
178
|
-
응답 시 확신도를 명시해주세요: [confidence: 0-100]
|
|
179
|
-
PROMPT
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
def create_escalation_notice
|
|
183
|
-
creative_id = @task.trigger_event_payload&.dig("creative", "id")
|
|
184
|
-
return unless creative_id && @task.topic_id
|
|
185
|
-
|
|
186
|
-
creative = Creative.find_by(id: creative_id)
|
|
187
|
-
return unless creative
|
|
188
|
-
|
|
189
|
-
creative.comments.create!(
|
|
190
|
-
content: escalation_notice_content,
|
|
191
|
-
user: system_user,
|
|
192
|
-
topic_id: @task.topic_id,
|
|
193
|
-
private: false
|
|
194
|
-
)
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
def escalation_notice_content
|
|
198
|
-
<<~NOTICE.strip
|
|
199
|
-
[시스템] ⚠️ 에스컬레이션 발생
|
|
200
|
-
|
|
201
|
-
Agent: #{@task.agent&.name}
|
|
202
|
-
작업: #{@task.name}
|
|
203
|
-
재시도 횟수: #{@task.retry_count}회
|
|
204
|
-
|
|
205
|
-
최대 재시도 횟수를 초과하여 관리자에게 에스컬레이션되었습니다.
|
|
206
|
-
admin 권한을 가진 사용자의 검토가 필요합니다.
|
|
207
|
-
NOTICE
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
def notify_admins
|
|
211
|
-
# Find admin users for this creative and notify them
|
|
212
|
-
creative_id = @task.trigger_event_payload&.dig("creative", "id")
|
|
213
|
-
return unless creative_id
|
|
214
|
-
|
|
215
|
-
creative = Creative.find_by(id: creative_id)
|
|
216
|
-
return unless creative
|
|
217
|
-
|
|
218
|
-
# This could trigger notifications via various channels
|
|
219
|
-
# For now, the escalation notice in the topic serves as notification
|
|
220
|
-
Rails.logger.info(
|
|
221
|
-
"[SelfReflection] Task #{@task.id} escalated for creative #{creative_id}"
|
|
222
|
-
)
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
def system_user
|
|
226
|
-
@system_user ||= User.find_by(email: "system@collavre.local") ||
|
|
227
|
-
@task.agent # Fallback to agent if no system user
|
|
228
|
-
end
|
|
229
|
-
end
|
|
230
|
-
end
|
|
231
|
-
end
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
<div id="comment-participants">
|
|
2
|
-
<% accessible_users = [creative.user].compact + creative.all_shared_users(:feedback).map(&:user) %>
|
|
3
|
-
<% accessible_users.uniq.each do |u| %>
|
|
4
|
-
<% classes = 'avatar comment-presence-avatar' %>
|
|
5
|
-
<% classes += ' inactive' unless present_ids.include?(u.id) %>
|
|
6
|
-
<%= render Collavre::AvatarComponent.new(user: u, size: 20, classes: classes, data: { email: u.email }) %>
|
|
7
|
-
<% end %>
|
|
8
|
-
</div>
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<%= render Collavre::PopupMenuComponent.new(
|
|
2
|
-
button_content: t('collavre.creatives.index.delete'),
|
|
3
|
-
button_classes: ["danger-link", local_assigns[:extra_button_classes]].compact.join(" "),
|
|
4
|
-
menu_id: 'delete-options-popup-' + [local_assigns[:extra_button_classes]].compact.join('-')) do %>
|
|
5
|
-
<%= button_to t('collavre.creatives.index.delete_only_this'), @parent_creative, method: :delete,
|
|
6
|
-
form: { data: { turbo_confirm: t('collavre.creatives.index.are_you_sure_delete_only_this') } },
|
|
7
|
-
params: {}, class: 'danger-link popup-menu-item' %>
|
|
8
|
-
<%= button_to t('collavre.creatives.index.delete_with_children'), @parent_creative, method: :delete,
|
|
9
|
-
params: { delete_with_children: true },
|
|
10
|
-
form: { data: { turbo_confirm: t('collavre.creatives.index.are_you_sure_delete_with_children') } },
|
|
11
|
-
class: 'danger-link' %>
|
|
12
|
-
<% end %>
|