mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-18 18:37:26 +00:00
chore: rename project to clawdbot
This commit is contained in:
@@ -3,21 +3,21 @@
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "ClawdisKit",
|
||||
name: "ClawdbotKit",
|
||||
platforms: [
|
||||
.iOS(.v17),
|
||||
.macOS(.v15),
|
||||
],
|
||||
products: [
|
||||
.library(name: "ClawdisKit", targets: ["ClawdisKit"]),
|
||||
.library(name: "ClawdisChatUI", targets: ["ClawdisChatUI"]),
|
||||
.library(name: "ClawdbotKit", targets: ["ClawdbotKit"]),
|
||||
.library(name: "ClawdbotChatUI", targets: ["ClawdbotChatUI"]),
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/steipete/ElevenLabsKit", exact: "0.1.0"),
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "ClawdisKit",
|
||||
name: "ClawdbotKit",
|
||||
dependencies: [
|
||||
.product(name: "ElevenLabsKit", package: "ElevenLabsKit"),
|
||||
],
|
||||
@@ -28,14 +28,14 @@ let package = Package(
|
||||
.enableUpcomingFeature("StrictConcurrency"),
|
||||
]),
|
||||
.target(
|
||||
name: "ClawdisChatUI",
|
||||
dependencies: ["ClawdisKit"],
|
||||
name: "ClawdbotChatUI",
|
||||
dependencies: ["ClawdbotKit"],
|
||||
swiftSettings: [
|
||||
.enableUpcomingFeature("StrictConcurrency"),
|
||||
]),
|
||||
.testTarget(
|
||||
name: "ClawdisKitTests",
|
||||
dependencies: ["ClawdisKit", "ClawdisChatUI"],
|
||||
name: "ClawdbotKitTests",
|
||||
dependencies: ["ClawdbotKit", "ClawdbotChatUI"],
|
||||
swiftSettings: [
|
||||
.enableUpcomingFeature("StrictConcurrency"),
|
||||
.enableExperimentalFeature("SwiftTesting"),
|
||||
@@ -8,9 +8,9 @@ import UniformTypeIdentifiers
|
||||
#endif
|
||||
|
||||
@MainActor
|
||||
struct ClawdisChatComposer: View {
|
||||
@Bindable var viewModel: ClawdisChatViewModel
|
||||
let style: ClawdisChatView.Style
|
||||
struct ClawdbotChatComposer: View {
|
||||
@Bindable var viewModel: ClawdbotChatViewModel
|
||||
let style: ClawdbotChatView.Style
|
||||
let showsSessionSwitcher: Bool
|
||||
|
||||
#if !os(macOS)
|
||||
@@ -54,21 +54,21 @@ struct ClawdisChatComposer: View {
|
||||
topTrailing: 0),
|
||||
style: .continuous)
|
||||
shape
|
||||
.fill(ClawdisChatTheme.composerBackground)
|
||||
.overlay(shape.strokeBorder(ClawdisChatTheme.composerBorder, lineWidth: 1))
|
||||
.fill(ClawdbotChatTheme.composerBackground)
|
||||
.overlay(shape.strokeBorder(ClawdbotChatTheme.composerBorder, lineWidth: 1))
|
||||
.shadow(color: .black.opacity(0.12), radius: 12, y: 6)
|
||||
} else {
|
||||
let shape = RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)
|
||||
shape
|
||||
.fill(ClawdisChatTheme.composerBackground)
|
||||
.overlay(shape.strokeBorder(ClawdisChatTheme.composerBorder, lineWidth: 1))
|
||||
.fill(ClawdbotChatTheme.composerBackground)
|
||||
.overlay(shape.strokeBorder(ClawdbotChatTheme.composerBorder, lineWidth: 1))
|
||||
.shadow(color: .black.opacity(0.12), radius: 12, y: 6)
|
||||
}
|
||||
#else
|
||||
let shape = RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)
|
||||
shape
|
||||
.fill(ClawdisChatTheme.composerBackground)
|
||||
.overlay(shape.strokeBorder(ClawdisChatTheme.composerBorder, lineWidth: 1))
|
||||
.fill(ClawdbotChatTheme.composerBackground)
|
||||
.overlay(shape.strokeBorder(ClawdbotChatTheme.composerBorder, lineWidth: 1))
|
||||
.shadow(color: .black.opacity(0.12), radius: 12, y: 6)
|
||||
#endif
|
||||
}
|
||||
@@ -144,11 +144,11 @@ struct ClawdisChatComposer: View {
|
||||
HStack(spacing: 6) {
|
||||
ForEach(
|
||||
self.viewModel.attachments,
|
||||
id: \ClawdisPendingAttachment.id)
|
||||
{ (att: ClawdisPendingAttachment) in
|
||||
id: \ClawdbotPendingAttachment.id)
|
||||
{ (att: ClawdbotPendingAttachment) in
|
||||
HStack(spacing: 6) {
|
||||
if let img = att.preview {
|
||||
ClawdisPlatformImageFactory.image(img)
|
||||
ClawdbotPlatformImageFactory.image(img)
|
||||
.resizable()
|
||||
.scaledToFill()
|
||||
.frame(width: 22, height: 22)
|
||||
@@ -181,7 +181,7 @@ struct ClawdisChatComposer: View {
|
||||
self.editorOverlay
|
||||
|
||||
Rectangle()
|
||||
.fill(ClawdisChatTheme.divider)
|
||||
.fill(ClawdbotChatTheme.divider)
|
||||
.frame(height: 1)
|
||||
.padding(.horizontal, 2)
|
||||
|
||||
@@ -197,10 +197,10 @@ struct ClawdisChatComposer: View {
|
||||
.padding(.vertical, 8)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
||||
.fill(ClawdisChatTheme.composerField)
|
||||
.fill(ClawdbotChatTheme.composerField)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
||||
.strokeBorder(ClawdisChatTheme.composerBorder)))
|
||||
.strokeBorder(ClawdbotChatTheme.composerBorder)))
|
||||
.padding(self.editorPadding)
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ struct ClawdisChatComposer: View {
|
||||
}
|
||||
.padding(.horizontal, 8)
|
||||
.padding(.vertical, 4)
|
||||
.background(ClawdisChatTheme.subtleCard)
|
||||
.background(ClawdbotChatTheme.subtleCard)
|
||||
.clipShape(Capsule())
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ enum ChatMarkdownSplitter {
|
||||
struct InlineImage: Identifiable {
|
||||
let id = UUID()
|
||||
let label: String
|
||||
let image: ClawdisPlatformImage?
|
||||
let image: ClawdbotPlatformImage?
|
||||
}
|
||||
|
||||
struct Block: Identifiable {
|
||||
@@ -93,11 +93,11 @@ enum ChatMarkdownSplitter {
|
||||
let label = ns.substring(with: match.range(at: 1))
|
||||
let dataURL = ns.substring(with: match.range(at: 2))
|
||||
|
||||
let image: ClawdisPlatformImage? = {
|
||||
let image: ClawdbotPlatformImage? = {
|
||||
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 ClawdisPlatformImage(data: data)
|
||||
return ClawdbotPlatformImage(data: data)
|
||||
}()
|
||||
images.append(InlineImage(label: label, image: image))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdisKit
|
||||
import ClawdbotKit
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
@@ -135,8 +135,8 @@ private struct ChatBubbleShape: InsettableShape {
|
||||
|
||||
@MainActor
|
||||
struct ChatMessageBubble: View {
|
||||
let message: ClawdisChatMessage
|
||||
let style: ClawdisChatView.Style
|
||||
let message: ClawdbotChatMessage
|
||||
let style: ClawdbotChatView.Style
|
||||
let userAccent: Color?
|
||||
|
||||
var body: some View {
|
||||
@@ -151,14 +151,14 @@ struct ChatMessageBubble: View {
|
||||
|
||||
@MainActor
|
||||
private struct ChatMessageBody: View {
|
||||
let message: ClawdisChatMessage
|
||||
let message: ClawdbotChatMessage
|
||||
let isUser: Bool
|
||||
let style: ClawdisChatView.Style
|
||||
let style: ClawdbotChatView.Style
|
||||
let userAccent: Color?
|
||||
|
||||
var body: some View {
|
||||
let text = self.primaryText
|
||||
let textColor = self.isUser ? ClawdisChatTheme.userText : ClawdisChatTheme.assistantText
|
||||
let textColor = self.isUser ? ClawdbotChatTheme.userText : ClawdbotChatTheme.assistantText
|
||||
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
if self.isToolResultMessage {
|
||||
@@ -185,7 +185,7 @@ private struct ChatMessageBody: View {
|
||||
id: \ChatMarkdownSplitter.InlineImage.id)
|
||||
{ (item: ChatMarkdownSplitter.InlineImage) in
|
||||
if let img = item.image {
|
||||
ClawdisPlatformImageFactory.image(img)
|
||||
ClawdbotPlatformImageFactory.image(img)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(maxHeight: 260)
|
||||
@@ -250,7 +250,7 @@ private struct ChatMessageBody: View {
|
||||
return parts.joined(separator: "\n").trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
}
|
||||
|
||||
private var inlineAttachments: [ClawdisChatMessageContent] {
|
||||
private var inlineAttachments: [ClawdbotChatMessageContent] {
|
||||
self.message.content.filter { content in
|
||||
switch content.type ?? "text" {
|
||||
case "file", "attachment":
|
||||
@@ -261,7 +261,7 @@ private struct ChatMessageBody: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var toolCalls: [ClawdisChatMessageContent] {
|
||||
private var toolCalls: [ClawdbotChatMessageContent] {
|
||||
self.message.content.filter { content in
|
||||
let kind = (content.type ?? "").lowercased()
|
||||
if ["toolcall", "tool_call", "tooluse", "tool_use"].contains(kind) {
|
||||
@@ -271,7 +271,7 @@ private struct ChatMessageBody: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var inlineToolResults: [ClawdisChatMessageContent] {
|
||||
private var inlineToolResults: [ClawdbotChatMessageContent] {
|
||||
self.message.content.filter { content in
|
||||
let kind = (content.type ?? "").lowercased()
|
||||
return kind == "toolresult" || kind == "tool_result"
|
||||
@@ -294,12 +294,12 @@ private struct ChatMessageBody: View {
|
||||
|
||||
private var bubbleFillColor: Color {
|
||||
if self.isUser {
|
||||
return self.userAccent ?? ClawdisChatTheme.userBubble
|
||||
return self.userAccent ?? ClawdbotChatTheme.userBubble
|
||||
}
|
||||
if self.style == .onboarding {
|
||||
return ClawdisChatTheme.onboardingAssistantBubble
|
||||
return ClawdbotChatTheme.onboardingAssistantBubble
|
||||
}
|
||||
return ClawdisChatTheme.assistantBubble
|
||||
return ClawdbotChatTheme.assistantBubble
|
||||
}
|
||||
|
||||
private var bubbleBackground: AnyShapeStyle {
|
||||
@@ -311,7 +311,7 @@ private struct ChatMessageBody: View {
|
||||
return Color.white.opacity(0.12)
|
||||
}
|
||||
if self.style == .onboarding {
|
||||
return ClawdisChatTheme.onboardingAssistantBorder
|
||||
return ClawdbotChatTheme.onboardingAssistantBorder
|
||||
}
|
||||
return Color.white.opacity(0.08)
|
||||
}
|
||||
@@ -357,7 +357,7 @@ private struct ChatMessageBody: View {
|
||||
}
|
||||
|
||||
private struct AttachmentRow: View {
|
||||
let att: ClawdisChatMessageContent
|
||||
let att: ClawdbotChatMessageContent
|
||||
let isUser: Bool
|
||||
|
||||
var body: some View {
|
||||
@@ -366,7 +366,7 @@ private struct AttachmentRow: View {
|
||||
Text(self.att.fileName ?? "Attachment")
|
||||
.font(.footnote)
|
||||
.lineLimit(1)
|
||||
.foregroundStyle(self.isUser ? ClawdisChatTheme.userText : ClawdisChatTheme.assistantText)
|
||||
.foregroundStyle(self.isUser ? ClawdbotChatTheme.userText : ClawdbotChatTheme.assistantText)
|
||||
Spacer()
|
||||
}
|
||||
.padding(10)
|
||||
@@ -376,7 +376,7 @@ private struct AttachmentRow: View {
|
||||
}
|
||||
|
||||
private struct ToolCallCard: View {
|
||||
let content: ClawdisChatMessageContent
|
||||
let content: ClawdbotChatMessageContent
|
||||
let isUser: Bool
|
||||
|
||||
var body: some View {
|
||||
@@ -397,7 +397,7 @@ private struct ToolCallCard: View {
|
||||
.padding(10)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
||||
.fill(ClawdisChatTheme.subtleCard)
|
||||
.fill(ClawdbotChatTheme.subtleCard)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
||||
.strokeBorder(Color.white.opacity(0.08), lineWidth: 1)))
|
||||
@@ -432,7 +432,7 @@ private struct ToolResultCard: View {
|
||||
|
||||
Text(self.displayText)
|
||||
.font(.footnote.monospaced())
|
||||
.foregroundStyle(self.isUser ? ClawdisChatTheme.userText : ClawdisChatTheme.assistantText)
|
||||
.foregroundStyle(self.isUser ? ClawdbotChatTheme.userText : ClawdbotChatTheme.assistantText)
|
||||
.lineLimit(self.expanded ? nil : Self.previewLineLimit)
|
||||
|
||||
if self.shouldShowToggle {
|
||||
@@ -447,7 +447,7 @@ private struct ToolResultCard: View {
|
||||
.padding(10)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
||||
.fill(ClawdisChatTheme.subtleCard)
|
||||
.fill(ClawdbotChatTheme.subtleCard)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 12, style: .continuous)
|
||||
.strokeBorder(Color.white.opacity(0.08), lineWidth: 1)))
|
||||
@@ -471,7 +471,7 @@ private struct ToolResultCard: View {
|
||||
|
||||
@MainActor
|
||||
struct ChatTypingIndicatorBubble: View {
|
||||
let style: ClawdisChatView.Style
|
||||
let style: ClawdbotChatView.Style
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 10) {
|
||||
@@ -487,7 +487,7 @@ struct ChatTypingIndicatorBubble: View {
|
||||
.padding(.horizontal, self.style == .standard ? 12 : 14)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
.fill(ClawdisChatTheme.assistantBubble))
|
||||
.fill(ClawdbotChatTheme.assistantBubble))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
.strokeBorder(Color.white.opacity(0.08), lineWidth: 1))
|
||||
@@ -513,7 +513,7 @@ struct ChatStreamingAssistantBubble: View {
|
||||
.padding(12)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
.fill(ClawdisChatTheme.assistantBubble))
|
||||
.fill(ClawdbotChatTheme.assistantBubble))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
.strokeBorder(Color.white.opacity(0.08), lineWidth: 1))
|
||||
@@ -524,7 +524,7 @@ struct ChatStreamingAssistantBubble: View {
|
||||
|
||||
@MainActor
|
||||
struct ChatPendingToolsBubble: View {
|
||||
let toolCalls: [ClawdisChatPendingToolCall]
|
||||
let toolCalls: [ClawdbotChatPendingToolCall]
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
@@ -557,7 +557,7 @@ struct ChatPendingToolsBubble: View {
|
||||
.padding(12)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
.fill(ClawdisChatTheme.assistantBubble))
|
||||
.fill(ClawdbotChatTheme.assistantBubble))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 16, style: .continuous)
|
||||
.strokeBorder(Color.white.opacity(0.08), lineWidth: 1))
|
||||
@@ -646,7 +646,7 @@ private struct ChatAssistantTextBody: View {
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
ForEach(segments) { segment in
|
||||
let font = segment.kind == .thinking ? Font.system(size: 14).italic() : Font.system(size: 14)
|
||||
ChatMarkdownBody(text: segment.text, textColor: ClawdisChatTheme.assistantText, font: font)
|
||||
ChatMarkdownBody(text: segment.text, textColor: ClawdbotChatTheme.assistantText, font: font)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -676,7 +676,7 @@ private struct ChatMarkdownBody: View {
|
||||
id: \ChatMarkdownSplitter.InlineImage.id)
|
||||
{ (item: ChatMarkdownSplitter.InlineImage) in
|
||||
if let img = item.image {
|
||||
ClawdisPlatformImageFactory.image(img)
|
||||
ClawdbotPlatformImageFactory.image(img)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(maxHeight: 260)
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdisKit
|
||||
import ClawdbotKit
|
||||
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 ClawdisPlatformImage = NSImage
|
||||
public typealias ClawdbotPlatformImage = NSImage
|
||||
#elseif canImport(UIKit)
|
||||
import UIKit
|
||||
|
||||
public typealias ClawdisPlatformImage = UIImage
|
||||
public typealias ClawdbotPlatformImage = UIImage
|
||||
#endif
|
||||
|
||||
public struct ClawdisChatUsageCost: Codable, Hashable, Sendable {
|
||||
public struct ClawdbotChatUsageCost: Codable, Hashable, Sendable {
|
||||
public let input: Double?
|
||||
public let output: Double?
|
||||
public let cacheRead: Double?
|
||||
@@ -21,12 +21,12 @@ public struct ClawdisChatUsageCost: Codable, Hashable, Sendable {
|
||||
public let total: Double?
|
||||
}
|
||||
|
||||
public struct ClawdisChatUsage: Codable, Hashable, Sendable {
|
||||
public struct ClawdbotChatUsage: Codable, Hashable, Sendable {
|
||||
public let input: Int?
|
||||
public let output: Int?
|
||||
public let cacheRead: Int?
|
||||
public let cacheWrite: Int?
|
||||
public let cost: ClawdisChatUsageCost?
|
||||
public let cost: ClawdbotChatUsageCost?
|
||||
public let total: Int?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
@@ -45,7 +45,7 @@ public struct ClawdisChatUsage: 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(ClawdisChatUsageCost.self, forKey: .cost)
|
||||
self.cost = try container.decodeIfPresent(ClawdbotChatUsageCost.self, forKey: .cost)
|
||||
self.total =
|
||||
try container.decodeIfPresent(Int.self, forKey: .total) ??
|
||||
container.decodeIfPresent(Int.self, forKey: .totalTokens)
|
||||
@@ -62,7 +62,7 @@ public struct ClawdisChatUsage: Codable, Hashable, Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdisChatMessageContent: Codable, Hashable, Sendable {
|
||||
public struct ClawdbotChatMessageContent: Codable, Hashable, Sendable {
|
||||
public let type: String?
|
||||
public let text: String?
|
||||
public let thinking: String?
|
||||
@@ -135,14 +135,14 @@ public struct ClawdisChatMessageContent: Codable, Hashable, Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdisChatMessage: Codable, Identifiable, Sendable {
|
||||
public struct ClawdbotChatMessage: Codable, Identifiable, Sendable {
|
||||
public var id: UUID = .init()
|
||||
public let role: String
|
||||
public let content: [ClawdisChatMessageContent]
|
||||
public let content: [ClawdbotChatMessageContent]
|
||||
public let timestamp: Double?
|
||||
public let toolCallId: String?
|
||||
public let toolName: String?
|
||||
public let usage: ClawdisChatUsage?
|
||||
public let usage: ClawdbotChatUsage?
|
||||
public let stopReason: String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
@@ -160,11 +160,11 @@ public struct ClawdisChatMessage: Codable, Identifiable, Sendable {
|
||||
public init(
|
||||
id: UUID = .init(),
|
||||
role: String,
|
||||
content: [ClawdisChatMessageContent],
|
||||
content: [ClawdbotChatMessageContent],
|
||||
timestamp: Double?,
|
||||
toolCallId: String? = nil,
|
||||
toolName: String? = nil,
|
||||
usage: ClawdisChatUsage? = nil,
|
||||
usage: ClawdbotChatUsage? = nil,
|
||||
stopReason: String? = nil)
|
||||
{
|
||||
self.id = id
|
||||
@@ -187,10 +187,10 @@ public struct ClawdisChatMessage: Codable, Identifiable, Sendable {
|
||||
self.toolName =
|
||||
try container.decodeIfPresent(String.self, forKey: .toolName) ??
|
||||
container.decodeIfPresent(String.self, forKey: .tool_name)
|
||||
self.usage = try container.decodeIfPresent(ClawdisChatUsage.self, forKey: .usage)
|
||||
self.usage = try container.decodeIfPresent(ClawdbotChatUsage.self, forKey: .usage)
|
||||
self.stopReason = try container.decodeIfPresent(String.self, forKey: .stopReason)
|
||||
|
||||
if let decoded = try? container.decode([ClawdisChatMessageContent].self, forKey: .content) {
|
||||
if let decoded = try? container.decode([ClawdbotChatMessageContent].self, forKey: .content) {
|
||||
self.content = decoded
|
||||
return
|
||||
}
|
||||
@@ -198,7 +198,7 @@ public struct ClawdisChatMessage: 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 = [
|
||||
ClawdisChatMessageContent(
|
||||
ClawdbotChatMessageContent(
|
||||
type: "text",
|
||||
text: text,
|
||||
thinking: nil,
|
||||
@@ -228,19 +228,19 @@ public struct ClawdisChatMessage: Codable, Identifiable, Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdisChatHistoryPayload: Codable, Sendable {
|
||||
public struct ClawdbotChatHistoryPayload: Codable, Sendable {
|
||||
public let sessionKey: String
|
||||
public let sessionId: String?
|
||||
public let messages: [AnyCodable]?
|
||||
public let thinkingLevel: String?
|
||||
}
|
||||
|
||||
public struct ClawdisChatSendResponse: Codable, Sendable {
|
||||
public struct ClawdbotChatSendResponse: Codable, Sendable {
|
||||
public let runId: String
|
||||
public let status: String
|
||||
}
|
||||
|
||||
public struct ClawdisChatEventPayload: Codable, Sendable {
|
||||
public struct ClawdbotChatEventPayload: Codable, Sendable {
|
||||
public let runId: String?
|
||||
public let sessionKey: String?
|
||||
public let state: String?
|
||||
@@ -248,7 +248,7 @@ public struct ClawdisChatEventPayload: Codable, Sendable {
|
||||
public let errorMessage: String?
|
||||
}
|
||||
|
||||
public struct ClawdisAgentEventPayload: Codable, Sendable, Identifiable {
|
||||
public struct ClawdbotAgentEventPayload: Codable, Sendable, Identifiable {
|
||||
public var id: String { "\(self.runId)-\(self.seq ?? -1)" }
|
||||
public let runId: String
|
||||
public let seq: Int?
|
||||
@@ -257,7 +257,7 @@ public struct ClawdisAgentEventPayload: Codable, Sendable, Identifiable {
|
||||
public let data: [String: AnyCodable]
|
||||
}
|
||||
|
||||
public struct ClawdisChatPendingToolCall: Identifiable, Hashable, Sendable {
|
||||
public struct ClawdbotChatPendingToolCall: Identifiable, Hashable, Sendable {
|
||||
public var id: String { self.toolCallId }
|
||||
public let toolCallId: String
|
||||
public let name: String
|
||||
@@ -266,18 +266,18 @@ public struct ClawdisChatPendingToolCall: Identifiable, Hashable, Sendable {
|
||||
public let isError: Bool?
|
||||
}
|
||||
|
||||
public struct ClawdisGatewayHealthOK: Codable, Sendable {
|
||||
public struct ClawdbotGatewayHealthOK: Codable, Sendable {
|
||||
public let ok: Bool?
|
||||
}
|
||||
|
||||
public struct ClawdisPendingAttachment: Identifiable {
|
||||
public struct ClawdbotPendingAttachment: 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: ClawdisPlatformImage?
|
||||
public let preview: ClawdbotPlatformImage?
|
||||
|
||||
public init(
|
||||
url: URL?,
|
||||
@@ -285,7 +285,7 @@ public struct ClawdisPendingAttachment: Identifiable {
|
||||
fileName: String,
|
||||
mimeType: String,
|
||||
type: String = "file",
|
||||
preview: ClawdisPlatformImage?)
|
||||
preview: ClawdbotPlatformImage?)
|
||||
{
|
||||
self.url = url
|
||||
self.data = data
|
||||
@@ -296,7 +296,7 @@ public struct ClawdisPendingAttachment: Identifiable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdisChatAttachmentPayload: Codable, Sendable, Hashable {
|
||||
public struct ClawdbotChatAttachmentPayload: Codable, Sendable, Hashable {
|
||||
public let type: String
|
||||
public let mimeType: String
|
||||
public let fileName: String
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdisKit
|
||||
import ClawdbotKit
|
||||
import Foundation
|
||||
|
||||
enum ChatPayloadDecoding {
|
||||
@@ -1,11 +1,11 @@
|
||||
import Foundation
|
||||
|
||||
public struct ClawdisChatSessionsDefaults: Codable, Sendable {
|
||||
public struct ClawdbotChatSessionsDefaults: Codable, Sendable {
|
||||
public let model: String?
|
||||
public let contextTokens: Int?
|
||||
}
|
||||
|
||||
public struct ClawdisChatSessionEntry: Codable, Identifiable, Sendable, Hashable {
|
||||
public struct ClawdbotChatSessionEntry: Codable, Identifiable, Sendable, Hashable {
|
||||
public var id: String { self.key }
|
||||
|
||||
public let key: String
|
||||
@@ -31,10 +31,10 @@ public struct ClawdisChatSessionEntry: Codable, Identifiable, Sendable, Hashable
|
||||
public let contextTokens: Int?
|
||||
}
|
||||
|
||||
public struct ClawdisChatSessionsListResponse: Codable, Sendable {
|
||||
public struct ClawdbotChatSessionsListResponse: Codable, Sendable {
|
||||
public let ts: Double?
|
||||
public let path: String?
|
||||
public let count: Int?
|
||||
public let defaults: ClawdisChatSessionsDefaults?
|
||||
public let sessions: [ClawdisChatSessionEntry]
|
||||
public let defaults: ClawdbotChatSessionsDefaults?
|
||||
public let sessions: [ClawdbotChatSessionEntry]
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import SwiftUI
|
||||
|
||||
@MainActor
|
||||
struct ChatSessionsSheet: View {
|
||||
@Bindable var viewModel: ClawdisChatViewModel
|
||||
@Bindable var viewModel: ClawdbotChatViewModel
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
var body: some View {
|
||||
@@ -14,7 +14,7 @@ extension NSAppearance {
|
||||
}
|
||||
#endif
|
||||
|
||||
enum ClawdisChatTheme {
|
||||
enum ClawdbotChatTheme {
|
||||
#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 ClawdisChatTheme {
|
||||
}
|
||||
|
||||
static let assistantBubbleDynamicNSColor = NSColor(
|
||||
name: NSColor.Name("ClawdisChatTheme.assistantBubble"),
|
||||
name: NSColor.Name("ClawdbotChatTheme.assistantBubble"),
|
||||
dynamicProvider: resolvedAssistantBubbleColor(for:))
|
||||
|
||||
static let onboardingAssistantBubbleDynamicNSColor = NSColor(
|
||||
name: NSColor.Name("ClawdisChatTheme.onboardingAssistantBubble"),
|
||||
name: NSColor.Name("ClawdbotChatTheme.onboardingAssistantBubble"),
|
||||
dynamicProvider: resolvedOnboardingAssistantBubbleColor(for:))
|
||||
#endif
|
||||
|
||||
@@ -163,8 +163,8 @@ enum ClawdisChatTheme {
|
||||
}
|
||||
}
|
||||
|
||||
enum ClawdisPlatformImageFactory {
|
||||
static func image(_ image: ClawdisPlatformImage) -> Image {
|
||||
enum ClawdbotPlatformImageFactory {
|
||||
static func image(_ image: ClawdbotPlatformImage) -> Image {
|
||||
#if os(macOS)
|
||||
Image(nsImage: image)
|
||||
#else
|
||||
@@ -1,44 +1,44 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdisChatTransportEvent: Sendable {
|
||||
public enum ClawdbotChatTransportEvent: Sendable {
|
||||
case health(ok: Bool)
|
||||
case tick
|
||||
case chat(ClawdisChatEventPayload)
|
||||
case agent(ClawdisAgentEventPayload)
|
||||
case chat(ClawdbotChatEventPayload)
|
||||
case agent(ClawdbotAgentEventPayload)
|
||||
case seqGap
|
||||
}
|
||||
|
||||
public protocol ClawdisChatTransport: Sendable {
|
||||
func requestHistory(sessionKey: String) async throws -> ClawdisChatHistoryPayload
|
||||
public protocol ClawdbotChatTransport: Sendable {
|
||||
func requestHistory(sessionKey: String) async throws -> ClawdbotChatHistoryPayload
|
||||
func sendMessage(
|
||||
sessionKey: String,
|
||||
message: String,
|
||||
thinking: String,
|
||||
idempotencyKey: String,
|
||||
attachments: [ClawdisChatAttachmentPayload]) async throws -> ClawdisChatSendResponse
|
||||
attachments: [ClawdbotChatAttachmentPayload]) async throws -> ClawdbotChatSendResponse
|
||||
|
||||
func abortRun(sessionKey: String, runId: String) async throws
|
||||
func listSessions(limit: Int?) async throws -> ClawdisChatSessionsListResponse
|
||||
func listSessions(limit: Int?) async throws -> ClawdbotChatSessionsListResponse
|
||||
|
||||
func requestHealth(timeoutMs: Int) async throws -> Bool
|
||||
func events() -> AsyncStream<ClawdisChatTransportEvent>
|
||||
func events() -> AsyncStream<ClawdbotChatTransportEvent>
|
||||
|
||||
func setActiveSessionKey(_ sessionKey: String) async throws
|
||||
}
|
||||
|
||||
extension ClawdisChatTransport {
|
||||
extension ClawdbotChatTransport {
|
||||
public func setActiveSessionKey(_: String) async throws {}
|
||||
|
||||
public func abortRun(sessionKey _: String, runId _: String) async throws {
|
||||
throw NSError(
|
||||
domain: "ClawdisChatTransport",
|
||||
domain: "ClawdbotChatTransport",
|
||||
code: 0,
|
||||
userInfo: [NSLocalizedDescriptionKey: "chat.abort not supported by this transport"])
|
||||
}
|
||||
|
||||
public func listSessions(limit _: Int?) async throws -> ClawdisChatSessionsListResponse {
|
||||
public func listSessions(limit _: Int?) async throws -> ClawdbotChatSessionsListResponse {
|
||||
throw NSError(
|
||||
domain: "ClawdisChatTransport",
|
||||
domain: "ClawdbotChatTransport",
|
||||
code: 0,
|
||||
userInfo: [NSLocalizedDescriptionKey: "sessions.list not supported by this transport"])
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
public struct ClawdisChatView: View {
|
||||
public struct ClawdbotChatView: View {
|
||||
public enum Style {
|
||||
case standard
|
||||
case onboarding
|
||||
}
|
||||
|
||||
@State private var viewModel: ClawdisChatViewModel
|
||||
@State private var viewModel: ClawdbotChatViewModel
|
||||
@State private var scrollerBottomID = UUID()
|
||||
@State private var scrollPosition: UUID?
|
||||
@State private var showSessions = false
|
||||
@@ -39,7 +39,7 @@ public struct ClawdisChatView: View {
|
||||
}
|
||||
|
||||
public init(
|
||||
viewModel: ClawdisChatViewModel,
|
||||
viewModel: ClawdbotChatViewModel,
|
||||
showsSessionSwitcher: Bool = false,
|
||||
style: Style = .standard,
|
||||
userAccent: Color? = nil)
|
||||
@@ -52,13 +52,13 @@ public struct ClawdisChatView: View {
|
||||
|
||||
public var body: some View {
|
||||
ZStack {
|
||||
ClawdisChatTheme.background
|
||||
ClawdbotChatTheme.background
|
||||
.ignoresSafeArea()
|
||||
|
||||
VStack(spacing: Layout.stackSpacing) {
|
||||
self.messageList
|
||||
.padding(.horizontal, Layout.outerPaddingHorizontal)
|
||||
ClawdisChatComposer(
|
||||
ClawdbotChatComposer(
|
||||
viewModel: self.viewModel,
|
||||
style: self.style,
|
||||
showsSessionSwitcher: self.showsSessionSwitcher)
|
||||
@@ -175,8 +175,8 @@ public struct ClawdisChatView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var visibleMessages: [ClawdisChatMessage] {
|
||||
let base: [ClawdisChatMessage]
|
||||
private var visibleMessages: [ClawdbotChatMessage] {
|
||||
let base: [ClawdbotChatMessage]
|
||||
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
|
||||
@@ -293,8 +293,8 @@ public struct ClawdisChatView: View {
|
||||
return ("Error", "exclamationmark.triangle.fill", .orange)
|
||||
}
|
||||
|
||||
private func mergeToolResults(in messages: [ClawdisChatMessage]) -> [ClawdisChatMessage] {
|
||||
var result: [ClawdisChatMessage] = []
|
||||
private func mergeToolResults(in messages: [ClawdbotChatMessage]) -> [ClawdbotChatMessage] {
|
||||
var result: [ClawdbotChatMessage] = []
|
||||
result.reserveCapacity(messages.count)
|
||||
|
||||
for message in messages {
|
||||
@@ -318,7 +318,7 @@ public struct ClawdisChatView: View {
|
||||
|
||||
var content = last.content
|
||||
content.append(
|
||||
ClawdisChatMessageContent(
|
||||
ClawdbotChatMessageContent(
|
||||
type: "tool_result",
|
||||
text: toolText,
|
||||
thinking: nil,
|
||||
@@ -330,7 +330,7 @@ public struct ClawdisChatView: View {
|
||||
name: message.toolName,
|
||||
arguments: nil))
|
||||
|
||||
let merged = ClawdisChatMessage(
|
||||
let merged = ClawdbotChatMessage(
|
||||
id: last.id,
|
||||
role: last.role,
|
||||
content: content,
|
||||
@@ -345,12 +345,12 @@ public struct ClawdisChatView: View {
|
||||
return result
|
||||
}
|
||||
|
||||
private func isToolResultMessage(_ message: ClawdisChatMessage) -> Bool {
|
||||
private func isToolResultMessage(_ message: ClawdbotChatMessage) -> Bool {
|
||||
let role = message.role.lowercased()
|
||||
return role == "toolresult" || role == "tool_result"
|
||||
}
|
||||
|
||||
private func toolCallIds(in message: ClawdisChatMessage) -> Set<String> {
|
||||
private func toolCallIds(in message: ClawdbotChatMessage) -> Set<String> {
|
||||
var ids = Set<String>()
|
||||
for content in message.content {
|
||||
let kind = (content.type ?? "").lowercased()
|
||||
@@ -367,7 +367,7 @@ public struct ClawdisChatView: View {
|
||||
return ids
|
||||
}
|
||||
|
||||
private func toolResultText(from message: ClawdisChatMessage) -> String {
|
||||
private func toolResultText(from message: ClawdbotChatMessage) -> String {
|
||||
let parts = message.content.compactMap { content -> String? in
|
||||
let kind = (content.type ?? "text").lowercased()
|
||||
guard kind == "text" || kind.isEmpty else { return nil }
|
||||
@@ -415,7 +415,7 @@ private struct ChatNoticeCard: View {
|
||||
.padding(18)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
||||
.fill(ClawdisChatTheme.subtleCard)
|
||||
.fill(ClawdbotChatTheme.subtleCard)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 18, style: .continuous)
|
||||
.strokeBorder(Color.white.opacity(0.12), lineWidth: 1)))
|
||||
@@ -468,7 +468,7 @@ private struct ChatNoticeBanner: View {
|
||||
.padding(.vertical, 10)
|
||||
.background(
|
||||
RoundedRectangle(cornerRadius: 14, style: .continuous)
|
||||
.fill(ClawdisChatTheme.subtleCard)
|
||||
.fill(ClawdbotChatTheme.subtleCard)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 14, style: .continuous)
|
||||
.strokeBorder(Color.white.opacity(0.12), lineWidth: 1)))
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdisKit
|
||||
import ClawdbotKit
|
||||
import Foundation
|
||||
import Observation
|
||||
import OSLog
|
||||
@@ -10,28 +10,28 @@ import AppKit
|
||||
import UIKit
|
||||
#endif
|
||||
|
||||
private let chatUILogger = Logger(subsystem: "com.clawdis", category: "ClawdisChatUI")
|
||||
private let chatUILogger = Logger(subsystem: "com.clawdbot", category: "ClawdbotChatUI")
|
||||
|
||||
@MainActor
|
||||
@Observable
|
||||
public final class ClawdisChatViewModel {
|
||||
public private(set) var messages: [ClawdisChatMessage] = []
|
||||
public final class ClawdbotChatViewModel {
|
||||
public private(set) var messages: [ClawdbotChatMessage] = []
|
||||
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: [ClawdisPendingAttachment] = []
|
||||
public var attachments: [ClawdbotPendingAttachment] = []
|
||||
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: [ClawdisChatPendingToolCall] = []
|
||||
public private(set) var sessions: [ClawdisChatSessionEntry] = []
|
||||
private let transport: any ClawdisChatTransport
|
||||
public private(set) var pendingToolCalls: [ClawdbotChatPendingToolCall] = []
|
||||
public private(set) var sessions: [ClawdbotChatSessionEntry] = []
|
||||
private let transport: any ClawdbotChatTransport
|
||||
|
||||
@ObservationIgnored
|
||||
private nonisolated(unsafe) var eventTask: Task<Void, Never>?
|
||||
@@ -43,7 +43,7 @@ public final class ClawdisChatViewModel {
|
||||
private nonisolated(unsafe) var pendingRunTimeoutTasks: [String: Task<Void, Never>] = [:]
|
||||
private let pendingRunTimeoutMs: UInt64 = 120_000
|
||||
|
||||
private var pendingToolCallsById: [String: ClawdisChatPendingToolCall] = [:] {
|
||||
private var pendingToolCallsById: [String: ClawdbotChatPendingToolCall] = [:] {
|
||||
didSet {
|
||||
self.pendingToolCalls = self.pendingToolCallsById.values
|
||||
.sorted { ($0.startedAt ?? 0) < ($1.startedAt ?? 0) }
|
||||
@@ -52,7 +52,7 @@ public final class ClawdisChatViewModel {
|
||||
|
||||
private var lastHealthPollAt: Date?
|
||||
|
||||
public init(sessionKey: String, transport: any ClawdisChatTransport) {
|
||||
public init(sessionKey: String, transport: any ClawdbotChatTransport) {
|
||||
self.sessionKey = sessionKey
|
||||
self.transport = transport
|
||||
|
||||
@@ -99,12 +99,12 @@ public final class ClawdisChatViewModel {
|
||||
Task { await self.performSwitchSession(to: sessionKey) }
|
||||
}
|
||||
|
||||
public var sessionChoices: [ClawdisChatSessionEntry] {
|
||||
public var sessionChoices: [ClawdbotChatSessionEntry] {
|
||||
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: [ClawdisChatSessionEntry] = []
|
||||
var recent: [ClawdbotChatSessionEntry] = []
|
||||
for entry in sorted {
|
||||
guard !seen.contains(entry.key) else { continue }
|
||||
seen.insert(entry.key)
|
||||
@@ -113,7 +113,7 @@ public final class ClawdisChatViewModel {
|
||||
}
|
||||
|
||||
let mainKey = "main"
|
||||
var result: [ClawdisChatSessionEntry] = []
|
||||
var result: [ClawdbotChatSessionEntry] = []
|
||||
var included = Set<String>()
|
||||
if let main = sorted.first(where: { $0.key == mainKey }) {
|
||||
result.append(main)
|
||||
@@ -143,7 +143,7 @@ public final class ClawdisChatViewModel {
|
||||
Task { await self.addImageAttachment(url: nil, data: data, fileName: fileName, mimeType: mimeType) }
|
||||
}
|
||||
|
||||
public func removeAttachment(_ id: ClawdisPendingAttachment.ID) {
|
||||
public func removeAttachment(_ id: ClawdbotPendingAttachment.ID) {
|
||||
self.attachments.removeAll { $0.id == id }
|
||||
}
|
||||
|
||||
@@ -185,15 +185,15 @@ public final class ClawdisChatViewModel {
|
||||
}
|
||||
}
|
||||
|
||||
private static func decodeMessages(_ raw: [AnyCodable]) -> [ClawdisChatMessage] {
|
||||
private static func decodeMessages(_ raw: [AnyCodable]) -> [ClawdbotChatMessage] {
|
||||
let decoded = raw.compactMap { item in
|
||||
(try? ChatPayloadDecoding.decode(item, as: ClawdisChatMessage.self))
|
||||
(try? ChatPayloadDecoding.decode(item, as: ClawdbotChatMessage.self))
|
||||
}
|
||||
return Self.dedupeMessages(decoded)
|
||||
}
|
||||
|
||||
private static func dedupeMessages(_ messages: [ClawdisChatMessage]) -> [ClawdisChatMessage] {
|
||||
var result: [ClawdisChatMessage] = []
|
||||
private static func dedupeMessages(_ messages: [ClawdbotChatMessage]) -> [ClawdbotChatMessage] {
|
||||
var result: [ClawdbotChatMessage] = []
|
||||
result.reserveCapacity(messages.count)
|
||||
var seen = Set<String>()
|
||||
|
||||
@@ -210,7 +210,7 @@ public final class ClawdisChatViewModel {
|
||||
return result
|
||||
}
|
||||
|
||||
private static func dedupeKey(for message: ClawdisChatMessage) -> String? {
|
||||
private static func dedupeKey(for message: ClawdbotChatMessage) -> String? {
|
||||
guard let timestamp = message.timestamp else { return nil }
|
||||
let text = message.content.compactMap(\.text).joined(separator: "\n")
|
||||
.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
@@ -238,8 +238,8 @@ public final class ClawdisChatViewModel {
|
||||
self.streamingAssistantText = nil
|
||||
|
||||
// Optimistically append user message to UI.
|
||||
var userContent: [ClawdisChatMessageContent] = [
|
||||
ClawdisChatMessageContent(
|
||||
var userContent: [ClawdbotChatMessageContent] = [
|
||||
ClawdbotChatMessageContent(
|
||||
type: "text",
|
||||
text: messageText,
|
||||
thinking: nil,
|
||||
@@ -251,8 +251,8 @@ public final class ClawdisChatViewModel {
|
||||
name: nil,
|
||||
arguments: nil),
|
||||
]
|
||||
let encodedAttachments = self.attachments.map { att -> ClawdisChatAttachmentPayload in
|
||||
ClawdisChatAttachmentPayload(
|
||||
let encodedAttachments = self.attachments.map { att -> ClawdbotChatAttachmentPayload in
|
||||
ClawdbotChatAttachmentPayload(
|
||||
type: att.type,
|
||||
mimeType: att.mimeType,
|
||||
fileName: att.fileName,
|
||||
@@ -260,7 +260,7 @@ public final class ClawdisChatViewModel {
|
||||
}
|
||||
for att in encodedAttachments {
|
||||
userContent.append(
|
||||
ClawdisChatMessageContent(
|
||||
ClawdbotChatMessageContent(
|
||||
type: att.type,
|
||||
text: nil,
|
||||
thinking: nil,
|
||||
@@ -273,7 +273,7 @@ public final class ClawdisChatViewModel {
|
||||
arguments: nil))
|
||||
}
|
||||
self.messages.append(
|
||||
ClawdisChatMessage(
|
||||
ClawdbotChatMessage(
|
||||
id: UUID(),
|
||||
role: "user",
|
||||
content: userContent,
|
||||
@@ -337,8 +337,8 @@ public final class ClawdisChatViewModel {
|
||||
await self.bootstrap()
|
||||
}
|
||||
|
||||
private func placeholderSession(key: String) -> ClawdisChatSessionEntry {
|
||||
ClawdisChatSessionEntry(
|
||||
private func placeholderSession(key: String) -> ClawdbotChatSessionEntry {
|
||||
ClawdbotChatSessionEntry(
|
||||
key: key,
|
||||
kind: nil,
|
||||
displayName: nil,
|
||||
@@ -359,7 +359,7 @@ public final class ClawdisChatViewModel {
|
||||
contextTokens: nil)
|
||||
}
|
||||
|
||||
private func handleTransportEvent(_ evt: ClawdisChatTransportEvent) {
|
||||
private func handleTransportEvent(_ evt: ClawdbotChatTransportEvent) {
|
||||
switch evt {
|
||||
case let .health(ok):
|
||||
self.healthOK = ok
|
||||
@@ -375,7 +375,7 @@ public final class ClawdisChatViewModel {
|
||||
}
|
||||
}
|
||||
|
||||
private func handleChatEvent(_ chat: ClawdisChatEventPayload) {
|
||||
private func handleChatEvent(_ chat: ClawdbotChatEventPayload) {
|
||||
if let sessionKey = chat.sessionKey, sessionKey != self.sessionKey {
|
||||
return
|
||||
}
|
||||
@@ -412,7 +412,7 @@ public final class ClawdisChatViewModel {
|
||||
}
|
||||
}
|
||||
|
||||
private func handleAgentEvent(_ evt: ClawdisAgentEventPayload) {
|
||||
private func handleAgentEvent(_ evt: ClawdbotAgentEventPayload) {
|
||||
if let sessionId, evt.runId != sessionId {
|
||||
return
|
||||
}
|
||||
@@ -428,7 +428,7 @@ public final class ClawdisChatViewModel {
|
||||
guard let toolCallId = evt.data["toolCallId"]?.value as? String else { return }
|
||||
if phase == "start" {
|
||||
let args = evt.data["args"]
|
||||
self.pendingToolCallsById[toolCallId] = ClawdisChatPendingToolCall(
|
||||
self.pendingToolCallsById[toolCallId] = ClawdbotChatPendingToolCall(
|
||||
toolCallId: toolCallId,
|
||||
name: name,
|
||||
args: args,
|
||||
@@ -539,7 +539,7 @@ public final class ClawdisChatViewModel {
|
||||
|
||||
let preview = Self.previewImage(data: data)
|
||||
self.attachments.append(
|
||||
ClawdisPendingAttachment(
|
||||
ClawdbotPendingAttachment(
|
||||
url: url,
|
||||
data: data,
|
||||
fileName: fileName,
|
||||
@@ -547,7 +547,7 @@ public final class ClawdisChatViewModel {
|
||||
preview: preview))
|
||||
}
|
||||
|
||||
private static func previewImage(data: Data) -> ClawdisPlatformImage? {
|
||||
private static func previewImage(data: Data) -> ClawdbotPlatformImage? {
|
||||
#if canImport(AppKit)
|
||||
NSImage(data: data)
|
||||
#elseif canImport(UIKit)
|
||||
@@ -1,10 +1,10 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdisBonjour {
|
||||
public enum ClawdbotBonjour {
|
||||
// v0: internal-only, subject to rename.
|
||||
public static let bridgeServiceType = "_clawdis-bridge._tcp"
|
||||
public static let bridgeServiceType = "_clawdbot-bridge._tcp"
|
||||
public static let bridgeServiceDomain = "local."
|
||||
public static let wideAreaBridgeServiceDomain = "clawdis.internal."
|
||||
public static let wideAreaBridgeServiceDomain = "clawdbot.internal."
|
||||
|
||||
public static let bridgeServiceDomains = [
|
||||
bridgeServiceDomain,
|
||||
@@ -27,14 +27,14 @@ public struct BridgeInvokeResponse: Codable, Sendable {
|
||||
public let id: String
|
||||
public let ok: Bool
|
||||
public let payloadJSON: String?
|
||||
public let error: ClawdisNodeError?
|
||||
public let error: ClawdbotNodeError?
|
||||
|
||||
public init(
|
||||
type: String = "invoke-res",
|
||||
id: String,
|
||||
ok: Bool,
|
||||
payloadJSON: String? = nil,
|
||||
error: ClawdisNodeError? = nil)
|
||||
error: ClawdbotNodeError? = nil)
|
||||
{
|
||||
self.type = type
|
||||
self.id = id
|
||||
@@ -1,38 +1,38 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdisCameraCommand: String, Codable, Sendable {
|
||||
public enum ClawdbotCameraCommand: String, Codable, Sendable {
|
||||
case list = "camera.list"
|
||||
case snap = "camera.snap"
|
||||
case clip = "camera.clip"
|
||||
}
|
||||
|
||||
public enum ClawdisCameraFacing: String, Codable, Sendable {
|
||||
public enum ClawdbotCameraFacing: String, Codable, Sendable {
|
||||
case back
|
||||
case front
|
||||
}
|
||||
|
||||
public enum ClawdisCameraImageFormat: String, Codable, Sendable {
|
||||
public enum ClawdbotCameraImageFormat: String, Codable, Sendable {
|
||||
case jpg
|
||||
case jpeg
|
||||
}
|
||||
|
||||
public enum ClawdisCameraVideoFormat: String, Codable, Sendable {
|
||||
public enum ClawdbotCameraVideoFormat: String, Codable, Sendable {
|
||||
case mp4
|
||||
}
|
||||
|
||||
public struct ClawdisCameraSnapParams: Codable, Sendable, Equatable {
|
||||
public var facing: ClawdisCameraFacing?
|
||||
public struct ClawdbotCameraSnapParams: Codable, Sendable, Equatable {
|
||||
public var facing: ClawdbotCameraFacing?
|
||||
public var maxWidth: Int?
|
||||
public var quality: Double?
|
||||
public var format: ClawdisCameraImageFormat?
|
||||
public var format: ClawdbotCameraImageFormat?
|
||||
public var deviceId: String?
|
||||
public var delayMs: Int?
|
||||
|
||||
public init(
|
||||
facing: ClawdisCameraFacing? = nil,
|
||||
facing: ClawdbotCameraFacing? = nil,
|
||||
maxWidth: Int? = nil,
|
||||
quality: Double? = nil,
|
||||
format: ClawdisCameraImageFormat? = nil,
|
||||
format: ClawdbotCameraImageFormat? = nil,
|
||||
deviceId: String? = nil,
|
||||
delayMs: Int? = nil)
|
||||
{
|
||||
@@ -45,18 +45,18 @@ public struct ClawdisCameraSnapParams: Codable, Sendable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdisCameraClipParams: Codable, Sendable, Equatable {
|
||||
public var facing: ClawdisCameraFacing?
|
||||
public struct ClawdbotCameraClipParams: Codable, Sendable, Equatable {
|
||||
public var facing: ClawdbotCameraFacing?
|
||||
public var durationMs: Int?
|
||||
public var includeAudio: Bool?
|
||||
public var format: ClawdisCameraVideoFormat?
|
||||
public var format: ClawdbotCameraVideoFormat?
|
||||
public var deviceId: String?
|
||||
|
||||
public init(
|
||||
facing: ClawdisCameraFacing? = nil,
|
||||
facing: ClawdbotCameraFacing? = nil,
|
||||
durationMs: Int? = nil,
|
||||
includeAudio: Bool? = nil,
|
||||
format: ClawdisCameraVideoFormat? = nil,
|
||||
format: ClawdbotCameraVideoFormat? = nil,
|
||||
deviceId: String? = nil)
|
||||
{
|
||||
self.facing = facing
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdisCanvasA2UIAction: Sendable {
|
||||
public enum ClawdbotCanvasA2UIAction: Sendable {
|
||||
public struct AgentMessageContext: Sendable {
|
||||
public struct Session: Sendable {
|
||||
public var key: String
|
||||
@@ -94,6 +94,6 @@ public enum ClawdisCanvasA2UIAction: Sendable {
|
||||
}
|
||||
return "{\"id\":\"\(actionId)\",\"ok\":\(ok ? "true" : "false"),\"error\":\"\"}"
|
||||
}()
|
||||
return "window.dispatchEvent(new CustomEvent('clawdis:a2ui-action-status', { detail: \(json) }));"
|
||||
return "window.dispatchEvent(new CustomEvent('clawdbot:a2ui-action-status', { detail: \(json) }));"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdisCanvasA2UICommand: String, Codable, Sendable {
|
||||
public enum ClawdbotCanvasA2UICommand: 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 ClawdisCanvasA2UICommand: String, Codable, Sendable {
|
||||
case reset = "canvas.a2ui.reset"
|
||||
}
|
||||
|
||||
public struct ClawdisCanvasA2UIPushParams: Codable, Sendable, Equatable {
|
||||
public struct ClawdbotCanvasA2UIPushParams: Codable, Sendable, Equatable {
|
||||
public var messages: [AnyCodable]
|
||||
|
||||
public init(messages: [AnyCodable]) {
|
||||
@@ -17,7 +17,7 @@ public struct ClawdisCanvasA2UIPushParams: Codable, Sendable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdisCanvasA2UIPushJSONLParams: Codable, Sendable, Equatable {
|
||||
public struct ClawdbotCanvasA2UIPushJSONLParams: Codable, Sendable, Equatable {
|
||||
public var jsonl: String
|
||||
|
||||
public init(jsonl: String) {
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdisCanvasA2UIJSONL: Sendable {
|
||||
public enum ClawdbotCanvasA2UIJSONL: Sendable {
|
||||
public struct ParsedItem: Sendable {
|
||||
public var lineNumber: Int
|
||||
public var message: AnyCodable
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
public struct ClawdisCanvasNavigateParams: Codable, Sendable, Equatable {
|
||||
public struct ClawdbotCanvasNavigateParams: Codable, Sendable, Equatable {
|
||||
public var url: String
|
||||
|
||||
public init(url: String) {
|
||||
@@ -8,7 +8,7 @@ public struct ClawdisCanvasNavigateParams: Codable, Sendable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdisCanvasPlacement: Codable, Sendable, Equatable {
|
||||
public struct ClawdbotCanvasPlacement: Codable, Sendable, Equatable {
|
||||
public var x: Double?
|
||||
public var y: Double?
|
||||
public var width: Double?
|
||||
@@ -22,17 +22,17 @@ public struct ClawdisCanvasPlacement: Codable, Sendable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdisCanvasPresentParams: Codable, Sendable, Equatable {
|
||||
public struct ClawdbotCanvasPresentParams: Codable, Sendable, Equatable {
|
||||
public var url: String?
|
||||
public var placement: ClawdisCanvasPlacement?
|
||||
public var placement: ClawdbotCanvasPlacement?
|
||||
|
||||
public init(url: String? = nil, placement: ClawdisCanvasPlacement? = nil) {
|
||||
public init(url: String? = nil, placement: ClawdbotCanvasPlacement? = nil) {
|
||||
self.url = url
|
||||
self.placement = placement
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdisCanvasEvalParams: Codable, Sendable, Equatable {
|
||||
public struct ClawdbotCanvasEvalParams: Codable, Sendable, Equatable {
|
||||
public var javaScript: String
|
||||
|
||||
public init(javaScript: String) {
|
||||
@@ -40,7 +40,7 @@ public struct ClawdisCanvasEvalParams: Codable, Sendable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public enum ClawdisCanvasSnapshotFormat: String, Codable, Sendable {
|
||||
public enum ClawdbotCanvasSnapshotFormat: String, Codable, Sendable {
|
||||
case png
|
||||
case jpeg
|
||||
|
||||
@@ -63,12 +63,12 @@ public enum ClawdisCanvasSnapshotFormat: String, Codable, Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdisCanvasSnapshotParams: Codable, Sendable, Equatable {
|
||||
public struct ClawdbotCanvasSnapshotParams: Codable, Sendable, Equatable {
|
||||
public var maxWidth: Int?
|
||||
public var quality: Double?
|
||||
public var format: ClawdisCanvasSnapshotFormat?
|
||||
public var format: ClawdbotCanvasSnapshotFormat?
|
||||
|
||||
public init(maxWidth: Int? = nil, quality: Double? = nil, format: ClawdisCanvasSnapshotFormat? = nil) {
|
||||
public init(maxWidth: Int? = nil, quality: Double? = nil, format: ClawdbotCanvasSnapshotFormat? = nil) {
|
||||
self.maxWidth = maxWidth
|
||||
self.quality = quality
|
||||
self.format = format
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdisCanvasCommand: String, Codable, Sendable {
|
||||
public enum ClawdbotCanvasCommand: String, Codable, Sendable {
|
||||
case present = "canvas.present"
|
||||
case hide = "canvas.hide"
|
||||
case navigate = "canvas.navigate"
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdisCapability: String, Codable, Sendable {
|
||||
public enum ClawdbotCapability: String, Codable, Sendable {
|
||||
case canvas
|
||||
case camera
|
||||
case screen
|
||||
@@ -1,5 +1,5 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdisKitResources {
|
||||
public enum ClawdbotKitResources {
|
||||
public static let bundle: Bundle = .module
|
||||
}
|
||||
@@ -37,7 +37,7 @@ public struct AgentDeepLink: Codable, Sendable, Equatable {
|
||||
|
||||
public enum DeepLinkParser {
|
||||
public static func parse(_ url: URL) -> DeepLinkRoute? {
|
||||
guard url.scheme?.lowercased() == "clawdis" else { return nil }
|
||||
guard url.scheme?.lowercased() == "clawdbot" 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 }
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdisLocationCommand: String, Codable, Sendable {
|
||||
public enum ClawdbotLocationCommand: String, Codable, Sendable {
|
||||
case get = "location.get"
|
||||
}
|
||||
|
||||
public enum ClawdisLocationAccuracy: String, Codable, Sendable {
|
||||
public enum ClawdbotLocationAccuracy: String, Codable, Sendable {
|
||||
case coarse
|
||||
case balanced
|
||||
case precise
|
||||
}
|
||||
|
||||
public struct ClawdisLocationGetParams: Codable, Sendable, Equatable {
|
||||
public struct ClawdbotLocationGetParams: Codable, Sendable, Equatable {
|
||||
public var timeoutMs: Int?
|
||||
public var maxAgeMs: Int?
|
||||
public var desiredAccuracy: ClawdisLocationAccuracy?
|
||||
public var desiredAccuracy: ClawdbotLocationAccuracy?
|
||||
|
||||
public init(timeoutMs: Int? = nil, maxAgeMs: Int? = nil, desiredAccuracy: ClawdisLocationAccuracy? = nil) {
|
||||
public init(timeoutMs: Int? = nil, maxAgeMs: Int? = nil, desiredAccuracy: ClawdbotLocationAccuracy? = nil) {
|
||||
self.timeoutMs = timeoutMs
|
||||
self.maxAgeMs = maxAgeMs
|
||||
self.desiredAccuracy = desiredAccuracy
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdisLocationPayload: Codable, Sendable, Equatable {
|
||||
public struct ClawdbotLocationPayload: Codable, Sendable, Equatable {
|
||||
public var lat: Double
|
||||
public var lon: Double
|
||||
public var accuracyMeters: Double
|
||||
@@ -0,0 +1,7 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdbotLocationMode: String, Codable, Sendable, CaseIterable {
|
||||
case off
|
||||
case whileUsing
|
||||
case always
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdisNodeErrorCode: String, Codable, Sendable {
|
||||
public enum ClawdbotNodeErrorCode: String, Codable, Sendable {
|
||||
case notPaired = "NOT_PAIRED"
|
||||
case unauthorized = "UNAUTHORIZED"
|
||||
case backgroundUnavailable = "NODE_BACKGROUND_UNAVAILABLE"
|
||||
@@ -8,14 +8,14 @@ public enum ClawdisNodeErrorCode: String, Codable, Sendable {
|
||||
case unavailable = "UNAVAILABLE"
|
||||
}
|
||||
|
||||
public struct ClawdisNodeError: Error, Codable, Sendable, Equatable {
|
||||
public var code: ClawdisNodeErrorCode
|
||||
public struct ClawdbotNodeError: Error, Codable, Sendable, Equatable {
|
||||
public var code: ClawdbotNodeErrorCode
|
||||
public var message: String
|
||||
public var retryable: Bool?
|
||||
public var retryAfterMs: Int?
|
||||
|
||||
public init(
|
||||
code: ClawdisNodeErrorCode,
|
||||
code: ClawdbotNodeErrorCode,
|
||||
message: String,
|
||||
retryable: Bool? = nil,
|
||||
retryAfterMs: Int? = nil)
|
||||
@@ -55,7 +55,7 @@
|
||||
backface-visibility: hidden;
|
||||
opacity: 0.45;
|
||||
pointer-events: none;
|
||||
animation: clawdis-grid-drift 140s ease-in-out infinite alternate;
|
||||
animation: clawdbot-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: clawdis-glow-drift 110s ease-in-out infinite alternate;
|
||||
animation: clawdbot-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 clawdis-grid-drift {
|
||||
@keyframes clawdbot-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 clawdis-glow-drift {
|
||||
@keyframes clawdbot-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"] #clawdis-canvas {
|
||||
:root[data-platform="android"] #clawdbot-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;
|
||||
}
|
||||
#clawdis-status {
|
||||
#clawdbot-status {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
display: none;
|
||||
@@ -119,7 +119,7 @@
|
||||
pointer-events: none;
|
||||
z-index: 3;
|
||||
}
|
||||
#clawdis-status .card {
|
||||
#clawdbot-status .card {
|
||||
text-align: center;
|
||||
padding: 16px 18px;
|
||||
border-radius: 14px;
|
||||
@@ -129,13 +129,13 @@
|
||||
-webkit-backdrop-filter: blur(14px);
|
||||
backdrop-filter: blur(14px);
|
||||
}
|
||||
#clawdis-status .title {
|
||||
#clawdbot-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);
|
||||
}
|
||||
#clawdis-status .subtitle {
|
||||
#clawdbot-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="clawdis-canvas"></canvas>
|
||||
<div id="clawdis-status">
|
||||
<canvas id="clawdbot-canvas"></canvas>
|
||||
<div id="clawdbot-status">
|
||||
<div class="card">
|
||||
<div class="title" id="clawdis-status-title">Ready</div>
|
||||
<div class="subtitle" id="clawdis-status-subtitle">Waiting for agent</div>
|
||||
<div class="title" id="clawdbot-status-title">Ready</div>
|
||||
<div class="subtitle" id="clawdbot-status-subtitle">Waiting for agent</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
(() => {
|
||||
const canvas = document.getElementById('clawdis-canvas');
|
||||
const canvas = document.getElementById('clawdbot-canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
const statusEl = document.getElementById('clawdis-status');
|
||||
const titleEl = document.getElementById('clawdis-status-title');
|
||||
const subtitleEl = document.getElementById('clawdis-status-subtitle');
|
||||
const statusEl = document.getElementById('clawdbot-status');
|
||||
const titleEl = document.getElementById('clawdbot-status-title');
|
||||
const subtitleEl = document.getElementById('clawdbot-status-subtitle');
|
||||
const debugStatusEnabledByQuery = (() => {
|
||||
try {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
@@ -194,7 +194,7 @@
|
||||
statusEl.style.display = 'none';
|
||||
}
|
||||
|
||||
window.__clawdis = {
|
||||
window.__clawdbot = {
|
||||
canvas,
|
||||
ctx,
|
||||
setDebugStatusEnabled,
|
||||
@@ -1,10 +1,10 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdisScreenCommand: String, Codable, Sendable {
|
||||
public enum ClawdbotScreenCommand: String, Codable, Sendable {
|
||||
case record = "screen.record"
|
||||
}
|
||||
|
||||
public struct ClawdisScreenRecordParams: Codable, Sendable, Equatable {
|
||||
public struct ClawdbotScreenRecordParams: Codable, Sendable, Equatable {
|
||||
public var screenIndex: Int?
|
||||
public var durationMs: Int?
|
||||
public var fps: Double?
|
||||
@@ -1,14 +1,14 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdisNodeStorage {
|
||||
public enum ClawdbotNodeStorage {
|
||||
public static func appSupportDir() throws -> URL {
|
||||
let base = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first
|
||||
guard let base else {
|
||||
throw NSError(domain: "ClawdisNodeStorage", code: 1, userInfo: [
|
||||
throw NSError(domain: "ClawdbotNodeStorage", code: 1, userInfo: [
|
||||
NSLocalizedDescriptionKey: "Application Support directory unavailable",
|
||||
])
|
||||
}
|
||||
return base.appendingPathComponent("Clawdis", isDirectory: true)
|
||||
return base.appendingPathComponent("Clawdbot", isDirectory: true)
|
||||
}
|
||||
|
||||
public static func canvasRoot(sessionKey: String) throws -> URL {
|
||||
@@ -21,11 +21,11 @@ public enum ClawdisNodeStorage {
|
||||
public static func cachesDir() throws -> URL {
|
||||
let base = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first
|
||||
guard let base else {
|
||||
throw NSError(domain: "ClawdisNodeStorage", code: 2, userInfo: [
|
||||
throw NSError(domain: "ClawdbotNodeStorage", code: 2, userInfo: [
|
||||
NSLocalizedDescriptionKey: "Caches directory unavailable",
|
||||
])
|
||||
}
|
||||
return base.appendingPathComponent("Clawdis", isDirectory: true)
|
||||
return base.appendingPathComponent("Clawdbot", isDirectory: true)
|
||||
}
|
||||
|
||||
public static func canvasSnapshotsRoot(sessionKey: String) throws -> URL {
|
||||
@@ -1,23 +1,23 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdisSystemCommand: String, Codable, Sendable {
|
||||
public enum ClawdbotSystemCommand: String, Codable, Sendable {
|
||||
case run = "system.run"
|
||||
case notify = "system.notify"
|
||||
}
|
||||
|
||||
public enum ClawdisNotificationPriority: String, Codable, Sendable {
|
||||
public enum ClawdbotNotificationPriority: String, Codable, Sendable {
|
||||
case passive
|
||||
case active
|
||||
case timeSensitive
|
||||
}
|
||||
|
||||
public enum ClawdisNotificationDelivery: String, Codable, Sendable {
|
||||
public enum ClawdbotNotificationDelivery: String, Codable, Sendable {
|
||||
case system
|
||||
case overlay
|
||||
case auto
|
||||
}
|
||||
|
||||
public struct ClawdisSystemRunParams: Codable, Sendable, Equatable {
|
||||
public struct ClawdbotSystemRunParams: Codable, Sendable, Equatable {
|
||||
public var command: [String]
|
||||
public var cwd: String?
|
||||
public var env: [String: String]?
|
||||
@@ -39,19 +39,19 @@ public struct ClawdisSystemRunParams: Codable, Sendable, Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ClawdisSystemNotifyParams: Codable, Sendable, Equatable {
|
||||
public struct ClawdbotSystemNotifyParams: Codable, Sendable, Equatable {
|
||||
public var title: String
|
||||
public var body: String
|
||||
public var sound: String?
|
||||
public var priority: ClawdisNotificationPriority?
|
||||
public var delivery: ClawdisNotificationDelivery?
|
||||
public var priority: ClawdbotNotificationPriority?
|
||||
public var delivery: ClawdbotNotificationDelivery?
|
||||
|
||||
public init(
|
||||
title: String,
|
||||
body: String,
|
||||
sound: String? = nil,
|
||||
priority: ClawdisNotificationPriority? = nil,
|
||||
delivery: ClawdisNotificationDelivery? = nil)
|
||||
priority: ClawdbotNotificationPriority? = nil,
|
||||
delivery: ClawdbotNotificationDelivery? = nil)
|
||||
{
|
||||
self.title = title
|
||||
self.body = body
|
||||
@@ -90,7 +90,7 @@ public enum ToolDisplayRegistry {
|
||||
}
|
||||
|
||||
private static func loadConfig() -> ToolDisplayConfig {
|
||||
guard let url = ClawdisKitResources.bundle.url(forResource: "tool-display", withExtension: "json") else {
|
||||
guard let url = ClawdbotKitResources.bundle.url(forResource: "tool-display", withExtension: "json") else {
|
||||
return ToolDisplayConfig(version: nil, fallback: nil, tools: nil)
|
||||
}
|
||||
do {
|
||||
@@ -1,4 +1,4 @@
|
||||
@testable import ClawdisChatUI
|
||||
@testable import ClawdbotChatUI
|
||||
import Testing
|
||||
|
||||
@Suite struct AssistantTextParserTests {
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdisKit
|
||||
import ClawdbotKit
|
||||
import Testing
|
||||
|
||||
@Suite struct BonjourEscapesTests {
|
||||
@@ -8,7 +8,7 @@ import Testing
|
||||
}
|
||||
|
||||
@Test func decodeSpaces() {
|
||||
#expect(BonjourEscapes.decode("Clawdis\\032Gateway") == "Clawdis Gateway")
|
||||
#expect(BonjourEscapes.decode("Clawdbot\\032Gateway") == "Clawdbot Gateway")
|
||||
}
|
||||
|
||||
@Test func decodeMultipleEscapes() {
|
||||
@@ -1,28 +1,28 @@
|
||||
import ClawdisKit
|
||||
import ClawdbotKit
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@Suite struct CanvasA2UIActionTests {
|
||||
@Test func sanitizeTagValueIsStable() {
|
||||
#expect(ClawdisCanvasA2UIAction.sanitizeTagValue("Hello World!") == "Hello_World_")
|
||||
#expect(ClawdisCanvasA2UIAction.sanitizeTagValue(" ") == "-")
|
||||
#expect(ClawdisCanvasA2UIAction.sanitizeTagValue("macOS 26.2") == "macOS_26.2")
|
||||
#expect(ClawdbotCanvasA2UIAction.sanitizeTagValue("Hello World!") == "Hello_World_")
|
||||
#expect(ClawdbotCanvasA2UIAction.sanitizeTagValue(" ") == "-")
|
||||
#expect(ClawdbotCanvasA2UIAction.sanitizeTagValue("macOS 26.2") == "macOS_26.2")
|
||||
}
|
||||
|
||||
@Test func extractActionNameAcceptsNameOrAction() {
|
||||
#expect(ClawdisCanvasA2UIAction.extractActionName(["name": "Hello"]) == "Hello")
|
||||
#expect(ClawdisCanvasA2UIAction.extractActionName(["action": "Wave"]) == "Wave")
|
||||
#expect(ClawdisCanvasA2UIAction.extractActionName(["name": " ", "action": "Fallback"]) == "Fallback")
|
||||
#expect(ClawdisCanvasA2UIAction.extractActionName(["action": " "]) == nil)
|
||||
#expect(ClawdbotCanvasA2UIAction.extractActionName(["name": "Hello"]) == "Hello")
|
||||
#expect(ClawdbotCanvasA2UIAction.extractActionName(["action": "Wave"]) == "Wave")
|
||||
#expect(ClawdbotCanvasA2UIAction.extractActionName(["name": " ", "action": "Fallback"]) == "Fallback")
|
||||
#expect(ClawdbotCanvasA2UIAction.extractActionName(["action": " "]) == nil)
|
||||
}
|
||||
|
||||
@Test func formatAgentMessageIsTokenEfficientAndUnambiguous() {
|
||||
let messageContext = ClawdisCanvasA2UIAction.AgentMessageContext(
|
||||
let messageContext = ClawdbotCanvasA2UIAction.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 = ClawdisCanvasA2UIAction.formatAgentMessage(messageContext)
|
||||
let msg = ClawdbotCanvasA2UIAction.formatAgentMessage(messageContext)
|
||||
|
||||
#expect(msg.contains("CANVAS_A2UI "))
|
||||
#expect(msg.contains("action=Get_Weather"))
|
||||
@@ -1,11 +1,11 @@
|
||||
import ClawdisKit
|
||||
import ClawdbotKit
|
||||
import Testing
|
||||
|
||||
@Suite struct CanvasA2UITests {
|
||||
@Test func commandStringsAreStable() {
|
||||
#expect(ClawdisCanvasA2UICommand.push.rawValue == "canvas.a2ui.push")
|
||||
#expect(ClawdisCanvasA2UICommand.pushJSONL.rawValue == "canvas.a2ui.pushJSONL")
|
||||
#expect(ClawdisCanvasA2UICommand.reset.rawValue == "canvas.a2ui.reset")
|
||||
#expect(ClawdbotCanvasA2UICommand.push.rawValue == "canvas.a2ui.push")
|
||||
#expect(ClawdbotCanvasA2UICommand.pushJSONL.rawValue == "canvas.a2ui.pushJSONL")
|
||||
#expect(ClawdbotCanvasA2UICommand.reset.rawValue == "canvas.a2ui.reset")
|
||||
}
|
||||
|
||||
@Test func jsonlDecodesAndValidatesV0_8() throws {
|
||||
@@ -16,7 +16,7 @@ import Testing
|
||||
{"deleteSurface":{"surfaceId":"main"}}
|
||||
"""
|
||||
|
||||
let messages = try ClawdisCanvasA2UIJSONL.decodeMessagesFromJSONL(jsonl)
|
||||
let messages = try ClawdbotCanvasA2UIJSONL.decodeMessagesFromJSONL(jsonl)
|
||||
#expect(messages.count == 4)
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import Testing
|
||||
"""
|
||||
|
||||
#expect(throws: Error.self) {
|
||||
_ = try ClawdisCanvasA2UIJSONL.decodeMessagesFromJSONL(jsonl)
|
||||
_ = try ClawdbotCanvasA2UIJSONL.decodeMessagesFromJSONL(jsonl)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ import Testing
|
||||
"""
|
||||
|
||||
#expect(throws: Error.self) {
|
||||
_ = try ClawdisCanvasA2UIJSONL.decodeMessagesFromJSONL(jsonl)
|
||||
_ = try ClawdbotCanvasA2UIJSONL.decodeMessagesFromJSONL(jsonl)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import ClawdisKit
|
||||
import ClawdbotKit
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@Suite struct CanvasSnapshotFormatTests {
|
||||
@Test func acceptsJpgAlias() throws {
|
||||
struct Wrapper: Codable {
|
||||
var format: ClawdisCanvasSnapshotFormat
|
||||
var format: ClawdbotCanvasSnapshotFormat
|
||||
}
|
||||
|
||||
let data = try #require("{\"format\":\"jpg\"}".data(using: .utf8))
|
||||
@@ -1,4 +1,4 @@
|
||||
@testable import ClawdisChatUI
|
||||
@testable import ClawdbotChatUI
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@@ -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 = ClawdisChatTheme.resolvedAssistantBubbleColor(for: lightAppearance)
|
||||
let darkResolved = ClawdisChatTheme.resolvedAssistantBubbleColor(for: darkAppearance)
|
||||
let lightResolved = ClawdbotChatTheme.resolvedAssistantBubbleColor(for: lightAppearance)
|
||||
let darkResolved = ClawdbotChatTheme.resolvedAssistantBubbleColor(for: darkAppearance)
|
||||
#expect(try luminance(lightResolved) > luminance(darkResolved))
|
||||
#else
|
||||
#expect(Bool(true))
|
||||
@@ -1,5 +1,5 @@
|
||||
@testable import ClawdisChatUI
|
||||
import ClawdisKit
|
||||
@testable import ClawdbotChatUI
|
||||
import ClawdbotKit
|
||||
import Foundation
|
||||
import Testing
|
||||
|
||||
@@ -31,40 +31,40 @@ private actor TestChatTransportState {
|
||||
var abortedRunIds: [String] = []
|
||||
}
|
||||
|
||||
private final class TestChatTransport: @unchecked Sendable, ClawdisChatTransport {
|
||||
private final class TestChatTransport: @unchecked Sendable, ClawdbotChatTransport {
|
||||
private let state = TestChatTransportState()
|
||||
private let historyResponses: [ClawdisChatHistoryPayload]
|
||||
private let sessionsResponses: [ClawdisChatSessionsListResponse]
|
||||
private let historyResponses: [ClawdbotChatHistoryPayload]
|
||||
private let sessionsResponses: [ClawdbotChatSessionsListResponse]
|
||||
|
||||
private let stream: AsyncStream<ClawdisChatTransportEvent>
|
||||
private let continuation: AsyncStream<ClawdisChatTransportEvent>.Continuation
|
||||
private let stream: AsyncStream<ClawdbotChatTransportEvent>
|
||||
private let continuation: AsyncStream<ClawdbotChatTransportEvent>.Continuation
|
||||
|
||||
init(
|
||||
historyResponses: [ClawdisChatHistoryPayload],
|
||||
sessionsResponses: [ClawdisChatSessionsListResponse] = [])
|
||||
historyResponses: [ClawdbotChatHistoryPayload],
|
||||
sessionsResponses: [ClawdbotChatSessionsListResponse] = [])
|
||||
{
|
||||
self.historyResponses = historyResponses
|
||||
self.sessionsResponses = sessionsResponses
|
||||
var cont: AsyncStream<ClawdisChatTransportEvent>.Continuation!
|
||||
var cont: AsyncStream<ClawdbotChatTransportEvent>.Continuation!
|
||||
self.stream = AsyncStream { c in
|
||||
cont = c
|
||||
}
|
||||
self.continuation = cont
|
||||
}
|
||||
|
||||
func events() -> AsyncStream<ClawdisChatTransportEvent> {
|
||||
func events() -> AsyncStream<ClawdbotChatTransportEvent> {
|
||||
self.stream
|
||||
}
|
||||
|
||||
func setActiveSessionKey(_: String) async throws {}
|
||||
|
||||
func requestHistory(sessionKey: String) async throws -> ClawdisChatHistoryPayload {
|
||||
func requestHistory(sessionKey: String) async throws -> ClawdbotChatHistoryPayload {
|
||||
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 ?? ClawdisChatHistoryPayload(
|
||||
return self.historyResponses.last ?? ClawdbotChatHistoryPayload(
|
||||
sessionKey: sessionKey,
|
||||
sessionId: nil,
|
||||
messages: [],
|
||||
@@ -76,23 +76,23 @@ private final class TestChatTransport: @unchecked Sendable, ClawdisChatTransport
|
||||
message _: String,
|
||||
thinking _: String,
|
||||
idempotencyKey: String,
|
||||
attachments _: [ClawdisChatAttachmentPayload]) async throws -> ClawdisChatSendResponse
|
||||
attachments _: [ClawdbotChatAttachmentPayload]) async throws -> ClawdbotChatSendResponse
|
||||
{
|
||||
await self.state.sentRunIdsAppend(idempotencyKey)
|
||||
return ClawdisChatSendResponse(runId: idempotencyKey, status: "ok")
|
||||
return ClawdbotChatSendResponse(runId: idempotencyKey, status: "ok")
|
||||
}
|
||||
|
||||
func abortRun(sessionKey _: String, runId: String) async throws {
|
||||
await self.state.abortedRunIdsAppend(runId)
|
||||
}
|
||||
|
||||
func listSessions(limit _: Int?) async throws -> ClawdisChatSessionsListResponse {
|
||||
func listSessions(limit _: Int?) async throws -> ClawdbotChatSessionsListResponse {
|
||||
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 ?? ClawdisChatSessionsListResponse(
|
||||
return self.sessionsResponses.last ?? ClawdbotChatSessionsListResponse(
|
||||
ts: nil,
|
||||
path: nil,
|
||||
count: 0,
|
||||
@@ -104,7 +104,7 @@ private final class TestChatTransport: @unchecked Sendable, ClawdisChatTransport
|
||||
true
|
||||
}
|
||||
|
||||
func emit(_ evt: ClawdisChatTransportEvent) {
|
||||
func emit(_ evt: ClawdbotChatTransportEvent) {
|
||||
self.continuation.yield(evt)
|
||||
}
|
||||
|
||||
@@ -139,12 +139,12 @@ private extension TestChatTransportState {
|
||||
@Suite struct ChatViewModelTests {
|
||||
@Test func streamsAssistantAndClearsOnFinal() async throws {
|
||||
let sessionId = "sess-main"
|
||||
let history1 = ClawdisChatHistoryPayload(
|
||||
let history1 = ClawdbotChatHistoryPayload(
|
||||
sessionKey: "main",
|
||||
sessionId: sessionId,
|
||||
messages: [],
|
||||
thinkingLevel: "off")
|
||||
let history2 = ClawdisChatHistoryPayload(
|
||||
let history2 = ClawdbotChatHistoryPayload(
|
||||
sessionKey: "main",
|
||||
sessionId: sessionId,
|
||||
messages: [
|
||||
@@ -157,7 +157,7 @@ private extension TestChatTransportState {
|
||||
thinkingLevel: "off")
|
||||
|
||||
let transport = TestChatTransport(historyResponses: [history1, history2])
|
||||
let vm = await MainActor.run { ClawdisChatViewModel(sessionKey: "main", transport: transport) }
|
||||
let vm = await MainActor.run { ClawdbotChatViewModel(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 @@ private extension TestChatTransportState {
|
||||
|
||||
transport.emit(
|
||||
.agent(
|
||||
ClawdisAgentEventPayload(
|
||||
ClawdbotAgentEventPayload(
|
||||
runId: sessionId,
|
||||
seq: 1,
|
||||
stream: "assistant",
|
||||
@@ -181,7 +181,7 @@ private extension TestChatTransportState {
|
||||
|
||||
transport.emit(
|
||||
.agent(
|
||||
ClawdisAgentEventPayload(
|
||||
ClawdbotAgentEventPayload(
|
||||
runId: sessionId,
|
||||
seq: 2,
|
||||
stream: "tool",
|
||||
@@ -198,7 +198,7 @@ private extension TestChatTransportState {
|
||||
let runId = try #require(await transport.lastSentRunId())
|
||||
transport.emit(
|
||||
.chat(
|
||||
ClawdisChatEventPayload(
|
||||
ClawdbotChatEventPayload(
|
||||
runId: runId,
|
||||
sessionKey: "main",
|
||||
state: "final",
|
||||
@@ -213,20 +213,20 @@ private extension TestChatTransportState {
|
||||
|
||||
@Test func clearsStreamingOnExternalFinalEvent() async throws {
|
||||
let sessionId = "sess-main"
|
||||
let history = ClawdisChatHistoryPayload(
|
||||
let history = ClawdbotChatHistoryPayload(
|
||||
sessionKey: "main",
|
||||
sessionId: sessionId,
|
||||
messages: [],
|
||||
thinkingLevel: "off")
|
||||
let transport = TestChatTransport(historyResponses: [history, history])
|
||||
let vm = await MainActor.run { ClawdisChatViewModel(sessionKey: "main", transport: transport) }
|
||||
let vm = await MainActor.run { ClawdbotChatViewModel(sessionKey: "main", transport: transport) }
|
||||
|
||||
await MainActor.run { vm.load() }
|
||||
try await waitUntil("bootstrap") { await MainActor.run { vm.healthOK && vm.sessionId == sessionId } }
|
||||
|
||||
transport.emit(
|
||||
.agent(
|
||||
ClawdisAgentEventPayload(
|
||||
ClawdbotAgentEventPayload(
|
||||
runId: sessionId,
|
||||
seq: 1,
|
||||
stream: "assistant",
|
||||
@@ -235,7 +235,7 @@ private extension TestChatTransportState {
|
||||
|
||||
transport.emit(
|
||||
.agent(
|
||||
ClawdisAgentEventPayload(
|
||||
ClawdbotAgentEventPayload(
|
||||
runId: sessionId,
|
||||
seq: 2,
|
||||
stream: "tool",
|
||||
@@ -252,7 +252,7 @@ private extension TestChatTransportState {
|
||||
|
||||
transport.emit(
|
||||
.chat(
|
||||
ClawdisChatEventPayload(
|
||||
ClawdbotChatEventPayload(
|
||||
runId: "other-run",
|
||||
sessionKey: "main",
|
||||
state: "final",
|
||||
@@ -268,18 +268,18 @@ private 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 = ClawdisChatHistoryPayload(
|
||||
let history = ClawdbotChatHistoryPayload(
|
||||
sessionKey: "main",
|
||||
sessionId: "sess-main",
|
||||
messages: [],
|
||||
thinkingLevel: "off")
|
||||
let sessions = ClawdisChatSessionsListResponse(
|
||||
let sessions = ClawdbotChatSessionsListResponse(
|
||||
ts: now,
|
||||
path: nil,
|
||||
count: 4,
|
||||
defaults: nil,
|
||||
sessions: [
|
||||
ClawdisChatSessionEntry(
|
||||
ClawdbotChatSessionEntry(
|
||||
key: "recent-1",
|
||||
kind: nil,
|
||||
displayName: nil,
|
||||
@@ -298,7 +298,7 @@ private extension TestChatTransportState {
|
||||
totalTokens: nil,
|
||||
model: nil,
|
||||
contextTokens: nil),
|
||||
ClawdisChatSessionEntry(
|
||||
ClawdbotChatSessionEntry(
|
||||
key: "main",
|
||||
kind: nil,
|
||||
displayName: nil,
|
||||
@@ -317,7 +317,7 @@ private extension TestChatTransportState {
|
||||
totalTokens: nil,
|
||||
model: nil,
|
||||
contextTokens: nil),
|
||||
ClawdisChatSessionEntry(
|
||||
ClawdbotChatSessionEntry(
|
||||
key: "recent-2",
|
||||
kind: nil,
|
||||
displayName: nil,
|
||||
@@ -336,7 +336,7 @@ private extension TestChatTransportState {
|
||||
totalTokens: nil,
|
||||
model: nil,
|
||||
contextTokens: nil),
|
||||
ClawdisChatSessionEntry(
|
||||
ClawdbotChatSessionEntry(
|
||||
key: "old-1",
|
||||
kind: nil,
|
||||
displayName: nil,
|
||||
@@ -360,7 +360,7 @@ private extension TestChatTransportState {
|
||||
let transport = TestChatTransport(
|
||||
historyResponses: [history],
|
||||
sessionsResponses: [sessions])
|
||||
let vm = await MainActor.run { ClawdisChatViewModel(sessionKey: "main", transport: transport) }
|
||||
let vm = await MainActor.run { ClawdbotChatViewModel(sessionKey: "main", transport: transport) }
|
||||
await MainActor.run { vm.load() }
|
||||
try await waitUntil("sessions loaded") { await MainActor.run { !vm.sessions.isEmpty } }
|
||||
|
||||
@@ -371,18 +371,18 @@ private extension TestChatTransportState {
|
||||
@Test func sessionChoicesIncludeCurrentWhenMissing() async throws {
|
||||
let now = Date().timeIntervalSince1970 * 1000
|
||||
let recent = now - (30 * 60 * 1000)
|
||||
let history = ClawdisChatHistoryPayload(
|
||||
let history = ClawdbotChatHistoryPayload(
|
||||
sessionKey: "custom",
|
||||
sessionId: "sess-custom",
|
||||
messages: [],
|
||||
thinkingLevel: "off")
|
||||
let sessions = ClawdisChatSessionsListResponse(
|
||||
let sessions = ClawdbotChatSessionsListResponse(
|
||||
ts: now,
|
||||
path: nil,
|
||||
count: 1,
|
||||
defaults: nil,
|
||||
sessions: [
|
||||
ClawdisChatSessionEntry(
|
||||
ClawdbotChatSessionEntry(
|
||||
key: "main",
|
||||
kind: nil,
|
||||
displayName: nil,
|
||||
@@ -406,7 +406,7 @@ private extension TestChatTransportState {
|
||||
let transport = TestChatTransport(
|
||||
historyResponses: [history],
|
||||
sessionsResponses: [sessions])
|
||||
let vm = await MainActor.run { ClawdisChatViewModel(sessionKey: "custom", transport: transport) }
|
||||
let vm = await MainActor.run { ClawdbotChatViewModel(sessionKey: "custom", transport: transport) }
|
||||
await MainActor.run { vm.load() }
|
||||
try await waitUntil("sessions loaded") { await MainActor.run { !vm.sessions.isEmpty } }
|
||||
|
||||
@@ -416,20 +416,20 @@ private extension TestChatTransportState {
|
||||
|
||||
@Test func clearsStreamingOnExternalErrorEvent() async throws {
|
||||
let sessionId = "sess-main"
|
||||
let history = ClawdisChatHistoryPayload(
|
||||
let history = ClawdbotChatHistoryPayload(
|
||||
sessionKey: "main",
|
||||
sessionId: sessionId,
|
||||
messages: [],
|
||||
thinkingLevel: "off")
|
||||
let transport = TestChatTransport(historyResponses: [history, history])
|
||||
let vm = await MainActor.run { ClawdisChatViewModel(sessionKey: "main", transport: transport) }
|
||||
let vm = await MainActor.run { ClawdbotChatViewModel(sessionKey: "main", transport: transport) }
|
||||
|
||||
await MainActor.run { vm.load() }
|
||||
try await waitUntil("bootstrap") { await MainActor.run { vm.healthOK && vm.sessionId == sessionId } }
|
||||
|
||||
transport.emit(
|
||||
.agent(
|
||||
ClawdisAgentEventPayload(
|
||||
ClawdbotAgentEventPayload(
|
||||
runId: sessionId,
|
||||
seq: 1,
|
||||
stream: "assistant",
|
||||
@@ -440,7 +440,7 @@ private extension TestChatTransportState {
|
||||
|
||||
transport.emit(
|
||||
.chat(
|
||||
ClawdisChatEventPayload(
|
||||
ClawdbotChatEventPayload(
|
||||
runId: "other-run",
|
||||
sessionKey: "main",
|
||||
state: "error",
|
||||
@@ -452,13 +452,13 @@ private extension TestChatTransportState {
|
||||
|
||||
@Test func abortRequestsDoNotClearPendingUntilAbortedEvent() async throws {
|
||||
let sessionId = "sess-main"
|
||||
let history = ClawdisChatHistoryPayload(
|
||||
let history = ClawdbotChatHistoryPayload(
|
||||
sessionKey: "main",
|
||||
sessionId: sessionId,
|
||||
messages: [],
|
||||
thinkingLevel: "off")
|
||||
let transport = TestChatTransport(historyResponses: [history, history])
|
||||
let vm = await MainActor.run { ClawdisChatViewModel(sessionKey: "main", transport: transport) }
|
||||
let vm = await MainActor.run { ClawdbotChatViewModel(sessionKey: "main", transport: transport) }
|
||||
|
||||
await MainActor.run { vm.load() }
|
||||
try await waitUntil("bootstrap") { await MainActor.run { vm.healthOK && vm.sessionId == sessionId } }
|
||||
@@ -482,7 +482,7 @@ private extension TestChatTransportState {
|
||||
|
||||
transport.emit(
|
||||
.chat(
|
||||
ClawdisChatEventPayload(
|
||||
ClawdbotChatEventPayload(
|
||||
runId: runId,
|
||||
sessionKey: "main",
|
||||
state: "aborted",
|
||||
@@ -1,5 +1,5 @@
|
||||
import XCTest
|
||||
@testable import ClawdisKit
|
||||
@testable import ClawdbotKit
|
||||
|
||||
final class ElevenLabsTTSValidationTests: XCTestCase {
|
||||
func testValidatedOutputFormatAllowsOnlyMp3Presets() {
|
||||
@@ -1,4 +1,4 @@
|
||||
import ClawdisKit
|
||||
import ClawdbotKit
|
||||
import CoreGraphics
|
||||
import ImageIO
|
||||
import Testing
|
||||
@@ -1,5 +1,5 @@
|
||||
import XCTest
|
||||
@testable import ClawdisKit
|
||||
@testable import ClawdbotKit
|
||||
|
||||
final class TalkDirectiveTests: XCTestCase {
|
||||
func testParsesDirectiveAndStripsLine() {
|
||||
@@ -1,5 +1,5 @@
|
||||
import XCTest
|
||||
@testable import ClawdisKit
|
||||
@testable import ClawdbotKit
|
||||
|
||||
final class TalkHistoryTimestampTests: XCTestCase {
|
||||
func testSecondsTimestampsAreAcceptedWithSmallTolerance() {
|
||||
@@ -1,5 +1,5 @@
|
||||
import XCTest
|
||||
@testable import ClawdisKit
|
||||
@testable import ClawdbotKit
|
||||
|
||||
final class TalkPromptBuilderTests: XCTestCase {
|
||||
func testBuildIncludesTranscript() {
|
||||
@@ -4,7 +4,7 @@ import { ContextProvider } from "@lit/context";
|
||||
|
||||
import { v0_8 } from "@a2ui/lit";
|
||||
import "@a2ui/lit/ui";
|
||||
import { themeContext } from "@clawdis/a2ui-theme-context";
|
||||
import { themeContext } from "@clawdbot/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 clawdisTheme = {
|
||||
const clawdbotTheme = {
|
||||
components: {
|
||||
AudioPlayer: emptyClasses(),
|
||||
Button: emptyClasses(),
|
||||
@@ -152,7 +152,7 @@ const clawdisTheme = {
|
||||
},
|
||||
};
|
||||
|
||||
class ClawdisA2UIHost extends LitElement {
|
||||
class ClawdbotA2UIHost extends LitElement {
|
||||
static properties = {
|
||||
surfaces: { state: true },
|
||||
pendingAction: { state: true },
|
||||
@@ -162,7 +162,7 @@ class ClawdisA2UIHost extends LitElement {
|
||||
#processor = v0_8.Data.createSignalA2uiMessageProcessor();
|
||||
#themeProvider = new ContextProvider(this, {
|
||||
context: themeContext,
|
||||
initialValue: clawdisTheme,
|
||||
initialValue: clawdbotTheme,
|
||||
});
|
||||
|
||||
surfaces = [];
|
||||
@@ -177,10 +177,10 @@ class ClawdisA2UIHost extends LitElement {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
padding:
|
||||
var(--clawdis-a2ui-inset-top, 0px)
|
||||
var(--clawdis-a2ui-inset-right, 0px)
|
||||
var(--clawdis-a2ui-inset-bottom, 0px)
|
||||
var(--clawdis-a2ui-inset-left, 0px);
|
||||
var(--clawdbot-a2ui-inset-top, 0px)
|
||||
var(--clawdbot-a2ui-inset-right, 0px)
|
||||
var(--clawdbot-a2ui-inset-bottom, 0px)
|
||||
var(--clawdbot-a2ui-inset-left, 0px);
|
||||
}
|
||||
|
||||
#surfaces {
|
||||
@@ -189,14 +189,14 @@ class ClawdisA2UIHost extends LitElement {
|
||||
gap: 12px;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
padding-bottom: var(--clawdis-a2ui-scroll-pad-bottom, 0px);
|
||||
padding-bottom: var(--clawdbot-a2ui-scroll-pad-bottom, 0px);
|
||||
}
|
||||
|
||||
.status {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
top: var(--clawdis-a2ui-status-top, 12px);
|
||||
top: var(--clawdbot-a2ui-status-top, 12px);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
@@ -217,7 +217,7 @@ class ClawdisA2UIHost extends LitElement {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: var(--clawdis-a2ui-toast-bottom, 12px);
|
||||
bottom: var(--clawdbot-a2ui-toast-bottom, 12px);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
@@ -243,7 +243,7 @@ class ClawdisA2UIHost extends LitElement {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
top: var(--clawdis-a2ui-empty-top, var(--clawdis-a2ui-status-top, 12px));
|
||||
top: var(--clawdbot-a2ui-empty-top, var(--clawdbot-a2ui-status-top, 12px));
|
||||
text-align: center;
|
||||
opacity: 0.8;
|
||||
padding: 10px 12px;
|
||||
@@ -276,21 +276,21 @@ class ClawdisA2UIHost extends LitElement {
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
globalThis.clawdisA2UI = {
|
||||
globalThis.clawdbotA2UI = {
|
||||
applyMessages: (messages) => this.applyMessages(messages),
|
||||
reset: () => this.reset(),
|
||||
getSurfaces: () => Array.from(this.#processor.getSurfaces().keys()),
|
||||
};
|
||||
this.addEventListener("a2uiaction", (evt) => this.#handleA2UIAction(evt));
|
||||
this.#statusListener = (evt) => this.#handleActionStatus(evt);
|
||||
globalThis.addEventListener("clawdis:a2ui-action-status", this.#statusListener);
|
||||
globalThis.addEventListener("clawdbot:a2ui-action-status", this.#statusListener);
|
||||
this.#syncSurfaces();
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
super.disconnectedCallback();
|
||||
if (this.#statusListener) {
|
||||
globalThis.removeEventListener("clawdis:a2ui-action-status", this.#statusListener);
|
||||
globalThis.removeEventListener("clawdbot:a2ui-action-status", this.#statusListener);
|
||||
this.#statusListener = null;
|
||||
}
|
||||
}
|
||||
@@ -393,15 +393,15 @@ class ClawdisA2UIHost extends LitElement {
|
||||
...(Object.keys(context).length ? { context } : {}),
|
||||
};
|
||||
|
||||
globalThis.__clawdisLastA2UIAction = userAction;
|
||||
globalThis.__clawdbotLastA2UIAction = userAction;
|
||||
|
||||
const handler =
|
||||
globalThis.webkit?.messageHandlers?.clawdisCanvasA2UIAction ??
|
||||
globalThis.clawdisCanvasA2UIAction;
|
||||
globalThis.webkit?.messageHandlers?.clawdbotCanvasA2UIAction ??
|
||||
globalThis.clawdbotCanvasA2UIAction;
|
||||
if (handler?.postMessage) {
|
||||
try {
|
||||
// WebKit message handlers support structured objects; Android's JS interface expects strings.
|
||||
if (handler === globalThis.clawdisCanvasA2UIAction) {
|
||||
if (handler === globalThis.clawdbotCanvasA2UIAction) {
|
||||
handler.postMessage(JSON.stringify({ userAction }));
|
||||
} else {
|
||||
handler.postMessage({ userAction });
|
||||
@@ -481,4 +481,4 @@ class ClawdisA2UIHost extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("clawdis-a2ui-host", ClawdisA2UIHost);
|
||||
customElements.define("clawdbot-a2ui-host", ClawdbotA2UIHost);
|
||||
@@ -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"),
|
||||
"@clawdis/a2ui-theme-context": a2uiThemeContext,
|
||||
"@clawdbot/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"),
|
||||
@@ -1,7 +0,0 @@
|
||||
import Foundation
|
||||
|
||||
public enum ClawdisLocationMode: String, Codable, Sendable, CaseIterable {
|
||||
case off
|
||||
case whileUsing
|
||||
case always
|
||||
}
|
||||
Reference in New Issue
Block a user