mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-02 10:21:34 +00:00
fix(ios): Apple Watch chat inherits thinking defaults (#111301)
* fix(thinking): fall back instead of erroring on unsupported adaptive level (#109351) The adaptive level is the auto sentinel (normalizeThinkLevel maps auto -> adaptive) meaning 'pick an appropriate level', not 'force this exact level'. Some clients (e.g. the Apple Watch client) send it as a transport default while the iOS app sends none, so hard-erroring on an unsupported adaptive override rejected otherwise-valid turns from those clients. Now the auto sentinel always falls back to a supported level; explicit concrete levels (e.g. an explicit /think xhigh) still hard-error as before. Closes #109351 * docs(proof): add real-behavior-proof screenshot + run log for #111301 Captured run of the real get-reply-run.media-only test (101 passed) showing the adaptive-thinking fallback fix verified. Co-Authored-By: yuvrajlaptop2008-byte <284412773+yuvrajlaptop2008-byte@users.noreply.github.com> * fix(ios): inherit Watch chat thinking defaults Co-authored-by: yuvraj thakur <284412773+yuvrajlaptop2008-byte@users.noreply.github.com> * chore(ios): sync native i18n inventory --------- Co-authored-by: yuvrajlaptop2008-byte <284412773+yuvrajlaptop2008-byte@users.noreply.github.com> Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
@@ -25931,7 +25931,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 8825,
|
||||
"line": 8837,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "Approval",
|
||||
"surface": "apple",
|
||||
@@ -25939,7 +25939,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 8825,
|
||||
"line": 8837,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "This approval was already",
|
||||
"surface": "apple",
|
||||
@@ -25947,7 +25947,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 8831,
|
||||
"line": 8843,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "This approval was already set to Always Allow.",
|
||||
"surface": "apple",
|
||||
@@ -25955,7 +25955,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 8832,
|
||||
"line": 8844,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "Approval set to Always Allow.",
|
||||
"surface": "apple",
|
||||
@@ -25963,7 +25963,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 10202,
|
||||
"line": 10214,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "\\(urlText.prefix(500))…",
|
||||
"surface": "apple",
|
||||
|
||||
@@ -684,7 +684,7 @@ struct IOSGatewayChatTransport: OpenClawChatTransport {
|
||||
agentID: String? = nil,
|
||||
expectedSessionRoutingContract: String? = nil,
|
||||
message: String,
|
||||
thinking: String,
|
||||
thinking: String?,
|
||||
idempotencyKey: String,
|
||||
attachments: [OpenClawChatAttachmentPayload],
|
||||
ifCurrentRoute expectedRoute: GatewayNodeSessionRoute?,
|
||||
|
||||
@@ -6736,6 +6736,17 @@ extension NodeAppModel {
|
||||
event.messageKind ?? .chat
|
||||
}
|
||||
|
||||
nonisolated static func watchThinkingOverride(for messageKind: WatchMessageKind) -> String? {
|
||||
// Free-form Watch chat has no one-turn thinking control, so it must not
|
||||
// invent an override. Quick replies intentionally use a cheap level.
|
||||
switch messageKind {
|
||||
case .chat:
|
||||
nil
|
||||
case .quickReply:
|
||||
"low"
|
||||
}
|
||||
}
|
||||
|
||||
private func forwardWatchMessage(
|
||||
_ event: WatchAppCommandEvent,
|
||||
requeueOnFailure: Bool) async -> WatchMessageSendOutcome
|
||||
@@ -6758,7 +6769,7 @@ extension NodeAppModel {
|
||||
if messageKind == .chat {
|
||||
self.focusChatSession(sessionKey)
|
||||
}
|
||||
let thinking = messageKind == .quickReply ? "low" : "auto"
|
||||
let thinkingOverride = Self.watchThinkingOverride(for: messageKind)
|
||||
|
||||
do {
|
||||
let submittedAtMs = Int64(Date().timeIntervalSince1970 * 1000)
|
||||
@@ -6766,7 +6777,8 @@ extension NodeAppModel {
|
||||
let response = try await appleReviewDemoChatTransport.sendMessage(
|
||||
sessionKey: sessionKey,
|
||||
message: text,
|
||||
thinking: thinking,
|
||||
// Demo mode has no Gateway session from which to resolve an omitted level.
|
||||
thinking: thinkingOverride ?? "auto",
|
||||
idempotencyKey: event.commandId,
|
||||
attachments: [])
|
||||
if messageKind == .quickReply {
|
||||
@@ -6810,7 +6822,7 @@ extension NodeAppModel {
|
||||
let response = try await transport.sendMessage(
|
||||
sessionKey: sessionKey,
|
||||
message: text,
|
||||
thinking: thinking,
|
||||
thinking: thinkingOverride,
|
||||
idempotencyKey: event.commandId,
|
||||
attachments: [],
|
||||
ifCurrentRoute: operatorRoute)
|
||||
|
||||
@@ -6165,6 +6165,11 @@ private func overrideNotificationServingPreference(_ enabled: Bool) -> () -> Voi
|
||||
#expect(outbox.nextQueuedMessage(isAvailable: true, gatewayStableID: "gateway-a") == reply)
|
||||
}
|
||||
|
||||
@Test func `watch messages only override thinking for quick replies`() {
|
||||
#expect(NodeAppModel.watchThinkingOverride(for: .chat) == nil)
|
||||
#expect(NodeAppModel.watchThinkingOverride(for: .quickReply) == "low")
|
||||
}
|
||||
|
||||
@Test func `watch message outbox discards permanent gateway failures`() {
|
||||
#expect(NodeAppModel._test_shouldDiscardFailedWatchMessage(code: "INVALID_REQUEST"))
|
||||
#expect(!NodeAppModel._test_shouldDiscardFailedWatchMessage(
|
||||
|
||||
@@ -313,6 +313,18 @@ struct ChatGatewayRequestTests {
|
||||
#expect(String(decoding: encoded, as: UTF8.self).contains("a.png"))
|
||||
}
|
||||
|
||||
@Test func `send request omits inherited thinking override`() {
|
||||
let inherited = OpenClawChatGatewayRequests.sendMessage(
|
||||
sessionKey: "global",
|
||||
agentID: nil,
|
||||
expectedSessionRoutingContract: nil,
|
||||
message: "inherit",
|
||||
thinking: nil,
|
||||
idempotencyKey: "send-inherit",
|
||||
attachments: [])
|
||||
#expect(inherited.params["thinking"] == nil)
|
||||
}
|
||||
|
||||
@Test func `question resolve request preserves answer arrays`() throws {
|
||||
let request = OpenClawChatGatewayRequests.resolveQuestion(
|
||||
id: "ask_123",
|
||||
|
||||
Reference in New Issue
Block a user