Class: AgentsControl::Channels::Telegram::Keyboards
- Inherits:
-
Object
- Object
- AgentsControl::Channels::Telegram::Keyboards
- Defined in:
- lib/agents_control/channels/telegram/keyboards.rb
Overview
Building inline keyboards and rendering lists.
The key Bot API constraint: a button's callback_data can't
exceed 64 bytes. An iTerm2 session UUID alone (36 characters,
plus an action, plus separators) already cuts it close, let alone
a path or a command.
So a button carries only a short key from Store, and the actual action lives on the daemon's side. Side benefit: the key is one-shot, and pressing the same button twice does nothing the second time.
Constant Summary collapse
- ACTION_TTL =
How long a button lives. It has to survive a quick trip out, but not hang around forever: a stale message shouldn't stay a working remote control.
3600
Instance Method Summary collapse
- #confirm(action, session, label: "Yes, close it") ⇒ Object
-
#initialize(store:) ⇒ Keyboards
constructor
A new instance of Keyboards.
- #list_actions ⇒ Object
-
#main_menu ⇒ Object
Buttons under /start and /help — the full command list isn't always visible in the Telegram UI (the menu button is easy to miss among everything else), so this keeps it available at any moment right in the message.
-
#render_list(sessions, chat_id:, title:, universe: sessions) ⇒ Object
A list with short numbers: commands like
/run 2 lsaddress sessions by them later. -
#session_actions(session) ⇒ Object
Buttons under a single session's card.
- #session_for(chat_id, number) ⇒ Object
Constructor Details
#initialize(store:) ⇒ Keyboards
Returns a new instance of Keyboards.
23 24 25 |
# File 'lib/agents_control/channels/telegram/keyboards.rb', line 23 def initialize(store:) @store = store end |
Instance Method Details
#confirm(action, session, label: "Yes, close it") ⇒ Object
40 41 42 43 44 45 46 47 |
# File 'lib/agents_control/channels/telegram/keyboards.rb', line 40 def confirm(action, session, label: "Yes, close it") { inline_keyboard: [[ ("⚠️ #{label}", action: action, session: session), ("cancel", action: "cancel", session: session) ]] } end |
#list_actions ⇒ Object
49 50 51 52 53 54 |
# File 'lib/agents_control/channels/telegram/keyboards.rb', line 49 def list_actions { inline_keyboard: [[ { text: "🤖 agents", callback_data: put(action: "list_agents") }, { text: "📋 all tabs", callback_data: put(action: "list_tabs") } ]] } end |
#main_menu ⇒ Object
Buttons under /start and /help — the full command list isn't always visible in the Telegram UI (the menu button is easy to miss among everything else), so this keeps it available at any moment right in the message.
60 61 62 63 64 65 66 67 |
# File 'lib/agents_control/channels/telegram/keyboards.rb', line 60 def { inline_keyboard: [ [{ text: "🤖 agents", callback_data: put(action: "list_agents") }, { text: "📋 all tabs", callback_data: put(action: "list_tabs") }], [{ text: "📊 status", callback_data: put(action: "status") }, { text: "⚙️ settings", callback_data: put(action: "show_settings") }] ] } end |
#render_list(sessions, chat_id:, title:, universe: sessions) ⇒ Object
A list with short numbers: commands like /run 2 ls address
sessions by them later.
Numbers are assigned against the full session list (universe), not the displayed subset — "All tabs" and "Agents" both number against the same universe, so a session keeps the same number in either view as long as the set of tabs hasn't changed. An /run with a remembered number must always hit the session the human actually saw, never a different one that happened to land on the same row in a shorter, filtered list.
79 80 81 82 83 84 85 86 87 88 |
# File 'lib/agents_control/channels/telegram/keyboards.rb', line 79 def render_list(sessions, chat_id:, title:, universe: sessions) numbers = numbered(universe) @store.put(numbers.invert, ttl: ACTION_TTL, key: index_key(chat_id)) lines = sessions.map do |session| "#{numbers[session.id].to_s.rjust(2)}. #{marker(session)} #{describe(session)}" end ([title, ""] + lines).join("\n") end |
#session_actions(session) ⇒ Object
Buttons under a single session's card.
28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/agents_control/channels/telegram/keyboards.rb', line 28 def session_actions(session) rows = [[ ("🎯 focus", action: "focus", session: session), ("👁 screen", action: "screen", session: session) ]] # Closing a tab goes through confirmation: a mistap on a phone is too easy. rows << [("✖️ close", action: "close_confirm", session: session)] unless session.terminalless? { inline_keyboard: rows } end |
#session_for(chat_id, number) ⇒ Object
90 91 92 93 94 |
# File 'lib/agents_control/channels/telegram/keyboards.rb', line 90 def session_for(chat_id, number) map = @store.get(index_key(chat_id)) || {} map[number.to_s] end |