diff --git a/src/OpenClaw.Tray.WinUI/Chat/ChatComposerController.cs b/src/OpenClaw.Tray.WinUI/Chat/ChatComposerController.cs index af3542f8e..c018b6610 100644 --- a/src/OpenClaw.Tray.WinUI/Chat/ChatComposerController.cs +++ b/src/OpenClaw.Tray.WinUI/Chat/ChatComposerController.cs @@ -164,7 +164,7 @@ public async Task SendAsync() var thread = inputs.CurrentThread; var draft = _vm.Draft; var attachments = _vm.PendingAttachments; - var message = draft.Trim(); + var message = draft.Trim().Replace("\r\n", "\n").Replace('\r', '\n'); if ((message.Length == 0 && attachments.Count == 0) || _vm.SlashDisplay.IsLoading || inputs.ConnectionState != "connected") diff --git a/tests/OpenClaw.Tray.Tests/ChatComposerControllerTests.cs b/tests/OpenClaw.Tray.Tests/ChatComposerControllerTests.cs index a9e9ddcca..ab0511bca 100644 --- a/tests/OpenClaw.Tray.Tests/ChatComposerControllerTests.cs +++ b/tests/OpenClaw.Tray.Tests/ChatComposerControllerTests.cs @@ -98,6 +98,17 @@ public async Task SendAsync_OrdinaryMessage_CallsProviderExactlyOnceAndClearsDra Assert.Equal(string.Empty, vm.Draft); } + [Fact] + public async Task SendAsync_TextBoxLineBreaks_AreSentAsLineFeeds() + { + var (vm, controller, port, _) = MakeController(); + vm.SetDraft("line one\rline two\r\nline three"); + + Assert.True(await controller.SendAsync()); + + Assert.Equal("line one\nline two\nline three", port.LastSendMessageCall!.Value.Message); + } + [Fact] public async Task SendAsync_ActiveTurn_AcceptedFollowUpClearsComposerAndAllowsAnotherDraft() {