Class: Agent::SessionContext::LoopView

Inherits:
Object
  • Object
show all
Defined in:
lib/agent/session_context/loop_view.rb

Overview

Renders one Loop for a human (#ascii, #markdown) or a machine (#to_h).

Every rendering prints SIZES, never BODIES. A transcript can hold a credential or a customer's data anywhere — even a shell command line can carry a token — and this gem has no redaction before milestone 0.5, so a truncated preview is not a safer middle ground; it is the same leak with extra steps. A byte count and a tool name carry enough signal to see what a loop did without carrying what it said.

Every timestamp goes through #utc: two renderings of the same file must be byte-identical no matter which machine or time zone reads it, and a local time would make that false for a fact (the recorded instant) that has not actually changed.

The ending is always printed as inferred, because Loop#ending is always a deduction — no on-disk transcript records WHY a session stopped, since that fact lives in a non-interactive run's streamed output, never in the file itself. Printing it as a plain fact would claim information the file does not hold.

Constant Summary collapse

YOU_LANE =
2
HARNESS_LANE =
15
MODEL_LANE =
50
LABEL_SHAPE =

A label is a record TYPE name (hook_success, turn_duration), never prose — but the field carrying it is a free String, so this shape check is what actually keeps R9 (no bodies) true the day a format starts putting a sentence there instead of a type name.

/\A[A-Za-z0-9_.:-]{1,64}\z/

Instance Method Summary collapse

Constructor Details

#initialize(loop_model) ⇒ LoopView

Returns a new instance of LoopView.



35
36
37
# File 'lib/agent/session_context/loop_view.rb', line 35

def initialize(loop_model)
  @loop = loop_model
end

Instance Method Details

#ascii ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/agent/session_context/loop_view.rb', line 39

def ascii
  lines = [
    "session #{@loop.session.uid}",
    "round trips: #{@loop.round_trips.size}  (grouping: #{grouping})",
    "tool calls: #{@loop.tool_calls.size}  (#{unanswered_count} unanswered)",
    "",
    ascii_header
  ]
  @loop.round_trips.each { |trip| lines.concat(ascii_round_trip(trip)) }
  lines << "" << "ending: #{@loop.ending} (inferred) — #{@loop.ending_detail}"
  if @loop.warnings.any?
    lines << "" << "warnings:"
    @loop.warnings.each { |warning| lines << "  - #{warning}" }
  end
  "#{lines.join("\n")}\n"
end

#markdown ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/agent/session_context/loop_view.rb', line 56

def markdown
  lines = ["# session #{@loop.session.uid}", "",
           "- round trips: #{@loop.round_trips.size} (grouping: #{grouping})",
           "- tool calls: #{@loop.tool_calls.size} (#{unanswered_count} unanswered)",
           "", "## Round trips", ""]
  @loop.round_trips.each { |trip| lines << markdown_round_trip(trip) }
  lines << "" << "## Tool calls" << ""
  lines.concat(markdown_tool_calls_table)
  lines << "" << "## Ending" << "" << "#{@loop.ending} (inferred) — #{@loop.ending_detail}"
  if @loop.warnings.any?
    lines << "" << "## Warnings" << ""
    @loop.warnings.each { |warning| lines << "- #{warning}" }
  end
  "#{lines.join("\n")}\n"
end

#to_h ⇒ Object



72
73
74
75
76
77
78
79
80
81
# File 'lib/agent/session_context/loop_view.rb', line 72

def to_h
  {
    session: { agent: @loop.session.agent, id: @loop.session.id, uid: @loop.session.uid },
    round_trips: @loop.round_trips.map { |trip| round_trip_h(trip) },
    tool_calls: @loop.tool_calls.map { |call| tool_call_h(call) },
    ending: { name: @loop.ending, detail: @loop.ending_detail, inferred: true },
    recorded: @loop.recorded,
    warnings: @loop.warnings
  }
end