Files
openclaw/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatViewModel+SessionKeys.swift
Peter Steinberger 443c582949 fix(ios): restore in-flight runs after reconnect (#100277)
* fix(ios): restore in-flight chat runs from gateway history

Restore active Apple chat ownership across reconnect, foreground, and sequence-gap recovery using the existing chat.history snapshot. Preserve agent/session scoping and Gateway user-turn identity across Codex and Copilot mirrors, including current offline-cache integration.

* fix(ios): restore in-flight chat runs from gateway history
2026-07-06 03:23:38 +01:00

91 lines
3.5 KiB
Swift

import Foundation
extension OpenClawChatViewModel {
func matchesCurrentSessionKey(incoming: String, current: String) -> Bool {
Self.matchesCurrentSessionKey(
incoming: incoming,
current: current,
mainSessionKey: resolvedMainSessionKey,
activeAgentId: activeAgentId)
}
func matchesCurrentSessionKey(incoming: String, agentId: String?, current: String) -> Bool {
Self.matchesCurrentSessionKey(
incoming: incoming,
agentId: agentId,
current: current,
mainSessionKey: resolvedMainSessionKey,
activeAgentId: activeAgentId)
}
static func matchesCurrentSessionKey(
incoming: String,
agentId: String? = nil,
current: String,
mainSessionKey: String,
activeAgentId: String? = nil)
-> Bool
{
let incomingNormalized = incoming.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
let currentNormalized = current.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
if incomingNormalized == currentNormalized {
if incomingNormalized == "global" {
return Self.matchesGlobalAgent(agentId: agentId, activeAgentId: activeAgentId)
}
return true
}
let mainNormalized = mainSessionKey.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
if Self.matchesMainAlias(
incoming: incomingNormalized,
current: currentNormalized,
mainSessionKey: mainNormalized)
{
if incomingNormalized == "global" || currentNormalized == "global" || mainNormalized == "global" {
return Self.matchesGlobalAgent(agentId: agentId, activeAgentId: activeAgentId)
}
return true
}
if Self.matchesSelectedAgentGlobal(
incoming: incomingNormalized,
agentId: agentId,
current: currentNormalized)
{
return true
}
return false
}
private static func normalizedAgentId(_ agentId: String?) -> String? {
let normalized = agentId?.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
return normalized?.isEmpty == false ? normalized : nil
}
private static func matchesGlobalAgent(agentId: String?, activeAgentId: String?) -> Bool {
guard let activeAgentId = normalizedAgentId(activeAgentId) else { return false }
guard let incomingAgentId = normalizedAgentId(agentId) else { return true }
return incomingAgentId == activeAgentId
}
private static func matchesMainAlias(incoming: String, current: String, mainSessionKey: String) -> Bool {
if current == "main", incoming == mainSessionKey, mainSessionKey != "main" {
return true
}
if incoming == "main", current == mainSessionKey, mainSessionKey != "main" {
return true
}
return (current == "main" && incoming == "agent:main:main") ||
(incoming == "main" && current == "agent:main:main")
}
private static func matchesSelectedAgentGlobal(incoming: String, agentId: String?, current: String) -> Bool {
guard incoming == "global",
let selectedAgentId = agentId?.trimmingCharacters(in: .whitespacesAndNewlines).lowercased(),
!selectedAgentId.isEmpty
else {
return false
}
return current == "agent:\(selectedAgentId):global"
}
}