From 0e7cc8d0970c24cf24c0e3be221427981a799efb Mon Sep 17 00:00:00 2001 From: Ben Sima Date: Fri, 26 Dec 2025 10:57:03 -0500 Subject: fix UTF-8 encoding in deployed services MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Systemd.hs: add LANG and LC_ALL defaults (en_US.utf8) to all generated unit files to ensure proper UTF-8 handling - Systemd.hs: add generateUnitWithLocale that reads LOCALE_ARCHIVE from the deployer's environment and injects it into generated units - Telegram.hs: add safePutText wrapper that catches encoding errors in logging to prevent them from killing message sends The root cause was NixOS systemd services not inheriting locale settings from the system, causing emoji characters to fail encoding. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- Omni/Agent/Telegram.hs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'Omni/Agent') diff --git a/Omni/Agent/Telegram.hs b/Omni/Agent/Telegram.hs index 2bf7aed..57420a4 100644 --- a/Omni/Agent/Telegram.hs +++ b/Omni/Agent/Telegram.hs @@ -116,6 +116,13 @@ import qualified Omni.Test as Test import System.Environment (lookupEnv) import Text.Printf (printf) +safePutText :: Text -> IO () +safePutText msg = do + result <- try @SomeException (putText msg) + case result of + Left _ -> putText "[log encoding error - message contained unrepresentable characters]" + Right () -> pure () + defaultTelegramConfig :: Text -> [Int] -> Maybe Text -> Text -> Types.TelegramConfig defaultTelegramConfig = Types.defaultTelegramConfig @@ -623,7 +630,7 @@ runTelegramBot tgConfig provider = do handleBotAddedToGroup tgConfig addedEvent Nothing -> case Types.parseUpdate rawUpdate of Just msg -> do - putText <| "Received message from " <> Types.tmUserFirstName msg <> " in chat " <> tshow (Types.tmChatId msg) <> " (type: " <> tshow (Types.tmChatType msg) <> "): " <> Text.take 50 (Types.tmText msg) + safePutText <| "Received message from " <> Types.tmUserFirstName msg <> " in chat " <> tshow (Types.tmChatId msg) <> " (type: " <> tshow (Types.tmChatType msg) <> "): " <> Text.take 50 (Types.tmText msg) atomically (writeTVar offsetVar (Types.tmUpdateId msg + 1)) IncomingQueue.enqueueIncoming incomingQueues IncomingQueue.defaultBatchWindowSeconds msg Nothing -> do @@ -1329,7 +1336,7 @@ processEngagedMessage tgConfig provider engineCfg msg uid userName chatId userMe let baseResponse = Engine.resultFinalMessage agentResult response = baseResponse <> traceLink threadId = Types.tmThreadId msg - putText <| "Response text: " <> Text.take 200 response + safePutText <| "Response text: " <> Text.take 200 response if isGroup then void <| Memory.saveGroupMessage chatId threadId Memory.AssistantRole "Ava" response -- cgit v1.2.3