Module: TurnKit::Record

Defined in:
lib/turnkit/record.rb

Constant Summary collapse

TURN_STATUSES =
%w[pending running completed failed cancelled stale].freeze
TOOL_EXECUTION_STATUSES =
%w[pending running completed failed cancelled].freeze
TURN_UPDATE_KEYS =
%w[status options usage cost error output_text started_at heartbeat_at completed_at].freeze
TOOL_EXECUTION_UPDATE_KEYS =
%w[status result error started_at completed_at].freeze

Class Method Summary collapse

Class Method Details

.assert_status!(status, allowed, name) ⇒ Object

Raises:

  • (ArgumentError)


103
104
105
# File 'lib/turnkit/record.rb', line 103

def assert_status!(status, allowed, name)
  raise ArgumentError, "unknown #{name} status: #{status}" unless allowed.include?(status.to_s)
end

.conversation(attributes) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/turnkit/record.rb', line 13

def conversation(attributes)
  attrs = stringify(attributes)
  now = Clock.now
  {
    "id" => attrs["id"] || Id.generate(:conversation),
    "agent_name" => attrs["agent_name"],
    "model" => attrs["model"],
    "subject" => attrs["subject"],
    "metadata" => attrs["metadata"] || {},
    "created_at" => attrs["created_at"] || now,
    "updated_at" => attrs["updated_at"] || now
  }
end

.message(attributes) ⇒ Object



27
28
29
# File 'lib/turnkit/record.rb', line 27

def message(attributes)
  Message.new(attributes).to_h
end

.stringify(hash) ⇒ Object



89
90
91
# File 'lib/turnkit/record.rb', line 89

def stringify(hash)
  hash.transform_keys(&:to_s)
end

.subject_pair(subject) ⇒ Object



93
94
95
96
97
98
99
100
101
# File 'lib/turnkit/record.rb', line 93

def subject_pair(subject)
  case subject
  when Hash
    attrs = stringify(subject)
    [ attrs["type"] || attrs["class"], attrs["id"] ]
  else
    [ subject&.class&.name, subject&.respond_to?(:id) ? subject.id : nil ]
  end
end

.tool_execution(attributes) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/turnkit/record.rb', line 60

def tool_execution(attributes)
  attrs = stringify(attributes)
  status = attrs["status"] || "pending"
  assert_status!(status, TOOL_EXECUTION_STATUSES, "tool execution")
  now = Clock.now
  {
    "id" => attrs["id"] || Id.generate(:tool_execution),
    "turn_id" => attrs.fetch("turn_id"),
    "tool_call_id" => attrs.fetch("tool_call_id"),
    "tool_name" => attrs.fetch("tool_name"),
    "status" => status,
    "arguments" => attrs["arguments"] || {},
    "result" => attrs["result"],
    "error" => attrs["error"],
    "started_at" => attrs["started_at"],
    "completed_at" => attrs["completed_at"],
    "created_at" => attrs["created_at"] || now,
    "updated_at" => attrs["updated_at"] || now
  }
end

.tool_execution_update(attributes) ⇒ Object



85
86
87
# File 'lib/turnkit/record.rb', line 85

def tool_execution_update(attributes)
  update(attributes, TOOL_EXECUTION_UPDATE_KEYS, TOOL_EXECUTION_STATUSES, "tool execution")
end

.turn(attributes) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/turnkit/record.rb', line 31

def turn(attributes)
  attrs = stringify(attributes)
  id = attrs["id"] || Id.generate(:turn)
  status = attrs["status"] || "pending"
  assert_status!(status, TURN_STATUSES, "turn")
  now = Clock.now
  {
    "id" => id,
    "conversation_id" => attrs.fetch("conversation_id"),
    "agent_name" => attrs["agent_name"],
    "parent_turn_id" => attrs["parent_turn_id"],
    "parent_tool_execution_id" => attrs["parent_tool_execution_id"],
    "root_turn_id" => attrs["root_turn_id"] || id,
    "context_message_sequence" => attrs["context_message_sequence"].to_i,
    "status" => status,
    "model" => attrs["model"],
    "options" => attrs["options"] || {},
    "usage" => attrs["usage"] || {},
    "cost" => attrs["cost"],
    "error" => attrs["error"],
    "output_text" => attrs["output_text"],
    "started_at" => attrs["started_at"],
    "heartbeat_at" => attrs["heartbeat_at"],
    "completed_at" => attrs["completed_at"],
    "created_at" => attrs["created_at"] || now,
    "updated_at" => attrs["updated_at"] || now
  }
end

.turn_update(attributes) ⇒ Object



81
82
83
# File 'lib/turnkit/record.rb', line 81

def turn_update(attributes)
  update(attributes, TURN_UPDATE_KEYS, TURN_STATUSES, "turn")
end

.update(attributes, allowed_keys, allowed_statuses, name) ⇒ Object

Raises:

  • (ArgumentError)


107
108
109
110
111
112
113
114
# File 'lib/turnkit/record.rb', line 107

def update(attributes, allowed_keys, allowed_statuses, name)
  attrs = stringify(attributes)
  unknown = attrs.keys - allowed_keys
  raise ArgumentError, "unknown #{name} update attributes: #{unknown.join(", ")}" if unknown.any?

  assert_status!(attrs["status"], allowed_statuses, name) if attrs.key?("status")
  attrs
end