Class: Collavre::AiAgent::AgentLifecycleManager

Inherits:
Object
  • Object
show all
Defined in:
app/services/collavre/ai_agent/agent_lifecycle_manager.rb

Overview

Manages agent lifecycle during task execution:

  • Status broadcasting (thinking, streaming, idle)

  • Cancellation checking

  • Heartbeat management

Constant Summary collapse

CANCEL_CHECK_INTERVAL =

Minimum interval (in seconds) between cancellation checks to avoid excessive DB queries

1.0
AGENT_STATUS_HEARTBEAT_INTERVAL =

Interval (in seconds) between agent_status heartbeats during streaming

3.0

Instance Method Summary collapse

Constructor Details

#initialize(task:, agent:, creative:) ⇒ AgentLifecycleManager

Returns a new instance of AgentLifecycleManager.



15
16
17
18
19
20
21
# File 'app/services/collavre/ai_agent/agent_lifecycle_manager.rb', line 15

def initialize(task:, agent:, creative:)
  @task = task
  @agent = agent
  @creative = creative
  @last_cancel_check_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  @last_heartbeat_at = @last_cancel_check_at
end

Instance Method Details

#broadcast_status(status, content: nil) ⇒ Object

Broadcast agent status change



24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'app/services/collavre/ai_agent/agent_lifecycle_manager.rb', line 24

def broadcast_status(status, content: nil)
  return unless @creative

  CommentsPresenceChannel.broadcast_agent_status(
    @creative.effective_origin.id,
    status: status,
    agent_id: @agent.id,
    agent_name: @agent.display_name,
    task_id: @task.id,
    content: content,
    source_creative_id: @creative.id
  )
end

#check_cancelled!Object

Check if task was cancelled, raise Collavre::CancelledError if so



39
40
41
42
43
44
45
# File 'app/services/collavre/ai_agent/agent_lifecycle_manager.rb', line 39

def check_cancelled!
  now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  return if (now - @last_cancel_check_at) < CANCEL_CHECK_INTERVAL

  @last_cancel_check_at = now
  raise Collavre::CancelledError if @task.reload.status == "cancelled"
end

#handle_cancelled(reply_comment:, response_content:) ⇒ Object

Handle cancellation cleanup



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'app/services/collavre/ai_agent/agent_lifecycle_manager.rb', line 57

def handle_cancelled(reply_comment:, response_content:)
  if reply_comment
    if response_content.present?
      reply_comment.content_will_change!
      reply_comment.update!(content: response_content)
      reply_comment.broadcast_update_to(
        [ reply_comment.creative, :comments ],
        partial: "collavre/comments/comment",
        locals: { comment: reply_comment, streaming: false }
      )
      log_action("reply_created", { comment_id: reply_comment.id, content: response_content, partial: true })
    else
      reply_comment.destroy!
    end
  end

  broadcast_status("idle")
  log_action("cancelled", { message: "Task cancelled by user" })
end

#heartbeat_if_neededObject

Send heartbeat if interval passed



48
49
50
51
52
53
54
# File 'app/services/collavre/ai_agent/agent_lifecycle_manager.rb', line 48

def heartbeat_if_needed
  now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  if (now - @last_heartbeat_at) >= AGENT_STATUS_HEARTBEAT_INTERVAL
    broadcast_status("streaming")
    @last_heartbeat_at = now
  end
end