Class: Collavre::Comment
- Inherits:
-
ApplicationRecord
- Object
- ApplicationRecord
- ApplicationRecord
- Collavre::Comment
- Includes:
- Approvable, Broadcastable, ClaudeChannelPermission, Notifiable
- Defined in:
- app/models/collavre/comment.rb,
app/models/collavre/comment/approvable.rb,
app/models/collavre/comment/notifiable.rb,
app/models/collavre/comment/broadcastable.rb,
app/models/collavre/comment/claude_channel_permission.rb
Defined Under Namespace
Modules: Approvable, Broadcastable, ClaudeChannelPermission, Notifiable
Constant Summary collapse
- STREAMING_PLACEHOLDER_CONTENT =
"..."- WAITING_NOTICE_PREFIX =
Authorless “⏳” waiting-notice system messages posted when an agent is deferred for topic concurrency. AgentOrchestrator.cleanup_waiting_notices! matches the same prefix to remove them once the waiter is dequeued.
"⏳"
Constants included from ClaudeChannelPermission
ClaudeChannelPermission::ACTION_TYPE
Constants included from Broadcastable
Broadcastable::INBOX_BADGE_TARGETS
Instance Method Summary collapse
-
#creative_snippet ⇒ Object
public for db migration.
-
#dispatch_payload ⇒ Object
Build the dispatch payload for comment_created events.
- #next_version_number ⇒ Object
- #review_message? ⇒ Boolean
-
#to_partial_path ⇒ Object
Use non-namespaced partial path for backward compatibility.
-
#topic_blocking_task ⇒ Object
The task holding this topic’s concurrency slot — the blocker this waiting notice is about.
-
#waiting_notice? ⇒ Boolean
A system “⏳” waiting notice (no author) telling a user their agent is deferred because another task holds the topic’s running slot.
Methods included from ClaudeChannelPermission
#broadcast_claude_channel_permission_decision, #claude_channel_permission?, #claude_channel_permission_denied?, #claude_channel_permission_request_id, #decide_claude_channel_permission!, #rebroadcast_claude_channel_permission_decision
Methods included from Approvable
#approval_status, #can_be_approved_by?, #parsed_action_tool_name
Methods included from Notifiable
#mentioned_users, #notify_ai_completion
Instance Method Details
#creative_snippet ⇒ Object
public for db migration
122 123 124 |
# File 'app/models/collavre/comment.rb', line 122 def creative_snippet creative.creative_snippet end |
#dispatch_payload ⇒ Object
Build the dispatch payload for comment_created events. Used by both after_create_commit callback and DropTriggerJob to ensure a single source of truth (no payload drift).
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'app/models/collavre/comment.rb', line 129 def dispatch_payload { comment: { id: id, content: content, user_id: user_id, from_ai: user&.searchable? || false, quoted_comment_id: quoted_comment_id }.compact, creative: { id: creative_id, description: creative&.description }, topic: { id: topic_id }, chat: { content: content } } end |
#next_version_number ⇒ Object
113 114 115 |
# File 'app/models/collavre/comment.rb', line 113 def next_version_number (comment_versions.maximum(:version_number) || 0) + 1 end |
#review_message? ⇒ Boolean
117 118 119 |
# File 'app/models/collavre/comment.rb', line 117 def quoted_comment_id.present? && !review_type_question? end |
#to_partial_path ⇒ Object
Use non-namespaced partial path for backward compatibility
12 13 14 |
# File 'app/models/collavre/comment.rb', line 12 def to_partial_path "comments/comment" end |
#topic_blocking_task ⇒ Object
The task holding this topic’s concurrency slot — the blocker this waiting notice is about. Lets the notice render a stop button that cancels the blocker (freeing the topic so the deferred waiter proceeds) instead of being an anonymous dead end. Resolved at render time rather than stored on task_id, which Task#reply_comment keys on (a shared task_id would make the blocker’s reply_comment ambiguous).
Two gates keep the button honest:
1. Only THIS notice's own topic-concurrency defer qualifies. The same "⏳"
notice is also posted for :delayed decisions (busy / rate_limited),
which schedule a delayed job WITHOUT queuing a topic waiter —
cancelling some unrelated running task would not unblock them.
topic_concurrency_defer is set only on the :deferred path, so a
:delayed notice never shows the button even when an unrelated queued
waiter happens to share the topic. The queued_for_topic check then
confirms a waiter is still actually pending on the slot.
2. Resolve the blocker over occupying_topic_slot, not just running/
delegated: a holder paused on pending_approval still occupies the slot
and is cancellable, so the button must stay visible for it.
Returns nil once no slot holder remains — at which point the notice itself is cleaned up.
43 44 45 46 47 48 49 50 51 52 |
# File 'app/models/collavre/comment.rb', line 43 def topic_blocking_task return @topic_blocking_task if defined?(@topic_blocking_task) @topic_blocking_task = if topic_concurrency_defer? && topic_id && Collavre::Task.queued_for_topic(topic_id, creative_id).exists? Collavre::Task.(topic_id, creative_id) .includes(:agent).order(:created_at).first end end |
#waiting_notice? ⇒ Boolean
A system “⏳” waiting notice (no author) telling a user their agent is deferred because another task holds the topic’s running slot.
18 19 20 |
# File 'app/models/collavre/comment.rb', line 18 def waiting_notice? user_id.nil? && content.to_s.start_with?(WAITING_NOTICE_PREFIX) end |