Class: ActionAgent::SandboxSession
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- ActionAgent::SandboxSession
- Includes:
- Ownable
- Defined in:
- app/models/action_agent/sandbox_session.rb
Constant Summary collapse
- SANDBOX_TYPES =
Sandbox types
%w[playwright_mcp terminal research].freeze
- FREE_TIER_LIMITS =
Free tier limits
{ max_runs: 10, timeout_seconds: 300, max_tokens: 50_000, session_duration_minutes: 15 }.freeze
Constants included from Ownable
Instance Method Summary collapse
-
#active? ⇒ Boolean
Check if session is still valid.
-
#can_run? ⇒ Boolean
Check if can run more tasks.
-
#details ⇒ Object
Detailed info including runs.
-
#expire! ⇒ Object
Expire the session.
-
#mark_ready!(cloud_run_url:, cloud_run_job_id: nil) ⇒ Object
Mark as ready with Cloud Run URL.
-
#mcp_catalog_entries ⇒ Object
Catalog entries for the MCP servers this session was started with.
-
#provision! ⇒ Object
Provision the Cloud Run sandbox.
-
#record_run!(task:, result:, duration_ms:, tokens:, screenshots: [], provider: nil) ⇒ Object
Record a new run (thread-safe for parallel execution).
-
#summary ⇒ Object
Summary for API responses.
Methods included from Ownable
Methods inherited from ApplicationRecord
Instance Method Details
#active? ⇒ Boolean
Check if session is still valid
55 56 57 |
# File 'app/models/action_agent/sandbox_session.rb', line 55 def active? !expired? && !failed? && !completed? && expires_at > Time.current end |
#can_run? ⇒ Boolean
Check if can run more tasks
60 61 62 |
# File 'app/models/action_agent/sandbox_session.rb', line 60 def can_run? active? && runs_count < max_runs end |
#details ⇒ Object
Detailed info including runs
140 141 142 143 144 145 146 |
# File 'app/models/action_agent/sandbox_session.rb', line 140 def details summary.merge( runs: runs, total_duration_ms: total_duration_ms, last_activity_at: last_activity_at&.iso8601 ) end |
#expire! ⇒ Object
Expire the session
116 117 118 119 120 |
# File 'app/models/action_agent/sandbox_session.rb', line 116 def expire! update!(status: :expired) # Cleanup Cloud Run resources SandboxCleanupJob.perform_later(id) if cloud_run_job_id.present? end |
#mark_ready!(cloud_run_url:, cloud_run_job_id: nil) ⇒ Object
Mark as ready with Cloud Run URL
107 108 109 110 111 112 113 |
# File 'app/models/action_agent/sandbox_session.rb', line 107 def mark_ready!(cloud_run_url:, cloud_run_job_id: nil) update!( status: :ready, cloud_run_url: cloud_run_url, cloud_run_job_id: cloud_run_job_id ) end |
#mcp_catalog_entries ⇒ Object
Catalog entries for the MCP servers this session was started with. Unknown keys are dropped rather than raising — a session outlives a catalog edit.
50 51 52 |
# File 'app/models/action_agent/sandbox_session.rb', line 50 def mcp_catalog_entries Array(mcp_servers).filter_map { |key| McpCatalog.find(key) } end |
#provision! ⇒ Object
Provision the Cloud Run sandbox
93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'app/models/action_agent/sandbox_session.rb', line 93 def provision! return if provisioning? || ready? update!(status: :provisioning) # In development, run synchronously for immediate feedback if Rails.env.development? || Rails.env.test? SandboxProvisionJob.perform_now(id) else SandboxProvisionJob.perform_later(id) end end |
#record_run!(task:, result:, duration_ms:, tokens:, screenshots: [], provider: nil) ⇒ Object
Record a new run (thread-safe for parallel execution)
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'app/models/action_agent/sandbox_session.rb', line 65 def record_run!(task:, result:, duration_ms:, tokens:, screenshots: [], provider: nil) run = { id: SecureRandom.uuid, task: task, result: result, duration_ms: duration_ms, tokens: tokens, screenshots: screenshots, provider: provider, status: "completed", created_at: Time.current.iso8601 } # Use pessimistic locking to prevent race conditions when multiple providers run in parallel with_lock do reload # Reload to get the latest state self.runs = runs + [ run ] self.runs_count = runs.size self.total_tokens += tokens self.total_duration_ms += duration_ms self.last_activity_at = Time.current save! end run end |
#summary ⇒ Object
Summary for API responses
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'app/models/action_agent/sandbox_session.rb', line 123 def summary { id: id, session_id: session_id, sandbox_type: sandbox_type, status: status, runs_count: runs_count, max_runs: max_runs, total_tokens: total_tokens, expires_at: expires_at&.iso8601, created_at: created_at.iso8601, cloud_run_url: cloud_run_url, mcp_servers: Array(mcp_servers) } end |