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.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/collavre/comment_versions.css +76 -0
  3. data/app/assets/stylesheets/collavre/comments_popup.css +347 -37
  4. data/app/assets/stylesheets/collavre/creatives.css +73 -1
  5. data/app/assets/stylesheets/collavre/org_chart.css +319 -0
  6. data/app/assets/stylesheets/collavre/popup.css +68 -1
  7. data/app/controllers/collavre/application_controller.rb +13 -0
  8. data/app/controllers/collavre/comments/versions_controller.rb +82 -0
  9. data/app/controllers/collavre/comments_controller.rb +14 -153
  10. data/app/controllers/collavre/concerns/exportable.rb +30 -0
  11. data/app/controllers/collavre/concerns/shareable.rb +28 -0
  12. data/app/controllers/collavre/concerns/slide_viewable.rb +37 -0
  13. data/app/controllers/collavre/concerns/tree_manageable.rb +141 -0
  14. data/app/controllers/collavre/creative_imports_controller.rb +6 -0
  15. data/app/controllers/collavre/creative_invitations_controller.rb +46 -0
  16. data/app/controllers/collavre/creative_plans_controller.rb +1 -1
  17. data/app/controllers/collavre/creative_shares_controller.rb +84 -14
  18. data/app/controllers/collavre/creatives_controller.rb +70 -194
  19. data/app/controllers/collavre/google_auth_controller.rb +3 -0
  20. data/app/controllers/collavre/invites_controller.rb +2 -1
  21. data/app/controllers/collavre/sessions_controller.rb +3 -0
  22. data/app/controllers/collavre/topics_controller.rb +39 -2
  23. data/app/controllers/collavre/users_controller.rb +5 -404
  24. data/app/controllers/concerns/collavre/comments/approval_actions.rb +108 -0
  25. data/app/controllers/concerns/collavre/comments/batch_operations.rb +55 -0
  26. data/app/controllers/concerns/collavre/comments/conversion.rb +46 -0
  27. data/app/controllers/concerns/collavre/users_controller/admin_operations.rb +74 -0
  28. data/app/controllers/concerns/collavre/users_controller/ai_user_management.rb +119 -0
  29. data/app/controllers/concerns/collavre/users_controller/contact_management.rb +166 -0
  30. data/app/controllers/concerns/collavre/users_controller/profile_and_settings.rb +102 -0
  31. data/app/controllers/concerns/collavre/users_controller/registration.rb +63 -0
  32. data/app/helpers/collavre/application_helper.rb +1 -0
  33. data/app/helpers/collavre/creatives_helper.rb +12 -9
  34. data/app/helpers/collavre/navigation_helper.rb +1 -1
  35. data/app/javascript/collavre.js +0 -1
  36. data/app/javascript/controllers/comment_controller.js +33 -70
  37. data/app/javascript/controllers/comment_version_controller.js +164 -0
  38. data/app/javascript/controllers/comments/__tests__/form_controller_review.test.js +305 -0
  39. data/app/javascript/controllers/comments/__tests__/list_controller_selection.test.js +103 -0
  40. data/app/javascript/controllers/comments/__tests__/review_quotes_store.test.js +113 -0
  41. data/app/javascript/controllers/comments/contexts_controller.js +363 -0
  42. data/app/javascript/controllers/comments/form_controller.js +304 -13
  43. data/app/javascript/controllers/comments/list_controller.js +151 -62
  44. data/app/javascript/controllers/comments/popup_controller.js +66 -38
  45. data/app/javascript/controllers/comments/presence_controller.js +2 -10
  46. data/app/javascript/controllers/comments/review_quotes_store.js +189 -0
  47. data/app/javascript/controllers/comments/topics_controller.js +34 -10
  48. data/app/javascript/controllers/index.js +15 -1
  49. data/app/javascript/controllers/org_chart_controller.js +46 -0
  50. data/app/javascript/controllers/share_modal_controller.js +369 -0
  51. data/app/javascript/controllers/topic_search_controller.js +103 -0
  52. data/app/javascript/creatives/drag_drop/event_handlers.js +42 -1
  53. data/app/javascript/lib/api/creatives.js +12 -0
  54. data/app/javascript/lib/api/csrf_fetch.js +35 -0
  55. data/app/javascript/lib/api/drag_drop.js +17 -0
  56. data/app/javascript/modules/command_menu.js +40 -0
  57. data/app/javascript/modules/creative_row_editor.js +88 -0
  58. data/app/javascript/modules/slide_view.js +2 -1
  59. data/app/jobs/collavre/ai_agent_job.rb +42 -30
  60. data/app/jobs/collavre/compress_job.rb +92 -0
  61. data/app/models/collavre/comment.rb +36 -1
  62. data/app/models/collavre/comment_version.rb +15 -0
  63. data/app/models/collavre/creative/describable.rb +1 -1
  64. data/app/models/collavre/creative.rb +51 -0
  65. data/app/models/collavre/task.rb +30 -2
  66. data/app/models/collavre/user.rb +20 -3
  67. data/app/services/collavre/ai_agent/a2a_dispatcher.rb +68 -0
  68. data/app/services/collavre/ai_agent/agent_lifecycle_manager.rb +89 -0
  69. data/app/services/collavre/ai_agent/message_builder.rb +85 -6
  70. data/app/services/collavre/ai_agent/response_finalizer.rb +97 -0
  71. data/app/services/collavre/ai_agent/response_streamer.rb +56 -0
  72. data/app/services/collavre/ai_agent/review_handler.rb +18 -1
  73. data/app/services/collavre/ai_agent_service.rb +130 -183
  74. data/app/services/collavre/ai_client.rb +6 -0
  75. data/app/services/collavre/auto_theme_generator.rb +1 -1
  76. data/app/services/collavre/command_menu_service.rb +19 -0
  77. data/app/services/collavre/comments/command_processor.rb +3 -1
  78. data/app/services/collavre/comments/compress_command.rb +75 -0
  79. data/app/services/collavre/comments/concerns/workflow_support.rb +115 -0
  80. data/app/services/collavre/comments/work_command.rb +161 -0
  81. data/app/services/collavre/comments/workflow_executor.rb +276 -0
  82. data/app/services/collavre/creatives/plan_tagger.rb +14 -3
  83. data/app/services/collavre/creatives/tree_formatter.rb +53 -13
  84. data/app/services/collavre/gemini_parent_recommender.rb +4 -4
  85. data/app/services/collavre/orchestration/agent_context_builder.rb +1 -3
  86. data/app/services/collavre/orchestration/agent_orchestrator.rb +15 -4
  87. data/app/services/collavre/orchestration/policy_resolver.rb +0 -19
  88. data/app/services/collavre/orchestration/scheduler.rb +3 -2
  89. data/app/services/collavre/orchestration/stuck_detector.rb +1 -1
  90. data/app/services/collavre/system_events/dispatcher.rb +9 -0
  91. data/app/services/collavre/tools/creative_create_service.rb +1 -8
  92. data/app/services/collavre/tools/creative_import_service.rb +46 -0
  93. data/app/services/collavre/tools/creative_retrieval_service.rb +157 -96
  94. data/app/services/collavre/tools/creative_update_service.rb +1 -8
  95. data/app/services/collavre/tools/cron_list_service.rb +1 -1
  96. data/app/services/collavre/tools/description_normalizable.rb +16 -0
  97. data/app/views/collavre/comments/_comment.html.erb +25 -8
  98. data/app/views/collavre/comments/_comments_popup.html.erb +32 -5
  99. data/app/views/collavre/creatives/_inline_edit_form.html.erb +13 -0
  100. data/app/views/collavre/creatives/_share_button.html.erb +4 -1
  101. data/app/views/collavre/creatives/_share_modal.html.erb +31 -1
  102. data/app/views/collavre/creatives/index.html.erb +5 -5
  103. data/app/views/collavre/creatives/slide_view.html.erb +1 -1
  104. data/app/views/collavre/users/{_contact_management.html.erb → _contact_list.html.erb} +4 -8
  105. data/app/views/collavre/users/_org_chart.html.erb +68 -0
  106. data/app/views/collavre/users/_org_chart_node.html.erb +169 -0
  107. data/app/views/collavre/users/new_ai.html.erb +9 -0
  108. data/app/views/collavre/users/show.html.erb +32 -8
  109. data/config/locales/comments.en.yml +57 -2
  110. data/config/locales/comments.ko.yml +57 -2
  111. data/config/locales/contacts.en.yml +31 -0
  112. data/config/locales/contacts.ko.yml +31 -0
  113. data/config/locales/contexts.en.yml +8 -0
  114. data/config/locales/contexts.ko.yml +8 -0
  115. data/config/locales/creatives.en.yml +6 -0
  116. data/config/locales/creatives.ko.yml +6 -0
  117. data/config/locales/users.en.yml +1 -0
  118. data/config/locales/users.ko.yml +1 -0
  119. data/config/routes.rb +14 -1
  120. data/db/migrate/20260220072200_add_workflow_fields_to_tasks.rb +12 -0
  121. data/db/migrate/20260223173533_add_review_type_to_comments.rb +5 -0
  122. data/db/migrate/20260225065200_create_comment_versions.rb +14 -0
  123. data/db/migrate/20260225074416_add_selected_version_id_to_comments.rb +7 -0
  124. data/lib/collavre/version.rb +1 -1
  125. metadata +47 -10
  126. data/app/javascript/lib/lexical/__tests__/action_text_attachment_node.test.jsx +0 -91
  127. data/app/javascript/lib/lexical/action_text_attachment_node.js +0 -459
  128. data/app/javascript/lib/lexical/dom_attachment_utils.js +0 -66
  129. data/app/javascript/modules/share_modal.js +0 -76
  130. data/app/javascript/modules/share_user_popup.js +0 -77
  131. data/app/services/collavre/orchestration/self_reflection_evaluator.rb +0 -231
  132. data/app/views/collavre/comments/_presence_avatars.html.erb +0 -8
  133. 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 %>