diff --git a/apps/.i18n/native-source.json b/apps/.i18n/native-source.json index 9653b6214590..73aee5c00327 100644 --- a/apps/.i18n/native-source.json +++ b/apps/.i18n/native-source.json @@ -28099,7 +28099,7 @@ }, { "kind": "ui-localized-call", - "line": 2921, + "line": 2915, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Generating voice…", "surface": "apple", @@ -28107,7 +28107,7 @@ }, { "kind": "ui-localized-call", - "line": 3059, + "line": 3053, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Speak failed: %@", "surface": "apple", @@ -28115,7 +28115,7 @@ }, { "kind": "ui-localized-call", - "line": 3158, + "line": 3152, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Speaking (System)…", "surface": "apple", @@ -28123,7 +28123,7 @@ }, { "kind": "ui-localized-call", - "line": 4054, + "line": 4048, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "iOS System Voice", "surface": "apple", @@ -28131,7 +28131,7 @@ }, { "kind": "ui-localized-call", - "line": 4056, + "line": 4050, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Realtime Voice", "surface": "apple", @@ -28139,7 +28139,7 @@ }, { "kind": "ui-localized-call", - "line": 4060, + "line": 4054, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Gateway Default", "surface": "apple", @@ -28147,7 +28147,7 @@ }, { "kind": "ui-localized-call", - "line": 4121, + "line": 4115, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Listening (Realtime)", "surface": "apple", @@ -28155,7 +28155,7 @@ }, { "kind": "ui-localized-call", - "line": 4123, + "line": 4117, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Thinking", "surface": "apple", @@ -28163,7 +28163,7 @@ }, { "kind": "ui-localized-call", - "line": 4125, + "line": 4119, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Thinking…", "surface": "apple", @@ -28171,7 +28171,7 @@ }, { "kind": "ui-localized-call", - "line": 4127, + "line": 4121, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Asking OpenClaw", "surface": "apple", @@ -28179,7 +28179,7 @@ }, { "kind": "ui-localized-call", - "line": 4129, + "line": 4123, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Still asking OpenClaw", "surface": "apple", @@ -28187,7 +28187,7 @@ }, { "kind": "ui-localized-call", - "line": 4131, + "line": 4125, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Updating OpenClaw", "surface": "apple", @@ -28195,7 +28195,7 @@ }, { "kind": "ui-localized-call", - "line": 4133, + "line": 4127, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Speaking", "surface": "apple", @@ -28203,7 +28203,7 @@ }, { "kind": "ui-localized-call", - "line": 4135, + "line": 4129, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Speaking…", "surface": "apple", @@ -28211,7 +28211,7 @@ }, { "kind": "ui-localized-call", - "line": 4137, + "line": 4131, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Connecting", "surface": "apple", @@ -28219,7 +28219,7 @@ }, { "kind": "ui-localized-call", - "line": 4139, + "line": 4133, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Connecting realtime…", "surface": "apple", @@ -28227,7 +28227,7 @@ }, { "kind": "ui-localized-call", - "line": 4141, + "line": 4135, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Waiting for realtime…", "surface": "apple", @@ -28235,7 +28235,7 @@ }, { "kind": "ui-localized-call", - "line": 4143, + "line": 4137, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Ready", "surface": "apple", @@ -28243,7 +28243,7 @@ }, { "kind": "ui-localized-call", - "line": 4145, + "line": 4139, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Reconnecting", "surface": "apple", @@ -28251,7 +28251,7 @@ }, { "kind": "ui-localized-call", - "line": 4147, + "line": 4141, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Reconnecting…", "surface": "apple", @@ -28259,7 +28259,7 @@ }, { "kind": "ui-localized-call", - "line": 4149, + "line": 4143, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Realtime failed before connecting", "surface": "apple", @@ -28267,7 +28267,7 @@ }, { "kind": "ui-localized-call", - "line": 4151, + "line": 4145, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Realtime disconnected", "surface": "apple", @@ -28275,7 +28275,7 @@ }, { "kind": "ui-localized-call", - "line": 4153, + "line": 4147, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "OpenClaw unavailable", "surface": "apple", @@ -28283,7 +28283,7 @@ }, { "kind": "ui-localized-call", - "line": 4155, + "line": 4149, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Confirmation needed", "surface": "apple", @@ -28291,7 +28291,7 @@ }, { "kind": "ui-localized-call", - "line": 4198, + "line": 4192, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "iOS Speech + TTS", "surface": "apple", @@ -28299,7 +28299,7 @@ }, { "kind": "ui-localized-call", - "line": 4200, + "line": 4194, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Listening", "surface": "apple", @@ -28307,7 +28307,7 @@ }, { "kind": "ui-localized-call", - "line": 4204, + "line": 4198, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "iOS Speech fallback", "surface": "apple", @@ -28315,7 +28315,7 @@ }, { "kind": "ui-localized-call", - "line": 4465, + "line": 4469, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Gateway Relay", "surface": "apple", @@ -28323,7 +28323,7 @@ }, { "kind": "ui-localized-call", - "line": 4467, + "line": 4471, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Native WebRTC", "surface": "apple", @@ -28331,7 +28331,7 @@ }, { "kind": "ui-localized-call", - "line": 4468, + "line": 4472, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Native", "surface": "apple", @@ -28339,7 +28339,7 @@ }, { "kind": "ui-localized-call", - "line": 4529, + "line": 4533, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Gateway permission required", "surface": "apple", @@ -28347,7 +28347,7 @@ }, { "kind": "ui-localized-call", - "line": 4551, + "line": 4555, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Not loaded", "surface": "apple", @@ -28355,7 +28355,7 @@ }, { "kind": "ui-localized-call", - "line": 4569, + "line": 4573, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Approval requested", "surface": "apple", @@ -28363,7 +28363,7 @@ }, { "kind": "ui-localized-call", - "line": 5099, + "line": 5103, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Realtime unavailable", "surface": "apple", @@ -28371,7 +28371,7 @@ }, { "kind": "ui-localized-call", - "line": 5127, + "line": 5131, "path": "apps/ios/Sources/Voice/TalkModeManager.swift", "source": "Listening (PTT)", "surface": "apple", diff --git a/apps/ios/Sources/Voice/TalkModeManager.swift b/apps/ios/Sources/Voice/TalkModeManager.swift index 14e47b663087..d3b74921882c 100644 --- a/apps/ios/Sources/Voice/TalkModeManager.swift +++ b/apps/ios/Sources/Voice/TalkModeManager.swift @@ -2360,13 +2360,7 @@ final class TalkModeManager: NSObject { }, onIssue: { [weak self] relayIssue in guard let self, self.realtimeRelayGeneration == relayGeneration else { return } - let issue = TalkRuntimeIssue( - code: .realtimeUnavailable, - message: relayIssue.message, - provider: relayIssue.provider, - model: relayIssue.model, - transport: relayIssue.transport, - phase: relayIssue.phase) + let issue = Self.runtimeIssue(from: relayIssue) self.realtimeRelayStartIssue = issue self.pendingRealtimeIssue = issue self.gatewayTalkLastIssueText = issue.diagnosticSummary @@ -4217,6 +4211,16 @@ extension TalkModeManager { phase: phase) } + static func runtimeIssue(from issue: RealtimeTalkRelayIssue) -> TalkRuntimeIssue { + TalkRuntimeIssue( + code: TalkRuntimeIssue.Code(rawValue: issue.code) ?? .realtimeUnavailable, + message: issue.message, + provider: issue.provider, + model: issue.model, + transport: issue.transport, + phase: issue.phase) + } + private func realtimeIssue(from error: Error, phase: String) -> TalkRuntimeIssue { if let gatewayError = error as? GatewayResponseError, let issue = Self.talkRuntimeIssue( diff --git a/apps/ios/Tests/TalkModeConfigParsingTests.swift b/apps/ios/Tests/TalkModeConfigParsingTests.swift index e84c0e1eabd8..2d7b253eed03 100644 --- a/apps/ios/Tests/TalkModeConfigParsingTests.swift +++ b/apps/ios/Tests/TalkModeConfigParsingTests.swift @@ -403,6 +403,16 @@ struct TalkModeManagerTests { #expect(issue.technicalDetails.contains("code: realtime_unavailable")) } + @Test func `relay issue preserves known code and falls back for unknown code`() { + let codes = ["realtime_output_cancel_failed", "future_code"].map { rawCode in + TalkModeManager.runtimeIssue(from: RealtimeTalkRelayIssue( + code: rawCode, + message: "failed")).code + } + + #expect(codes == [.realtimeOutputCancelFailed, .realtimeUnavailable]) + } + @Test func `native fallback keeps realtime issue visible`() { let manager = TalkModeManager(allowSimulatorCapture: true) let issue = TalkRuntimeIssue(