From 9dec7acc91f00d8d8bbe39005e016e511181a9ca Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 18 Jul 2026 04:05:50 +0100 Subject: [PATCH] feat(macos): visible-markdown copy, full-message reader, and independent reasoning/tool toggles (#110276) * feat(clients): copy visible markdown, full-message reader for truncated messages, and independent reasoning/tool toggles * chore(i18n): translate new reader and trace strings and regenerate catalogs * test(ios): adopt reader display-options API in render smoke tests --- apps/.i18n/native-source.json | 252 +-- apps/.i18n/native/ar.json | 81 +- apps/.i18n/native/de.json | 81 +- apps/.i18n/native/es.json | 81 +- apps/.i18n/native/fa.json | 81 +- apps/.i18n/native/fr.json | 81 +- apps/.i18n/native/hi.json | 81 +- apps/.i18n/native/id.json | 81 +- apps/.i18n/native/it.json | 81 +- apps/.i18n/native/ja-JP.json | 81 +- apps/.i18n/native/ko.json | 81 +- apps/.i18n/native/nl.json | 81 +- apps/.i18n/native/pl.json | 81 +- apps/.i18n/native/pt-BR.json | 81 +- apps/.i18n/native/ru.json | 81 +- apps/.i18n/native/sv.json | 81 +- apps/.i18n/native/th.json | 81 +- apps/.i18n/native/tr.json | 81 +- apps/.i18n/native/uk.json | 81 +- apps/.i18n/native/vi.json | 81 +- apps/.i18n/native/zh-CN.json | 81 +- apps/.i18n/native/zh-TW.json | 81 +- apps/ios/Resources/Localizable.xcstrings | 1360 +++++++++++++++-- apps/ios/Tests/SwiftUIRenderSmokeTests.swift | 4 +- .../Sources/OpenClaw/WebChatSwiftUI.swift | 74 +- .../MacGatewayChatTransportMappingTests.swift | 28 + .../WebChatSwiftUISmokeTests.swift | 22 +- .../ChatFullMessageReader.swift | 92 ++ .../OpenClawChatUI/ChatMessageViews.swift | 20 +- .../ChatMessageVisibleText.swift | 5 + .../Sources/OpenClawChatUI/ChatModels.swift | 21 + .../OpenClawChatUI/ChatTransport.swift | 5 + .../Sources/OpenClawChatUI/ChatView.swift | 218 ++- .../OpenClawChatUI/ChatWindowShell.swift | 30 +- .../ChatMessageVisibleTextTests.swift | 50 + docs/platforms/mac/webchat.md | 6 +- 36 files changed, 3171 insertions(+), 717 deletions(-) create mode 100644 apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatFullMessageReader.swift diff --git a/apps/.i18n/native-source.json b/apps/.i18n/native-source.json index 9c3f5038f584..5a8857e75cc5 100644 --- a/apps/.i18n/native-source.json +++ b/apps/.i18n/native-source.json @@ -35891,7 +35891,7 @@ }, { "kind": "ui-localized-call", - "line": 682, + "line": 746, "path": "apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift", "source": "Talk mode off", "surface": "apple", @@ -35899,7 +35899,7 @@ }, { "kind": "ui-localized-call", - "line": 683, + "line": 747, "path": "apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift", "source": "Talk mode paused", "surface": "apple", @@ -35907,7 +35907,7 @@ }, { "kind": "ui-localized-call", - "line": 685, + "line": 749, "path": "apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift", "source": "Talk mode ready", "surface": "apple", @@ -35915,7 +35915,7 @@ }, { "kind": "ui-localized-call", - "line": 686, + "line": 750, "path": "apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift", "source": "Listening", "surface": "apple", @@ -35923,7 +35923,7 @@ }, { "kind": "ui-localized-call", - "line": 687, + "line": 751, "path": "apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift", "source": "Thinking", "surface": "apple", @@ -35931,7 +35931,7 @@ }, { "kind": "ui-localized-call", - "line": 688, + "line": 752, "path": "apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift", "source": "Speaking", "surface": "apple", @@ -35939,7 +35939,7 @@ }, { "kind": "ui-localized-call", - "line": 692, + "line": 756, "path": "apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift", "source": "What would you like to work on?", "surface": "apple", @@ -35947,7 +35947,7 @@ }, { "kind": "ui-localized-call", - "line": 696, + "line": 760, "path": "apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift", "source": "Check OpenClaw status", "surface": "apple", @@ -35955,7 +35955,7 @@ }, { "kind": "ui-localized-call", - "line": 697, + "line": 761, "path": "apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift", "source": "Summarize the current OpenClaw status and tell me what needs attention.", "surface": "apple", @@ -35963,7 +35963,7 @@ }, { "kind": "ui-localized-call", - "line": 700, + "line": 764, "path": "apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift", "source": "What can you do?", "surface": "apple", @@ -35971,7 +35971,7 @@ }, { "kind": "ui-localized-call", - "line": 701, + "line": 765, "path": "apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift", "source": "Show me what you can help with on this Mac right now.", "surface": "apple", @@ -35979,7 +35979,7 @@ }, { "kind": "ui-localized-call", - "line": 704, + "line": 768, "path": "apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift", "source": "Catch me up", "surface": "apple", @@ -35987,7 +35987,7 @@ }, { "kind": "ui-localized-call", - "line": 705, + "line": 769, "path": "apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift", "source": "Summarize what happened in my sessions since yesterday.", "surface": "apple", @@ -36385,6 +36385,62 @@ "surface": "apple", "id": "native.apple.9243b96b3d4d590f" }, + { + "kind": "ui-call", + "line": 34, + "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatFullMessageReader.swift", + "source": "Loading full message…", + "surface": "apple", + "id": "native.apple.ccfd6ae994d82449" + }, + { + "kind": "ui-localized-call", + "line": 52, + "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatFullMessageReader.swift", + "source": "Full message unavailable", + "surface": "apple", + "id": "native.apple.669ad52de4a26b87" + }, + { + "kind": "ui-modifier", + "line": 58, + "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatFullMessageReader.swift", + "source": "Full Message", + "surface": "apple", + "id": "native.apple.6f79794ee74caf99" + }, + { + "kind": "ui-call", + "line": 61, + "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatFullMessageReader.swift", + "source": "Close", + "surface": "apple", + "id": "native.apple.d648251591db5dec" + }, + { + "kind": "ui-localized-call", + "line": 77, + "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatFullMessageReader.swift", + "source": "The full message is no longer available.", + "surface": "apple", + "id": "native.apple.ba3963204bda5e84" + }, + { + "kind": "ui-localized-call", + "line": 82, + "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatFullMessageReader.swift", + "source": "The full message has no readable text.", + "surface": "apple", + "id": "native.apple.8bb98bd86ae85c1c" + }, + { + "kind": "ui-localized-call", + "line": 89, + "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatFullMessageReader.swift", + "source": "The full message could not be loaded.", + "surface": "apple", + "id": "native.apple.2f43669d87c0e26d" + }, { "kind": "ui-call", "line": 328, @@ -36971,7 +37027,7 @@ }, { "kind": "ui-call", - "line": 457, + "line": 487, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift", "source": "Retry Send", "surface": "apple", @@ -36979,7 +37035,7 @@ }, { "kind": "ui-call", - "line": 471, + "line": 501, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift", "source": "Delete", "surface": "apple", @@ -36987,7 +37043,7 @@ }, { "kind": "ui-call", - "line": 503, + "line": 535, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift", "source": "Stop Listening", "surface": "apple", @@ -36995,7 +37051,7 @@ }, { "kind": "ui-call", - "line": 506, + "line": 538, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift", "source": "Listen", "surface": "apple", @@ -37003,39 +37059,7 @@ }, { "kind": "ui-call", - "line": 550, - "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift", - "source": "Copy Message", - "surface": "apple", - "id": "native.apple.fe9f30f12f1dcfaf" - }, - { - "kind": "ui-localized-call", - "line": 571, - "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift", - "source": "Reply", - "surface": "apple", - "id": "native.apple.b37ec7bd7dc1579a" - }, - { - "kind": "ui-localized-call", - "line": 581, - "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift", - "source": "You", - "surface": "apple", - "id": "native.apple.8d80a6bb3d6e99b0" - }, - { - "kind": "ui-localized-call", - "line": 583, - "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift", - "source": "Assistant", - "surface": "apple", - "id": "native.apple.3b44a67aa284886f" - }, - { - "kind": "ui-call", - "line": 636, + "line": 616, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift", "source": "Jump to latest", "surface": "apple", @@ -37043,7 +37067,7 @@ }, { "kind": "ui-modifier", - "line": 647, + "line": 627, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift", "source": "Jump to latest reply", "surface": "apple", @@ -37051,7 +37075,7 @@ }, { "kind": "ui-named-argument", - "line": 667, + "line": 647, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift", "source": "Refresh", "surface": "apple", @@ -37059,7 +37083,47 @@ }, { "kind": "ui-call", - "line": 1093, + "line": 1033, + "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift", + "source": "Copy Message", + "surface": "apple", + "id": "native.apple.fe9f30f12f1dcfaf" + }, + { + "kind": "ui-call", + "line": 1056, + "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift", + "source": "Open Full Message", + "surface": "apple", + "id": "native.apple.90bc8a8045e7017e" + }, + { + "kind": "ui-localized-call", + "line": 1077, + "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift", + "source": "Reply", + "surface": "apple", + "id": "native.apple.b37ec7bd7dc1579a" + }, + { + "kind": "ui-localized-call", + "line": 1087, + "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift", + "source": "You", + "surface": "apple", + "id": "native.apple.8d80a6bb3d6e99b0" + }, + { + "kind": "ui-localized-call", + "line": 1089, + "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift", + "source": "Assistant", + "surface": "apple", + "id": "native.apple.3b44a67aa284886f" + }, + { + "kind": "ui-call", + "line": 1155, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift", "source": "Loading chat", "surface": "apple", @@ -37067,7 +37131,7 @@ }, { "kind": "ui-modifier", - "line": 1173, + "line": 1235, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift", "source": "Dismiss", "surface": "apple", @@ -37171,7 +37235,7 @@ }, { "kind": "ui-modifier", - "line": 73, + "line": 77, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Clear this session's history?", "surface": "apple", @@ -37179,7 +37243,7 @@ }, { "kind": "ui-call", - "line": 79, + "line": 83, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Clear History", "surface": "apple", @@ -37187,7 +37251,7 @@ }, { "kind": "ui-localized-call-multiline", - "line": 84, + "line": 88, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "This resets the conversation for %@. The session key stays the same.", "surface": "apple", @@ -37195,7 +37259,7 @@ }, { "kind": "ui-localized-call", - "line": 90, + "line": 94, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Rename Session", "surface": "apple", @@ -37203,7 +37267,7 @@ }, { "kind": "ui-localized-call", - "line": 91, + "line": 95, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Session name", "surface": "apple", @@ -37211,7 +37275,7 @@ }, { "kind": "ui-localized-call", - "line": 92, + "line": 96, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Rename", "surface": "apple", @@ -37219,7 +37283,7 @@ }, { "kind": "ui-localized-call", - "line": 97, + "line": 101, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Cancel", "surface": "apple", @@ -37227,7 +37291,7 @@ }, { "kind": "ui-call", - "line": 138, + "line": 142, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Export Transcript", "surface": "apple", @@ -37235,7 +37299,7 @@ }, { "kind": "ui-call", - "line": 147, + "line": 151, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Sessions", "surface": "apple", @@ -37243,7 +37307,7 @@ }, { "kind": "ui-call", - "line": 231, + "line": 235, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Thinking", "surface": "apple", @@ -37251,7 +37315,7 @@ }, { "kind": "ui-modifier", - "line": 235, + "line": 239, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Thinking level", "surface": "apple", @@ -37259,7 +37323,7 @@ }, { "kind": "ui-call", - "line": 251, + "line": 255, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Pinned", "surface": "apple", @@ -37267,7 +37331,7 @@ }, { "kind": "ui-call", - "line": 254, + "line": 258, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Recent", "surface": "apple", @@ -37275,7 +37339,7 @@ }, { "kind": "ui-call", - "line": 257, + "line": 261, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Models", "surface": "apple", @@ -37283,7 +37347,7 @@ }, { "kind": "ui-call", - "line": 261, + "line": 265, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Model", "surface": "apple", @@ -37291,7 +37355,7 @@ }, { "kind": "ui-call", - "line": 281, + "line": 285, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "New Session", "surface": "apple", @@ -37299,7 +37363,7 @@ }, { "kind": "ui-call", - "line": 289, + "line": 293, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Refresh", "surface": "apple", @@ -37307,7 +37371,7 @@ }, { "kind": "ui-call", - "line": 296, + "line": 300, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Sessions…", "surface": "apple", @@ -37315,7 +37379,7 @@ }, { "kind": "ui-localized-call", - "line": 308, + "line": 312, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Rename Session…", "surface": "apple", @@ -37323,7 +37387,7 @@ }, { "kind": "ui-localized-call", - "line": 316, + "line": 320, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Fork Session", "surface": "apple", @@ -37331,7 +37395,7 @@ }, { "kind": "ui-localized-call", - "line": 327, + "line": 331, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Unpin", "surface": "apple", @@ -37339,7 +37403,7 @@ }, { "kind": "ui-localized-call", - "line": 328, + "line": 332, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Pin", "surface": "apple", @@ -37347,7 +37411,7 @@ }, { "kind": "ui-localized-call", - "line": 339, + "line": 343, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Mark Read", "surface": "apple", @@ -37355,7 +37419,7 @@ }, { "kind": "ui-localized-call", - "line": 340, + "line": 344, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Mark Unread", "surface": "apple", @@ -37363,7 +37427,7 @@ }, { "kind": "ui-localized-call", - "line": 356, + "line": 360, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Restore", "surface": "apple", @@ -37371,7 +37435,7 @@ }, { "kind": "ui-localized-call", - "line": 357, + "line": 361, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Archive", "surface": "apple", @@ -37379,7 +37443,7 @@ }, { "kind": "ui-call", - "line": 369, + "line": 373, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Copy Session Key", "surface": "apple", @@ -37387,7 +37451,7 @@ }, { "kind": "ui-call", - "line": 375, + "line": 379, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Export Transcript…", "surface": "apple", @@ -37395,15 +37459,23 @@ }, { "kind": "ui-call", - "line": 387, + "line": 391, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", - "source": "Show reasoning & tool activity", + "source": "Show Reasoning", "surface": "apple", - "id": "native.apple.3294ababd29c4457" + "id": "native.apple.ebb130189022c7ec" }, { "kind": "ui-call", - "line": 404, + "line": 403, + "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", + "source": "Show Tool Activity", + "surface": "apple", + "id": "native.apple.d0dba9aad550fa6e" + }, + { + "kind": "ui-call", + "line": 420, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Clear History…", "surface": "apple", @@ -37411,7 +37483,7 @@ }, { "kind": "ui-call", - "line": 407, + "line": 423, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Session", "surface": "apple", @@ -37419,7 +37491,7 @@ }, { "kind": "ui-modifier", - "line": 410, + "line": 426, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Session actions", "surface": "apple", @@ -37427,7 +37499,7 @@ }, { "kind": "ui-localized-call", - "line": 444, + "line": 460, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Session cost %@", "surface": "apple", @@ -37435,7 +37507,7 @@ }, { "kind": "ui-call", - "line": 450, + "line": 466, "path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift", "source": "Compact Session", "surface": "apple", diff --git a/apps/.i18n/native/ar.json b/apps/.i18n/native/ar.json index 21d673ebabd3..41f99d4a3b70 100644 --- a/apps/.i18n/native/ar.json +++ b/apps/.i18n/native/ar.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "تم استخدام %@ من الرموز" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "جارٍ تحميل الرسالة كاملة…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "الرسالة الكاملة غير متاحة" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "الرسالة الكاملة" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "إغلاق" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "لم تعد الرسالة الكاملة متاحة." + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "لا تحتوي الرسالة الكاملة على نص قابل للقراءة." + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "تعذّر تحميل الرسالة الكاملة." + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "استمع" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "الانتقال إلى الأحدث" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "الانتقال إلى أحدث رد" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "تحديث" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "نسخ الرسالة" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "فتح الرسالة الكاملة" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "المساعد" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "الانتقال إلى الأحدث" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "الانتقال إلى أحدث رد" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "تحديث" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "تصدير النص…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "إظهار الاستدلال ونشاط الأدوات" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "إظهار الاستدلال" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "إظهار نشاط الأداة" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/de.json b/apps/.i18n/native/de.json index 86128c72e64d..88f6a4323053 100644 --- a/apps/.i18n/native/de.json +++ b/apps/.i18n/native/de.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "%@ Token verwendet" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "Vollständige Nachricht wird geladen…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "Vollständige Nachricht nicht verfügbar" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "Vollständige Nachricht" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "Schließen" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "Die vollständige Nachricht ist nicht mehr verfügbar." + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "Die vollständige Nachricht enthält keinen lesbaren Text." + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "Die vollständige Nachricht konnte nicht geladen werden." + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "Zuhören" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "Zum neuesten springen" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "Zur neuesten Antwort springen" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "Aktualisieren" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "Nachricht kopieren" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "Vollständige Nachricht öffnen" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "Assistent" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "Zum neuesten springen" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "Zur neuesten Antwort springen" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "Aktualisieren" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "Transkript exportieren…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "Gedankengang und Werkzeugaktivität anzeigen" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "Gedankengang anzeigen" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "Tool-Aktivität anzeigen" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/es.json b/apps/.i18n/native/es.json index ea4ea7c510df..7fd77e01d59a 100644 --- a/apps/.i18n/native/es.json +++ b/apps/.i18n/native/es.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "%@ tokens utilizados" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "Cargando el mensaje completo…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "Mensaje completo no disponible" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "Mensaje completo" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "Cerrar" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "El mensaje completo ya no está disponible." + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "El mensaje completo no contiene texto legible." + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "No se pudo cargar el mensaje completo." + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "Escuchar" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "Ir a lo más reciente" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "Ir a la respuesta más reciente" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "Actualizar" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "Copiar mensaje" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "Abrir mensaje completo" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "Asistente" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "Ir a lo más reciente" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "Ir a la respuesta más reciente" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "Actualizar" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "Exportar transcripción…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "Mostrar el razonamiento y la actividad de las herramientas" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "Mostrar razonamiento" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "Mostrar actividad de las herramientas" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/fa.json b/apps/.i18n/native/fa.json index aae34c9f6b0f..2a881729790e 100644 --- a/apps/.i18n/native/fa.json +++ b/apps/.i18n/native/fa.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "%@ توکن استفاده شده است" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "در حال بارگذاری پیام کامل…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "پیام کامل در دسترس نیست" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "پیام کامل" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "بستن" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "پیام کامل دیگر در دسترس نیست." + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "پیام کامل متن خوانایی ندارد." + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "پیام کامل بارگذاری نشد." + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "گوش دادن" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "پرش به آخرین مورد" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "پرش به آخرین پاسخ" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "تازه‌سازی" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "کپی پیام" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "باز کردن پیام کامل" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "دستیار" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "پرش به آخرین مورد" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "پرش به آخرین پاسخ" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "تازه‌سازی" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "خروجی گرفتن رونوشت…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "نمایش استدلال و فعالیت ابزارها" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "نمایش استدلال" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "نمایش فعالیت ابزار" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/fr.json b/apps/.i18n/native/fr.json index 6d6f8a8c1184..50525cfd6f72 100644 --- a/apps/.i18n/native/fr.json +++ b/apps/.i18n/native/fr.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "%@ jetons utilisés" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "Chargement du message complet…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "Message complet indisponible" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "Message complet" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "Fermer" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "Le message complet n’est plus disponible." + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "Le message complet ne contient aucun texte lisible." + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "Le message complet n’a pas pu être chargé." + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "Écouter" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "Aller au plus récent" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "Aller à la réponse la plus récente" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "Actualiser" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "Copier le message" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "Ouvrir le message complet" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "Assistant" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "Aller au plus récent" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "Aller à la réponse la plus récente" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "Actualiser" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "Exporter la transcription…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "Afficher le raisonnement et l’activité des outils" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "Afficher le raisonnement" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "Afficher l’activité des outils" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/hi.json b/apps/.i18n/native/hi.json index cc9a2b3b4a0d..e8e53086f071 100644 --- a/apps/.i18n/native/hi.json +++ b/apps/.i18n/native/hi.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "%@ टोकन उपयोग किए गए" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "पूरा संदेश लोड हो रहा है…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "पूरा संदेश उपलब्ध नहीं है" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "पूरा संदेश" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "बंद करें" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "पूरा संदेश अब उपलब्ध नहीं है।" + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "पूरे संदेश में पढ़ने योग्य कोई टेक्स्ट नहीं है।" + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "पूरा संदेश लोड नहीं किया जा सका।" + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "सुनें" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "नवीनतम पर जाएँ" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "नवीनतम उत्तर पर जाएँ" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "रीफ़्रेश करें" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "संदेश कॉपी करें" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "पूरा संदेश खोलें" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "सहायक" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "नवीनतम पर जाएँ" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "नवीनतम उत्तर पर जाएँ" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "रीफ़्रेश करें" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "ट्रांसक्रिप्ट निर्यात करें…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "तर्क और टूल गतिविधि दिखाएँ" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "तर्क दिखाएँ" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "टूल गतिविधि दिखाएँ" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/id.json b/apps/.i18n/native/id.json index 1b586f87879e..c283d4bf69be 100644 --- a/apps/.i18n/native/id.json +++ b/apps/.i18n/native/id.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "%@ token telah digunakan" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "Memuat pesan lengkap…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "Pesan lengkap tidak tersedia" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "Pesan Lengkap" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "Tutup" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "Pesan lengkap sudah tidak tersedia." + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "Pesan lengkap tidak memiliki teks yang dapat dibaca." + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "Pesan lengkap tidak dapat dimuat." + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "Dengarkan" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "Lompat ke terbaru" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "Lompat ke balasan terbaru" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "Segarkan" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "Salin Pesan" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "Buka Pesan Lengkap" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "Asisten" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "Lompat ke terbaru" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "Lompat ke balasan terbaru" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "Segarkan" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "Ekspor Transkrip…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "Tampilkan penalaran & aktivitas alat" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "Tampilkan Penalaran" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "Tampilkan Aktivitas Alat" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/it.json b/apps/.i18n/native/it.json index cf00e4cf9a7e..6f9d5140c70a 100644 --- a/apps/.i18n/native/it.json +++ b/apps/.i18n/native/it.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "%@ token utilizzati" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "Caricamento del messaggio completo…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "Messaggio completo non disponibile" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "Messaggio completo" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "Chiudi" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "Il messaggio completo non è più disponibile." + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "Il messaggio completo non contiene testo leggibile." + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "Impossibile caricare il messaggio completo." + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "Ascolta" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "Vai all'ultimo" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "Vai all'ultima risposta" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "Aggiorna" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "Copia messaggio" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "Apri il messaggio completo" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "Assistente" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "Vai all'ultimo" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "Vai all'ultima risposta" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "Aggiorna" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "Esporta trascrizione…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "Mostra il ragionamento e l'attività degli strumenti" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "Mostra il ragionamento" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "Mostra l'attività degli strumenti" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/ja-JP.json b/apps/.i18n/native/ja-JP.json index 804e71bdbeba..12b6c773b128 100644 --- a/apps/.i18n/native/ja-JP.json +++ b/apps/.i18n/native/ja-JP.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "%@トークンを使用" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "メッセージ全文を読み込み中…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "メッセージ全文を利用できません" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "メッセージ全文" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "閉じる" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "メッセージ全文は利用できなくなりました。" + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "メッセージ全文に読み取れるテキストがありません。" + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "メッセージ全文を読み込めませんでした。" + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "聞く" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "最新に移動" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "最新の返信に移動" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "更新" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "メッセージをコピー" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "メッセージ全文を開く" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "アシスタント" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "最新に移動" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "最新の返信に移動" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "更新" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "トランスクリプトをエクスポート…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "推論とツールのアクティビティを表示" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "推論を表示" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "ツールのアクティビティを表示" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/ko.json b/apps/.i18n/native/ko.json index ade3f50dc25d..b04501cd4b53 100644 --- a/apps/.i18n/native/ko.json +++ b/apps/.i18n/native/ko.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "%@개 토큰 사용됨" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "전체 메시지를 불러오는 중…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "전체 메시지를 사용할 수 없음" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "전체 메시지" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "닫기" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "전체 메시지를 더 이상 사용할 수 없습니다." + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "전체 메시지에 읽을 수 있는 텍스트가 없습니다." + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "전체 메시지를 불러올 수 없습니다." + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "듣기" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "최신 항목으로 이동" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "최신 답글로 이동" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "새로 고침" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "메시지 복사" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "전체 메시지 열기" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "어시스턴트" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "최신 항목으로 이동" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "최신 답글로 이동" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "새로 고침" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "기록 내보내기…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "추론 및 도구 활동 표시" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "추론 보기" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "도구 활동 보기" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/nl.json b/apps/.i18n/native/nl.json index 412f0f9459aa..8c25db486152 100644 --- a/apps/.i18n/native/nl.json +++ b/apps/.i18n/native/nl.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "%@ tokens gebruikt" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "Volledig bericht laden…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "Volledig bericht niet beschikbaar" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "Volledig bericht" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "Sluiten" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "Het volledige bericht is niet meer beschikbaar." + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "Het volledige bericht bevat geen leesbare tekst." + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "Het volledige bericht kon niet worden geladen." + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "Luisteren" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "Naar nieuwste springen" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "Naar nieuwste antwoord springen" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "Vernieuwen" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "Bericht kopiëren" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "Volledig bericht openen" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "Assistent" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "Naar nieuwste springen" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "Naar nieuwste antwoord springen" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "Vernieuwen" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "Transcript exporteren…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "Redenering en toolactiviteit tonen" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "Redenering tonen" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "Toolactiviteit tonen" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/pl.json b/apps/.i18n/native/pl.json index 4cd49483cb93..ec19238c266e 100644 --- a/apps/.i18n/native/pl.json +++ b/apps/.i18n/native/pl.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "Wykorzystano %@ tokenów" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "Wczytywanie pełnej wiadomości…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "Pełna wiadomość jest niedostępna" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "Pełna wiadomość" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "Zamknij" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "Pełna wiadomość nie jest już dostępna." + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "Pełna wiadomość nie zawiera tekstu możliwego do odczytania." + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "Nie udało się wczytać pełnej wiadomości." + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "Słuchaj" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "Przejdź do najnowszych" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "Przejdź do najnowszej odpowiedzi" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "Odśwież" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "Kopiuj wiadomość" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "Otwórz pełną wiadomość" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "Asystent" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "Przejdź do najnowszych" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "Przejdź do najnowszej odpowiedzi" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "Odśwież" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "Eksportuj transkrypcję…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "Pokaż tok rozumowania i aktywność narzędzi" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "Pokaż tok rozumowania" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "Pokaż aktywność narzędzi" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/pt-BR.json b/apps/.i18n/native/pt-BR.json index 49a6d11225f1..b75584d8fd80 100644 --- a/apps/.i18n/native/pt-BR.json +++ b/apps/.i18n/native/pt-BR.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "%@ tokens usados" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "Carregando mensagem completa…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "Mensagem completa indisponível" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "Mensagem completa" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "Fechar" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "A mensagem completa não está mais disponível." + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "A mensagem completa não contém texto legível." + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "Não foi possível carregar a mensagem completa." + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "Ouvir" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "Ir para a mais recente" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "Ir para a resposta mais recente" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "Atualizar" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "Copiar mensagem" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "Abrir mensagem completa" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "Assistente" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "Ir para a mais recente" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "Ir para a resposta mais recente" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "Atualizar" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "Exportar transcrição…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "Mostrar raciocínio e atividade das ferramentas" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "Mostrar raciocínio" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "Mostrar atividade das ferramentas" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/ru.json b/apps/.i18n/native/ru.json index 897bff6b6f5f..0167ee486eae 100644 --- a/apps/.i18n/native/ru.json +++ b/apps/.i18n/native/ru.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "Использовано токенов: %@" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "Загрузка полного сообщения…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "Полное сообщение недоступно" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "Полное сообщение" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "Закрыть" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "Полное сообщение больше недоступно." + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "В полном сообщении нет читаемого текста." + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "Не удалось загрузить полное сообщение." + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "Слушать" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "Перейти к последнему" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "Перейти к последнему ответу" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "Обновить" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "Копировать сообщение" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "Открыть полное сообщение" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "Ассистент" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "Перейти к последнему" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "Перейти к последнему ответу" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "Обновить" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "Экспорт транскрипта…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "Показывать ход рассуждений и действия инструментов" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "Показать ход рассуждений" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "Показать действия инструментов" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/sv.json b/apps/.i18n/native/sv.json index 615d4fe52b47..c61b08aea4e1 100644 --- a/apps/.i18n/native/sv.json +++ b/apps/.i18n/native/sv.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "%@ token används" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "Läser in hela meddelandet…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "Hela meddelandet är inte tillgängligt" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "Hela meddelandet" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "Stäng" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "Hela meddelandet är inte längre tillgängligt." + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "Hela meddelandet saknar läsbar text." + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "Det gick inte att läsa in hela meddelandet." + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "Lyssna" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "Hoppa till senaste" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "Hoppa till senaste svar" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "Uppdatera" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "Kopiera meddelande" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "Öppna hela meddelandet" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "Assistent" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "Hoppa till senaste" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "Hoppa till senaste svar" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "Uppdatera" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "Exportera transkription…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "Visa resonemang och verktygsaktivitet" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "Visa resonemang" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "Visa verktygsaktivitet" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/th.json b/apps/.i18n/native/th.json index 338d8f836a55..e0f843b9648c 100644 --- a/apps/.i18n/native/th.json +++ b/apps/.i18n/native/th.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "ใช้โทเค็นไป %@ รายการ" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "กำลังโหลดข้อความฉบับเต็ม…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "ไม่สามารถดูข้อความฉบับเต็มได้" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "ข้อความฉบับเต็ม" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "ปิด" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "ข้อความฉบับเต็มไม่พร้อมใช้งานแล้ว" + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "ข้อความฉบับเต็มไม่มีข้อความที่อ่านได้" + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "ไม่สามารถโหลดข้อความฉบับเต็มได้" + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "ฟัง" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "ข้ามไปยังล่าสุด" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "ข้ามไปยังการตอบกลับล่าสุด" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "รีเฟรช" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "คัดลอกข้อความ" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "เปิดข้อความฉบับเต็ม" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "ผู้ช่วย" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "ข้ามไปยังล่าสุด" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "ข้ามไปยังการตอบกลับล่าสุด" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "รีเฟรช" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "ส่งออกสำเนาบทสนทนา…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "แสดงกระบวนการให้เหตุผลและการทำงานของเครื่องมือ" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "แสดงกระบวนการให้เหตุผล" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "แสดงกิจกรรมของเครื่องมือ" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/tr.json b/apps/.i18n/native/tr.json index d94ba757111d..26bedfd81d1d 100644 --- a/apps/.i18n/native/tr.json +++ b/apps/.i18n/native/tr.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "%@ token kullanıldı" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "Tam ileti yükleniyor…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "Tam ileti kullanılamıyor" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "Tam İleti" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "Kapat" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "Tam ileti artık kullanılamıyor." + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "Tam iletide okunabilir metin yok." + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "Tam ileti yüklenemedi." + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "Dinle" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "En yeniye atla" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "En yeni yanıta atla" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "Yenile" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "Mesajı Kopyala" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "Tam İletiyi Aç" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "Asistan" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "En yeniye atla" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "En yeni yanıta atla" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "Yenile" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "Dökümü Dışa Aktar…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "Akıl yürütme ve araç etkinliğini göster" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "Akıl Yürütmeyi Göster" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "Araç Etkinliğini Göster" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/uk.json b/apps/.i18n/native/uk.json index 27cf4ead9f44..a15918a61b04 100644 --- a/apps/.i18n/native/uk.json +++ b/apps/.i18n/native/uk.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "Використано токенів: %@" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "Завантаження повного повідомлення…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "Повідомлення повністю недоступне" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "Повне повідомлення" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "Закрити" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "Повне повідомлення більше недоступне." + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "Повне повідомлення не містить тексту, який можна прочитати." + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "Не вдалося завантажити повне повідомлення." + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "Слухати" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "Перейти до останнього" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "Перейти до останньої відповіді" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "Оновити" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "Копіювати повідомлення" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "Відкрити повне повідомлення" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "Асистент" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "Перейти до останнього" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "Перейти до останньої відповіді" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "Оновити" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "Експортувати стенограму…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "Показувати міркування та дії інструментів" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "Показати міркування" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "Показати активність інструментів" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/vi.json b/apps/.i18n/native/vi.json index 82ccca7e6a62..cb11c6a727f0 100644 --- a/apps/.i18n/native/vi.json +++ b/apps/.i18n/native/vi.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "Đã sử dụng %@ token" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "Đang tải toàn bộ tin nhắn…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "Không có toàn bộ tin nhắn" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "Toàn bộ tin nhắn" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "Đóng" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "Toàn bộ tin nhắn không còn khả dụng." + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "Toàn bộ tin nhắn không có văn bản có thể đọc được." + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "Không thể tải toàn bộ tin nhắn." + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "Nghe" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "Chuyển đến mới nhất" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "Chuyển đến phản hồi mới nhất" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "Làm mới" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "Sao chép tin nhắn" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "Mở toàn bộ tin nhắn" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "Trợ lý" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "Chuyển đến mới nhất" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "Chuyển đến phản hồi mới nhất" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "Làm mới" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "Xuất Bản ghi…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "Hiển thị quá trình suy luận và hoạt động của công cụ" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "Hiển thị lập luận" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "Hiển thị hoạt động của công cụ" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/zh-CN.json b/apps/.i18n/native/zh-CN.json index a4909bef647e..ca3634003a63 100644 --- a/apps/.i18n/native/zh-CN.json +++ b/apps/.i18n/native/zh-CN.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "已使用 %@ 个 token" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "正在加载完整消息…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "完整消息不可用" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "完整消息" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "关闭" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "完整消息已不再可用。" + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "完整消息中没有可读文本。" + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "无法加载完整消息。" + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "聆听" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "跳转到最新" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "跳转到最新回复" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "刷新" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "复制消息" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "打开完整消息" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "助手" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "跳转到最新" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "跳转到最新回复" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "刷新" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "导出对话记录…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "显示推理和工具活动" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "显示推理过程" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "显示工具活动" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/.i18n/native/zh-TW.json b/apps/.i18n/native/zh-TW.json index e675f322e475..48c160680c7f 100644 --- a/apps/.i18n/native/zh-TW.json +++ b/apps/.i18n/native/zh-TW.json @@ -22743,6 +22743,41 @@ "source": "%@ tokens used", "translated": "已使用 %@ 個權杖" }, + { + "id": "native.apple.ccfd6ae994d82449", + "source": "Loading full message…", + "translated": "正在載入完整訊息…" + }, + { + "id": "native.apple.669ad52de4a26b87", + "source": "Full message unavailable", + "translated": "無法取得完整訊息" + }, + { + "id": "native.apple.6f79794ee74caf99", + "source": "Full Message", + "translated": "完整訊息" + }, + { + "id": "native.apple.d648251591db5dec", + "source": "Close", + "translated": "關閉" + }, + { + "id": "native.apple.ba3963204bda5e84", + "source": "The full message is no longer available.", + "translated": "完整訊息已無法取得。" + }, + { + "id": "native.apple.8bb98bd86ae85c1c", + "source": "The full message has no readable text.", + "translated": "完整訊息中沒有可讀取的文字。" + }, + { + "id": "native.apple.2f43669d87c0e26d", + "source": "The full message could not be loaded.", + "translated": "無法載入完整訊息。" + }, { "id": "native.apple.2c865ac4a69645d3", "source": "Widget unavailable", @@ -23128,11 +23163,31 @@ "source": "Listen", "translated": "聆聽" }, + { + "id": "native.apple.f84b674ad395b694", + "source": "Jump to latest", + "translated": "跳至最新內容" + }, + { + "id": "native.apple.429d825201b2cb85", + "source": "Jump to latest reply", + "translated": "跳至最新回覆" + }, + { + "id": "native.apple.9ab586b85834705c", + "source": "Refresh", + "translated": "重新整理" + }, { "id": "native.apple.fe9f30f12f1dcfaf", "source": "Copy Message", "translated": "複製訊息" }, + { + "id": "native.apple.90bc8a8045e7017e", + "source": "Open Full Message", + "translated": "開啟完整訊息" + }, { "id": "native.apple.b37ec7bd7dc1579a", "source": "Reply", @@ -23148,21 +23203,6 @@ "source": "Assistant", "translated": "助理" }, - { - "id": "native.apple.f84b674ad395b694", - "source": "Jump to latest", - "translated": "跳至最新內容" - }, - { - "id": "native.apple.429d825201b2cb85", - "source": "Jump to latest reply", - "translated": "跳至最新回覆" - }, - { - "id": "native.apple.9ab586b85834705c", - "source": "Refresh", - "translated": "重新整理" - }, { "id": "native.apple.28c2691c03030434", "source": "Loading chat", @@ -23374,9 +23414,14 @@ "translated": "匯出對話紀錄…" }, { - "id": "native.apple.3294ababd29c4457", - "source": "Show reasoning & tool activity", - "translated": "顯示推理與工具活動" + "id": "native.apple.ebb130189022c7ec", + "source": "Show Reasoning", + "translated": "顯示推理過程" + }, + { + "id": "native.apple.d0dba9aad550fa6e", + "source": "Show Tool Activity", + "translated": "顯示工具活動" }, { "id": "native.apple.4b24d792545e5086", diff --git a/apps/ios/Resources/Localizable.xcstrings b/apps/ios/Resources/Localizable.xcstrings index 66c5a466c1f2..54d44819977c 100644 --- a/apps/ios/Resources/Localizable.xcstrings +++ b/apps/ios/Resources/Localizable.xcstrings @@ -67729,6 +67729,278 @@ } } }, + "Full Message": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Full Message" + } + }, + "zh-CN": { + "stringUnit": { + "state": "translated", + "value": "完整消息" + } + }, + "zh-TW": { + "stringUnit": { + "state": "translated", + "value": "完整訊息" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Mensagem completa" + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Vollständige Nachricht" + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Mensaje completo" + } + }, + "ja-JP": { + "stringUnit": { + "state": "translated", + "value": "メッセージ全文" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "전체 메시지" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Message complet" + } + }, + "hi": { + "stringUnit": { + "state": "translated", + "value": "पूरा संदेश" + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "الرسالة الكاملة" + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Messaggio completo" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Tam İleti" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Повне повідомлення" + } + }, + "id": { + "stringUnit": { + "state": "translated", + "value": "Pesan Lengkap" + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Pełna wiadomość" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "ข้อความฉบับเต็ม" + } + }, + "vi": { + "stringUnit": { + "state": "translated", + "value": "Toàn bộ tin nhắn" + } + }, + "nl": { + "stringUnit": { + "state": "translated", + "value": "Volledig bericht" + } + }, + "fa": { + "stringUnit": { + "state": "translated", + "value": "پیام کامل" + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Полное сообщение" + } + }, + "sv": { + "stringUnit": { + "state": "translated", + "value": "Hela meddelandet" + } + } + } + }, + "Full message unavailable": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Full message unavailable" + } + }, + "zh-CN": { + "stringUnit": { + "state": "translated", + "value": "完整消息不可用" + } + }, + "zh-TW": { + "stringUnit": { + "state": "translated", + "value": "無法取得完整訊息" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Mensagem completa indisponível" + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Vollständige Nachricht nicht verfügbar" + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Mensaje completo no disponible" + } + }, + "ja-JP": { + "stringUnit": { + "state": "translated", + "value": "メッセージ全文を利用できません" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "전체 메시지를 사용할 수 없음" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Message complet indisponible" + } + }, + "hi": { + "stringUnit": { + "state": "translated", + "value": "पूरा संदेश उपलब्ध नहीं है" + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "الرسالة الكاملة غير متاحة" + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Messaggio completo non disponibile" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Tam ileti kullanılamıyor" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Повідомлення повністю недоступне" + } + }, + "id": { + "stringUnit": { + "state": "translated", + "value": "Pesan lengkap tidak tersedia" + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Pełna wiadomość jest niedostępna" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "ไม่สามารถดูข้อความฉบับเต็มได้" + } + }, + "vi": { + "stringUnit": { + "state": "translated", + "value": "Không có toàn bộ tin nhắn" + } + }, + "nl": { + "stringUnit": { + "state": "translated", + "value": "Volledig bericht niet beschikbaar" + } + }, + "fa": { + "stringUnit": { + "state": "translated", + "value": "پیام کامل در دسترس نیست" + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Полное сообщение недоступно" + } + }, + "sv": { + "stringUnit": { + "state": "translated", + "value": "Hela meddelandet är inte tillgängligt" + } + } + } + }, "Future runs are active.": { "localizations": { "en": { @@ -85953,6 +86225,142 @@ } } }, + "Loading full message…": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Loading full message…" + } + }, + "zh-CN": { + "stringUnit": { + "state": "translated", + "value": "正在加载完整消息…" + } + }, + "zh-TW": { + "stringUnit": { + "state": "translated", + "value": "正在載入完整訊息…" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Carregando mensagem completa…" + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Vollständige Nachricht wird geladen…" + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Cargando el mensaje completo…" + } + }, + "ja-JP": { + "stringUnit": { + "state": "translated", + "value": "メッセージ全文を読み込み中…" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "전체 메시지를 불러오는 중…" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Chargement du message complet…" + } + }, + "hi": { + "stringUnit": { + "state": "translated", + "value": "पूरा संदेश लोड हो रहा है…" + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "جارٍ تحميل الرسالة كاملة…" + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Caricamento del messaggio completo…" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Tam ileti yükleniyor…" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Завантаження повного повідомлення…" + } + }, + "id": { + "stringUnit": { + "state": "translated", + "value": "Memuat pesan lengkap…" + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Wczytywanie pełnej wiadomości…" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "กำลังโหลดข้อความฉบับเต็ม…" + } + }, + "vi": { + "stringUnit": { + "state": "translated", + "value": "Đang tải toàn bộ tin nhắn…" + } + }, + "nl": { + "stringUnit": { + "state": "translated", + "value": "Volledig bericht laden…" + } + }, + "fa": { + "stringUnit": { + "state": "translated", + "value": "در حال بارگذاری پیام کامل…" + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Загрузка полного сообщения…" + } + }, + "sv": { + "stringUnit": { + "state": "translated", + "value": "Läser in hela meddelandet…" + } + } + } + }, "Loading installed skills and readiness.": { "localizations": { "en": { @@ -108801,6 +109209,142 @@ } } }, + "Open Full Message": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open Full Message" + } + }, + "zh-CN": { + "stringUnit": { + "state": "translated", + "value": "打开完整消息" + } + }, + "zh-TW": { + "stringUnit": { + "state": "translated", + "value": "開啟完整訊息" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Abrir mensagem completa" + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Vollständige Nachricht öffnen" + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Abrir mensaje completo" + } + }, + "ja-JP": { + "stringUnit": { + "state": "translated", + "value": "メッセージ全文を開く" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "전체 메시지 열기" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Ouvrir le message complet" + } + }, + "hi": { + "stringUnit": { + "state": "translated", + "value": "पूरा संदेश खोलें" + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "فتح الرسالة الكاملة" + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Apri il messaggio completo" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Tam İletiyi Aç" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Відкрити повне повідомлення" + } + }, + "id": { + "stringUnit": { + "state": "translated", + "value": "Buka Pesan Lengkap" + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Otwórz pełną wiadomość" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "เปิดข้อความฉบับเต็ม" + } + }, + "vi": { + "stringUnit": { + "state": "translated", + "value": "Mở toàn bộ tin nhắn" + } + }, + "nl": { + "stringUnit": { + "state": "translated", + "value": "Volledig bericht openen" + } + }, + "fa": { + "stringUnit": { + "state": "translated", + "value": "باز کردن پیام کامل" + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Открыть полное сообщение" + } + }, + "sv": { + "stringUnit": { + "state": "translated", + "value": "Öppna hela meddelandet" + } + } + } + }, "Open Gateway Settings": { "localizations": { "en": { @@ -150961,6 +151505,142 @@ } } }, + "Show Reasoning": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Show Reasoning" + } + }, + "zh-CN": { + "stringUnit": { + "state": "translated", + "value": "显示推理过程" + } + }, + "zh-TW": { + "stringUnit": { + "state": "translated", + "value": "顯示推理過程" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Mostrar raciocínio" + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Gedankengang anzeigen" + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Mostrar razonamiento" + } + }, + "ja-JP": { + "stringUnit": { + "state": "translated", + "value": "推論を表示" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "추론 보기" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Afficher le raisonnement" + } + }, + "hi": { + "stringUnit": { + "state": "translated", + "value": "तर्क दिखाएँ" + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "إظهار الاستدلال" + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Mostra il ragionamento" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Akıl Yürütmeyi Göster" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Показати міркування" + } + }, + "id": { + "stringUnit": { + "state": "translated", + "value": "Tampilkan Penalaran" + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Pokaż tok rozumowania" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "แสดงกระบวนการให้เหตุผล" + } + }, + "vi": { + "stringUnit": { + "state": "translated", + "value": "Hiển thị lập luận" + } + }, + "nl": { + "stringUnit": { + "state": "translated", + "value": "Redenering tonen" + } + }, + "fa": { + "stringUnit": { + "state": "translated", + "value": "نمایش استدلال" + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Показать ход рассуждений" + } + }, + "sv": { + "stringUnit": { + "state": "translated", + "value": "Visa resonemang" + } + } + } + }, "Show Sidebar": { "localizations": { "en": { @@ -151233,6 +151913,142 @@ } } }, + "Show Tool Activity": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Show Tool Activity" + } + }, + "zh-CN": { + "stringUnit": { + "state": "translated", + "value": "显示工具活动" + } + }, + "zh-TW": { + "stringUnit": { + "state": "translated", + "value": "顯示工具活動" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Mostrar atividade das ferramentas" + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Tool-Aktivität anzeigen" + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Mostrar actividad de las herramientas" + } + }, + "ja-JP": { + "stringUnit": { + "state": "translated", + "value": "ツールのアクティビティを表示" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "도구 활동 보기" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Afficher l’activité des outils" + } + }, + "hi": { + "stringUnit": { + "state": "translated", + "value": "टूल गतिविधि दिखाएँ" + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "إظهار نشاط الأداة" + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Mostra l'attività degli strumenti" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Araç Etkinliğini Göster" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Показати активність інструментів" + } + }, + "id": { + "stringUnit": { + "state": "translated", + "value": "Tampilkan Aktivitas Alat" + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Pokaż aktywność narzędzi" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "แสดงกิจกรรมของเครื่องมือ" + } + }, + "vi": { + "stringUnit": { + "state": "translated", + "value": "Hiển thị hoạt động của công cụ" + } + }, + "nl": { + "stringUnit": { + "state": "translated", + "value": "Toolactiviteit tonen" + } + }, + "fa": { + "stringUnit": { + "state": "translated", + "value": "نمایش فعالیت ابزار" + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Показать действия инструментов" + } + }, + "sv": { + "stringUnit": { + "state": "translated", + "value": "Visa verktygsaktivitet" + } + } + } + }, "Show full output": { "localizations": { "en": { @@ -151641,142 +152457,6 @@ } } }, - "Show reasoning & tool activity": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Show reasoning & tool activity" - } - }, - "zh-CN": { - "stringUnit": { - "state": "translated", - "value": "显示推理和工具活动" - } - }, - "zh-TW": { - "stringUnit": { - "state": "translated", - "value": "顯示推理與工具活動" - } - }, - "pt-BR": { - "stringUnit": { - "state": "translated", - "value": "Mostrar raciocínio e atividade das ferramentas" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Gedankengang und Werkzeugaktivität anzeigen" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Mostrar el razonamiento y la actividad de las herramientas" - } - }, - "ja-JP": { - "stringUnit": { - "state": "translated", - "value": "推論とツールのアクティビティを表示" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "추론 및 도구 활동 표시" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Afficher le raisonnement et l’activité des outils" - } - }, - "hi": { - "stringUnit": { - "state": "translated", - "value": "तर्क और टूल गतिविधि दिखाएँ" - } - }, - "ar": { - "stringUnit": { - "state": "translated", - "value": "إظهار الاستدلال ونشاط الأدوات" - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "Mostra il ragionamento e l'attività degli strumenti" - } - }, - "tr": { - "stringUnit": { - "state": "translated", - "value": "Akıl yürütme ve araç etkinliğini göster" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Показувати міркування та дії інструментів" - } - }, - "id": { - "stringUnit": { - "state": "translated", - "value": "Tampilkan penalaran & aktivitas alat" - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "Pokaż tok rozumowania i aktywność narzędzi" - } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "แสดงกระบวนการให้เหตุผลและการทำงานของเครื่องมือ" - } - }, - "vi": { - "stringUnit": { - "state": "translated", - "value": "Hiển thị quá trình suy luận và hoạt động của công cụ" - } - }, - "nl": { - "stringUnit": { - "state": "translated", - "value": "Redenering en toolactiviteit tonen" - } - }, - "fa": { - "stringUnit": { - "state": "translated", - "value": "نمایش استدلال و فعالیت ابزارها" - } - }, - "ru": { - "stringUnit": { - "state": "translated", - "value": "Показывать ход рассуждений и действия инструментов" - } - }, - "sv": { - "stringUnit": { - "state": "translated", - "value": "Visa resonemang och verktygsaktivitet" - } - } - } - }, "Show talk transcript": { "localizations": { "en": { @@ -165649,6 +166329,414 @@ } } }, + "The full message could not be loaded.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "The full message could not be loaded." + } + }, + "zh-CN": { + "stringUnit": { + "state": "translated", + "value": "无法加载完整消息。" + } + }, + "zh-TW": { + "stringUnit": { + "state": "translated", + "value": "無法載入完整訊息。" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Não foi possível carregar a mensagem completa." + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Die vollständige Nachricht konnte nicht geladen werden." + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "No se pudo cargar el mensaje completo." + } + }, + "ja-JP": { + "stringUnit": { + "state": "translated", + "value": "メッセージ全文を読み込めませんでした。" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "전체 메시지를 불러올 수 없습니다." + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Le message complet n’a pas pu être chargé." + } + }, + "hi": { + "stringUnit": { + "state": "translated", + "value": "पूरा संदेश लोड नहीं किया जा सका।" + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "تعذّر تحميل الرسالة الكاملة." + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Impossibile caricare il messaggio completo." + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Tam ileti yüklenemedi." + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Не вдалося завантажити повне повідомлення." + } + }, + "id": { + "stringUnit": { + "state": "translated", + "value": "Pesan lengkap tidak dapat dimuat." + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Nie udało się wczytać pełnej wiadomości." + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "ไม่สามารถโหลดข้อความฉบับเต็มได้" + } + }, + "vi": { + "stringUnit": { + "state": "translated", + "value": "Không thể tải toàn bộ tin nhắn." + } + }, + "nl": { + "stringUnit": { + "state": "translated", + "value": "Het volledige bericht kon niet worden geladen." + } + }, + "fa": { + "stringUnit": { + "state": "translated", + "value": "پیام کامل بارگذاری نشد." + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Не удалось загрузить полное сообщение." + } + }, + "sv": { + "stringUnit": { + "state": "translated", + "value": "Det gick inte att läsa in hela meddelandet." + } + } + } + }, + "The full message has no readable text.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "The full message has no readable text." + } + }, + "zh-CN": { + "stringUnit": { + "state": "translated", + "value": "完整消息中没有可读文本。" + } + }, + "zh-TW": { + "stringUnit": { + "state": "translated", + "value": "完整訊息中沒有可讀取的文字。" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "A mensagem completa não contém texto legível." + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Die vollständige Nachricht enthält keinen lesbaren Text." + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "El mensaje completo no contiene texto legible." + } + }, + "ja-JP": { + "stringUnit": { + "state": "translated", + "value": "メッセージ全文に読み取れるテキストがありません。" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "전체 메시지에 읽을 수 있는 텍스트가 없습니다." + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Le message complet ne contient aucun texte lisible." + } + }, + "hi": { + "stringUnit": { + "state": "translated", + "value": "पूरे संदेश में पढ़ने योग्य कोई टेक्स्ट नहीं है।" + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "لا تحتوي الرسالة الكاملة على نص قابل للقراءة." + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Il messaggio completo non contiene testo leggibile." + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Tam iletide okunabilir metin yok." + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Повне повідомлення не містить тексту, який можна прочитати." + } + }, + "id": { + "stringUnit": { + "state": "translated", + "value": "Pesan lengkap tidak memiliki teks yang dapat dibaca." + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Pełna wiadomość nie zawiera tekstu możliwego do odczytania." + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "ข้อความฉบับเต็มไม่มีข้อความที่อ่านได้" + } + }, + "vi": { + "stringUnit": { + "state": "translated", + "value": "Toàn bộ tin nhắn không có văn bản có thể đọc được." + } + }, + "nl": { + "stringUnit": { + "state": "translated", + "value": "Het volledige bericht bevat geen leesbare tekst." + } + }, + "fa": { + "stringUnit": { + "state": "translated", + "value": "پیام کامل متن خوانایی ندارد." + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "В полном сообщении нет читаемого текста." + } + }, + "sv": { + "stringUnit": { + "state": "translated", + "value": "Hela meddelandet saknar läsbar text." + } + } + } + }, + "The full message is no longer available.": { + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "The full message is no longer available." + } + }, + "zh-CN": { + "stringUnit": { + "state": "translated", + "value": "完整消息已不再可用。" + } + }, + "zh-TW": { + "stringUnit": { + "state": "translated", + "value": "完整訊息已無法取得。" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "A mensagem completa não está mais disponível." + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Die vollständige Nachricht ist nicht mehr verfügbar." + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "El mensaje completo ya no está disponible." + } + }, + "ja-JP": { + "stringUnit": { + "state": "translated", + "value": "メッセージ全文は利用できなくなりました。" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "전체 메시지를 더 이상 사용할 수 없습니다." + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Le message complet n’est plus disponible." + } + }, + "hi": { + "stringUnit": { + "state": "translated", + "value": "पूरा संदेश अब उपलब्ध नहीं है।" + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "لم تعد الرسالة الكاملة متاحة." + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Il messaggio completo non è più disponibile." + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Tam ileti artık kullanılamıyor." + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Повне повідомлення більше недоступне." + } + }, + "id": { + "stringUnit": { + "state": "translated", + "value": "Pesan lengkap sudah tidak tersedia." + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Pełna wiadomość nie jest już dostępna." + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "ข้อความฉบับเต็มไม่พร้อมใช้งานแล้ว" + } + }, + "vi": { + "stringUnit": { + "state": "translated", + "value": "Toàn bộ tin nhắn không còn khả dụng." + } + }, + "nl": { + "stringUnit": { + "state": "translated", + "value": "Het volledige bericht is niet meer beschikbaar." + } + }, + "fa": { + "stringUnit": { + "state": "translated", + "value": "پیام کامل دیگر در دسترس نیست." + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Полное сообщение больше недоступно." + } + }, + "sv": { + "stringUnit": { + "state": "translated", + "value": "Hela meddelandet är inte längre tillgängligt." + } + } + } + }, "The gateway did not report any system presence entries.": { "localizations": { "en": { diff --git a/apps/ios/Tests/SwiftUIRenderSmokeTests.swift b/apps/ios/Tests/SwiftUIRenderSmokeTests.swift index 68c9b6ea53c2..f434ee279934 100644 --- a/apps/ios/Tests/SwiftUIRenderSmokeTests.swift +++ b/apps/ios/Tests/SwiftUIRenderSmokeTests.swift @@ -208,7 +208,7 @@ struct SwiftUIRenderSmokeTests { let root = ChatStreamingAssistantBubble( text: text, markdownVariant: .standard, - showsAssistantTrace: false, + showsReasoning: false, assistantName: "OpenClaw", assistantAvatarText: "OC", assistantAvatarTint: nil, @@ -245,7 +245,7 @@ struct SwiftUIRenderSmokeTests { style: .standard, markdownVariant: .standard, userAccent: nil, - showsAssistantTrace: false, + displayOptions: [], assistantName: "OpenClaw", assistantAvatarText: "OC", assistantAvatarTint: nil, diff --git a/apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift b/apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift index 84c16f9e793f..6ef269d9e7ad 100644 --- a/apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift +++ b/apps/macos/Sources/OpenClaw/WebChatSwiftUI.swift @@ -18,6 +18,30 @@ private enum WebChatSwiftUILayout { static let anchorPadding: CGFloat = 8 } +enum WebChatTracePreferences { + static func displayOptions(defaults: UserDefaults = .standard) -> OpenClawChatDisplayOptions { + if let legacyValue = defaults.object( + forKey: OpenClawChatWindowShell.assistantTraceDefaultsKey) as? Bool + { + for key in [ + OpenClawChatWindowShell.assistantReasoningDefaultsKey, + OpenClawChatWindowShell.assistantToolActivityDefaultsKey, + ] where defaults.object(forKey: key) == nil { + defaults.set(legacyValue, forKey: key) + } + } + + var options: OpenClawChatDisplayOptions = [] + if defaults.object(forKey: OpenClawChatWindowShell.assistantReasoningDefaultsKey) as? Bool ?? true { + options.insert(.reasoning) + } + if defaults.object(forKey: OpenClawChatWindowShell.assistantToolActivityDefaultsKey) as? Bool ?? true { + options.insert(.toolActivity) + } + return options + } +} + /// SwiftUI's native toolbar bridge may restore visible title chrome while it /// installs toolbar items. Keep the full-window chat's titlebar merged. private final class WebChatWindow: NSWindow { @@ -89,6 +113,37 @@ struct MacGatewayChatTransport: OpenClawChatTransport { agentID: target.agentID) } + func requestFullMessage(sessionKey: String, messageID: String) async throws -> OpenClawChatMessage? { + let target = self.sessionTarget(for: sessionKey) + let request = try Self.fullMessageRequest( + sessionKey: target.sessionKey, + agentID: target.agentID, + messageID: messageID) + let data = try await GatewayConnection.shared.request(request) + let result = try JSONDecoder().decode(ChatMessageGetResult.self, from: data) + guard result.ok, let encodedMessage = result.message else { return nil } + return try JSONDecoder().decode( + OpenClawChatMessage.self, + from: JSONEncoder().encode(encodedMessage)) + } + + static func fullMessageRequest( + sessionKey: String, + agentID: String?, + messageID: String) throws -> OpenClawChatGatewayRequest + { + let params = ChatMessageGetParams( + sessionkey: sessionKey, + agentid: agentID, + messageid: messageID, + maxchars: 500_000) + let encoded = try JSONEncoder().encode(params) + return try OpenClawChatGatewayRequest( + method: "chat.message.get", + params: JSONDecoder().decode([String: AnyCodable].self, from: encoded), + timeoutMs: 15000) + } + func resolveInlineWidgetResource( path: String, replacing failedResource: OpenClawChatWidgetResource?) async -> OpenClawChatWidgetResource? @@ -594,8 +649,10 @@ private struct MacChatSurface: View { @State private var appState = AppStateStore.shared @State private var talkController = TalkModeController.shared @State private var audioInputCatalog = MacChatAudioInputCatalog() - @AppStorage(OpenClawChatWindowShell.assistantTraceDefaultsKey) - private var showsAssistantTrace = true + @AppStorage(OpenClawChatWindowShell.assistantReasoningDefaultsKey) + private var showsReasoning = WebChatTracePreferences.displayOptions().contains(.reasoning) + @AppStorage(OpenClawChatWindowShell.assistantToolActivityDefaultsKey) + private var showsToolActivity = WebChatTracePreferences.displayOptions().contains(.toolActivity) private let isFullWindow: Bool private let userAccent: Color? @@ -622,7 +679,7 @@ private struct MacChatSurface: View { OpenClawChatWindowShell( viewModel: self.viewModel, userAccent: self.userAccent, - showsAssistantTrace: self.showsAssistantTrace, + displayOptions: self.displayOptions, emptyAssistantIntro: Self.emptyAssistantIntro, emptyAssistantPrompts: Self.emptyAssistantPrompts, talkControl: self.talkControl, @@ -670,6 +727,13 @@ private struct MacChatSurface: View { }) } + private var displayOptions: OpenClawChatDisplayOptions { + var options: OpenClawChatDisplayOptions = [] + if self.showsReasoning { options.insert(.reasoning) } + if self.showsToolActivity { options.insert(.toolActivity) } + return options + } + private var voiceNoteControl: OpenClawChatVoiceNoteControl { OpenClawChatVoiceNoteControl( recorder: self.voiceNoteRecorder, @@ -711,7 +775,7 @@ private struct MacChatSurface: View { hasTalkControl: true, hasSpeech: true, hasVoiceNoteControl: true, - showsAssistantTrace: self.isFullWindow && self.showsAssistantTrace) + displayOptions: self.isFullWindow ? self.displayOptions : []) } #endif } @@ -721,7 +785,7 @@ struct MacChatSurfaceCapabilities: Equatable { let hasTalkControl: Bool let hasSpeech: Bool let hasVoiceNoteControl: Bool - let showsAssistantTrace: Bool + let displayOptions: OpenClawChatDisplayOptions } #endif diff --git a/apps/macos/Tests/OpenClawIPCTests/MacGatewayChatTransportMappingTests.swift b/apps/macos/Tests/OpenClawIPCTests/MacGatewayChatTransportMappingTests.swift index 16b5462182b9..27d32274a62d 100644 --- a/apps/macos/Tests/OpenClawIPCTests/MacGatewayChatTransportMappingTests.swift +++ b/apps/macos/Tests/OpenClawIPCTests/MacGatewayChatTransportMappingTests.swift @@ -1,3 +1,4 @@ +import Foundation import OpenClawChatUI import OpenClawKit import OpenClawProtocol @@ -54,6 +55,33 @@ struct MacGatewayChatTransportMappingTests { #expect(request.params["verboseLevel"]?.value as? String == "full") } + @Test func `full message request uses generated gateway field names`() throws { + let request = try MacGatewayChatTransport.fullMessageRequest( + sessionKey: "global", + agentID: "reviewer", + messageID: "msg-42") + + #expect(request.method == "chat.message.get") + #expect(request.params["sessionKey"]?.value as? String == "global") + #expect(request.params["agentId"]?.value as? String == "reviewer") + #expect(request.params["messageId"]?.value as? String == "msg-42") + #expect(request.params["maxChars"]?.value as? Int == 500_000) + } + + @Test func `legacy trace preference migrates to independent defaults once`() throws { + let suiteName = "MacGatewayChatTransportMappingTests.\(UUID().uuidString)" + let defaults = try #require(UserDefaults(suiteName: suiteName)) + defer { defaults.removePersistentDomain(forName: suiteName) } + defaults.set(false, forKey: OpenClawChatWindowShell.assistantTraceDefaultsKey) + + #expect(WebChatTracePreferences.displayOptions(defaults: defaults).isEmpty) + #expect(defaults.object(forKey: OpenClawChatWindowShell.assistantReasoningDefaultsKey) as? Bool == false) + #expect(defaults.object(forKey: OpenClawChatWindowShell.assistantToolActivityDefaultsKey) as? Bool == false) + + defaults.set(true, forKey: OpenClawChatWindowShell.assistantReasoningDefaultsKey) + #expect(WebChatTracePreferences.displayOptions(defaults: defaults) == [.reasoning]) + } + @Test func `snapshot maps to health`() { let snapshot = Snapshot( presence: [], diff --git a/apps/macos/Tests/OpenClawIPCTests/WebChatSwiftUISmokeTests.swift b/apps/macos/Tests/OpenClawIPCTests/WebChatSwiftUISmokeTests.swift index 8444ed8446a0..45a397408b2b 100644 --- a/apps/macos/Tests/OpenClawIPCTests/WebChatSwiftUISmokeTests.swift +++ b/apps/macos/Tests/OpenClawIPCTests/WebChatSwiftUISmokeTests.swift @@ -42,14 +42,20 @@ struct WebChatSwiftUISmokeTests { } @Test func `window controller merges titlebar and keeps toolbar controls`() throws { - let traceKey = OpenClawChatWindowShell.assistantTraceDefaultsKey - let previousTraceValue = UserDefaults.standard.object(forKey: traceKey) - UserDefaults.standard.removeObject(forKey: traceKey) + let traceKeys = [ + OpenClawChatWindowShell.assistantTraceDefaultsKey, + OpenClawChatWindowShell.assistantReasoningDefaultsKey, + OpenClawChatWindowShell.assistantToolActivityDefaultsKey, + ] + let previousTraceValues = traceKeys.map { ($0, UserDefaults.standard.object(forKey: $0)) } + traceKeys.forEach { UserDefaults.standard.removeObject(forKey: $0) } defer { - if let previousTraceValue { - UserDefaults.standard.set(previousTraceValue, forKey: traceKey) - } else { - UserDefaults.standard.removeObject(forKey: traceKey) + for (key, value) in previousTraceValues { + if let value { + UserDefaults.standard.set(value, forKey: key) + } else { + UserDefaults.standard.removeObject(forKey: key) + } } } let controller = WebChatSwiftUIWindowController( @@ -70,7 +76,7 @@ struct WebChatSwiftUISmokeTests { #expect(capabilities.hasTalkControl) #expect(capabilities.hasSpeech) #expect(capabilities.hasVoiceNoteControl) - #expect(capabilities.showsAssistantTrace) + #expect(capabilities.displayOptions == .assistantTrace) controller.show() #expect(window.titleVisibility == .hidden) diff --git a/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatFullMessageReader.swift b/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatFullMessageReader.swift new file mode 100644 index 000000000000..cd25591bcbe5 --- /dev/null +++ b/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatFullMessageReader.swift @@ -0,0 +1,92 @@ +import SwiftUI + +struct ChatFullMessageReaderRequest: Identifiable, Sendable { + let sessionKey: String + let messageID: String + + var id: String { + "\(self.sessionKey)\u{0}\(self.messageID)" + } +} + +@MainActor +struct ChatFullMessageReader: View { + private enum Phase { + case loading + case loaded(String) + case failed(String) + } + + let request: ChatFullMessageReaderRequest + let markdownVariant: ChatMarkdownVariant + let load: @MainActor @Sendable () async throws -> OpenClawChatMessage? + + @Environment(\.dismiss) private var dismiss + @State private var phase: Phase = .loading + + var body: some View { + NavigationStack { + Group { + switch self.phase { + case .loading: + VStack(spacing: 10) { + ProgressView() + Text("Loading full message…") + .font(OpenClawChatTypography.body) + .foregroundStyle(.secondary) + } + case let .loaded(markdown): + ScrollView { + ChatMarkdownRenderer( + text: markdown, + context: .assistant, + variant: self.markdownVariant, + font: OpenClawChatTypography.body, + textColor: OpenClawChatTheme.assistantText) + .textSelection(.enabled) + .frame(maxWidth: .infinity, alignment: .leading) + .padding(20) + } + case let .failed(message): + ContentUnavailableView( + String(localized: "Full message unavailable"), + systemImage: "doc.text.magnifyingglass", + description: Text(message)) + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .navigationTitle("Full Message") + .toolbar { + ToolbarItem(placement: .confirmationAction) { + Button("Close") { self.dismiss() } + } + } + } + #if os(macOS) + .frame(minWidth: 560, minHeight: 420) + #endif + .task(id: self.request.id) { + await self.loadMessage() + } + } + + private func loadMessage() async { + self.phase = .loading + do { + guard let message = try await self.load() else { + self.phase = .failed(String(localized: "The full message is no longer available.")) + return + } + let markdown = ChatMessageVisibleText.visibleText(in: message) + guard !markdown.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else { + self.phase = .failed(String(localized: "The full message has no readable text.")) + return + } + self.phase = .loaded(markdown) + } catch is CancellationError { + return + } catch { + self.phase = .failed(String(localized: "The full message could not be loaded.")) + } + } +} diff --git a/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMessageViews.swift b/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMessageViews.swift index 79f285a4cc10..4ce9329740f3 100644 --- a/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMessageViews.swift +++ b/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMessageViews.swift @@ -206,7 +206,7 @@ struct ChatMessageBubble: View { let style: OpenClawChatView.Style let markdownVariant: ChatMarkdownVariant let userAccent: Color? - let showsAssistantTrace: Bool + let displayOptions: OpenClawChatDisplayOptions let assistantName: String? let assistantAvatarText: String? let assistantAvatarTint: Color? @@ -253,7 +253,7 @@ struct ChatMessageBubble: View { style: self.style, markdownVariant: self.markdownVariant, userAccent: self.userAccent, - showsAssistantTrace: self.showsAssistantTrace, + displayOptions: self.displayOptions, isClean: self.isClean, contextWindowTokens: self.contextWindowTokens, inlineWidgetResolverReady: self.inlineWidgetResolverReady, @@ -269,7 +269,7 @@ private struct ChatMessageBody: View { let style: OpenClawChatView.Style let markdownVariant: ChatMarkdownVariant let userAccent: Color? - let showsAssistantTrace: Bool + let displayOptions: OpenClawChatDisplayOptions let isClean: Bool let contextWindowTokens: Int? let inlineWidgetResolverReady: Bool @@ -303,8 +303,8 @@ private struct ChatMessageBody: View { private func messageContent(text: String, textColor: Color) -> some View { VStack(alignment: .leading, spacing: 10) { - if self.isToolResultMessage, self.showsAssistantTrace { - if !text.isEmpty { + if self.isToolResultMessage { + if self.displayOptions.contains(.toolActivity), !text.isEmpty { ToolResultCard( title: self.toolResultTitle, text: text, @@ -322,7 +322,7 @@ private struct ChatMessageBody: View { ChatAssistantTextBody( text: text, markdownVariant: self.markdownVariant, - includesThinking: self.showsAssistantTrace) + includesThinking: self.displayOptions.contains(.reasoning)) } if self.showsLinkPreview, let previewURL = chatFirstPreviewURL(in: text) { @@ -342,14 +342,14 @@ private struct ChatMessageBody: View { resolveResource: self.inlineWidgetResourceResolver) } - if self.showsAssistantTrace, !self.toolCalls.isEmpty { + if self.displayOptions.contains(.toolActivity), !self.toolCalls.isEmpty { ForEach(self.toolCalls.indices, id: \.self) { idx in ToolCallCard( content: self.toolCalls[idx]) } } - if self.showsAssistantTrace, !self.inlineToolResults.isEmpty { + if self.displayOptions.contains(.toolActivity), !self.inlineToolResults.isEmpty { ForEach(self.inlineToolResults.indices, id: \.self) { idx in let toolResult = self.inlineToolResults[idx] let display = ToolDisplayRegistry.resolve(name: toolResult.name ?? "tool", args: nil) @@ -855,7 +855,7 @@ extension View { struct ChatStreamingAssistantBubble: View { let text: String let markdownVariant: ChatMarkdownVariant - let showsAssistantTrace: Bool + let showsReasoning: Bool let assistantName: String? let assistantAvatarText: String? let assistantAvatarTint: Color? @@ -876,7 +876,7 @@ struct ChatStreamingAssistantBubble: View { ChatAssistantTextBody( text: self.text, markdownVariant: self.markdownVariant, - includesThinking: self.showsAssistantTrace, + includesThinking: self.showsReasoning, isComplete: false) } .padding(self.isClean ? 4 : 12) diff --git a/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMessageVisibleText.swift b/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMessageVisibleText.swift index 775cc30cae80..4d15c4250762 100644 --- a/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMessageVisibleText.swift +++ b/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatMessageVisibleText.swift @@ -5,6 +5,11 @@ import Foundation /// transcript exporter and the Listen action so exported and spoken text /// always match the visible transcript. enum ChatMessageVisibleText { + static func copyText(in message: OpenClawChatMessage) -> String { + let role = message.role.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() + return role == "assistant" ? self.visibleText(in: message) : self.primaryText(in: message) + } + static func visibleText(in message: OpenClawChatMessage) -> String { let text = self.primaryText(in: message) let role = message.role.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() diff --git a/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatModels.swift b/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatModels.swift index 08675b3f438c..c5d038e85f6e 100644 --- a/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatModels.swift +++ b/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatModels.swift @@ -220,10 +220,14 @@ public struct OpenClawChatCanvasPreview: Codable, Hashable, Sendable { public struct OpenClawChatMessage: Codable, Hashable, Identifiable, Sendable { private struct OpenClawMetadata: Codable { + let id: String? let idempotencyKey: String? + let truncated: Bool? } public var id: UUID = .init() + public var transcriptMessageID: String? + public var isTruncated = false public let role: String public let content: [OpenClawChatMessageContent] public let timestamp: Double? @@ -258,6 +262,8 @@ public struct OpenClawChatMessage: Codable, Hashable, Identifiable, Sendable { role: String, content: [OpenClawChatMessageContent], timestamp: Double?, + transcriptMessageID: String? = nil, + isTruncated: Bool = false, idempotencyKey: String? = nil, toolCallId: String? = nil, toolName: String? = nil, @@ -266,6 +272,8 @@ public struct OpenClawChatMessage: Codable, Hashable, Identifiable, Sendable { errorMessage: String? = nil) { self.id = id + self.transcriptMessageID = transcriptMessageID + self.isTruncated = isTruncated self.role = role self.content = content self.timestamp = timestamp @@ -295,6 +303,7 @@ public struct OpenClawChatMessage: Codable, Hashable, Identifiable, Sendable { let decodedErrorMessage = try container.decodeIfPresent(String.self, forKey: .errorMessage) self.role = decodedRole + self.transcriptMessageID = decodedOpenClaw?.id self.timestamp = decodedTimestamp self.idempotencyKey = decodedIdempotencyKey self.toolCallId = decodedToolCallId @@ -352,6 +361,9 @@ public struct OpenClawChatMessage: Codable, Hashable, Identifiable, Sendable { content: nil) } self.content = decodedContent + audioAttachments + self.isTruncated = decodedOpenClaw?.truncated == true || decodedContent.contains { content in + content.text?.contains(Self.transcriptTruncationMarker) == true + } } static func displayText( @@ -388,11 +400,20 @@ public struct OpenClawChatMessage: Codable, Hashable, Identifiable, Sendable { } private static let streamErrorFallbackText = "[assistant turn failed before producing content]" + private static let transcriptTruncationMarker = "\n...(truncated)..." public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(self.role, forKey: .role) try container.encodeIfPresent(self.timestamp, forKey: .timestamp) + if self.transcriptMessageID != nil || self.isTruncated { + try container.encode( + OpenClawMetadata( + id: self.transcriptMessageID, + idempotencyKey: nil, + truncated: self.isTruncated ? true : nil), + forKey: .openClaw) + } try container.encodeIfPresent(self.idempotencyKey, forKey: .idempotencyKey) try container.encodeIfPresent(self.toolCallId, forKey: .toolCallId) try container.encodeIfPresent(self.toolName, forKey: .toolName) diff --git a/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatTransport.swift b/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatTransport.swift index 3e57ba45f775..8a493b089755 100644 --- a/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatTransport.swift +++ b/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatTransport.swift @@ -265,6 +265,7 @@ public protocol OpenClawChatTransport: Sendable { worktree: Bool?) async throws -> OpenClawChatCreateSessionResponse func requestHistory(sessionKey: String) async throws -> OpenClawChatHistoryPayload + func requestFullMessage(sessionKey: String, messageID: String) async throws -> OpenClawChatMessage? func listModels() async throws -> [OpenClawChatModelChoice] var supportsSlashCommandCatalog: Bool { get } func listCommands(sessionKey: String) async throws -> [OpenClawChatCommandChoice] @@ -331,6 +332,10 @@ public protocol OpenClawChatTransport: Sendable { } extension OpenClawChatTransport { + public func requestFullMessage(sessionKey _: String, messageID _: String) async throws -> OpenClawChatMessage? { + nil + } + public func resolveInlineWidgetResource( path: String, replacing failedResource: OpenClawChatWidgetResource?) async -> OpenClawChatWidgetResource? diff --git a/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift b/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift index 7b29e5528b00..e740afebe13a 100644 --- a/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift +++ b/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatView.swift @@ -49,6 +49,22 @@ func chatReaderScrollReleasesFollow(_ phase: ScrollPhase) -> Bool { } } +public struct OpenClawChatDisplayOptions: OptionSet, Sendable { + public let rawValue: UInt8 + + public init(rawValue: UInt8) { + self.rawValue = rawValue + } + + public static let reasoning = Self(rawValue: 1 << 0) + public static let toolActivity = Self(rawValue: 1 << 1) + public static let assistantTrace: Self = [.reasoning, .toolActivity] + + public static func assistantTrace(_ isVisible: Bool) -> Self { + isVisible ? .assistantTrace : [] + } +} + @MainActor public struct OpenClawChatView: View { public enum Style { @@ -83,12 +99,13 @@ public struct OpenClawChatView: View { @State private var followTarget: ScrollFollowTarget? = .latest @State private var isAtLiveEdge = true @State private var isUserScrolling = false + @State private var fullMessageRequest: ChatFullMessageReaderRequest? private let showsSessionSwitcher: Bool private let drawsBackground: Bool private let style: Style private let markdownVariant: ChatMarkdownVariant private let userAccent: Color? - private let showsAssistantTrace: Bool + private let displayOptions: OpenClawChatDisplayOptions private let assistantName: String? private let assistantAvatarText: String? private let assistantAvatarTint: Color? @@ -134,6 +151,7 @@ public struct OpenClawChatView: View { #endif } + /// `showsAssistantTrace` remains as a source-compatible convenience that sets both display options. public init( viewModel: OpenClawChatViewModel, drawsBackground: Bool = true, @@ -141,6 +159,7 @@ public struct OpenClawChatView: View { style: Style = .standard, markdownVariant: ChatMarkdownVariant = .standard, userAccent: Color? = nil, + displayOptions: OpenClawChatDisplayOptions? = nil, showsAssistantTrace: Bool = false, assistantName: String? = nil, assistantAvatarText: String? = nil, @@ -162,7 +181,7 @@ public struct OpenClawChatView: View { self.style = style self.markdownVariant = markdownVariant self.userAccent = userAccent - self.showsAssistantTrace = showsAssistantTrace + self.displayOptions = displayOptions ?? .assistantTrace(showsAssistantTrace) self.assistantName = assistantName self.assistantAvatarText = assistantAvatarText self.assistantAvatarTint = assistantAvatarTint @@ -189,6 +208,16 @@ public struct OpenClawChatView: View { } .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) .onAppear { self.viewModel.load() } + .sheet(item: self.$fullMessageRequest) { request in + ChatFullMessageReader( + request: request, + markdownVariant: self.markdownVariant, + load: { + try await self.viewModel.transport.requestFullMessage( + sessionKey: request.sessionKey, + messageID: request.messageID) + }) + } } @ViewBuilder @@ -391,7 +420,7 @@ public struct OpenClawChatView: View { .equatable() } - if !self.viewModel.pendingToolCalls.isEmpty { + if self.displayOptions.contains(.toolActivity), !self.viewModel.pendingToolCalls.isEmpty { ChatPendingToolsBubble( toolCalls: self.viewModel.pendingToolCalls, isClean: self.composerChrome == .clean) @@ -403,7 +432,7 @@ public struct OpenClawChatView: View { ChatStreamingAssistantBubble( text: text, markdownVariant: self.markdownVariant, - showsAssistantTrace: self.showsAssistantTrace, + showsReasoning: self.displayOptions.contains(.reasoning), assistantName: self.assistantName, assistantAvatarText: self.assistantAvatarText, assistantAvatarTint: self.assistantAvatarTint, @@ -423,7 +452,7 @@ public struct OpenClawChatView: View { style: self.style, markdownVariant: self.markdownVariant, userAccent: self.userAccent, - showsAssistantTrace: self.showsAssistantTrace, + displayOptions: self.displayOptions, assistantName: self.assistantName, assistantAvatarText: self.assistantAvatarText, assistantAvatarTint: self.assistantAvatarTint, @@ -449,6 +478,7 @@ public struct OpenClawChatView: View { .contextMenu { self.copyMessageButton(for: msg) self.replyMessageButton(for: msg) + self.openFullMessageButton(for: msg) if outboxState.isFailed { Button { self.viewModel.retryOutboxMessage(msg.id) @@ -488,7 +518,9 @@ public struct OpenClawChatView: View { } .frame(maxWidth: .infinity, alignment: .leading) .contextMenu { + self.copyMessageButton(for: msg) self.replyMessageButton(for: msg) + self.openFullMessageButton(for: msg) Button { if speech.isActive(msg.id) { speech.stop() @@ -516,6 +548,7 @@ public struct OpenClawChatView: View { .contextMenu { self.copyMessageButton(for: msg) self.replyMessageButton(for: msg) + self.openFullMessageButton(for: msg) } } } @@ -539,59 +572,6 @@ public struct OpenClawChatView: View { } } - @ViewBuilder - private func copyMessageButton(for message: OpenClawChatMessage) -> some View { - let text = self.primaryText(in: message) - if !text.isEmpty { - Button { - Self.copyToClipboard(text) - } label: { - Label { - Text("Copy Message") - .font(OpenClawChatTypography.body) - } icon: { - Image(systemName: "doc.on.doc") - } - } - } - } - - @ViewBuilder - private func replyMessageButton(for message: OpenClawChatMessage) -> some View { - let role = message.role.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - let text = ChatReplyQuote.targetText(ChatMessageVisibleText.visibleText(in: message)) - if role == "user" || role == "assistant", !text.isEmpty { - Button { - self.viewModel.setReplyTarget( - messageID: message.id, - text: text, - senderLabel: self.replySenderLabel(forRole: role)) - } label: { - Label { - Text(String(localized: "Reply")) - .font(OpenClawChatTypography.body) - } icon: { - Image(systemName: "arrowshape.turn.up.left") - } - } - } - } - - private func replySenderLabel(forRole role: String) -> String { - guard role == "assistant" else { return String(localized: "You") } - let name = self.assistantName?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - return name.isEmpty ? String(localized: "Assistant") : name - } - - private static func copyToClipboard(_ text: String) { - #if os(macOS) - NSPasteboard.general.clearContents() - NSPasteboard.general.setString(text, forType: .string) - #else - UIPasteboard.general.string = text - #endif - } - private var visibleMessages: [OpenClawChatMessage] { let base: [OpenClawChatMessage] if self.style == .onboarding { @@ -700,12 +680,14 @@ public struct OpenClawChatView: View { private var hasVisibleStreamingAssistantText: Bool { guard let text = self.viewModel.streamingAssistantText else { return false } - return AssistantTextParser.hasVisibleContent(in: text, includeThinking: self.showsAssistantTrace) + return AssistantTextParser.hasVisibleContent( + in: text, + includeThinking: self.displayOptions.contains(.reasoning)) } private var hasVisibleTransientContent: Bool { self.viewModel.hasBlockingRunActivity || - !self.viewModel.pendingToolCalls.isEmpty || + (self.displayOptions.contains(.toolActivity) && !self.viewModel.pendingToolCalls.isEmpty) || self.hasVisibleStreamingAssistantText } @@ -883,6 +865,18 @@ public struct OpenClawChatView: View { } } + private func dismissKeyboardIfNeeded() { + #if canImport(UIKit) + UIApplication.shared.sendAction( + #selector(UIResponder.resignFirstResponder), + to: nil, + from: nil, + for: nil) + #endif + } +} + +extension OpenClawChatView { private func mergeToolResults(in messages: [OpenClawChatMessage]) -> [OpenClawChatMessage] { var result: [OpenClawChatMessage] = [] result.reserveCapacity(messages.count) @@ -925,6 +919,8 @@ public struct OpenClawChatView: View { role: last.role, content: content, timestamp: last.timestamp, + transcriptMessageID: last.transcriptMessageID, + isTruncated: last.isTruncated, idempotencyKey: last.idempotencyKey, toolCallId: last.toolCallId, toolName: last.toolName, @@ -943,29 +939,29 @@ public struct OpenClawChatView: View { } private func shouldDisplayMessage(_ message: OpenClawChatMessage) -> Bool { + let primaryText = self.primaryText(in: message) if self.hasInlineAttachments(in: message) { return true } - let primaryText = self.primaryText(in: message) + if self.isToolResultMessage(message) { + return self.displayOptions.contains(.toolActivity) && !primaryText.isEmpty + } + if !primaryText.isEmpty { if message.role.lowercased() == "user" { return true } - if AssistantTextParser.hasVisibleContent(in: primaryText, includeThinking: self.showsAssistantTrace) { + if AssistantTextParser.hasVisibleContent( + in: primaryText, + includeThinking: self.displayOptions.contains(.reasoning)) + { return true } } - guard self.showsAssistantTrace else { - return false - } - - if self.isToolResultMessage(message) { - return !primaryText.isEmpty - } - - return !self.toolCalls(in: message).isEmpty || !self.inlineToolResults(in: message).isEmpty + return self.displayOptions.contains(.toolActivity) && + (!self.toolCalls(in: message).isEmpty || !self.inlineToolResults(in: message).isEmpty) } private func primaryText(in message: OpenClawChatMessage) -> String { @@ -1026,13 +1022,79 @@ public struct OpenClawChatView: View { self.primaryText(in: message) } - private func dismissKeyboardIfNeeded() { - #if canImport(UIKit) - UIApplication.shared.sendAction( - #selector(UIResponder.resignFirstResponder), - to: nil, - from: nil, - for: nil) + @ViewBuilder + private func copyMessageButton(for message: OpenClawChatMessage) -> some View { + let text = ChatMessageVisibleText.copyText(in: message) + if !text.isEmpty { + Button { + Self.copyToClipboard(text) + } label: { + Label { + Text("Copy Message") + .font(OpenClawChatTypography.body) + } icon: { + Image(systemName: "doc.on.doc") + } + } + } + } + + @ViewBuilder + private func openFullMessageButton(for message: OpenClawChatMessage) -> some View { + let role = message.role.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() + if role == "assistant", + message.isTruncated, + let messageID = message.transcriptMessageID?.trimmingCharacters(in: .whitespacesAndNewlines), + !messageID.isEmpty + { + Button { + self.fullMessageRequest = ChatFullMessageReaderRequest( + sessionKey: self.viewModel.sessionKey, + messageID: messageID) + } label: { + Label { + Text("Open Full Message") + .font(OpenClawChatTypography.body) + } icon: { + Image(systemName: "doc.text.magnifyingglass") + } + } + } + } + + @ViewBuilder + private func replyMessageButton(for message: OpenClawChatMessage) -> some View { + let role = message.role.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() + let text = ChatReplyQuote.targetText(ChatMessageVisibleText.visibleText(in: message)) + if role == "user" || role == "assistant", !text.isEmpty { + Button { + self.viewModel.setReplyTarget( + messageID: message.id, + text: text, + senderLabel: self.replySenderLabel(forRole: role)) + } label: { + Label { + Text(String(localized: "Reply")) + .font(OpenClawChatTypography.body) + } icon: { + Image(systemName: "arrowshape.turn.up.left") + } + } + } + } + + private func replySenderLabel(forRole role: String) -> String { + guard role == "assistant" else { return String(localized: "You") } + let name = self.assistantName?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" + return name.isEmpty ? String(localized: "Assistant") : name + } + + fileprivate static func copyToClipboard(_ text: String) { + #if os(macOS) + NSPasteboard.general.clearContents() + NSPasteboard.general.setString(text, forType: .string) + #else + UIPasteboard.general.string = text #endif } } diff --git a/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift b/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift index 86325a802e2a..db012f94f820 100644 --- a/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift +++ b/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatWindowShell.swift @@ -9,7 +9,9 @@ import UniformTypeIdentifiers /// window experience. @MainActor public struct OpenClawChatWindowShell: View { - public static let assistantTraceDefaultsKey = "openclaw.webchat.showAssistantTrace" + public nonisolated static let assistantTraceDefaultsKey = "openclaw.webchat.showAssistantTrace" + public nonisolated static let assistantReasoningDefaultsKey = "openclaw.webchat.showAssistantReasoning" + public nonisolated static let assistantToolActivityDefaultsKey = "openclaw.webchat.showAssistantToolActivity" @State private var viewModel: OpenClawChatViewModel @State private var sessionQuery = "" @@ -19,16 +21,18 @@ public struct OpenClawChatWindowShell: View { @State private var renameSessionKey: String? @State private var renameText = "" private let userAccent: Color? - private let showsAssistantTrace: Bool + private let displayOptions: OpenClawChatDisplayOptions private let emptyAssistantIntro: String? private let emptyAssistantPrompts: [OpenClawChatView.StarterPrompt] private let talkControl: OpenClawChatTalkControl? private let voiceNoteControl: OpenClawChatVoiceNoteControl? private let speech: OpenClawChatSpeechController? + /// `showsAssistantTrace` remains as a source-compatible convenience that sets both display options. public init( viewModel: OpenClawChatViewModel, userAccent: Color? = nil, + displayOptions: OpenClawChatDisplayOptions? = nil, showsAssistantTrace: Bool = false, emptyAssistantIntro: String? = nil, emptyAssistantPrompts: [OpenClawChatView.StarterPrompt] = [], @@ -38,7 +42,7 @@ public struct OpenClawChatWindowShell: View { { _viewModel = State(initialValue: viewModel) self.userAccent = userAccent - self.showsAssistantTrace = showsAssistantTrace + self.displayOptions = displayOptions ?? .assistantTrace(showsAssistantTrace) self.emptyAssistantIntro = emptyAssistantIntro self.emptyAssistantPrompts = emptyAssistantPrompts self.talkControl = talkControl @@ -57,7 +61,7 @@ public struct OpenClawChatWindowShell: View { viewModel: self.viewModel, drawsBackground: false, userAccent: self.userAccent, - showsAssistantTrace: self.showsAssistantTrace, + displayOptions: self.displayOptions, composerChrome: .clean, emptyAssistantIntro: self.emptyAssistantIntro, emptyAssistantPrompts: self.emptyAssistantPrompts, @@ -378,17 +382,29 @@ public struct OpenClawChatWindowShell: View { .disabled(self.viewModel.messages.isEmpty) Toggle(isOn: Binding( - get: { self.showsAssistantTrace }, + get: { self.displayOptions.contains(.reasoning) }, set: { UserDefaults.standard.set( $0, - forKey: Self.assistantTraceDefaultsKey) + forKey: Self.assistantReasoningDefaultsKey) })) { chatWindowActionLabel( - "Show reasoning & tool activity", + "Show Reasoning", systemImage: "brain.head.profile") } + Toggle(isOn: Binding( + get: { self.displayOptions.contains(.toolActivity) }, + set: { + UserDefaults.standard.set( + $0, + forKey: Self.assistantToolActivityDefaultsKey) + })) { + chatWindowActionLabel( + "Show Tool Activity", + systemImage: "hammer") + } + Divider() Button { diff --git a/apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatMessageVisibleTextTests.swift b/apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatMessageVisibleTextTests.swift index 20da30eaeb71..4d613064734d 100644 --- a/apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatMessageVisibleTextTests.swift +++ b/apps/shared/OpenClawKit/Tests/OpenClawKitTests/ChatMessageVisibleTextTests.swift @@ -42,6 +42,56 @@ struct ChatMessageVisibleTextTests { #expect(ChatMessageVisibleText.visibleText(in: message) == "What is up?") } + @Test func `assistant copy excludes thinking while user copy stays exact`() { + let assistant = OpenClawChatMessage( + role: "assistant", + content: [textContent("private reasoning\nVisible **answer**")], + timestamp: 1) + let user = OpenClawChatMessage( + role: "user", + content: [textContent("Keep this literal tag")], + timestamp: 1) + + #expect(ChatMessageVisibleText.copyText(in: assistant) == "Visible **answer**") + #expect(ChatMessageVisibleText.copyText(in: user) == "Keep this literal tag") + } + + @Test func `history decode retains transcript identity and truncation signals`() throws { + let metadata = try JSONDecoder().decode( + OpenClawChatMessage.self, + from: Data(#"{"role":"assistant","content":"short","__openclaw":{"id":"msg-1","truncated":true}}"#.utf8)) + let marker = try JSONDecoder().decode( + OpenClawChatMessage.self, + from: Data(#"{"role":"assistant","content":"short\n...(truncated)...","__openclaw":{"id":"msg-2"}}"#.utf8)) + + #expect(metadata.transcriptMessageID == "msg-1") + #expect(metadata.isTruncated) + #expect(marker.transcriptMessageID == "msg-2") + #expect(marker.isTruncated) + } + + @Test func `transcript metadata survives message coding round trip`() throws { + let original = OpenClawChatMessage( + role: "assistant", + content: [textContent("short\n...(truncated)...")], + timestamp: 1, + transcriptMessageID: "msg-round-trip", + isTruncated: true) + + let decoded = try JSONDecoder().decode( + OpenClawChatMessage.self, + from: JSONEncoder().encode(original)) + + #expect(decoded.transcriptMessageID == "msg-round-trip") + #expect(decoded.isTruncated) + } + + @Test func `legacy trace mapping sets both independent display options`() { + #expect(OpenClawChatDisplayOptions.assistantTrace(true) == [.reasoning, .toolActivity]) + #expect(OpenClawChatDisplayOptions.assistantTrace(false).isEmpty) + #expect(OpenClawChatDisplayOptions.reasoning != .toolActivity) + } + @Test func `has visible text ignores tool blank and thinking only messages`() { let toolOnly = OpenClawChatMessage( role: "assistant", diff --git a/docs/platforms/mac/webchat.md b/docs/platforms/mac/webchat.md index ca0952be1315..ef9406c4646f 100644 --- a/docs/platforms/mac/webchat.md +++ b/docs/platforms/mac/webchat.md @@ -10,8 +10,8 @@ The macOS menu bar app embeds the WebChat UI as a native SwiftUI view. It connec The full chat window is a native split view: - **Sessions sidebar**: searchable session list with pinned and recent sections. Spawned child sessions nest beneath their parent when the Gateway provides hierarchy metadata; collapsed parents summarize running, failed, and unread descendants. Context menus support rename, pin, fork, read/unread, archive/restore, copy session key, and delete. A toolbar button (or Cmd-N) creates a real new session via `sessions.create`. -- **Window toolbar**: context-usage ring (tokens and session cost, with a compact action), thinking-level picker, model picker, and a session actions menu. The menu can rename or fork the current session and update its pin, read, or archive state. **Sessions…** (Shift-Cmd-S) opens the Active/Archived manager for gateway search, rename, pin, archive, and restore. The same menu can show or hide assistant reasoning and tool activity; this is on by default and remembered across launches. -- **Transcript and composer**: assistant messages render as plain text with an avatar, user messages as accent bubbles. Empty chats offer desktop starter prompts. Typing `/` opens slash-command autocomplete backed by `commands.list`, with arrow/Tab/Return/Escape keyboard navigation. Right-click a message to copy it, or use **Listen** for gateway TTS with a local speech fallback. +- **Window toolbar**: context-usage ring (tokens and session cost, with a compact action), thinking-level picker, model picker, and a session actions menu. The menu can rename or fork the current session and update its pin, read, or archive state. **Sessions…** (Shift-Cmd-S) opens the Active/Archived manager for gateway search, rename, pin, archive, and restore. Separate menu checkmarks show or hide assistant reasoning and tool activity; both are on by default and remembered across launches. +- **Transcript and composer**: assistant messages render as plain text with an avatar, user messages as accent bubbles. Empty chats offer desktop starter prompts. Typing `/` opens slash-command autocomplete backed by `commands.list`, with arrow/Tab/Return/Escape keyboard navigation. Right-click a message to copy its visible Markdown without hidden reasoning. Truncated assistant messages also offer **Open Full Message**, which loads a selectable Markdown reader. Use **Listen** for gateway TTS with a local speech fallback. - **Voice controls**: the composer can start or stop the existing macOS Talk Mode without replacing its menu-bar overlay. While Talk Mode is active, the composer shows its listening/thinking/speaking state, live audio activity, and an expandable rolling transcript. Right-click the Talk button to choose **System Default** or a connected microphone; this is the same microphone selection used by Voice Wake and push-to-talk. If a selected microphone disconnects, the active Talk session falls back to the system default and tries the selection again the next time Talk Mode starts. A separate microphone action records a voice note when Talk Mode does not own audio capture. The anchored compact chat panel from the menu bar keeps the compact single-column layout with inline pickers, starter prompts, Talk Mode, voice notes, and Listen. Assistant reasoning and tool activity remain hidden in this compact surface. @@ -46,7 +46,7 @@ Disable the feature entirely with **Settings → General → Quick Chat**; the s ## How it is wired -- Data plane: Gateway WS methods `chat.history`, `chat.send`, `chat.abort`, `chat.inject`, and events `chat`, `agent`, `presence`, `tick`, `health`. +- Data plane: Gateway WS methods `chat.history`, `chat.message.get`, `chat.send`, `chat.abort`, `chat.inject`, and events `chat`, `agent`, `presence`, `tick`, `health`. - `chat.history` returns a display-normalized transcript: inline directive tags are stripped from visible text, plain-text tool-call XML payloads (``, ``, ``, ``, including truncated blocks) and leaked model control tokens are stripped, pure silent-token assistant rows such as exact `NO_REPLY`/`no_reply` are omitted, and oversized rows can be replaced with a truncated placeholder. - Session: defaults to the primary session as above; the UI can switch between sessions. - Unread state: after a session activates and its live history loads successfully, the app clears that session's unread marker. Failed history loads do not clear it; a transient patch failure retries on the next activation.