Refactor existing Telegram callbacks to type-safe Action system

t-280.2.8·WorkTask·
·
·
·Omni/Agent/Telegram.hs
Parent:t-280.2·Created1 month ago·Updated1 month ago

Dependencies

Description

Edit

Migrate existing callback handlers to the new Action system before adding orchestrator actions.

Current Callbacks to Migrate

From handleCallbackQueryInner:

  • subagent_approve:<id> - approve pending subagent spawn
  • subagent_reject:<id> - reject pending subagent spawn

Steps

1. Create Omni/Agent/Telegram/Actions.hs

module Omni.Agent.Telegram.Actions
  ( Action(..)
  , ActionInput(..)
  , ActionResult(..)
  , ActionOutcome(..)
  , executeAction
  , actionRegistry
  ) where

-- Core types as designed in t-280.2.7

2. Implement existing actions

approveSubagentAction :: Action
approveSubagentAction = Action
  { actionId = "subagent_approve"
  , actionExecute = \input -> do
      let pendingId = aiPayload input
      result <- Subagent.approveAndSpawnSubagentWithCallback pendingId Nothing
      case result of
        Left err -> pure ActionResult
          { arUserMessage = "[Approved subagent: " <> pendingId <> "]"
          , arAssistantMessage = "Failed to spawn: " <> err
          , arOutcome = ActionFailed err
          }
        Right subagentId -> pure ActionResult
          { arUserMessage = "[Approved subagent: " <> pendingId <> "]"
          , arAssistantMessage = "Subagent " <> subagentId <> " queued! I'll notify you when it completes."
          , arOutcome = ActionPending subagentId
          }
  }

rejectSubagentAction :: Action
-- similar

3. Refactor handleCallbackQueryInner

Replace the case statement with:

handleCallbackQueryInner tgConfig cq chatId userId callbackData = do
  let (actionId, payload) = parseCallbackData callbackData
      input = ActionInput userId chatId payload
  
  result <- executeAction actionId input
  case result of
    Nothing -> do
      answerCallbackQuery tgConfig (cqId cq) (Just "Unknown action")
      putText <| "Unknown callback: " <> callbackData
    Just ar -> do
      -- Log to conversation (type system guarantees these fields exist)
      Memory.appendMessage chatId User (arUserMessage ar)
      Memory.appendMessage chatId Assistant (arAssistantMessage ar)
      -- Send response
      sendMessage tgConfig chatId (arAssistantMessage ar)
      answerCallbackQuery tgConfig (cqId cq) (Just "Done")

4. Update keyboard button creation

Ensure buttons use actionId format: actionId:payload

Success Criteria

  • Existing subagent approve/reject still works
  • Callback actions now appear in conversation history
  • New actions can only be added via Action type (enforced by removing old code path)

Blocked by

t-280.2.7 (design task - but can do both together)

Timeline (2)

🔄[human]Open → InProgress1 month ago
🔄[human]InProgress → Done1 month ago