refactor: rename clawdbot to moltbot with legacy compat
This commit is contained in:
@@ -3,15 +3,15 @@
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "ClawdbotKit",
|
||||
name: "MoltbotKit",
|
||||
platforms: [
|
||||
.iOS(.v18),
|
||||
.macOS(.v15),
|
||||
],
|
||||
products: [
|
||||
.library(name: "ClawdbotProtocol", targets: ["ClawdbotProtocol"]),
|
||||
.library(name: "ClawdbotKit", targets: ["ClawdbotKit"]),
|
||||
.library(name: "ClawdbotChatUI", targets: ["ClawdbotChatUI"]),
|
||||
.library(name: "MoltbotProtocol", targets: ["MoltbotProtocol"]),
|
||||
.library(name: "MoltbotKit", targets: ["MoltbotKit"]),
|
||||
.library(name: "MoltbotChatUI", targets: ["MoltbotChatUI"]),
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/steipete/ElevenLabsKit", exact: "0.1.0"),
|
||||
@@ -19,14 +19,16 @@ let package = Package(
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "ClawdbotProtocol",
|
||||
name: "MoltbotProtocol",
|
||||
path: "Sources/ClawdbotProtocol",
|
||||
swiftSettings: [
|
||||
.enableUpcomingFeature("StrictConcurrency"),
|
||||
]),
|
||||
.target(
|
||||
name: "ClawdbotKit",
|
||||
name: "MoltbotKit",
|
||||
path: "Sources/ClawdbotKit",
|
||||
dependencies: [
|
||||
"ClawdbotProtocol",
|
||||
"MoltbotProtocol",
|
||||
.product(name: "ElevenLabsKit", package: "ElevenLabsKit"),
|
||||
],
|
||||
resources: [
|
||||
@@ -36,9 +38,10 @@ let package = Package(
|
||||
.enableUpcomingFeature("StrictConcurrency"),
|
||||
]),
|
||||
.target(
|
||||
name: "ClawdbotChatUI",
|
||||
name: "MoltbotChatUI",
|
||||
path: "Sources/ClawdbotChatUI",
|
||||
dependencies: [
|
||||
"ClawdbotKit",
|
||||
"MoltbotKit",
|
||||
.product(
|
||||
name: "Textual",
|
||||
package: "textual",
|
||||
@@ -48,8 +51,9 @@ let package = Package(
|
||||
.enableUpcomingFeature("StrictConcurrency"),
|
||||
]),
|
||||
.testTarget(
|
||||
name: "ClawdbotKitTests",
|
||||
dependencies: ["ClawdbotKit", "ClawdbotChatUI"],
|
||||
name: "MoltbotKitTests",
|
||||
dependencies: ["MoltbotKit", "MoltbotChatUI"],
|
||||
path: "Tests/ClawdbotKitTests",
|
||||
swiftSettings: [
|
||||
.enableUpcomingFeature("StrictConcurrency"),
|
||||
.enableExperimentalFeature("SwiftTesting"),
|
||||
|
||||
@@ -8,9 +8,9 @@ import UniformTypeIdentifiers
|
||||
#endif
|
||||
|
||||
@MainActor
|
||||
struct ClawdbotChatComposer: View {
|
||||
@Bindable var viewModel: ClawdbotChatViewModel
|
||||
let style: ClawdbotChatView.Style
|
||||
struct MoltbotChatComposer: View {
|
||||
@Bindable var viewModel: MoltbotChatViewModel
|
||||
let style: MoltbotChatView.Style
|
||||
let showsSessionSwitcher: Bool
|
||||
|
||||
#if !os(macOS)
|
||||
@@ -54,21 +54,21 @@ struct ClawdbotChatComposer: View {
|
||||
topTrailing: 0),
|
||||
style: .continuous)
|
||||
shape
|
||||
.fill(ClawdbotChatTheme.composerBackground)
|
||||
.overlay(shape.strokeBorder(ClawdbotChatTheme.composerBorder, lineWidth: 1))
|
||||
.fill(MoltbotChatTheme.composerBackground)
|
||||
.overlay(shape.strokeBorder(MoltbotChatTheme.composerBorder, lineWidth: 1))
|
||||
.shadow(color: .black.opacity(0.12), radius: 12, y: 6)
|
||||
} else {
|
||||
let shape = RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)
|
||||
shape
|
||||
.fill(ClawdbotChatTheme.composerBackground)
|
||||
.overlay(shape.strokeBorder(ClawdbotChatTheme.composerBorder, lineWidth: 1))
|
||||
.fill(MoltbotChatTheme.composerBackground)
|
||||
.overlay(shape.strokeBorder(MoltbotChatTheme.composerBorder, lineWidth: 1))
|
||||
.shadow(color: .black.opacity(0.12), radius: 12, y: 6)
|
||||
}
|
||||
#else
|
||||
let shape = RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)
|
||||
shape
|
||||
.fill(ClawdbotChatTheme.composerBackground)
|
||||
.overlay(shape.strokeBorder(ClawdbotChatTheme.composerBorder, lineWidth: 1))
|
||||
.fill(MoltbotChatTheme.composerBackground)
|
||||
.overlay(shape.strokeBorder(MoltbotChatTheme.composerBorder, lineWidth: 1))
|
||||
.shadow(color: .black.opacity(0.12), radius: 12, y: 6)
|
||||
#endif
|
||||
}
|
||||
@@ -144,11 +144,11 @@ struct ClawdbotChatComposer: View {
|
||||
HStack(spacing: 6) {
|
||||
ForEach(
|
||||
self.viewModel.attachments,
|
||||
id: \ClawdbotPendingAttachment.id)
|
||||
{ (att: ClawdbotPendingAttachment) in
|
||||
id: \MoltbotPendingAttachment.id)
|
||||
{ (att: MoltbotPendingAttachment) in
|
||||
HStack(spacing: 6) {
|
||||
if let img = att.preview {
|
||||
ClawdbotPlatformImageFactory.image(img)
|
||||
MoltbotPlatformImageFactory.image(img)
|
||||
.resizable()
|
||||
.scaledToFill()
|
||||
.frame(width: 22, height: 22)
|
||||
@@ -181,7 +181,7 @@ struct ClawdbotChatComposer: View {
|
||||
self.editorOverlay
|
||||
|
||||
Rectangle()
|
||||
.fill(ClawdbotChatTheme.divider)
|
||||
.fill(MoltbotChatTheme.divider)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, 2)
|
||||
|
||||
@@ -197,10 +197,10 @@ struct ClawdbotChatComposer: View {
|
||||
.padding(.vertical, 8)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
||||
.fill(ClawdbotChatTheme.composerField)
|
||||
.fill(MoltbotChatTheme.composerField)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
||||
.strokeBorder(ClawdbotChatTheme.composerBorder)))
|
||||
.strokeBorder(MoltbotChatTheme.composerBorder)))
|
||||
.padding(self.editorPadding)
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ struct ClawdbotChatComposer: View {
|
||||
}
|
||||
.padding(.horizontal, 8)
|
||||
.padding(.vertical, 4)
|
||||
.background(ClawdbotChatTheme.subtleCard)
|
||||
.background(MoltbotChatTheme.subtleCard)
|
||||
.clipShape(Capsule())
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ enum ChatMarkdownPreprocessor {
|
||||
struct InlineImage: Identifiable {
|
||||
let id = UUID()
|
||||
let label: String
|
||||
let image: ClawdbotPlatformImage?
|
||||
let image: MoltbotPlatformImage?
|
||||
}
|
||||
|
||||
struct Result {
|
||||
@@ -30,11 +30,11 @@ enum ChatMarkdownPreprocessor {
|
||||
let label = ns.substring(with: match.range(at: 1))
|
||||
let dataURL = ns.substring(with: match.range(at: 2))
|
||||
|
||||
let image: ClawdbotPlatformImage? = {
|
||||
let image: MoltbotPlatformImage? = {
|
||||
guard let comma = dataURL.firstIndex(of: ",") else { return nil }
|
||||
let b64 = String(dataURL[dataURL.index(after: comma)...])
|
||||
guard let data = Data(base64Encoded: b64) else { return nil }
|
||||
return ClawdbotPlatformImage(data: data)
|
||||
return MoltbotPlatformImage(data: data)
|
||||
}()
|
||||
images.append(InlineImage(label: label, image: image))
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ private struct InlineImageList: View {
|
||||
var body: some View {
|
||||
ForEach(images, id: \.id) { item in
|
||||
if let img = item.image {
|
||||
ClawdbotPlatformImageFactory.image(img)
|
||||
MoltbotPlatformImageFactory.image(img)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(maxHeight: 260)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotKit
|
||||
import MoltbotKit
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
@@ -135,8 +135,8 @@ private struct ChatBubbleShape: InsettableShape {
|
||||
|
||||
@MainActor
|
||||
struct ChatMessageBubble: View {
|
||||
let message: ClawdbotChatMessage
|
||||
let style: ClawdbotChatView.Style
|
||||
let message: MoltbotChatMessage
|
||||
let style: MoltbotChatView.Style
|
||||
let markdownVariant: ChatMarkdownVariant
|
||||
let userAccent: Color?
|
||||
|
||||
@@ -157,15 +157,15 @@ struct ChatMessageBubble: View {
|
||||
|
||||
@MainActor
|
||||
private struct ChatMessageBody: View {
|
||||
let message: ClawdbotChatMessage
|
||||
let message: MoltbotChatMessage
|
||||
let isUser: Bool
|
||||
let style: ClawdbotChatView.Style
|
||||
let style: MoltbotChatView.Style
|
||||
let markdownVariant: ChatMarkdownVariant
|
||||
let userAccent: Color?
|
||||
|
||||
var body: some View {
|
||||
let text = self.primaryText
|
||||
let textColor = self.isUser ? ClawdbotChatTheme.userText : ClawdbotChatTheme.assistantText
|
||||
let textColor = self.isUser ? MoltbotChatTheme.userText : MoltbotChatTheme.assistantText
|
||||
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
if self.isToolResultMessage {
|
||||
@@ -232,7 +232,7 @@ private struct ChatMessageBody: View {
|
||||
return parts.joined(separator: "\n").trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
}
|
||||
|
||||
private var inlineAttachments: [ClawdbotChatMessageContent] {
|
||||
private var inlineAttachments: [MoltbotChatMessageContent] {
|
||||
self.message.content.filter { content in
|
||||
switch content.type ?? "text" {
|
||||
case "file", "attachment":
|
||||
@@ -243,7 +243,7 @@ private struct ChatMessageBody: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var toolCalls: [ClawdbotChatMessageContent] {
|
||||
private var toolCalls: [MoltbotChatMessageContent] {
|
||||
self.message.content.filter { content in
|
||||
let kind = (content.type ?? "").lowercased()
|
||||
if ["toolcall", "tool_call", "tooluse", "tool_use"].contains(kind) {
|
||||
@@ -253,7 +253,7 @@ private struct ChatMessageBody: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var inlineToolResults: [ClawdbotChatMessageContent] {
|
||||
private var inlineToolResults: [MoltbotChatMessageContent] {
|
||||
self.message.content.filter { content in
|
||||
let kind = (content.type ?? "").lowercased()
|
||||
return kind == "toolresult" || kind == "tool_result"
|
||||
@@ -276,12 +276,12 @@ private struct ChatMessageBody: View {
|
||||
|
||||
private var bubbleFillColor: Color {
|
||||
if self.isUser {
|
||||
return self.userAccent ?? ClawdbotChatTheme.userBubble
|
||||
return self.userAccent ?? MoltbotChatTheme.userBubble
|
||||
}
|
||||
if self.style == .onboarding {
|
||||
return ClawdbotChatTheme.onboardingAssistantBubble
|
||||
return MoltbotChatTheme.onboardingAssistantBubble
|
||||
}
|
||||
return ClawdbotChatTheme.assistantBubble
|
||||
return MoltbotChatTheme.assistantBubble
|
||||
}
|
||||
|
||||
private var bubbleBackground: AnyShapeStyle {
|
||||
@@ -293,7 +293,7 @@ private struct ChatMessageBody: View {
|
||||
return Color.white.opacity(0.12)
|
||||
}
|
||||
if self.style == .onboarding {
|
||||
return ClawdbotChatTheme.onboardingAssistantBorder
|
||||
return MoltbotChatTheme.onboardingAssistantBorder
|
||||
}
|
||||
return Color.white.opacity(0.08)
|
||||
}
|
||||
@@ -339,7 +339,7 @@ private struct ChatMessageBody: View {
|
||||
}
|
||||
|
||||
private struct AttachmentRow: View {
|
||||
let att: ClawdbotChatMessageContent
|
||||
let att: MoltbotChatMessageContent
|
||||
let isUser: Bool
|
||||
|
||||
var body: some View {
|
||||
@@ -348,7 +348,7 @@ private struct AttachmentRow: View {
|
||||
Text(self.att.fileName ?? "Attachment")
|
||||
.font(.footnote)
|
||||
.lineLimit(1)
|
||||
.foregroundStyle(self.isUser ? ClawdbotChatTheme.userText : ClawdbotChatTheme.assistantText)
|
||||
.foregroundStyle(self.isUser ? MoltbotChatTheme.userText : MoltbotChatTheme.assistantText)
|
||||
Spacer()
|
||||
}
|
||||
.padding(10)
|
||||
@@ -358,7 +358,7 @@ private struct AttachmentRow: View {
|
||||
}
|
||||
|
||||
private struct ToolCallCard: View {
|
||||
let content: ClawdbotChatMessageContent
|
||||
let content: MoltbotChatMessageContent
|
||||
let isUser: Bool
|
||||
|
||||
var body: some View {
|
||||
@@ -379,7 +379,7 @@ private struct ToolCallCard: View {
|
||||
.padding(10)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
||||
.fill(ClawdbotChatTheme.subtleCard)
|
||||
.fill(MoltbotChatTheme.subtleCard)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
||||
.strokeBorder(Color.white.opacity(0.08), lineWidth: 1)))
|
||||
@@ -414,7 +414,7 @@ private struct ToolResultCard: View {
|
||||
|
||||
Text(self.displayText)
|
||||
.font(.footnote.monospaced())
|
||||
.foregroundStyle(self.isUser ? ClawdbotChatTheme.userText : ClawdbotChatTheme.assistantText)
|
||||
.foregroundStyle(self.isUser ? MoltbotChatTheme.userText : MoltbotChatTheme.assistantText)
|
||||
.lineLimit(self.expanded ? nil : Self.previewLineLimit)
|
||||
|
||||
if self.shouldShowToggle {
|
||||
@@ -429,7 +429,7 @@ private struct ToolResultCard: View {
|
||||
.padding(10)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
||||
.fill(ClawdbotChatTheme.subtleCard)
|
||||
.fill(MoltbotChatTheme.subtleCard)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
||||
.strokeBorder(Color.white.opacity(0.08), lineWidth: 1)))
|
||||
@@ -453,7 +453,7 @@ private struct ToolResultCard: View {
|
||||
|
||||
@MainActor
|
||||
struct ChatTypingIndicatorBubble: View {
|
||||
let style: ClawdbotChatView.Style
|
||||
let style: MoltbotChatView.Style
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 10) {
|
||||
@@ -469,7 +469,7 @@ struct ChatTypingIndicatorBubble: View {
|
||||
.padding(.horizontal, self.style == .standard ? 12 : 14)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
.fill(ClawdbotChatTheme.assistantBubble))
|
||||
.fill(MoltbotChatTheme.assistantBubble))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
.strokeBorder(Color.white.opacity(0.08), lineWidth: 1))
|
||||
@@ -496,7 +496,7 @@ struct ChatStreamingAssistantBubble: View {
|
||||
.padding(12)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
.fill(ClawdbotChatTheme.assistantBubble))
|
||||
.fill(MoltbotChatTheme.assistantBubble))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
.strokeBorder(Color.white.opacity(0.08), lineWidth: 1))
|
||||
@@ -507,7 +507,7 @@ struct ChatStreamingAssistantBubble: View {
|
||||
|
||||
@MainActor
|
||||
struct ChatPendingToolsBubble: View {
|
||||
let toolCalls: [ClawdbotChatPendingToolCall]
|
||||
let toolCalls: [MoltbotChatPendingToolCall]
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
@@ -540,7 +540,7 @@ struct ChatPendingToolsBubble: View {
|
||||
.padding(12)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
.fill(ClawdbotChatTheme.assistantBubble))
|
||||
.fill(MoltbotChatTheme.assistantBubble))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
.strokeBorder(Color.white.opacity(0.08), lineWidth: 1))
|
||||
@@ -609,7 +609,7 @@ private struct ChatAssistantTextBody: View {
|
||||
context: .assistant,
|
||||
variant: self.markdownVariant,
|
||||
font: font,
|
||||
textColor: ClawdbotChatTheme.assistantText)
|
||||
textColor: MoltbotChatTheme.assistantText)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotKit
|
||||
import MoltbotKit
|
||||
import Foundation
|
||||
|
||||
// NOTE: keep this file lightweight; decode must be resilient to varying transcript formats.
|
||||
@@ -6,14 +6,14 @@ import Foundation
|
||||
#if canImport(AppKit)
|
||||
import AppKit
|
||||
|
||||
public typealias ClawdbotPlatformImage = NSImage
|
||||
public typealias MoltbotPlatformImage = NSImage
|
||||
#elseif canImport(UIKit)
|
||||
import UIKit
|
||||
|
||||
public typealias ClawdbotPlatformImage = UIImage
|
||||
public typealias MoltbotPlatformImage = UIImage
|
||||
#endif
|
||||
|
||||
public struct ClawdbotChatUsageCost: Codable, Hashable, Sendable {
|
||||
public struct MoltbotChatUsageCost: Codable, Hashable, Sendable {
|
||||
public let input: Double?
|
||||
public let output: Double?
|
||||
public let cacheRead: Double?
|
||||
@@ -21,12 +21,12 @@ public struct ClawdbotChatUsageCost: Codable, Hashable, Sendable {
|
||||
public let total: Double?
|
||||
}
|
||||
|
||||
public struct ClawdbotChatUsage: Codable, Hashable, Sendable {
|
||||
public struct MoltbotChatUsage: Codable, Hashable, Sendable {
|
||||
public let input: Int?
|
||||
public let output: Int?
|
||||
public let cacheRead: Int?
|
||||
public let cacheWrite: Int?
|
||||
public let cost: ClawdbotChatUsageCost?
|
||||
public let cost: MoltbotChatUsageCost?
|
||||
public let total: Int?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
@@ -45,7 +45,7 @@ public struct ClawdbotChatUsage: Codable, Hashable, Sendable {
|
||||
self.output = try container.decodeIfPresent(Int.self, forKey: .output)
|
||||
self.cacheRead = try container.decodeIfPresent(Int.self, forKey: .cacheRead)
|
||||
self.cacheWrite = try container.decodeIfPresent(Int.self, forKey: .cacheWrite)
|
||||
self.cost = try container.decodeIfPresent(ClawdbotChatUsageCost.self, forKey: .cost)
|
||||
self.cost = try container.decodeIfPresent(MoltbotChatUsageCost.self, forKey: .cost)
|
||||
self.total =
|
||||
try container.decodeIfPresent(Int.self, forKey: .total) ??
|
||||
container.decodeIfPresent(Int.self, forKey: .totalTokens)
|
||||
@@ -62,7 +62,7 @@ public struct ClawdbotChatUsage: Codable, Hashable, Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdbotChatMessageContent: Codable, Hashable, Sendable {
|
||||
public struct MoltbotChatMessageContent: Codable, Hashable, Sendable {
|
||||
public let type: String?
|
||||
public let text: String?
|
||||
public let thinking: String?
|
||||
@@ -135,14 +135,14 @@ public struct ClawdbotChatMessageContent: Codable, Hashable, Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdbotChatMessage: Codable, Identifiable, Sendable {
|
||||
public struct MoltbotChatMessage: Codable, Identifiable, Sendable {
|
||||
public var id: UUID = .init()
|
||||
public let role: String
|
||||
public let content: [ClawdbotChatMessageContent]
|
||||
public let content: [MoltbotChatMessageContent]
|
||||
public let timestamp: Double?
|
||||
public let toolCallId: String?
|
||||
public let toolName: String?
|
||||
public let usage: ClawdbotChatUsage?
|
||||
public let usage: MoltbotChatUsage?
|
||||
public let stopReason: String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
@@ -160,11 +160,11 @@ public struct ClawdbotChatMessage: Codable, Identifiable, Sendable {
|
||||
public init(
|
||||
id: UUID = .init(),
|
||||
role: String,
|
||||
content: [ClawdbotChatMessageContent],
|
||||
content: [MoltbotChatMessageContent],
|
||||
timestamp: Double?,
|
||||
toolCallId: String? = nil,
|
||||
toolName: String? = nil,
|
||||
usage: ClawdbotChatUsage? = nil,
|
||||
usage: MoltbotChatUsage? = nil,
|
||||
stopReason: String? = nil)
|
||||
{
|
||||
self.id = id
|
||||
@@ -187,10 +187,10 @@ public struct ClawdbotChatMessage: Codable, Identifiable, Sendable {
|
||||
self.toolName =
|
||||
try container.decodeIfPresent(String.self, forKey: .toolName) ??
|
||||
container.decodeIfPresent(String.self, forKey: .tool_name)
|
||||
self.usage = try container.decodeIfPresent(ClawdbotChatUsage.self, forKey: .usage)
|
||||
self.usage = try container.decodeIfPresent(MoltbotChatUsage.self, forKey: .usage)
|
||||
self.stopReason = try container.decodeIfPresent(String.self, forKey: .stopReason)
|
||||
|
||||
if let decoded = try? container.decode([ClawdbotChatMessageContent].self, forKey: .content) {
|
||||
if let decoded = try? container.decode([MoltbotChatMessageContent].self, forKey: .content) {
|
||||
self.content = decoded
|
||||
return
|
||||
}
|
||||
@@ -198,7 +198,7 @@ public struct ClawdbotChatMessage: Codable, Identifiable, Sendable {
|
||||
// Some session log formats store `content` as a plain string.
|
||||
if let text = try? container.decode(String.self, forKey: .content) {
|
||||
self.content = [
|
||||
ClawdbotChatMessageContent(
|
||||
MoltbotChatMessageContent(
|
||||
type: "text",
|
||||
text: text,
|
||||
thinking: nil,
|
||||
@@ -228,40 +228,40 @@ public struct ClawdbotChatMessage: Codable, Identifiable, Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdbotChatHistoryPayload: Codable, Sendable {
|
||||
public struct MoltbotChatHistoryPayload: Codable, Sendable {
|
||||
public let sessionKey: String
|
||||
public let sessionId: String?
|
||||
public let messages: [AnyCodable]?
|
||||
public let thinkingLevel: String?
|
||||
}
|
||||
|
||||
public struct ClawdbotSessionPreviewItem: Codable, Hashable, Sendable {
|
||||
public struct MoltbotSessionPreviewItem: Codable, Hashable, Sendable {
|
||||
public let role: String
|
||||
public let text: String
|
||||
}
|
||||
|
||||
public struct ClawdbotSessionPreviewEntry: Codable, Sendable {
|
||||
public struct MoltbotSessionPreviewEntry: Codable, Sendable {
|
||||
public let key: String
|
||||
public let status: String
|
||||
public let items: [ClawdbotSessionPreviewItem]
|
||||
public let items: [MoltbotSessionPreviewItem]
|
||||
}
|
||||
|
||||
public struct ClawdbotSessionsPreviewPayload: Codable, Sendable {
|
||||
public struct MoltbotSessionsPreviewPayload: Codable, Sendable {
|
||||
public let ts: Int
|
||||
public let previews: [ClawdbotSessionPreviewEntry]
|
||||
public let previews: [MoltbotSessionPreviewEntry]
|
||||
|
||||
public init(ts: Int, previews: [ClawdbotSessionPreviewEntry]) {
|
||||
public init(ts: Int, previews: [MoltbotSessionPreviewEntry]) {
|
||||
self.ts = ts
|
||||
self.previews = previews
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdbotChatSendResponse: Codable, Sendable {
|
||||
public struct MoltbotChatSendResponse: Codable, Sendable {
|
||||
public let runId: String
|
||||
public let status: String
|
||||
}
|
||||
|
||||
public struct ClawdbotChatEventPayload: Codable, Sendable {
|
||||
public struct MoltbotChatEventPayload: Codable, Sendable {
|
||||
public let runId: String?
|
||||
public let sessionKey: String?
|
||||
public let state: String?
|
||||
@@ -269,7 +269,7 @@ public struct ClawdbotChatEventPayload: Codable, Sendable {
|
||||
public let errorMessage: String?
|
||||
}
|
||||
|
||||
public struct ClawdbotAgentEventPayload: Codable, Sendable, Identifiable {
|
||||
public struct MoltbotAgentEventPayload: Codable, Sendable, Identifiable {
|
||||
public var id: String { "\(self.runId)-\(self.seq ?? -1)" }
|
||||
public let runId: String
|
||||
public let seq: Int?
|
||||
@@ -278,7 +278,7 @@ public struct ClawdbotAgentEventPayload: Codable, Sendable, Identifiable {
|
||||
public let data: [String: AnyCodable]
|
||||
}
|
||||
|
||||
public struct ClawdbotChatPendingToolCall: Identifiable, Hashable, Sendable {
|
||||
public struct MoltbotChatPendingToolCall: Identifiable, Hashable, Sendable {
|
||||
public var id: String { self.toolCallId }
|
||||
public let toolCallId: String
|
||||
public let name: String
|
||||
@@ -287,18 +287,18 @@ public struct ClawdbotChatPendingToolCall: Identifiable, Hashable, Sendable {
|
||||
public let isError: Bool?
|
||||
}
|
||||
|
||||
public struct ClawdbotGatewayHealthOK: Codable, Sendable {
|
||||
public struct MoltbotGatewayHealthOK: Codable, Sendable {
|
||||
public let ok: Bool?
|
||||
}
|
||||
|
||||
public struct ClawdbotPendingAttachment: Identifiable {
|
||||
public struct MoltbotPendingAttachment: Identifiable {
|
||||
public let id = UUID()
|
||||
public let url: URL?
|
||||
public let data: Data
|
||||
public let fileName: String
|
||||
public let mimeType: String
|
||||
public let type: String
|
||||
public let preview: ClawdbotPlatformImage?
|
||||
public let preview: MoltbotPlatformImage?
|
||||
|
||||
public init(
|
||||
url: URL?,
|
||||
@@ -306,7 +306,7 @@ public struct ClawdbotPendingAttachment: Identifiable {
|
||||
fileName: String,
|
||||
mimeType: String,
|
||||
type: String = "file",
|
||||
preview: ClawdbotPlatformImage?)
|
||||
preview: MoltbotPlatformImage?)
|
||||
{
|
||||
self.url = url
|
||||
self.data = data
|
||||
@@ -317,7 +317,7 @@ public struct ClawdbotPendingAttachment: Identifiable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdbotChatAttachmentPayload: Codable, Sendable, Hashable {
|
||||
public struct MoltbotChatAttachmentPayload: Codable, Sendable, Hashable {
|
||||
public let type: String
|
||||
public let mimeType: String
|
||||
public let fileName: String
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotKit
|
||||
import MoltbotKit
|
||||
import Foundation
|
||||
|
||||
enum ChatPayloadDecoding {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import Foundation
|
||||
|
||||
public struct ClawdbotChatSessionsDefaults: Codable, Sendable {
|
||||
public struct MoltbotChatSessionsDefaults: Codable, Sendable {
|
||||
public let model: String?
|
||||
public let contextTokens: Int?
|
||||
}
|
||||
|
||||
public struct ClawdbotChatSessionEntry: Codable, Identifiable, Sendable, Hashable {
|
||||
public struct MoltbotChatSessionEntry: Codable, Identifiable, Sendable, Hashable {
|
||||
public var id: String { self.key }
|
||||
|
||||
public let key: String
|
||||
@@ -31,10 +31,10 @@ public struct ClawdbotChatSessionEntry: Codable, Identifiable, Sendable, Hashabl
|
||||
public let contextTokens: Int?
|
||||
}
|
||||
|
||||
public struct ClawdbotChatSessionsListResponse: Codable, Sendable {
|
||||
public struct MoltbotChatSessionsListResponse: Codable, Sendable {
|
||||
public let ts: Double?
|
||||
public let path: String?
|
||||
public let count: Int?
|
||||
public let defaults: ClawdbotChatSessionsDefaults?
|
||||
public let sessions: [ClawdbotChatSessionEntry]
|
||||
public let defaults: MoltbotChatSessionsDefaults?
|
||||
public let sessions: [MoltbotChatSessionEntry]
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import SwiftUI
|
||||
|
||||
@MainActor
|
||||
struct ChatSessionsSheet: View {
|
||||
@Bindable var viewModel: ClawdbotChatViewModel
|
||||
@Bindable var viewModel: MoltbotChatViewModel
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
var body: some View {
|
||||
|
||||
@@ -14,7 +14,7 @@ extension NSAppearance {
|
||||
}
|
||||
#endif
|
||||
|
||||
enum ClawdbotChatTheme {
|
||||
enum MoltbotChatTheme {
|
||||
#if os(macOS)
|
||||
static func resolvedAssistantBubbleColor(for appearance: NSAppearance) -> NSColor {
|
||||
// NSColor semantic colors don't reliably resolve for arbitrary NSAppearance in SwiftPM.
|
||||
@@ -31,11 +31,11 @@ enum ClawdbotChatTheme {
|
||||
}
|
||||
|
||||
static let assistantBubbleDynamicNSColor = NSColor(
|
||||
name: NSColor.Name("ClawdbotChatTheme.assistantBubble"),
|
||||
name: NSColor.Name("MoltbotChatTheme.assistantBubble"),
|
||||
dynamicProvider: resolvedAssistantBubbleColor(for:))
|
||||
|
||||
static let onboardingAssistantBubbleDynamicNSColor = NSColor(
|
||||
name: NSColor.Name("ClawdbotChatTheme.onboardingAssistantBubble"),
|
||||
name: NSColor.Name("MoltbotChatTheme.onboardingAssistantBubble"),
|
||||
dynamicProvider: resolvedOnboardingAssistantBubbleColor(for:))
|
||||
#endif
|
||||
|
||||
@@ -163,8 +163,8 @@ enum ClawdbotChatTheme {
|
||||
}
|
||||
}
|
||||
|
||||
enum ClawdbotPlatformImageFactory {
|
||||
static func image(_ image: ClawdbotPlatformImage) -> Image {
|
||||
enum MoltbotPlatformImageFactory {
|
||||
static func image(_ image: MoltbotPlatformImage) -> Image {
|
||||
#if os(macOS)
|
||||
Image(nsImage: image)
|
||||
#else
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdbotChatTransportEvent: Sendable {
|
||||
public enum MoltbotChatTransportEvent: Sendable {
|
||||
case health(ok: Bool)
|
||||
case tick
|
||||
case chat(ClawdbotChatEventPayload)
|
||||
case agent(ClawdbotAgentEventPayload)
|
||||
case chat(MoltbotChatEventPayload)
|
||||
case agent(MoltbotAgentEventPayload)
|
||||
case seqGap
|
||||
}
|
||||
|
||||
public protocol ClawdbotChatTransport: Sendable {
|
||||
func requestHistory(sessionKey: String) async throws -> ClawdbotChatHistoryPayload
|
||||
public protocol MoltbotChatTransport: Sendable {
|
||||
func requestHistory(sessionKey: String) async throws -> MoltbotChatHistoryPayload
|
||||
func sendMessage(
|
||||
sessionKey: String,
|
||||
message: String,
|
||||
thinking: String,
|
||||
idempotencyKey: String,
|
||||
attachments: [ClawdbotChatAttachmentPayload]) async throws -> ClawdbotChatSendResponse
|
||||
attachments: [MoltbotChatAttachmentPayload]) async throws -> MoltbotChatSendResponse
|
||||
|
||||
func abortRun(sessionKey: String, runId: String) async throws
|
||||
func listSessions(limit: Int?) async throws -> ClawdbotChatSessionsListResponse
|
||||
func listSessions(limit: Int?) async throws -> MoltbotChatSessionsListResponse
|
||||
|
||||
func requestHealth(timeoutMs: Int) async throws -> Bool
|
||||
func events() -> AsyncStream<ClawdbotChatTransportEvent>
|
||||
func events() -> AsyncStream<MoltbotChatTransportEvent>
|
||||
|
||||
func setActiveSessionKey(_ sessionKey: String) async throws
|
||||
}
|
||||
|
||||
extension ClawdbotChatTransport {
|
||||
extension MoltbotChatTransport {
|
||||
public func setActiveSessionKey(_: String) async throws {}
|
||||
|
||||
public func abortRun(sessionKey _: String, runId _: String) async throws {
|
||||
throw NSError(
|
||||
domain: "ClawdbotChatTransport",
|
||||
domain: "MoltbotChatTransport",
|
||||
code: 0,
|
||||
userInfo: [NSLocalizedDescriptionKey: "chat.abort not supported by this transport"])
|
||||
}
|
||||
|
||||
public func listSessions(limit _: Int?) async throws -> ClawdbotChatSessionsListResponse {
|
||||
public func listSessions(limit _: Int?) async throws -> MoltbotChatSessionsListResponse {
|
||||
throw NSError(
|
||||
domain: "ClawdbotChatTransport",
|
||||
domain: "MoltbotChatTransport",
|
||||
code: 0,
|
||||
userInfo: [NSLocalizedDescriptionKey: "sessions.list not supported by this transport"])
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
public struct ClawdbotChatView: View {
|
||||
public struct MoltbotChatView: View {
|
||||
public enum Style {
|
||||
case standard
|
||||
case onboarding
|
||||
}
|
||||
|
||||
@State private var viewModel: ClawdbotChatViewModel
|
||||
@State private var viewModel: MoltbotChatViewModel
|
||||
@State private var scrollerBottomID = UUID()
|
||||
@State private var scrollPosition: UUID?
|
||||
@State private var showSessions = false
|
||||
@@ -42,7 +42,7 @@ public struct ClawdbotChatView: View {
|
||||
}
|
||||
|
||||
public init(
|
||||
viewModel: ClawdbotChatViewModel,
|
||||
viewModel: MoltbotChatViewModel,
|
||||
showsSessionSwitcher: Bool = false,
|
||||
style: Style = .standard,
|
||||
markdownVariant: ChatMarkdownVariant = .standard,
|
||||
@@ -58,14 +58,14 @@ public struct ClawdbotChatView: View {
|
||||
public var body: some View {
|
||||
ZStack {
|
||||
if self.style == .standard {
|
||||
ClawdbotChatTheme.background
|
||||
MoltbotChatTheme.background
|
||||
.ignoresSafeArea()
|
||||
}
|
||||
|
||||
VStack(spacing: Layout.stackSpacing) {
|
||||
self.messageList
|
||||
.padding(.horizontal, Layout.outerPaddingHorizontal)
|
||||
ClawdbotChatComposer(
|
||||
MoltbotChatComposer(
|
||||
viewModel: self.viewModel,
|
||||
style: self.style,
|
||||
showsSessionSwitcher: self.showsSessionSwitcher)
|
||||
@@ -206,8 +206,8 @@ public struct ClawdbotChatView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var visibleMessages: [ClawdbotChatMessage] {
|
||||
let base: [ClawdbotChatMessage]
|
||||
private var visibleMessages: [MoltbotChatMessage] {
|
||||
let base: [MoltbotChatMessage]
|
||||
if self.style == .onboarding {
|
||||
guard let first = self.viewModel.messages.first else { return [] }
|
||||
base = first.role.lowercased() == "user" ? Array(self.viewModel.messages.dropFirst()) : self.viewModel
|
||||
@@ -324,8 +324,8 @@ public struct ClawdbotChatView: View {
|
||||
return ("Error", "exclamationmark.triangle.fill", .orange)
|
||||
}
|
||||
|
||||
private func mergeToolResults(in messages: [ClawdbotChatMessage]) -> [ClawdbotChatMessage] {
|
||||
var result: [ClawdbotChatMessage] = []
|
||||
private func mergeToolResults(in messages: [MoltbotChatMessage]) -> [MoltbotChatMessage] {
|
||||
var result: [MoltbotChatMessage] = []
|
||||
result.reserveCapacity(messages.count)
|
||||
|
||||
for message in messages {
|
||||
@@ -349,7 +349,7 @@ public struct ClawdbotChatView: View {
|
||||
|
||||
var content = last.content
|
||||
content.append(
|
||||
ClawdbotChatMessageContent(
|
||||
MoltbotChatMessageContent(
|
||||
type: "tool_result",
|
||||
text: toolText,
|
||||
thinking: nil,
|
||||
@@ -361,7 +361,7 @@ public struct ClawdbotChatView: View {
|
||||
name: message.toolName,
|
||||
arguments: nil))
|
||||
|
||||
let merged = ClawdbotChatMessage(
|
||||
let merged = MoltbotChatMessage(
|
||||
id: last.id,
|
||||
role: last.role,
|
||||
content: content,
|
||||
@@ -376,12 +376,12 @@ public struct ClawdbotChatView: View {
|
||||
return result
|
||||
}
|
||||
|
||||
private func isToolResultMessage(_ message: ClawdbotChatMessage) -> Bool {
|
||||
private func isToolResultMessage(_ message: MoltbotChatMessage) -> Bool {
|
||||
let role = message.role.lowercased()
|
||||
return role == "toolresult" || role == "tool_result"
|
||||
}
|
||||
|
||||
private func toolCallIds(in message: ClawdbotChatMessage) -> Set<String> {
|
||||
private func toolCallIds(in message: MoltbotChatMessage) -> Set<String> {
|
||||
var ids = Set<String>()
|
||||
for content in message.content {
|
||||
let kind = (content.type ?? "").lowercased()
|
||||
@@ -398,7 +398,7 @@ public struct ClawdbotChatView: View {
|
||||
return ids
|
||||
}
|
||||
|
||||
private func toolResultText(from message: ClawdbotChatMessage) -> String {
|
||||
private func toolResultText(from message: MoltbotChatMessage) -> String {
|
||||
let parts = message.content.compactMap { content -> String? in
|
||||
let kind = (content.type ?? "text").lowercased()
|
||||
guard kind == "text" || kind.isEmpty else { return nil }
|
||||
@@ -446,7 +446,7 @@ private struct ChatNoticeCard: View {
|
||||
.padding(18)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
||||
.fill(ClawdbotChatTheme.subtleCard)
|
||||
.fill(MoltbotChatTheme.subtleCard)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
||||
.strokeBorder(Color.white.opacity(0.12), lineWidth: 1)))
|
||||
@@ -499,7 +499,7 @@ private struct ChatNoticeBanner: View {
|
||||
.padding(.vertical, 10)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 14, style: .continuous)
|
||||
.fill(ClawdbotChatTheme.subtleCard)
|
||||
.fill(MoltbotChatTheme.subtleCard)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 14, style: .continuous)
|
||||
.strokeBorder(Color.white.opacity(0.12), lineWidth: 1)))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdbotBonjour {
|
||||
public enum MoltbotBonjour {
|
||||
// v0: internal-only, subject to rename.
|
||||
public static let gatewayServiceType = "_clawdbot-gw._tcp"
|
||||
public static let gatewayServiceType = "_moltbot-gw._tcp"
|
||||
public static let gatewayServiceDomain = "local."
|
||||
public static let wideAreaGatewayServiceDomain = "clawdbot.internal."
|
||||
public static let wideAreaGatewayServiceDomain = "moltbot.internal."
|
||||
|
||||
public static let gatewayServiceDomains = [
|
||||
gatewayServiceDomain,
|
||||
|
||||
@@ -27,14 +27,14 @@ public struct BridgeInvokeResponse: Codable, Sendable {
|
||||
public let id: String
|
||||
public let ok: Bool
|
||||
public let payloadJSON: String?
|
||||
public let error: ClawdbotNodeError?
|
||||
public let error: MoltbotNodeError?
|
||||
|
||||
public init(
|
||||
type: String = "invoke-res",
|
||||
id: String,
|
||||
ok: Bool,
|
||||
payloadJSON: String? = nil,
|
||||
error: ClawdbotNodeError? = nil)
|
||||
error: MoltbotNodeError? = nil)
|
||||
{
|
||||
self.type = type
|
||||
self.id = id
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdbotCameraCommand: String, Codable, Sendable {
|
||||
public enum MoltbotCameraCommand: String, Codable, Sendable {
|
||||
case list = "camera.list"
|
||||
case snap = "camera.snap"
|
||||
case clip = "camera.clip"
|
||||
}
|
||||
|
||||
public enum ClawdbotCameraFacing: String, Codable, Sendable {
|
||||
public enum MoltbotCameraFacing: String, Codable, Sendable {
|
||||
case back
|
||||
case front
|
||||
}
|
||||
|
||||
public enum ClawdbotCameraImageFormat: String, Codable, Sendable {
|
||||
public enum MoltbotCameraImageFormat: String, Codable, Sendable {
|
||||
case jpg
|
||||
case jpeg
|
||||
}
|
||||
|
||||
public enum ClawdbotCameraVideoFormat: String, Codable, Sendable {
|
||||
public enum MoltbotCameraVideoFormat: String, Codable, Sendable {
|
||||
case mp4
|
||||
}
|
||||
|
||||
public struct ClawdbotCameraSnapParams: Codable, Sendable, Equatable {
|
||||
public var facing: ClawdbotCameraFacing?
|
||||
public struct MoltbotCameraSnapParams: Codable, Sendable, Equatable {
|
||||
public var facing: MoltbotCameraFacing?
|
||||
public var maxWidth: Int?
|
||||
public var quality: Double?
|
||||
public var format: ClawdbotCameraImageFormat?
|
||||
public var format: MoltbotCameraImageFormat?
|
||||
public var deviceId: String?
|
||||
public var delayMs: Int?
|
||||
|
||||
public init(
|
||||
facing: ClawdbotCameraFacing? = nil,
|
||||
facing: MoltbotCameraFacing? = nil,
|
||||
maxWidth: Int? = nil,
|
||||
quality: Double? = nil,
|
||||
format: ClawdbotCameraImageFormat? = nil,
|
||||
format: MoltbotCameraImageFormat? = nil,
|
||||
deviceId: String? = nil,
|
||||
delayMs: Int? = nil)
|
||||
{
|
||||
@@ -45,18 +45,18 @@ public struct ClawdbotCameraSnapParams: Codable, Sendable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdbotCameraClipParams: Codable, Sendable, Equatable {
|
||||
public var facing: ClawdbotCameraFacing?
|
||||
public struct MoltbotCameraClipParams: Codable, Sendable, Equatable {
|
||||
public var facing: MoltbotCameraFacing?
|
||||
public var durationMs: Int?
|
||||
public var includeAudio: Bool?
|
||||
public var format: ClawdbotCameraVideoFormat?
|
||||
public var format: MoltbotCameraVideoFormat?
|
||||
public var deviceId: String?
|
||||
|
||||
public init(
|
||||
facing: ClawdbotCameraFacing? = nil,
|
||||
facing: MoltbotCameraFacing? = nil,
|
||||
durationMs: Int? = nil,
|
||||
includeAudio: Bool? = nil,
|
||||
format: ClawdbotCameraVideoFormat? = nil,
|
||||
format: MoltbotCameraVideoFormat? = nil,
|
||||
deviceId: String? = nil)
|
||||
{
|
||||
self.facing = facing
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdbotCanvasA2UIAction: Sendable {
|
||||
public enum MoltbotCanvasA2UIAction: Sendable {
|
||||
public struct AgentMessageContext: Sendable {
|
||||
public struct Session: Sendable {
|
||||
public var key: String
|
||||
@@ -94,6 +94,6 @@ public enum ClawdbotCanvasA2UIAction: Sendable {
|
||||
}
|
||||
return "{\"id\":\"\(actionId)\",\"ok\":\(ok ? "true" : "false"),\"error\":\"\"}"
|
||||
}()
|
||||
return "window.dispatchEvent(new CustomEvent('clawdbot:a2ui-action-status', { detail: \(json) }));"
|
||||
return "window.dispatchEvent(new CustomEvent('moltbot:a2ui-action-status', { detail: \(json) }));"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdbotCanvasA2UICommand: String, Codable, Sendable {
|
||||
public enum MoltbotCanvasA2UICommand: String, Codable, Sendable {
|
||||
/// Render A2UI content on the device canvas.
|
||||
case push = "canvas.a2ui.push"
|
||||
/// Legacy alias for `push` when sending JSONL.
|
||||
@@ -9,7 +9,7 @@ public enum ClawdbotCanvasA2UICommand: String, Codable, Sendable {
|
||||
case reset = "canvas.a2ui.reset"
|
||||
}
|
||||
|
||||
public struct ClawdbotCanvasA2UIPushParams: Codable, Sendable, Equatable {
|
||||
public struct MoltbotCanvasA2UIPushParams: Codable, Sendable, Equatable {
|
||||
public var messages: [AnyCodable]
|
||||
|
||||
public init(messages: [AnyCodable]) {
|
||||
@@ -17,7 +17,7 @@ public struct ClawdbotCanvasA2UIPushParams: Codable, Sendable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdbotCanvasA2UIPushJSONLParams: Codable, Sendable, Equatable {
|
||||
public struct MoltbotCanvasA2UIPushJSONLParams: Codable, Sendable, Equatable {
|
||||
public var jsonl: String
|
||||
|
||||
public init(jsonl: String) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdbotCanvasA2UIJSONL: Sendable {
|
||||
public enum MoltbotCanvasA2UIJSONL: Sendable {
|
||||
public struct ParsedItem: Sendable {
|
||||
public var lineNumber: Int
|
||||
public var message: AnyCodable
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
public struct ClawdbotCanvasNavigateParams: Codable, Sendable, Equatable {
|
||||
public struct MoltbotCanvasNavigateParams: Codable, Sendable, Equatable {
|
||||
public var url: String
|
||||
|
||||
public init(url: String) {
|
||||
@@ -8,7 +8,7 @@ public struct ClawdbotCanvasNavigateParams: Codable, Sendable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdbotCanvasPlacement: Codable, Sendable, Equatable {
|
||||
public struct MoltbotCanvasPlacement: Codable, Sendable, Equatable {
|
||||
public var x: Double?
|
||||
public var y: Double?
|
||||
public var width: Double?
|
||||
@@ -22,17 +22,17 @@ public struct ClawdbotCanvasPlacement: Codable, Sendable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdbotCanvasPresentParams: Codable, Sendable, Equatable {
|
||||
public struct MoltbotCanvasPresentParams: Codable, Sendable, Equatable {
|
||||
public var url: String?
|
||||
public var placement: ClawdbotCanvasPlacement?
|
||||
public var placement: MoltbotCanvasPlacement?
|
||||
|
||||
public init(url: String? = nil, placement: ClawdbotCanvasPlacement? = nil) {
|
||||
public init(url: String? = nil, placement: MoltbotCanvasPlacement? = nil) {
|
||||
self.url = url
|
||||
self.placement = placement
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdbotCanvasEvalParams: Codable, Sendable, Equatable {
|
||||
public struct MoltbotCanvasEvalParams: Codable, Sendable, Equatable {
|
||||
public var javaScript: String
|
||||
|
||||
public init(javaScript: String) {
|
||||
@@ -40,7 +40,7 @@ public struct ClawdbotCanvasEvalParams: Codable, Sendable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public enum ClawdbotCanvasSnapshotFormat: String, Codable, Sendable {
|
||||
public enum MoltbotCanvasSnapshotFormat: String, Codable, Sendable {
|
||||
case png
|
||||
case jpeg
|
||||
|
||||
@@ -63,12 +63,12 @@ public enum ClawdbotCanvasSnapshotFormat: String, Codable, Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdbotCanvasSnapshotParams: Codable, Sendable, Equatable {
|
||||
public struct MoltbotCanvasSnapshotParams: Codable, Sendable, Equatable {
|
||||
public var maxWidth: Int?
|
||||
public var quality: Double?
|
||||
public var format: ClawdbotCanvasSnapshotFormat?
|
||||
public var format: MoltbotCanvasSnapshotFormat?
|
||||
|
||||
public init(maxWidth: Int? = nil, quality: Double? = nil, format: ClawdbotCanvasSnapshotFormat? = nil) {
|
||||
public init(maxWidth: Int? = nil, quality: Double? = nil, format: MoltbotCanvasSnapshotFormat? = nil) {
|
||||
self.maxWidth = maxWidth
|
||||
self.quality = quality
|
||||
self.format = format
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdbotCanvasCommand: String, Codable, Sendable {
|
||||
public enum MoltbotCanvasCommand: String, Codable, Sendable {
|
||||
case present = "canvas.present"
|
||||
case hide = "canvas.hide"
|
||||
case navigate = "canvas.navigate"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdbotCapability: String, Codable, Sendable {
|
||||
public enum MoltbotCapability: String, Codable, Sendable {
|
||||
case canvas
|
||||
case camera
|
||||
case screen
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdbotKitResources {
|
||||
/// Resource bundle for ClawdbotKit.
|
||||
public enum MoltbotKitResources {
|
||||
/// Resource bundle for MoltbotKit.
|
||||
///
|
||||
/// Locates the SwiftPM-generated resource bundle, checking multiple locations:
|
||||
/// 1. Inside Bundle.main (packaged apps)
|
||||
@@ -13,7 +13,7 @@ public enum ClawdbotKitResources {
|
||||
/// SwiftPM's expectations.
|
||||
public static let bundle: Bundle = locateBundle()
|
||||
|
||||
private static let bundleName = "ClawdbotKit_ClawdbotKit"
|
||||
private static let bundleName = "MoltbotKit_MoltbotKit"
|
||||
|
||||
private static func locateBundle() -> Bundle {
|
||||
// 1. Check inside Bundle.main (packaged apps copy resources here)
|
||||
|
||||
@@ -37,7 +37,7 @@ public struct AgentDeepLink: Codable, Sendable, Equatable {
|
||||
|
||||
public enum DeepLinkParser {
|
||||
public static func parse(_ url: URL) -> DeepLinkRoute? {
|
||||
guard url.scheme?.lowercased() == "clawdbot" else { return nil }
|
||||
guard url.scheme?.lowercased() == "moltbot" else { return nil }
|
||||
guard let host = url.host?.lowercased(), !host.isEmpty else { return nil }
|
||||
guard let comps = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return nil }
|
||||
|
||||
|
||||
@@ -27,10 +27,10 @@ enum DeviceIdentityPaths {
|
||||
}
|
||||
|
||||
if let appSupport = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first {
|
||||
return appSupport.appendingPathComponent("clawdbot", isDirectory: true)
|
||||
return appSupport.appendingPathComponent("moltbot", isDirectory: true)
|
||||
}
|
||||
|
||||
return FileManager.default.temporaryDirectory.appendingPathComponent("clawdbot", isDirectory: true)
|
||||
return FileManager.default.temporaryDirectory.appendingPathComponent("moltbot", isDirectory: true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotProtocol
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
import OSLog
|
||||
|
||||
@@ -102,7 +102,7 @@ public enum GatewayAuthSource: String, Sendable {
|
||||
}
|
||||
|
||||
// Avoid ambiguity with the app's own AnyCodable type.
|
||||
private typealias ProtoAnyCodable = ClawdbotProtocol.AnyCodable
|
||||
private typealias ProtoAnyCodable = MoltbotProtocol.AnyCodable
|
||||
|
||||
private enum ConnectChallengeError: Error {
|
||||
case timeout
|
||||
@@ -268,7 +268,7 @@ public actor GatewayChannelActor {
|
||||
caps: [],
|
||||
commands: [],
|
||||
permissions: [:],
|
||||
clientId: "clawdbot-macos",
|
||||
clientId: "moltbot-macos",
|
||||
clientMode: "ui",
|
||||
clientDisplayName: InstanceIdentity.displayName)
|
||||
let clientDisplayName = options.clientDisplayName ?? InstanceIdentity.displayName
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotProtocol
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
|
||||
/// Structured error surfaced when the gateway responds with `{ ok: false }`.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotProtocol
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
import OSLog
|
||||
|
||||
@@ -41,7 +41,7 @@ public actor GatewayNodeSession {
|
||||
return BridgeInvokeResponse(
|
||||
id: request.id,
|
||||
ok: false,
|
||||
error: ClawdbotNodeError(
|
||||
error: MoltbotNodeError(
|
||||
code: .unavailable,
|
||||
message: "node invoke timed out")
|
||||
)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import ClawdbotProtocol
|
||||
import MoltbotProtocol
|
||||
import Foundation
|
||||
|
||||
public enum GatewayPayloadDecoding {
|
||||
public static func decode<T: Decodable>(
|
||||
_ payload: ClawdbotProtocol.AnyCodable,
|
||||
_ payload: MoltbotProtocol.AnyCodable,
|
||||
as _: T.Type = T.self) throws -> T
|
||||
{
|
||||
let data = try JSONEncoder().encode(payload)
|
||||
@@ -19,7 +19,7 @@ public enum GatewayPayloadDecoding {
|
||||
}
|
||||
|
||||
public static func decodeIfPresent<T: Decodable>(
|
||||
_ payload: ClawdbotProtocol.AnyCodable?,
|
||||
_ payload: MoltbotProtocol.AnyCodable?,
|
||||
as _: T.Type = T.self) throws -> T?
|
||||
{
|
||||
guard let payload else { return nil }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotProtocol
|
||||
import MoltbotProtocol
|
||||
|
||||
/// Server-push messages from the gateway websocket.
|
||||
///
|
||||
|
||||
@@ -42,14 +42,14 @@ public enum InstanceIdentity {
|
||||
let name = Self.readMainActor {
|
||||
UIDevice.current.name.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
}
|
||||
return name.isEmpty ? "clawdbot" : name
|
||||
return name.isEmpty ? "moltbot" : name
|
||||
#else
|
||||
if let name = Host.current().localizedName?.trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
!name.isEmpty
|
||||
{
|
||||
return name
|
||||
}
|
||||
return "clawdbot"
|
||||
return "moltbot"
|
||||
#endif
|
||||
}()
|
||||
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdbotLocationCommand: String, Codable, Sendable {
|
||||
public enum MoltbotLocationCommand: String, Codable, Sendable {
|
||||
case get = "location.get"
|
||||
}
|
||||
|
||||
public enum ClawdbotLocationAccuracy: String, Codable, Sendable {
|
||||
public enum MoltbotLocationAccuracy: String, Codable, Sendable {
|
||||
case coarse
|
||||
case balanced
|
||||
case precise
|
||||
}
|
||||
|
||||
public struct ClawdbotLocationGetParams: Codable, Sendable, Equatable {
|
||||
public struct MoltbotLocationGetParams: Codable, Sendable, Equatable {
|
||||
public var timeoutMs: Int?
|
||||
public var maxAgeMs: Int?
|
||||
public var desiredAccuracy: ClawdbotLocationAccuracy?
|
||||
public var desiredAccuracy: MoltbotLocationAccuracy?
|
||||
|
||||
public init(timeoutMs: Int? = nil, maxAgeMs: Int? = nil, desiredAccuracy: ClawdbotLocationAccuracy? = nil) {
|
||||
public init(timeoutMs: Int? = nil, maxAgeMs: Int? = nil, desiredAccuracy: MoltbotLocationAccuracy? = nil) {
|
||||
self.timeoutMs = timeoutMs
|
||||
self.maxAgeMs = maxAgeMs
|
||||
self.desiredAccuracy = desiredAccuracy
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdbotLocationPayload: Codable, Sendable, Equatable {
|
||||
public struct MoltbotLocationPayload: Codable, Sendable, Equatable {
|
||||
public var lat: Double
|
||||
public var lon: Double
|
||||
public var accuracyMeters: Double
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdbotLocationMode: String, Codable, Sendable, CaseIterable {
|
||||
public enum MoltbotLocationMode: String, Codable, Sendable, CaseIterable {
|
||||
case off
|
||||
case whileUsing
|
||||
case always
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdbotNodeErrorCode: String, Codable, Sendable {
|
||||
public enum MoltbotNodeErrorCode: String, Codable, Sendable {
|
||||
case notPaired = "NOT_PAIRED"
|
||||
case unauthorized = "UNAUTHORIZED"
|
||||
case backgroundUnavailable = "NODE_BACKGROUND_UNAVAILABLE"
|
||||
@@ -8,14 +8,14 @@ public enum ClawdbotNodeErrorCode: String, Codable, Sendable {
|
||||
case unavailable = "UNAVAILABLE"
|
||||
}
|
||||
|
||||
public struct ClawdbotNodeError: Error, Codable, Sendable, Equatable {
|
||||
public var code: ClawdbotNodeErrorCode
|
||||
public struct MoltbotNodeError: Error, Codable, Sendable, Equatable {
|
||||
public var code: MoltbotNodeErrorCode
|
||||
public var message: String
|
||||
public var retryable: Bool?
|
||||
public var retryAfterMs: Int?
|
||||
|
||||
public init(
|
||||
code: ClawdbotNodeErrorCode,
|
||||
code: MoltbotNodeErrorCode,
|
||||
message: String,
|
||||
retryable: Bool? = nil,
|
||||
retryAfterMs: Int? = nil)
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
backface-visibility: hidden;
|
||||
opacity: 0.45;
|
||||
pointer-events: none;
|
||||
animation: clawdbot-grid-drift 140s ease-in-out infinite alternate;
|
||||
animation: moltbot-grid-drift 140s ease-in-out infinite alternate;
|
||||
}
|
||||
:root[data-platform="android"] body::before { opacity: 0.80; }
|
||||
body::after {
|
||||
@@ -73,7 +73,7 @@
|
||||
backface-visibility: hidden;
|
||||
transform: translate3d(0,0,0);
|
||||
pointer-events: none;
|
||||
animation: clawdbot-glow-drift 110s ease-in-out infinite alternate;
|
||||
animation: moltbot-glow-drift 110s ease-in-out infinite alternate;
|
||||
}
|
||||
:root[data-platform="android"] body::after { opacity: 0.85; }
|
||||
@supports (mix-blend-mode: screen) {
|
||||
@@ -82,12 +82,12 @@
|
||||
@supports not (mix-blend-mode: screen) {
|
||||
body::after { opacity: 0.70; }
|
||||
}
|
||||
@keyframes clawdbot-grid-drift {
|
||||
@keyframes moltbot-grid-drift {
|
||||
0% { transform: translate3d(-12px, 8px, 0) rotate(-7deg); opacity: 0.40; }
|
||||
50% { transform: translate3d( 10px,-7px, 0) rotate(-6.6deg); opacity: 0.56; }
|
||||
100% { transform: translate3d(-8px, 6px, 0) rotate(-7.2deg); opacity: 0.42; }
|
||||
}
|
||||
@keyframes clawdbot-glow-drift {
|
||||
@keyframes moltbot-glow-drift {
|
||||
0% { transform: translate3d(-18px, 12px, 0) scale(1.02); opacity: 0.40; }
|
||||
50% { transform: translate3d( 14px,-10px, 0) scale(1.05); opacity: 0.52; }
|
||||
100% { transform: translate3d(-10px, 8px, 0) scale(1.03); opacity: 0.43; }
|
||||
@@ -101,14 +101,14 @@
|
||||
touch-action: none;
|
||||
z-index: 1;
|
||||
}
|
||||
:root[data-platform="android"] #clawdbot-canvas {
|
||||
:root[data-platform="android"] #moltbot-canvas {
|
||||
background:
|
||||
radial-gradient(1100px 800px at 20% 15%, rgba(42, 113, 255, 0.78), rgba(0,0,0,0) 58%),
|
||||
radial-gradient(900px 650px at 82% 28%, rgba(255, 0, 138, 0.66), rgba(0,0,0,0) 62%),
|
||||
radial-gradient(1000px 900px at 60% 88%, rgba(0, 209, 255, 0.58), rgba(0,0,0,0) 62%),
|
||||
#141c33;
|
||||
}
|
||||
#clawdbot-status {
|
||||
#moltbot-status {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
display: none;
|
||||
@@ -119,7 +119,7 @@
|
||||
pointer-events: none;
|
||||
z-index: 3;
|
||||
}
|
||||
#clawdbot-status .card {
|
||||
#moltbot-status .card {
|
||||
text-align: center;
|
||||
padding: 16px 18px;
|
||||
border-radius: 14px;
|
||||
@@ -129,13 +129,13 @@
|
||||
-webkit-backdrop-filter: blur(14px);
|
||||
backdrop-filter: blur(14px);
|
||||
}
|
||||
#clawdbot-status .title {
|
||||
#moltbot-status .title {
|
||||
font: 600 20px -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", system-ui, sans-serif;
|
||||
letter-spacing: 0.2px;
|
||||
color: rgba(255,255,255,0.92);
|
||||
text-shadow: 0 0 22px rgba(42, 113, 255, 0.35);
|
||||
}
|
||||
#clawdbot-status .subtitle {
|
||||
#moltbot-status .subtitle {
|
||||
margin-top: 6px;
|
||||
font: 500 12px -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, sans-serif;
|
||||
color: rgba(255,255,255,0.58);
|
||||
@@ -143,20 +143,20 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="clawdbot-canvas"></canvas>
|
||||
<div id="clawdbot-status">
|
||||
<canvas id="moltbot-canvas"></canvas>
|
||||
<div id="moltbot-status">
|
||||
<div class="card">
|
||||
<div class="title" id="clawdbot-status-title">Ready</div>
|
||||
<div class="subtitle" id="clawdbot-status-subtitle">Waiting for agent</div>
|
||||
<div class="title" id="moltbot-status-title">Ready</div>
|
||||
<div class="subtitle" id="moltbot-status-subtitle">Waiting for agent</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
(() => {
|
||||
const canvas = document.getElementById('clawdbot-canvas');
|
||||
const canvas = document.getElementById('moltbot-canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
const statusEl = document.getElementById('clawdbot-status');
|
||||
const titleEl = document.getElementById('clawdbot-status-title');
|
||||
const subtitleEl = document.getElementById('clawdbot-status-subtitle');
|
||||
const statusEl = document.getElementById('moltbot-status');
|
||||
const titleEl = document.getElementById('moltbot-status-title');
|
||||
const subtitleEl = document.getElementById('moltbot-status-subtitle');
|
||||
const debugStatusEnabledByQuery = (() => {
|
||||
try {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
@@ -194,7 +194,7 @@
|
||||
statusEl.style.display = 'none';
|
||||
}
|
||||
|
||||
window.__clawdbot = {
|
||||
window.__moltbot = {
|
||||
canvas,
|
||||
ctx,
|
||||
setDebugStatusEnabled,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdbotScreenCommand: String, Codable, Sendable {
|
||||
public enum MoltbotScreenCommand: String, Codable, Sendable {
|
||||
case record = "screen.record"
|
||||
}
|
||||
|
||||
public struct ClawdbotScreenRecordParams: Codable, Sendable, Equatable {
|
||||
public struct MoltbotScreenRecordParams: Codable, Sendable, Equatable {
|
||||
public var screenIndex: Int?
|
||||
public var durationMs: Int?
|
||||
public var fps: Double?
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdbotNodeStorage {
|
||||
public enum MoltbotNodeStorage {
|
||||
public static func appSupportDir() throws -> URL {
|
||||
let base = FileManager().urls(for: .applicationSupportDirectory, in: .userDomainMask).first
|
||||
guard let base else {
|
||||
throw NSError(domain: "ClawdbotNodeStorage", code: 1, userInfo: [
|
||||
throw NSError(domain: "MoltbotNodeStorage", code: 1, userInfo: [
|
||||
NSLocalizedDescriptionKey: "Application Support directory unavailable",
|
||||
])
|
||||
}
|
||||
return base.appendingPathComponent("Clawdbot", isDirectory: true)
|
||||
return base.appendingPathComponent("Moltbot", isDirectory: true)
|
||||
}
|
||||
|
||||
public static func canvasRoot(sessionKey: String) throws -> URL {
|
||||
@@ -21,11 +21,11 @@ public enum ClawdbotNodeStorage {
|
||||
public static func cachesDir() throws -> URL {
|
||||
let base = FileManager().urls(for: .cachesDirectory, in: .userDomainMask).first
|
||||
guard let base else {
|
||||
throw NSError(domain: "ClawdbotNodeStorage", code: 2, userInfo: [
|
||||
throw NSError(domain: "MoltbotNodeStorage", code: 2, userInfo: [
|
||||
NSLocalizedDescriptionKey: "Caches directory unavailable",
|
||||
])
|
||||
}
|
||||
return base.appendingPathComponent("Clawdbot", isDirectory: true)
|
||||
return base.appendingPathComponent("Moltbot", isDirectory: true)
|
||||
}
|
||||
|
||||
public static func canvasSnapshotsRoot(sessionKey: String) throws -> URL {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdbotSystemCommand: String, Codable, Sendable {
|
||||
public enum MoltbotSystemCommand: String, Codable, Sendable {
|
||||
case run = "system.run"
|
||||
case which = "system.which"
|
||||
case notify = "system.notify"
|
||||
@@ -8,19 +8,19 @@ public enum ClawdbotSystemCommand: String, Codable, Sendable {
|
||||
case execApprovalsSet = "system.execApprovals.set"
|
||||
}
|
||||
|
||||
public enum ClawdbotNotificationPriority: String, Codable, Sendable {
|
||||
public enum MoltbotNotificationPriority: String, Codable, Sendable {
|
||||
case passive
|
||||
case active
|
||||
case timeSensitive
|
||||
}
|
||||
|
||||
public enum ClawdbotNotificationDelivery: String, Codable, Sendable {
|
||||
public enum MoltbotNotificationDelivery: String, Codable, Sendable {
|
||||
case system
|
||||
case overlay
|
||||
case auto
|
||||
}
|
||||
|
||||
public struct ClawdbotSystemRunParams: Codable, Sendable, Equatable {
|
||||
public struct MoltbotSystemRunParams: Codable, Sendable, Equatable {
|
||||
public var command: [String]
|
||||
public var rawCommand: String?
|
||||
public var cwd: String?
|
||||
@@ -57,7 +57,7 @@ public struct ClawdbotSystemRunParams: Codable, Sendable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdbotSystemWhichParams: Codable, Sendable, Equatable {
|
||||
public struct MoltbotSystemWhichParams: Codable, Sendable, Equatable {
|
||||
public var bins: [String]
|
||||
|
||||
public init(bins: [String]) {
|
||||
@@ -65,19 +65,19 @@ public struct ClawdbotSystemWhichParams: Codable, Sendable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdbotSystemNotifyParams: Codable, Sendable, Equatable {
|
||||
public struct MoltbotSystemNotifyParams: Codable, Sendable, Equatable {
|
||||
public var title: String
|
||||
public var body: String
|
||||
public var sound: String?
|
||||
public var priority: ClawdbotNotificationPriority?
|
||||
public var delivery: ClawdbotNotificationDelivery?
|
||||
public var priority: MoltbotNotificationPriority?
|
||||
public var delivery: MoltbotNotificationDelivery?
|
||||
|
||||
public init(
|
||||
title: String,
|
||||
body: String,
|
||||
sound: String? = nil,
|
||||
priority: ClawdbotNotificationPriority? = nil,
|
||||
delivery: ClawdbotNotificationDelivery? = nil)
|
||||
priority: MoltbotNotificationPriority? = nil,
|
||||
delivery: MoltbotNotificationDelivery? = nil)
|
||||
{
|
||||
self.title = title
|
||||
self.body = body
|
||||
|
||||
@@ -90,7 +90,7 @@ public enum ToolDisplayRegistry {
|
||||
}
|
||||
|
||||
private static func loadConfig() -> ToolDisplayConfig {
|
||||
guard let url = ClawdbotKitResources.bundle.url(forResource: "tool-display", withExtension: "json") else {
|
||||
guard let url = MoltbotKitResources.bundle.url(forResource: "tool-display", withExtension: "json") else {
|
||||
return self.defaultConfig()
|
||||
}
|
||||
do {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Testing
|
||||
@testable import ClawdbotChatUI
|
||||
@testable import MoltbotChatUI
|
||||
|
||||
@Suite struct AssistantTextParserTests {
|
||||
@Test func splitsThinkAndFinalSegments() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotKit
|
||||
import MoltbotKit
|
||||
import Testing
|
||||
|
||||
@Suite struct BonjourEscapesTests {
|
||||
@@ -8,7 +8,7 @@ import Testing
|
||||
}
|
||||
|
||||
@Test func decodeSpaces() {
|
||||
#expect(BonjourEscapes.decode("Clawdbot\\032Gateway") == "Clawdbot Gateway")
|
||||
#expect(BonjourEscapes.decode("Moltbot\\032Gateway") == "Moltbot Gateway")
|
||||
}
|
||||
|
||||
@Test func decodeMultipleEscapes() {
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
import ClawdbotKit
|
||||
import MoltbotKit
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@Suite struct CanvasA2UIActionTests {
|
||||
@Test func sanitizeTagValueIsStable() {
|
||||
#expect(ClawdbotCanvasA2UIAction.sanitizeTagValue("Hello World!") == "Hello_World_")
|
||||
#expect(ClawdbotCanvasA2UIAction.sanitizeTagValue(" ") == "-")
|
||||
#expect(ClawdbotCanvasA2UIAction.sanitizeTagValue("macOS 26.2") == "macOS_26.2")
|
||||
#expect(MoltbotCanvasA2UIAction.sanitizeTagValue("Hello World!") == "Hello_World_")
|
||||
#expect(MoltbotCanvasA2UIAction.sanitizeTagValue(" ") == "-")
|
||||
#expect(MoltbotCanvasA2UIAction.sanitizeTagValue("macOS 26.2") == "macOS_26.2")
|
||||
}
|
||||
|
||||
@Test func extractActionNameAcceptsNameOrAction() {
|
||||
#expect(ClawdbotCanvasA2UIAction.extractActionName(["name": "Hello"]) == "Hello")
|
||||
#expect(ClawdbotCanvasA2UIAction.extractActionName(["action": "Wave"]) == "Wave")
|
||||
#expect(ClawdbotCanvasA2UIAction.extractActionName(["name": " ", "action": "Fallback"]) == "Fallback")
|
||||
#expect(ClawdbotCanvasA2UIAction.extractActionName(["action": " "]) == nil)
|
||||
#expect(MoltbotCanvasA2UIAction.extractActionName(["name": "Hello"]) == "Hello")
|
||||
#expect(MoltbotCanvasA2UIAction.extractActionName(["action": "Wave"]) == "Wave")
|
||||
#expect(MoltbotCanvasA2UIAction.extractActionName(["name": " ", "action": "Fallback"]) == "Fallback")
|
||||
#expect(MoltbotCanvasA2UIAction.extractActionName(["action": " "]) == nil)
|
||||
}
|
||||
|
||||
@Test func formatAgentMessageIsTokenEfficientAndUnambiguous() {
|
||||
let messageContext = ClawdbotCanvasA2UIAction.AgentMessageContext(
|
||||
let messageContext = MoltbotCanvasA2UIAction.AgentMessageContext(
|
||||
actionName: "Get Weather",
|
||||
session: .init(key: "main", surfaceId: "main"),
|
||||
component: .init(id: "btnWeather", host: "Peter’s iPad", instanceId: "ipad16,6"),
|
||||
contextJSON: "{\"city\":\"Vienna\"}")
|
||||
let msg = ClawdbotCanvasA2UIAction.formatAgentMessage(messageContext)
|
||||
let msg = MoltbotCanvasA2UIAction.formatAgentMessage(messageContext)
|
||||
|
||||
#expect(msg.contains("CANVAS_A2UI "))
|
||||
#expect(msg.contains("action=Get_Weather"))
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import ClawdbotKit
|
||||
import MoltbotKit
|
||||
import Testing
|
||||
|
||||
@Suite struct CanvasA2UITests {
|
||||
@Test func commandStringsAreStable() {
|
||||
#expect(ClawdbotCanvasA2UICommand.push.rawValue == "canvas.a2ui.push")
|
||||
#expect(ClawdbotCanvasA2UICommand.pushJSONL.rawValue == "canvas.a2ui.pushJSONL")
|
||||
#expect(ClawdbotCanvasA2UICommand.reset.rawValue == "canvas.a2ui.reset")
|
||||
#expect(MoltbotCanvasA2UICommand.push.rawValue == "canvas.a2ui.push")
|
||||
#expect(MoltbotCanvasA2UICommand.pushJSONL.rawValue == "canvas.a2ui.pushJSONL")
|
||||
#expect(MoltbotCanvasA2UICommand.reset.rawValue == "canvas.a2ui.reset")
|
||||
}
|
||||
|
||||
@Test func jsonlDecodesAndValidatesV0_8() throws {
|
||||
@@ -16,7 +16,7 @@ import Testing
|
||||
{"deleteSurface":{"surfaceId":"main"}}
|
||||
"""
|
||||
|
||||
let messages = try ClawdbotCanvasA2UIJSONL.decodeMessagesFromJSONL(jsonl)
|
||||
let messages = try MoltbotCanvasA2UIJSONL.decodeMessagesFromJSONL(jsonl)
|
||||
#expect(messages.count == 4)
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import Testing
|
||||
"""
|
||||
|
||||
#expect(throws: Error.self) {
|
||||
_ = try ClawdbotCanvasA2UIJSONL.decodeMessagesFromJSONL(jsonl)
|
||||
_ = try MoltbotCanvasA2UIJSONL.decodeMessagesFromJSONL(jsonl)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ import Testing
|
||||
"""
|
||||
|
||||
#expect(throws: Error.self) {
|
||||
_ = try ClawdbotCanvasA2UIJSONL.decodeMessagesFromJSONL(jsonl)
|
||||
_ = try MoltbotCanvasA2UIJSONL.decodeMessagesFromJSONL(jsonl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import ClawdbotKit
|
||||
import MoltbotKit
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@Suite struct CanvasSnapshotFormatTests {
|
||||
@Test func acceptsJpgAlias() throws {
|
||||
struct Wrapper: Codable {
|
||||
var format: ClawdbotCanvasSnapshotFormat
|
||||
var format: MoltbotCanvasSnapshotFormat
|
||||
}
|
||||
|
||||
let data = try #require("{\"format\":\"jpg\"}".data(using: .utf8))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Testing
|
||||
@testable import ClawdbotChatUI
|
||||
@testable import MoltbotChatUI
|
||||
|
||||
@Suite("ChatMarkdownPreprocessor")
|
||||
struct ChatMarkdownPreprocessorTests {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
import Testing
|
||||
@testable import ClawdbotChatUI
|
||||
@testable import MoltbotChatUI
|
||||
|
||||
#if os(macOS)
|
||||
import AppKit
|
||||
@@ -19,8 +19,8 @@ private func luminance(_ color: NSColor) throws -> CGFloat {
|
||||
let lightAppearance = try #require(NSAppearance(named: .aqua))
|
||||
let darkAppearance = try #require(NSAppearance(named: .darkAqua))
|
||||
|
||||
let lightResolved = ClawdbotChatTheme.resolvedAssistantBubbleColor(for: lightAppearance)
|
||||
let darkResolved = ClawdbotChatTheme.resolvedAssistantBubbleColor(for: darkAppearance)
|
||||
let lightResolved = MoltbotChatTheme.resolvedAssistantBubbleColor(for: lightAppearance)
|
||||
let darkResolved = MoltbotChatTheme.resolvedAssistantBubbleColor(for: darkAppearance)
|
||||
#expect(try luminance(lightResolved) > luminance(darkResolved))
|
||||
#else
|
||||
#expect(Bool(true))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import ClawdbotKit
|
||||
import MoltbotKit
|
||||
import Foundation
|
||||
import Testing
|
||||
@testable import ClawdbotChatUI
|
||||
@testable import MoltbotChatUI
|
||||
|
||||
private struct TimeoutError: Error, CustomStringConvertible {
|
||||
let label: String
|
||||
@@ -31,40 +31,40 @@ private actor TestChatTransportState {
|
||||
var abortedRunIds: [String] = []
|
||||
}
|
||||
|
||||
private final class TestChatTransport: @unchecked Sendable, ClawdbotChatTransport {
|
||||
private final class TestChatTransport: @unchecked Sendable, MoltbotChatTransport {
|
||||
private let state = TestChatTransportState()
|
||||
private let historyResponses: [ClawdbotChatHistoryPayload]
|
||||
private let sessionsResponses: [ClawdbotChatSessionsListResponse]
|
||||
private let historyResponses: [MoltbotChatHistoryPayload]
|
||||
private let sessionsResponses: [MoltbotChatSessionsListResponse]
|
||||
|
||||
private let stream: AsyncStream<ClawdbotChatTransportEvent>
|
||||
private let continuation: AsyncStream<ClawdbotChatTransportEvent>.Continuation
|
||||
private let stream: AsyncStream<MoltbotChatTransportEvent>
|
||||
private let continuation: AsyncStream<MoltbotChatTransportEvent>.Continuation
|
||||
|
||||
init(
|
||||
historyResponses: [ClawdbotChatHistoryPayload],
|
||||
sessionsResponses: [ClawdbotChatSessionsListResponse] = [])
|
||||
historyResponses: [MoltbotChatHistoryPayload],
|
||||
sessionsResponses: [MoltbotChatSessionsListResponse] = [])
|
||||
{
|
||||
self.historyResponses = historyResponses
|
||||
self.sessionsResponses = sessionsResponses
|
||||
var cont: AsyncStream<ClawdbotChatTransportEvent>.Continuation!
|
||||
var cont: AsyncStream<MoltbotChatTransportEvent>.Continuation!
|
||||
self.stream = AsyncStream { c in
|
||||
cont = c
|
||||
}
|
||||
self.continuation = cont
|
||||
}
|
||||
|
||||
func events() -> AsyncStream<ClawdbotChatTransportEvent> {
|
||||
func events() -> AsyncStream<MoltbotChatTransportEvent> {
|
||||
self.stream
|
||||
}
|
||||
|
||||
func setActiveSessionKey(_: String) async throws {}
|
||||
|
||||
func requestHistory(sessionKey: String) async throws -> ClawdbotChatHistoryPayload {
|
||||
func requestHistory(sessionKey: String) async throws -> MoltbotChatHistoryPayload {
|
||||
let idx = await self.state.historyCallCount
|
||||
await self.state.setHistoryCallCount(idx + 1)
|
||||
if idx < self.historyResponses.count {
|
||||
return self.historyResponses[idx]
|
||||
}
|
||||
return self.historyResponses.last ?? ClawdbotChatHistoryPayload(
|
||||
return self.historyResponses.last ?? MoltbotChatHistoryPayload(
|
||||
sessionKey: sessionKey,
|
||||
sessionId: nil,
|
||||
messages: [],
|
||||
@@ -76,23 +76,23 @@ private final class TestChatTransport: @unchecked Sendable, ClawdbotChatTranspor
|
||||
message _: String,
|
||||
thinking _: String,
|
||||
idempotencyKey: String,
|
||||
attachments _: [ClawdbotChatAttachmentPayload]) async throws -> ClawdbotChatSendResponse
|
||||
attachments _: [MoltbotChatAttachmentPayload]) async throws -> MoltbotChatSendResponse
|
||||
{
|
||||
await self.state.sentRunIdsAppend(idempotencyKey)
|
||||
return ClawdbotChatSendResponse(runId: idempotencyKey, status: "ok")
|
||||
return MoltbotChatSendResponse(runId: idempotencyKey, status: "ok")
|
||||
}
|
||||
|
||||
func abortRun(sessionKey _: String, runId: String) async throws {
|
||||
await self.state.abortedRunIdsAppend(runId)
|
||||
}
|
||||
|
||||
func listSessions(limit _: Int?) async throws -> ClawdbotChatSessionsListResponse {
|
||||
func listSessions(limit _: Int?) async throws -> MoltbotChatSessionsListResponse {
|
||||
let idx = await self.state.sessionsCallCount
|
||||
await self.state.setSessionsCallCount(idx + 1)
|
||||
if idx < self.sessionsResponses.count {
|
||||
return self.sessionsResponses[idx]
|
||||
}
|
||||
return self.sessionsResponses.last ?? ClawdbotChatSessionsListResponse(
|
||||
return self.sessionsResponses.last ?? MoltbotChatSessionsListResponse(
|
||||
ts: nil,
|
||||
path: nil,
|
||||
count: 0,
|
||||
@@ -104,7 +104,7 @@ private final class TestChatTransport: @unchecked Sendable, ClawdbotChatTranspor
|
||||
true
|
||||
}
|
||||
|
||||
func emit(_ evt: ClawdbotChatTransportEvent) {
|
||||
func emit(_ evt: MoltbotChatTransportEvent) {
|
||||
self.continuation.yield(evt)
|
||||
}
|
||||
|
||||
@@ -139,12 +139,12 @@ extension TestChatTransportState {
|
||||
@Suite struct ChatViewModelTests {
|
||||
@Test func streamsAssistantAndClearsOnFinal() async throws {
|
||||
let sessionId = "sess-main"
|
||||
let history1 = ClawdbotChatHistoryPayload(
|
||||
let history1 = MoltbotChatHistoryPayload(
|
||||
sessionKey: "main",
|
||||
sessionId: sessionId,
|
||||
messages: [],
|
||||
thinkingLevel: "off")
|
||||
let history2 = ClawdbotChatHistoryPayload(
|
||||
let history2 = MoltbotChatHistoryPayload(
|
||||
sessionKey: "main",
|
||||
sessionId: sessionId,
|
||||
messages: [
|
||||
@@ -157,7 +157,7 @@ extension TestChatTransportState {
|
||||
thinkingLevel: "off")
|
||||
|
||||
let transport = TestChatTransport(historyResponses: [history1, history2])
|
||||
let vm = await MainActor.run { ClawdbotChatViewModel(sessionKey: "main", transport: transport) }
|
||||
let vm = await MainActor.run { MoltbotChatViewModel(sessionKey: "main", transport: transport) }
|
||||
|
||||
await MainActor.run { vm.load() }
|
||||
try await waitUntil("bootstrap") { await MainActor.run { vm.healthOK && vm.sessionId == sessionId } }
|
||||
@@ -170,7 +170,7 @@ extension TestChatTransportState {
|
||||
|
||||
transport.emit(
|
||||
.agent(
|
||||
ClawdbotAgentEventPayload(
|
||||
MoltbotAgentEventPayload(
|
||||
runId: sessionId,
|
||||
seq: 1,
|
||||
stream: "assistant",
|
||||
@@ -183,7 +183,7 @@ extension TestChatTransportState {
|
||||
|
||||
transport.emit(
|
||||
.agent(
|
||||
ClawdbotAgentEventPayload(
|
||||
MoltbotAgentEventPayload(
|
||||
runId: sessionId,
|
||||
seq: 2,
|
||||
stream: "tool",
|
||||
@@ -200,7 +200,7 @@ extension TestChatTransportState {
|
||||
let runId = try #require(await transport.lastSentRunId())
|
||||
transport.emit(
|
||||
.chat(
|
||||
ClawdbotChatEventPayload(
|
||||
MoltbotChatEventPayload(
|
||||
runId: runId,
|
||||
sessionKey: "main",
|
||||
state: "final",
|
||||
@@ -217,20 +217,20 @@ extension TestChatTransportState {
|
||||
|
||||
@Test func clearsStreamingOnExternalFinalEvent() async throws {
|
||||
let sessionId = "sess-main"
|
||||
let history = ClawdbotChatHistoryPayload(
|
||||
let history = MoltbotChatHistoryPayload(
|
||||
sessionKey: "main",
|
||||
sessionId: sessionId,
|
||||
messages: [],
|
||||
thinkingLevel: "off")
|
||||
let transport = TestChatTransport(historyResponses: [history, history])
|
||||
let vm = await MainActor.run { ClawdbotChatViewModel(sessionKey: "main", transport: transport) }
|
||||
let vm = await MainActor.run { MoltbotChatViewModel(sessionKey: "main", transport: transport) }
|
||||
|
||||
await MainActor.run { vm.load() }
|
||||
try await waitUntil("bootstrap") { await MainActor.run { vm.healthOK && vm.sessionId == sessionId } }
|
||||
|
||||
transport.emit(
|
||||
.agent(
|
||||
ClawdbotAgentEventPayload(
|
||||
MoltbotAgentEventPayload(
|
||||
runId: sessionId,
|
||||
seq: 1,
|
||||
stream: "assistant",
|
||||
@@ -239,7 +239,7 @@ extension TestChatTransportState {
|
||||
|
||||
transport.emit(
|
||||
.agent(
|
||||
ClawdbotAgentEventPayload(
|
||||
MoltbotAgentEventPayload(
|
||||
runId: sessionId,
|
||||
seq: 2,
|
||||
stream: "tool",
|
||||
@@ -258,7 +258,7 @@ extension TestChatTransportState {
|
||||
|
||||
transport.emit(
|
||||
.chat(
|
||||
ClawdbotChatEventPayload(
|
||||
MoltbotChatEventPayload(
|
||||
runId: "other-run",
|
||||
sessionKey: "main",
|
||||
state: "final",
|
||||
@@ -274,18 +274,18 @@ extension TestChatTransportState {
|
||||
let recent = now - (2 * 60 * 60 * 1000)
|
||||
let recentOlder = now - (5 * 60 * 60 * 1000)
|
||||
let stale = now - (26 * 60 * 60 * 1000)
|
||||
let history = ClawdbotChatHistoryPayload(
|
||||
let history = MoltbotChatHistoryPayload(
|
||||
sessionKey: "main",
|
||||
sessionId: "sess-main",
|
||||
messages: [],
|
||||
thinkingLevel: "off")
|
||||
let sessions = ClawdbotChatSessionsListResponse(
|
||||
let sessions = MoltbotChatSessionsListResponse(
|
||||
ts: now,
|
||||
path: nil,
|
||||
count: 4,
|
||||
defaults: nil,
|
||||
sessions: [
|
||||
ClawdbotChatSessionEntry(
|
||||
MoltbotChatSessionEntry(
|
||||
key: "recent-1",
|
||||
kind: nil,
|
||||
displayName: nil,
|
||||
@@ -304,7 +304,7 @@ extension TestChatTransportState {
|
||||
totalTokens: nil,
|
||||
model: nil,
|
||||
contextTokens: nil),
|
||||
ClawdbotChatSessionEntry(
|
||||
MoltbotChatSessionEntry(
|
||||
key: "main",
|
||||
kind: nil,
|
||||
displayName: nil,
|
||||
@@ -323,7 +323,7 @@ extension TestChatTransportState {
|
||||
totalTokens: nil,
|
||||
model: nil,
|
||||
contextTokens: nil),
|
||||
ClawdbotChatSessionEntry(
|
||||
MoltbotChatSessionEntry(
|
||||
key: "recent-2",
|
||||
kind: nil,
|
||||
displayName: nil,
|
||||
@@ -342,7 +342,7 @@ extension TestChatTransportState {
|
||||
totalTokens: nil,
|
||||
model: nil,
|
||||
contextTokens: nil),
|
||||
ClawdbotChatSessionEntry(
|
||||
MoltbotChatSessionEntry(
|
||||
key: "old-1",
|
||||
kind: nil,
|
||||
displayName: nil,
|
||||
@@ -366,7 +366,7 @@ extension TestChatTransportState {
|
||||
let transport = TestChatTransport(
|
||||
historyResponses: [history],
|
||||
sessionsResponses: [sessions])
|
||||
let vm = await MainActor.run { ClawdbotChatViewModel(sessionKey: "main", transport: transport) }
|
||||
let vm = await MainActor.run { MoltbotChatViewModel(sessionKey: "main", transport: transport) }
|
||||
await MainActor.run { vm.load() }
|
||||
try await waitUntil("sessions loaded") { await MainActor.run { !vm.sessions.isEmpty } }
|
||||
|
||||
@@ -377,18 +377,18 @@ extension TestChatTransportState {
|
||||
@Test func sessionChoicesIncludeCurrentWhenMissing() async throws {
|
||||
let now = Date().timeIntervalSince1970 * 1000
|
||||
let recent = now - (30 * 60 * 1000)
|
||||
let history = ClawdbotChatHistoryPayload(
|
||||
let history = MoltbotChatHistoryPayload(
|
||||
sessionKey: "custom",
|
||||
sessionId: "sess-custom",
|
||||
messages: [],
|
||||
thinkingLevel: "off")
|
||||
let sessions = ClawdbotChatSessionsListResponse(
|
||||
let sessions = MoltbotChatSessionsListResponse(
|
||||
ts: now,
|
||||
path: nil,
|
||||
count: 1,
|
||||
defaults: nil,
|
||||
sessions: [
|
||||
ClawdbotChatSessionEntry(
|
||||
MoltbotChatSessionEntry(
|
||||
key: "main",
|
||||
kind: nil,
|
||||
displayName: nil,
|
||||
@@ -412,7 +412,7 @@ extension TestChatTransportState {
|
||||
let transport = TestChatTransport(
|
||||
historyResponses: [history],
|
||||
sessionsResponses: [sessions])
|
||||
let vm = await MainActor.run { ClawdbotChatViewModel(sessionKey: "custom", transport: transport) }
|
||||
let vm = await MainActor.run { MoltbotChatViewModel(sessionKey: "custom", transport: transport) }
|
||||
await MainActor.run { vm.load() }
|
||||
try await waitUntil("sessions loaded") { await MainActor.run { !vm.sessions.isEmpty } }
|
||||
|
||||
@@ -422,20 +422,20 @@ extension TestChatTransportState {
|
||||
|
||||
@Test func clearsStreamingOnExternalErrorEvent() async throws {
|
||||
let sessionId = "sess-main"
|
||||
let history = ClawdbotChatHistoryPayload(
|
||||
let history = MoltbotChatHistoryPayload(
|
||||
sessionKey: "main",
|
||||
sessionId: sessionId,
|
||||
messages: [],
|
||||
thinkingLevel: "off")
|
||||
let transport = TestChatTransport(historyResponses: [history, history])
|
||||
let vm = await MainActor.run { ClawdbotChatViewModel(sessionKey: "main", transport: transport) }
|
||||
let vm = await MainActor.run { MoltbotChatViewModel(sessionKey: "main", transport: transport) }
|
||||
|
||||
await MainActor.run { vm.load() }
|
||||
try await waitUntil("bootstrap") { await MainActor.run { vm.healthOK && vm.sessionId == sessionId } }
|
||||
|
||||
transport.emit(
|
||||
.agent(
|
||||
ClawdbotAgentEventPayload(
|
||||
MoltbotAgentEventPayload(
|
||||
runId: sessionId,
|
||||
seq: 1,
|
||||
stream: "assistant",
|
||||
@@ -448,7 +448,7 @@ extension TestChatTransportState {
|
||||
|
||||
transport.emit(
|
||||
.chat(
|
||||
ClawdbotChatEventPayload(
|
||||
MoltbotChatEventPayload(
|
||||
runId: "other-run",
|
||||
sessionKey: "main",
|
||||
state: "error",
|
||||
@@ -460,13 +460,13 @@ extension TestChatTransportState {
|
||||
|
||||
@Test func abortRequestsDoNotClearPendingUntilAbortedEvent() async throws {
|
||||
let sessionId = "sess-main"
|
||||
let history = ClawdbotChatHistoryPayload(
|
||||
let history = MoltbotChatHistoryPayload(
|
||||
sessionKey: "main",
|
||||
sessionId: sessionId,
|
||||
messages: [],
|
||||
thinkingLevel: "off")
|
||||
let transport = TestChatTransport(historyResponses: [history, history])
|
||||
let vm = await MainActor.run { ClawdbotChatViewModel(sessionKey: "main", transport: transport) }
|
||||
let vm = await MainActor.run { MoltbotChatViewModel(sessionKey: "main", transport: transport) }
|
||||
|
||||
await MainActor.run { vm.load() }
|
||||
try await waitUntil("bootstrap") { await MainActor.run { vm.healthOK && vm.sessionId == sessionId } }
|
||||
@@ -490,7 +490,7 @@ extension TestChatTransportState {
|
||||
|
||||
transport.emit(
|
||||
.chat(
|
||||
ClawdbotChatEventPayload(
|
||||
MoltbotChatEventPayload(
|
||||
runId: runId,
|
||||
sessionKey: "main",
|
||||
state: "aborted",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import XCTest
|
||||
@testable import ClawdbotKit
|
||||
@testable import MoltbotKit
|
||||
|
||||
final class ElevenLabsTTSValidationTests: XCTestCase {
|
||||
func testValidatedOutputFormatAllowsOnlyMp3Presets() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Foundation
|
||||
import Testing
|
||||
@testable import ClawdbotKit
|
||||
import ClawdbotProtocol
|
||||
@testable import MoltbotKit
|
||||
import MoltbotProtocol
|
||||
|
||||
struct GatewayNodeSessionTests {
|
||||
@Test
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdbotKit
|
||||
import MoltbotKit
|
||||
import CoreGraphics
|
||||
import ImageIO
|
||||
import Testing
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import XCTest
|
||||
@testable import ClawdbotKit
|
||||
@testable import MoltbotKit
|
||||
|
||||
final class TalkDirectiveTests: XCTestCase {
|
||||
func testParsesDirectiveAndStripsLine() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import XCTest
|
||||
@testable import ClawdbotKit
|
||||
@testable import MoltbotKit
|
||||
|
||||
final class TalkHistoryTimestampTests: XCTestCase {
|
||||
func testSecondsTimestampsAreAcceptedWithSmallTolerance() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import XCTest
|
||||
@testable import ClawdbotKit
|
||||
@testable import MoltbotKit
|
||||
|
||||
final class TalkPromptBuilderTests: XCTestCase {
|
||||
func testBuildIncludesTranscript() {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import ClawdbotKit
|
||||
import MoltbotKit
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@Suite struct ToolDisplayRegistryTests {
|
||||
@Test func loadsToolDisplayConfigFromBundle() {
|
||||
let url = ClawdbotKitResources.bundle.url(forResource: "tool-display", withExtension: "json")
|
||||
let url = MoltbotKitResources.bundle.url(forResource: "tool-display", withExtension: "json")
|
||||
#expect(url != nil)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { ContextProvider } from "@lit/context";
|
||||
|
||||
import { v0_8 } from "@a2ui/lit";
|
||||
import "@a2ui/lit/ui";
|
||||
import { themeContext } from "@clawdbot/a2ui-theme-context";
|
||||
import { themeContext } from "@moltbot/a2ui-theme-context";
|
||||
|
||||
const modalStyles = css`
|
||||
dialog {
|
||||
@@ -42,7 +42,7 @@ const buttonShadow = isAndroid ? "0 2px 10px rgba(6, 182, 212, 0.14)" : "0 10px
|
||||
const statusShadow = isAndroid ? "0 2px 10px rgba(0, 0, 0, 0.18)" : "0 10px 24px rgba(0, 0, 0, 0.25)";
|
||||
const statusBlur = isAndroid ? "10px" : "14px";
|
||||
|
||||
const clawdbotTheme = {
|
||||
const moltbotTheme = {
|
||||
components: {
|
||||
AudioPlayer: emptyClasses(),
|
||||
Button: emptyClasses(),
|
||||
@@ -152,7 +152,7 @@ const clawdbotTheme = {
|
||||
},
|
||||
};
|
||||
|
||||
class ClawdbotA2UIHost extends LitElement {
|
||||
class MoltbotA2UIHost extends LitElement {
|
||||
static properties = {
|
||||
surfaces: { state: true },
|
||||
pendingAction: { state: true },
|
||||
@@ -162,7 +162,7 @@ class ClawdbotA2UIHost extends LitElement {
|
||||
#processor = v0_8.Data.createSignalA2uiMessageProcessor();
|
||||
#themeProvider = new ContextProvider(this, {
|
||||
context: themeContext,
|
||||
initialValue: clawdbotTheme,
|
||||
initialValue: moltbotTheme,
|
||||
});
|
||||
|
||||
surfaces = [];
|
||||
@@ -177,10 +177,10 @@ class ClawdbotA2UIHost extends LitElement {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
padding:
|
||||
var(--clawdbot-a2ui-inset-top, 0px)
|
||||
var(--clawdbot-a2ui-inset-right, 0px)
|
||||
var(--clawdbot-a2ui-inset-bottom, 0px)
|
||||
var(--clawdbot-a2ui-inset-left, 0px);
|
||||
var(--moltbot-a2ui-inset-top, 0px)
|
||||
var(--moltbot-a2ui-inset-right, 0px)
|
||||
var(--moltbot-a2ui-inset-bottom, 0px)
|
||||
var(--moltbot-a2ui-inset-left, 0px);
|
||||
}
|
||||
|
||||
#surfaces {
|
||||
@@ -189,14 +189,14 @@ class ClawdbotA2UIHost extends LitElement {
|
||||
gap: 12px;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
padding-bottom: var(--clawdbot-a2ui-scroll-pad-bottom, 0px);
|
||||
padding-bottom: var(--moltbot-a2ui-scroll-pad-bottom, 0px);
|
||||
}
|
||||
|
||||
.status {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
top: var(--clawdbot-a2ui-status-top, 12px);
|
||||
top: var(--moltbot-a2ui-status-top, 12px);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
@@ -217,7 +217,7 @@ class ClawdbotA2UIHost extends LitElement {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: var(--clawdbot-a2ui-toast-bottom, 12px);
|
||||
bottom: var(--moltbot-a2ui-toast-bottom, 12px);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
@@ -243,7 +243,7 @@ class ClawdbotA2UIHost extends LitElement {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
top: var(--clawdbot-a2ui-empty-top, var(--clawdbot-a2ui-status-top, 12px));
|
||||
top: var(--moltbot-a2ui-empty-top, var(--moltbot-a2ui-status-top, 12px));
|
||||
text-align: center;
|
||||
opacity: 0.8;
|
||||
padding: 10px 12px;
|
||||
@@ -276,21 +276,23 @@ class ClawdbotA2UIHost extends LitElement {
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
globalThis.clawdbotA2UI = {
|
||||
const api = {
|
||||
applyMessages: (messages) => this.applyMessages(messages),
|
||||
reset: () => this.reset(),
|
||||
getSurfaces: () => Array.from(this.#processor.getSurfaces().keys()),
|
||||
};
|
||||
globalThis.moltbotA2UI = api;
|
||||
globalThis.clawdbotA2UI = api;
|
||||
this.addEventListener("a2uiaction", (evt) => this.#handleA2UIAction(evt));
|
||||
this.#statusListener = (evt) => this.#handleActionStatus(evt);
|
||||
globalThis.addEventListener("clawdbot:a2ui-action-status", this.#statusListener);
|
||||
globalThis.addEventListener("moltbot:a2ui-action-status", this.#statusListener);
|
||||
this.#syncSurfaces();
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
if (this.#statusListener) {
|
||||
globalThis.removeEventListener("clawdbot:a2ui-action-status", this.#statusListener);
|
||||
globalThis.removeEventListener("moltbot:a2ui-action-status", this.#statusListener);
|
||||
this.#statusListener = null;
|
||||
}
|
||||
}
|
||||
@@ -393,15 +395,20 @@ class ClawdbotA2UIHost extends LitElement {
|
||||
...(Object.keys(context).length ? { context } : {}),
|
||||
};
|
||||
|
||||
globalThis.__clawdbotLastA2UIAction = userAction;
|
||||
globalThis.__moltbotLastA2UIAction = userAction;
|
||||
|
||||
const handler =
|
||||
globalThis.webkit?.messageHandlers?.moltbotCanvasA2UIAction ??
|
||||
globalThis.webkit?.messageHandlers?.clawdbotCanvasA2UIAction ??
|
||||
globalThis.moltbotCanvasA2UIAction ??
|
||||
globalThis.clawdbotCanvasA2UIAction;
|
||||
if (handler?.postMessage) {
|
||||
try {
|
||||
// WebKit message handlers support structured objects; Android's JS interface expects strings.
|
||||
if (handler === globalThis.clawdbotCanvasA2UIAction) {
|
||||
if (
|
||||
handler === globalThis.moltbotCanvasA2UIAction ||
|
||||
handler === globalThis.clawdbotCanvasA2UIAction
|
||||
) {
|
||||
handler.postMessage(JSON.stringify({ userAction }));
|
||||
} else {
|
||||
handler.postMessage({ userAction });
|
||||
@@ -481,4 +488,4 @@ class ClawdbotA2UIHost extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("clawdbot-a2ui-host", ClawdbotA2UIHost);
|
||||
customElements.define("moltbot-a2ui-host", MoltbotA2UIHost);
|
||||
|
||||
@@ -27,7 +27,7 @@ export default defineConfig({
|
||||
alias: {
|
||||
"@a2ui/lit": path.resolve(a2uiLitDist, "index.js"),
|
||||
"@a2ui/lit/ui": path.resolve(a2uiLitDist, "0.8/ui/ui.js"),
|
||||
"@clawdbot/a2ui-theme-context": a2uiThemeContext,
|
||||
"@moltbot/a2ui-theme-context": a2uiThemeContext,
|
||||
"@lit/context": path.resolve(repoRoot, "node_modules/@lit/context/index.js"),
|
||||
"@lit/context/": path.resolve(repoRoot, "node_modules/@lit/context/"),
|
||||
"@lit-labs/signals": path.resolve(repoRoot, "node_modules/@lit-labs/signals/index.js"),
|
||||
|
||||
Reference in New Issue
Block a user