Class: Ask::AppServer::EventTranslator

Inherits:
Object
  • Object
show all
Defined in:
lib/ask/app_server/event_translator.rb

Overview

Translates ask-agent Events into app-server protocol events.

ask-agent emits events like TurnStart, TextDelta, ToolExecutionStart, etc. The app-server protocol uses a different set: turn.started, model.streaming, tool.updated, turn.completed, turn.failed, message.upserted.

This class maps between the two models, emitting app-server protocol events that clients such as the Python Telegram bot and Vercel AI SDK expect.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(session_id) ⇒ EventTranslator

Returns a new instance of EventTranslator.



18
19
20
21
22
23
24
25
26
# File 'lib/ask/app_server/event_translator.rb', line 18

def initialize(session_id)
  @session_id = session_id
  @turn_id = nil
  @seq = 0
  @events = []
  @streaming_text = +""
  @turn_active = false
  @in_reflection = false
end

Instance Attribute Details

#session_idObject (readonly)

Returns the value of attribute session_id.



16
17
18
# File 'lib/ask/app_server/event_translator.rb', line 16

def session_id
  @session_id
end

#turn_idObject (readonly)

Returns the value of attribute turn_id.



16
17
18
# File 'lib/ask/app_server/event_translator.rb', line 16

def turn_id
  @turn_id
end

Instance Method Details

#drain_eventsObject

Drain and return all pending events, clearing the buffer.



87
88
89
90
91
# File 'lib/ask/app_server/event_translator.rb', line 87

def drain_events
  evs = @events.dup
  @events.clear
  evs
end

#last_seqObject

The last sequence number we emitted.



94
95
96
# File 'lib/ask/app_server/event_translator.rb', line 94

def last_seq
  @seq
end

#pending_eventsObject

All events emitted since last poll.



82
83
84
# File 'lib/ask/app_server/event_translator.rb', line 82

def pending_events
  @events
end

#translate(agent_event) ⇒ Object

Translate an ask-agent event into zero or more app-server events. Returns an array of event hashes (may be empty).



30
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/ask/app_server/event_translator.rb', line 30

def translate(agent_event)
  case agent_event
  when Ask::Agent::Events::TurnStart
    translate_turn_start
  when Ask::Agent::Events::TextDelta
    translate_text_delta(agent_event)
  when Ask::Agent::Events::ToolCallDelta
    # ToolCallDelta is informational; we track calls but don't emit
    # until execution actually starts.
    []
  when Ask::Agent::Events::ToolExecutionStart
    translate_tool_start(agent_event)
  when Ask::Agent::Events::ToolExecutionUpdate
    translate_tool_update(agent_event)
  when Ask::Agent::Events::ToolExecutionEnd
    translate_tool_end(agent_event)
  when Ask::Agent::Events::MessageEnd
    # Fires after the LLM response is complete (before tool execution).
    # Not mapped directly; we already streamed the text.
    []
  when Ask::Agent::Events::TurnEnd
    # Fires after tool execution completes for one recursive iteration.
    # The session may continue with more tool calls.
    []
  when Ask::Agent::Events::ReflectionStart
    # Reflection is an internal detail — skip
    @in_reflection = true
    []
  when Ask::Agent::Events::ReflectionDelta
    # Treat reflection text as regular model output
    translate_text_delta(agent_event)
  when Ask::Agent::Events::ReflectionEnd
    @in_reflection = false
    []
  when Ask::Agent::Events::CompactionStart
    []
  when Ask::Agent::Events::CompactionEnd
    []
  when Ask::Agent::Events::Error
    translate_error(agent_event)
  when Ask::Agent::Events::SessionEnd
    translate_session_end(agent_event)
  when Ask::Agent::Events::MaxTurnsExceeded
    translate_turn_failed("Max turns exceeded (#{agent_event.max_turns})")
  when Ask::Agent::Events::LoopDetected
    translate_turn_failed("Loop detected on tool: #{agent_event.tool_name}")
  else
    []
  end
end