refactor: rename clawdbot to moltbot with legacy compat

This commit is contained in:
Peter Steinberger
2026-01-27 12:19:58 +00:00
parent 83460df96f
commit 6d16a658e5
1839 changed files with 11250 additions and 11199 deletions
@@ -1,4 +1,4 @@
import ClawdbotKit
import MoltbotKit
import Foundation
import Observation
import OSLog
@@ -10,28 +10,28 @@ import AppKit
import UIKit
#endif
private let chatUILogger = Logger(subsystem: "com.clawdbot", category: "ClawdbotChatUI")
private let chatUILogger = Logger(subsystem: "com.clawdbot", category: "MoltbotChatUI")
@MainActor
@Observable
public final class ClawdbotChatViewModel {
public private(set) var messages: [ClawdbotChatMessage] = []
public final class MoltbotChatViewModel {
public private(set) var messages: [MoltbotChatMessage] = []
public var input: String = ""
public var thinkingLevel: String = "off"
public private(set) var isLoading = false
public private(set) var isSending = false
public private(set) var isAborting = false
public var errorText: String?
public var attachments: [ClawdbotPendingAttachment] = []
public var attachments: [MoltbotPendingAttachment] = []
public private(set) var healthOK: Bool = false
public private(set) var pendingRunCount: Int = 0
public private(set) var sessionKey: String
public private(set) var sessionId: String?
public private(set) var streamingAssistantText: String?
public private(set) var pendingToolCalls: [ClawdbotChatPendingToolCall] = []
public private(set) var sessions: [ClawdbotChatSessionEntry] = []
private let transport: any ClawdbotChatTransport
public private(set) var pendingToolCalls: [MoltbotChatPendingToolCall] = []
public private(set) var sessions: [MoltbotChatSessionEntry] = []
private let transport: any MoltbotChatTransport
@ObservationIgnored
private nonisolated(unsafe) var eventTask: Task<Void, Never>?
@@ -43,7 +43,7 @@ public final class ClawdbotChatViewModel {
private nonisolated(unsafe) var pendingRunTimeoutTasks: [String: Task<Void, Never>] = [:]
private let pendingRunTimeoutMs: UInt64 = 120_000
private var pendingToolCallsById: [String: ClawdbotChatPendingToolCall] = [:] {
private var pendingToolCallsById: [String: MoltbotChatPendingToolCall] = [:] {
didSet {
self.pendingToolCalls = self.pendingToolCallsById.values
.sorted { ($0.startedAt ?? 0) < ($1.startedAt ?? 0) }
@@ -52,7 +52,7 @@ public final class ClawdbotChatViewModel {
private var lastHealthPollAt: Date?
public init(sessionKey: String, transport: any ClawdbotChatTransport) {
public init(sessionKey: String, transport: any MoltbotChatTransport) {
self.sessionKey = sessionKey
self.transport = transport
@@ -99,12 +99,12 @@ public final class ClawdbotChatViewModel {
Task { await self.performSwitchSession(to: sessionKey) }
}
public var sessionChoices: [ClawdbotChatSessionEntry] {
public var sessionChoices: [MoltbotChatSessionEntry] {
let now = Date().timeIntervalSince1970 * 1000
let cutoff = now - (24 * 60 * 60 * 1000)
let sorted = self.sessions.sorted { ($0.updatedAt ?? 0) > ($1.updatedAt ?? 0) }
var seen = Set<String>()
var recent: [ClawdbotChatSessionEntry] = []
var recent: [MoltbotChatSessionEntry] = []
for entry in sorted {
guard !seen.contains(entry.key) else { continue }
seen.insert(entry.key)
@@ -112,7 +112,7 @@ public final class ClawdbotChatViewModel {
recent.append(entry)
}
var result: [ClawdbotChatSessionEntry] = []
var result: [MoltbotChatSessionEntry] = []
var included = Set<String>()
for entry in recent where !included.contains(entry.key) {
result.append(entry)
@@ -138,7 +138,7 @@ public final class ClawdbotChatViewModel {
Task { await self.addImageAttachment(url: nil, data: data, fileName: fileName, mimeType: mimeType) }
}
public func removeAttachment(_ id: ClawdbotPendingAttachment.ID) {
public func removeAttachment(_ id: MoltbotPendingAttachment.ID) {
self.attachments.removeAll { $0.id == id }
}
@@ -180,15 +180,15 @@ public final class ClawdbotChatViewModel {
}
}
private static func decodeMessages(_ raw: [AnyCodable]) -> [ClawdbotChatMessage] {
private static func decodeMessages(_ raw: [AnyCodable]) -> [MoltbotChatMessage] {
let decoded = raw.compactMap { item in
(try? ChatPayloadDecoding.decode(item, as: ClawdbotChatMessage.self))
(try? ChatPayloadDecoding.decode(item, as: MoltbotChatMessage.self))
}
return Self.dedupeMessages(decoded)
}
private static func dedupeMessages(_ messages: [ClawdbotChatMessage]) -> [ClawdbotChatMessage] {
var result: [ClawdbotChatMessage] = []
private static func dedupeMessages(_ messages: [MoltbotChatMessage]) -> [MoltbotChatMessage] {
var result: [MoltbotChatMessage] = []
result.reserveCapacity(messages.count)
var seen = Set<String>()
@@ -205,7 +205,7 @@ public final class ClawdbotChatViewModel {
return result
}
private static func dedupeKey(for message: ClawdbotChatMessage) -> String? {
private static func dedupeKey(for message: MoltbotChatMessage) -> String? {
guard let timestamp = message.timestamp else { return nil }
let text = message.content.compactMap(\.text).joined(separator: "\n")
.trimmingCharacters(in: .whitespacesAndNewlines)
@@ -233,8 +233,8 @@ public final class ClawdbotChatViewModel {
self.streamingAssistantText = nil
// Optimistically append user message to UI.
var userContent: [ClawdbotChatMessageContent] = [
ClawdbotChatMessageContent(
var userContent: [MoltbotChatMessageContent] = [
MoltbotChatMessageContent(
type: "text",
text: messageText,
thinking: nil,
@@ -246,8 +246,8 @@ public final class ClawdbotChatViewModel {
name: nil,
arguments: nil),
]
let encodedAttachments = self.attachments.map { att -> ClawdbotChatAttachmentPayload in
ClawdbotChatAttachmentPayload(
let encodedAttachments = self.attachments.map { att -> MoltbotChatAttachmentPayload in
MoltbotChatAttachmentPayload(
type: att.type,
mimeType: att.mimeType,
fileName: att.fileName,
@@ -255,7 +255,7 @@ public final class ClawdbotChatViewModel {
}
for att in encodedAttachments {
userContent.append(
ClawdbotChatMessageContent(
MoltbotChatMessageContent(
type: att.type,
text: nil,
thinking: nil,
@@ -268,7 +268,7 @@ public final class ClawdbotChatViewModel {
arguments: nil))
}
self.messages.append(
ClawdbotChatMessage(
MoltbotChatMessage(
id: UUID(),
role: "user",
content: userContent,
@@ -332,8 +332,8 @@ public final class ClawdbotChatViewModel {
await self.bootstrap()
}
private func placeholderSession(key: String) -> ClawdbotChatSessionEntry {
ClawdbotChatSessionEntry(
private func placeholderSession(key: String) -> MoltbotChatSessionEntry {
MoltbotChatSessionEntry(
key: key,
kind: nil,
displayName: nil,
@@ -354,7 +354,7 @@ public final class ClawdbotChatViewModel {
contextTokens: nil)
}
private func handleTransportEvent(_ evt: ClawdbotChatTransportEvent) {
private func handleTransportEvent(_ evt: MoltbotChatTransportEvent) {
switch evt {
case let .health(ok):
self.healthOK = ok
@@ -370,7 +370,7 @@ public final class ClawdbotChatViewModel {
}
}
private func handleChatEvent(_ chat: ClawdbotChatEventPayload) {
private func handleChatEvent(_ chat: MoltbotChatEventPayload) {
if let sessionKey = chat.sessionKey, sessionKey != self.sessionKey {
return
}
@@ -407,7 +407,7 @@ public final class ClawdbotChatViewModel {
}
}
private func handleAgentEvent(_ evt: ClawdbotAgentEventPayload) {
private func handleAgentEvent(_ evt: MoltbotAgentEventPayload) {
if let sessionId, evt.runId != sessionId {
return
}
@@ -423,7 +423,7 @@ public final class ClawdbotChatViewModel {
guard let toolCallId = evt.data["toolCallId"]?.value as? String else { return }
if phase == "start" {
let args = evt.data["args"]
self.pendingToolCallsById[toolCallId] = ClawdbotChatPendingToolCall(
self.pendingToolCallsById[toolCallId] = MoltbotChatPendingToolCall(
toolCallId: toolCallId,
name: name,
args: args,
@@ -534,7 +534,7 @@ public final class ClawdbotChatViewModel {
let preview = Self.previewImage(data: data)
self.attachments.append(
ClawdbotPendingAttachment(
MoltbotPendingAttachment(
url: url,
data: data,
fileName: fileName,
@@ -542,7 +542,7 @@ public final class ClawdbotChatViewModel {
preview: preview))
}
private static func previewImage(data: Data) -> ClawdbotPlatformImage? {
private static func previewImage(data: Data) -> MoltbotPlatformImage? {
#if canImport(AppKit)
NSImage(data: data)
#elseif canImport(UIKit)