Class: Antigravity::Guards::AgentLogger

Inherits:
Object
  • Object
show all
Defined in:
lib/antigravity/guards.rb

Overview

Dual-output logger guard:

1. JSONL (log/antigravity.jsonl) — structured, machine-parseable, full data
2. Compact log (log/antigravity.log) — human-readable one-liners with byte sizes

Falls back to Rails.logger for both if available.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(log_target = nil, level: :info, silent_notice: false) ⇒ AgentLogger

Returns a new instance of AgentLogger.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/antigravity/guards.rb', line 15

def initialize(log_target = nil, level: :info, silent_notice: false)
  resolved = resolve_log_target(log_target)

  if resolved.is_a?(String)
    dir = File.dirname(resolved)
    FileUtils.mkdir_p(dir) unless Dir.exist?(dir)

    # Fat JSONL log
    @jsonl = File.open(resolved, 'a')
    @jsonl.sync = true

    # Skinny compact log (same dir, .log extension)
    compact_path = resolved.sub(/\.jsonl$/, '.log')
    @compact = File.open(compact_path, 'a')
    @compact.sync = true

    @rails_logger = nil
    @target_description = resolved
  elsif resolved.respond_to?(:info)
    @jsonl = nil
    @compact = nil
    @rails_logger = resolved
    @target_description = "Rails.logger"
  else
    @jsonl = $stdout
    @compact = nil
    @rails_logger = nil
    @target_description = "$stdout"
  end

  @level = level

  unless silent_notice
    puts "#{Antigravity.emoji(:logger)} Logging to #{@target_description}"
  end
end

Instance Attribute Details

#target_descriptionObject (readonly)

Returns the value of attribute target_description.



13
14
15
# File 'lib/antigravity/guards.rb', line 13

def target_description
  @target_description
end

Instance Method Details

#after_response(response) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/antigravity/guards.rb', line 58

def after_response(response)
  content = response.content&.strip || ''
  log_jsonl('response', {
    model: response.model_id,
    content: content,
    tokens: response.usage[:total_token_count],
    tool_calls: response.tool_calls_count,
    steps: response.steps&.length
  })
  log_compact("#{Antigravity.emoji(:response)} RESPONSE #{content.bytesize}B | " \
              "tokens=#{response.usage[:total_token_count]} " \
              "tools=#{response.tool_calls_count} " \
              "steps=#{response.steps&.length} " \
              "model=#{response.model_id}")
end

#after_tool_call(tool_name, params, result) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/antigravity/guards.rb', line 80

def after_tool_call(tool_name, params, result)
  blocked = result.to_s.include?("TOOL BLOCKED")
  result_size = result.to_s.bytesize
  log_jsonl('tool_result', {
    tool: tool_name,
    result: result.to_s[0, 500],
    blocked: blocked
  })
  status = blocked ? 'BLOCKED' : 'OK'
  log_compact("#{blocked ? Antigravity.emoji(:tool_blocked) : Antigravity.emoji(:tool_result)} TOOL_RESULT #{tool_name} #{status} result=#{result_size}B")
  result
end

#attach_to(agent) ⇒ Object



98
99
100
101
102
103
104
# File 'lib/antigravity/guards.rb', line 98

def attach_to(agent)
  logger_guard = self
  agent.before_prompt { |p| logger_guard.before_prompt(p) }
  agent.after_response { |r| logger_guard.after_response(r) }
  agent.before_tool_call { |t, p| logger_guard.before_tool_call(t, p) }
  agent.after_tool_call { |t, p, r| logger_guard.after_tool_call(t, p, r) }
end

#before_prompt(prompt_text) ⇒ Object



52
53
54
55
56
# File 'lib/antigravity/guards.rb', line 52

def before_prompt(prompt_text)
  size = prompt_text.to_s.bytesize
  log_jsonl('prompt', { user_input: prompt_text })
  log_compact("#{Antigravity.emoji(:prompt)} PROMPT #{size}B | #{prompt_text.to_s[0, 80]}")
end

#before_tool_call(tool_name, params) ⇒ Object



74
75
76
77
78
# File 'lib/antigravity/guards.rb', line 74

def before_tool_call(tool_name, params)
  params_size = params.to_s.bytesize
  log_jsonl('tool_call', { tool: tool_name, params: params })
  log_compact("#{Antigravity.emoji(:tool)} TOOL_CALL #{tool_name} params=#{params_size}B")
end

#sidecar_event(event_type, payload) ⇒ Object



93
94
95
96
# File 'lib/antigravity/guards.rb', line 93

def sidecar_event(event_type, payload)
  log_jsonl('sidecar', { type: event_type.to_s, payload: payload })
  log_compact("#{Antigravity.emoji(:sidecar)} SIDECAR :#{event_type}")
end